import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('State diagram', () => { it('v2 should render a simple info', () => { imgSnapshotTest( ` info `, { logLevel: 1, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a simple state diagrams', () => { imgSnapshotTest( ` stateDiagram-v2 [*] --> State1 State1 --> [*] `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a long descriptions instead of id when available', () => { imgSnapshotTest( ` stateDiagram-v2 [*] --> S1 state "Some long name" as S1 `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a long descriptions with additional descriptions', () => { imgSnapshotTest( ` stateDiagram-v2 [*] --> S1 state "Some long name" as S1: The description `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a single state with short descriptions', () => { imgSnapshotTest( ` stateDiagram-v2 state "A long long name" as long1 state "A" as longlonglongid `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a transition descriptions with new lines', () => { imgSnapshotTest( ` stateDiagram-v2 [*] --> S1 S1 --> S2: long line using
should work S1 --> S3: long line using
should work S1 --> S4: long line using \\nshould work `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a state with a note', () => { imgSnapshotTest( ` stateDiagram-v2 State1: The state with a note note right of State1 Important information! You can write notes. end note `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a state with on the left side when so specified', () => { 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 `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a state with a note together with another state', () => { 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 +,-
`, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a note with multiple lines in it', () => { 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 `, { logLevel: 0, fontFamily: 'courier' } ); }); it('v2 should handle multiline notes with different line breaks', () => { imgSnapshotTest( ` stateDiagram-v2 State1 note right of State1 Line1
Line2
Line3
Line4
Line5 end note `, { logLevel: 0, fontFamily: 'courier' } ); }); it('v2 should render a states with descriptions including multi-line descriptions', () => { 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 --> [*] `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a simple state diagrams 2', () => { imgSnapshotTest( ` stateDiagram-v2 [*] --> State1 State1 --> State2 State1 --> State3 State1 --> [*] `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a simple state diagrams with labels', () => { 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 --> [*] `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render state descriptions', () => { imgSnapshotTest( ` stateDiagram-v2 state "Long state description" as XState1 state "Another Long state description" as XState2 XState2 : New line XState1 --> XState2 `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render composite states', () => { 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 } `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render multiple composite states', () => { 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 } } `, { logLevel: 0, fontFamily: 'courier' } ); }); it('v2 should render forks in composite states', () => { 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 --> [*] } `, { logLevel: 0, fontFamily: 'courier' } ); }); it('v2 should render forks and joins', () => { 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 --> [*] `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render concurrency states', () => { 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 } `, { logLevel: 0, fontFamily: 'courier' } ); cy.get('svg'); }); it('v2 should render a state with states in it', () => { imgSnapshotTest( ` stateDiagram-v2 state PilotCockpit { state Parent { C } } `, { logLevel: 0, } ); }); it('v2 it should be possible to use a choice', () => { imgSnapshotTest( ` stateDiagram-v2 [*] --> Off Off --> On state MyChoice [[choice]] On --> MyChoice MyChoice --> Washing MyChoice --> Drying Washing --> Finished Finished --> [*] `, { logLevel: 0, } ); }); it('v2 A compound state should be able to link to itself', () => { imgSnapshotTest( ` stateDiagram state Active { Idle } Inactive --> Idle: ACT Active --> Active: LOG `, { logLevel: 0, } ); }); it('v2 width of compond state should grow with title if title is wider', () => { imgSnapshotTest( ` stateDiagram-v2 state "Long state name 2" as NotShooting { a-->b } `, { logLevel: 0, } ); }); it('v2 state label with names in it', () => { imgSnapshotTest( ` stateDiagram-v2 Yswsii: Your state with spaces in it [*] --> Yswsii `, { logLevel: 0, } ); }); it('v2 Simplest composite state', () => { imgSnapshotTest( ` stateDiagram-v2 state Parent { C } `, { logLevel: 0, fontFamily: 'courier', } ); }); it('v2 should handle multiple arrows from one node to another', () => { imgSnapshotTest( ` stateDiagram-v2 a --> b: Start a --> b: Stop `, { logLevel: 0, fontFamily: 'courier', } ); }); it('v2 should handle multiple notes added to one state', () => { imgSnapshotTest( ` stateDiagram-v2 MyState note left of MyState : I am a leftie note right of MyState : I am a rightie `, { logLevel: 0, fontFamily: 'courier', } ); }); it('v2 should handle different rendering directions in composite states', () => { imgSnapshotTest( ` stateDiagram-v2 direction LR state A { direction BT a --> b } state C { direction RL c --> d } A --> C `, { logLevel: 0, fontFamily: 'courier', } ); }); 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', } ); }); it('v2 should render a state diagram when useMaxWidth is true (default)', () => { renderGraph( ` stateDiagram-v2 [*] --> 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.be.within(177, 178); 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(65, 85); }); }); 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.be.within(177, 178); // use within because the absolute value can be slightly different depending on the environment ±5% expect(width).to.be.within(65, 85); expect(svg).to.not.have.attr('style'); }); }); it('v2 should render a state diagram and set the correct length of the labels', () => { imgSnapshotTest( ` stateDiagram-v2 [*] --> 1 1 --> 2: test({ foo#colon; 'far' }) 2 --> [*] `, { logLevel: 0, fontFamily: 'courier' } ); }); describe('classDefs and applying classes', () => { it('v2 states can have a class applied', () => { imgSnapshotTest( ` stateDiagram-v2 [*] --> A A --> B: test({ foo#colon; 'far' }) B --> [*] classDef badBadEvent fill:#f00,color:white,font-weight:bold class B badBadEvent `, { logLevel: 0, fontFamily: 'courier' } ); }); it('v2 can have multiple classes applied to multiple states', () => { imgSnapshotTest( ` stateDiagram-v2 classDef notMoving fill:white classDef movement font-style:italic; classDef badBadEvent fill:#f00,color:white,font-weight:bold [*] --> Still Still --> [*] Still --> Moving Moving --> Still Moving --> Crash Crash --> [*] class Still notMoving class Moving, Crash movement class Crash badBadEvent `, { logLevel: 0, fontFamily: 'courier' } ); }); }); it('1433: should render a simple state diagram with a title', () => { imgSnapshotTest( `--- title: simple state diagram --- stateDiagram-v2 [*] --> State1 State1 --> [*] `, {} ); }); });