2020-04-25 14:11:05 +02:00
|
|
|
/* eslint-env jest */
|
2020-08-25 17:05:01 +02:00
|
|
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
2020-04-25 14:11:05 +02:00
|
|
|
|
|
|
|
describe('State diagram', () => {
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a simple info', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
info
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 1, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a simple state diagrams', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
|
|
|
|
[*] --> State1
|
|
|
|
State1 --> [*]
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a long descriptions instead of id when available', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
|
|
|
|
[*] --> S1
|
|
|
|
state "Some long name" as S1
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a long descriptions with additional descriptions', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
|
|
|
|
[*] --> S1
|
|
|
|
state "Some long name" as S1: The description
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-08-25 17:05:01 +02:00
|
|
|
it('v2 should render a single state with short descriptions', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
state "A long long name" as long1
|
|
|
|
state "A" as longlonglongid
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-08-25 17:05:01 +02:00
|
|
|
it('v2 should render a transition descriptions with new lines', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
|
|
|
|
[*] --> S1
|
|
|
|
S1 --> S2: long line using<br/>should work
|
|
|
|
S1 --> S3: long line using <br>should work
|
|
|
|
S1 --> S4: long line using \\nshould work
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a state with a note', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
State1: The state with a note
|
|
|
|
note right of State1
|
|
|
|
Important information! You can write
|
|
|
|
notes.
|
|
|
|
end note
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a state with on the left side when so specified', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
State1: The state with a note with minus - and plus + in it
|
|
|
|
note left of State1
|
|
|
|
Important information! You can write
|
|
|
|
notes with . and in them.
|
|
|
|
end note
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a state with a note together with another state', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
State1: The state with a note +,-
|
|
|
|
note right of State1
|
|
|
|
Important information! You can write +,-
|
|
|
|
notes.
|
|
|
|
end note
|
|
|
|
State1 --> State2 : With +,-
|
|
|
|
note left of State2 : This is the note +,-<br/>
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a note with multiple lines in it', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
State1: The state with a note
|
|
|
|
note right of State1
|
|
|
|
Important information! You\ncan write
|
|
|
|
notes with multiple lines...
|
|
|
|
Here is another line...
|
|
|
|
And another line...
|
|
|
|
end note
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should handle multiline notes with different line breaks', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
State1
|
|
|
|
note right of State1
|
|
|
|
Line1<br>Line2<br/>Line3<br />Line4<br />Line5
|
|
|
|
end note
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a states with descriptions including multi-line descriptions', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
State1: This a a single line description
|
|
|
|
State2: This a a multi line description
|
|
|
|
State2: here comes the multi part
|
|
|
|
[*] --> State1
|
|
|
|
State1 --> State2
|
|
|
|
State2 --> [*]
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a simple state diagrams', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
[*] --> State1
|
|
|
|
State1 --> State2
|
|
|
|
State1 --> State3
|
|
|
|
State1 --> [*]
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a simple state diagrams with labels', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
[*] --> State1
|
|
|
|
State1 --> State2 : Transition 1
|
|
|
|
State1 --> State3 : Transition 2
|
|
|
|
State1 --> State4 : Transition 3
|
|
|
|
State1 --> State5 : Transition 4
|
|
|
|
State2 --> State3 : Transition 5
|
|
|
|
State1 --> [*]
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render state descriptions', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
state "Long state description" as XState1
|
|
|
|
state "Another Long state description" as XState2
|
|
|
|
XState2 : New line
|
|
|
|
XState1 --> XState2
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-08-25 17:05:01 +02:00
|
|
|
it('v2 should render composite states', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
[*] --> NotShooting: Pacifist
|
|
|
|
NotShooting --> A
|
|
|
|
NotShooting --> B
|
|
|
|
NotShooting --> C
|
|
|
|
|
|
|
|
state NotShooting {
|
|
|
|
[*] --> Idle: Yet another long long öong öong öong label
|
|
|
|
Idle --> Configuring : EvConfig
|
|
|
|
Configuring --> Idle : EvConfig EvConfig EvConfig EvConfig EvConfig
|
|
|
|
}
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-08-25 17:05:01 +02:00
|
|
|
it('v2 should render multiple composite states', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
[*]-->TV
|
|
|
|
|
|
|
|
state TV {
|
|
|
|
[*] --> Off: Off to start with
|
|
|
|
On --> Off : Turn off
|
|
|
|
Off --> On : Turn on
|
|
|
|
}
|
|
|
|
|
|
|
|
TV--> Console
|
|
|
|
|
|
|
|
state Console {
|
|
|
|
[*] --> Off2: Off to start with
|
|
|
|
On2--> Off2 : Turn off
|
|
|
|
Off2 --> On2 : Turn on
|
|
|
|
On2-->Playing
|
|
|
|
|
|
|
|
state Playing {
|
|
|
|
Alive --> Dead
|
|
|
|
Dead-->Alive
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
});
|
2020-08-25 17:05:01 +02:00
|
|
|
it('v2 should render forks in composite states', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
[*]-->TV
|
|
|
|
|
|
|
|
state TV {
|
|
|
|
state fork_state <<fork>>
|
|
|
|
[*] --> fork_state
|
|
|
|
fork_state --> State2
|
|
|
|
fork_state --> State3
|
|
|
|
|
|
|
|
state join_state <<join>>
|
|
|
|
State2 --> join_state
|
|
|
|
State3 --> join_state
|
|
|
|
join_state --> State4
|
|
|
|
State4 --> [*]
|
|
|
|
}
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render forks and joins', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
state fork_state <<fork>>
|
|
|
|
[*] --> fork_state
|
|
|
|
fork_state --> State2
|
|
|
|
fork_state --> State3
|
|
|
|
|
|
|
|
state join_state <<join>>
|
|
|
|
State2 --> join_state
|
|
|
|
State3 --> join_state
|
|
|
|
join_state --> State4
|
|
|
|
State4 --> [*]
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render concurrency states', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
[*] --> Active
|
|
|
|
|
|
|
|
state Active {
|
|
|
|
[*] --> NumLockOff
|
|
|
|
NumLockOff --> NumLockOn : EvNumLockPressed
|
|
|
|
NumLockOn --> NumLockOff : EvNumLockPressed
|
|
|
|
--
|
|
|
|
[*] --> CapsLockOff
|
|
|
|
CapsLockOff --> CapsLockOn : EvCapsLockPressed
|
|
|
|
CapsLockOn --> CapsLockOff : EvCapsLockPressed
|
|
|
|
--
|
|
|
|
[*] --> ScrollLockOff
|
|
|
|
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
|
|
|
|
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
|
|
|
|
}
|
|
|
|
`,
|
2020-08-16 21:49:36 +02:00
|
|
|
{ logLevel: 0, fontFamily: 'courier' }
|
2020-04-25 14:11:05 +02:00
|
|
|
);
|
|
|
|
cy.get('svg');
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should render a state with states in it', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
state PilotCockpit {
|
|
|
|
state Parent {
|
|
|
|
C
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
{
|
|
|
|
logLevel: 0,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2021-05-01 18:09:42 +02:00
|
|
|
it('v2 it should be possibel to use a choice', () => {
|
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
[*] --> Off
|
|
|
|
Off --> On
|
|
|
|
state MyChoice [[choice]]
|
|
|
|
On --> MyChoice
|
|
|
|
MyChoice --> Washing
|
|
|
|
MyChoice --> Drying
|
|
|
|
Washing --> Finished
|
|
|
|
Finished --> [*]
|
|
|
|
`,
|
|
|
|
{
|
|
|
|
logLevel: 0,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2020-08-25 17:05:01 +02:00
|
|
|
it('v2 Simplest composite state', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
state Parent {
|
|
|
|
C
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
{
|
2020-08-16 21:49:36 +02:00
|
|
|
logLevel: 0, fontFamily: 'courier'
|
2020-04-25 14:11:05 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2020-04-26 17:48:07 +02:00
|
|
|
it('v2 should handle multiple arrows from one node to another', () => {
|
2020-04-25 14:11:05 +02:00
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
a --> b: Start
|
|
|
|
a --> b: Stop
|
|
|
|
`,
|
|
|
|
{
|
2020-08-16 21:49:36 +02:00
|
|
|
logLevel: 0, fontFamily: 'courier',
|
2020-04-25 14:11:05 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2021-04-29 19:27:04 +02:00
|
|
|
it('v2 handle transition from one state in a composite state to a composite state', () => {
|
|
|
|
imgSnapshotTest(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
state S1 {
|
|
|
|
sub1 -->sub2
|
|
|
|
}
|
|
|
|
|
|
|
|
state S2 {
|
|
|
|
sub4
|
|
|
|
}
|
|
|
|
S1 --> S2
|
|
|
|
sub1 --> sub4
|
|
|
|
`,
|
|
|
|
{
|
|
|
|
logLevel: 0, fontFamily: 'courier',
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2020-08-25 17:05:01 +02:00
|
|
|
it('v2 should render a state diagram when useMaxWidth is true (default)', () => {
|
|
|
|
renderGraph(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
2020-04-25 14:11:05 +02:00
|
|
|
|
2020-08-25 17:05:01 +02:00
|
|
|
[*] --> State1
|
|
|
|
State1 --> [*]
|
|
|
|
`,
|
|
|
|
{ state: { useMaxWidth: true } }
|
|
|
|
);
|
|
|
|
cy.get('svg')
|
|
|
|
.should((svg) => {
|
|
|
|
expect(svg).to.have.attr('width', '100%');
|
|
|
|
expect(svg).to.have.attr('height');
|
|
|
|
const height = parseFloat(svg.attr('height'));
|
|
|
|
expect(height).to.eq(177);
|
|
|
|
const style = svg.attr('style');
|
|
|
|
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
|
|
|
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
|
|
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
|
|
|
expect(maxWidthValue).to.be.within(135 * .95, 135 * 1.05);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
it('v2 should render a state diagram when useMaxWidth is false', () => {
|
|
|
|
renderGraph(
|
|
|
|
`
|
|
|
|
stateDiagram-v2
|
|
|
|
|
|
|
|
[*] --> State1
|
|
|
|
State1 --> [*]
|
|
|
|
`,
|
|
|
|
{ state: { useMaxWidth: false } }
|
|
|
|
);
|
|
|
|
cy.get('svg')
|
|
|
|
.should((svg) => {
|
|
|
|
const height = parseFloat(svg.attr('height'));
|
|
|
|
const width = parseFloat(svg.attr('width'));
|
|
|
|
expect(height).to.eq(177);
|
|
|
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
|
|
|
expect(width).to.be.within(135 * .95, 135 * 1.05);
|
|
|
|
expect(svg).to.not.have.attr('style');
|
|
|
|
});
|
|
|
|
});
|
2020-04-25 14:11:05 +02:00
|
|
|
});
|