Skip to content

Commit aaba515

Browse files
Merge pull request #84 from cgreeno/feat/seq-async-arrows
2 parents c94ea9a + 96840ca commit aaba515

14 files changed

Lines changed: 338 additions & 35 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ Note that with `--coords` enabled, the grid-coords shown show the starting locat
595595
### Sequence Diagrams ✅
596596
- [x] Basic message syntax (`A->>B: message`)
597597
- [x] Solid and dotted arrows, with or without an arrowhead (`->>`, `-->>`, `->`, `-->`)
598+
- [x] Cross (`-x`, `--x`), async point (`-)`, `--)`) and bidirectional (`<<->>`, `<<-->>`) arrows
598599
- [x] Self-messages (`A->>A: think`)
599600
- [x] Participant declarations (`participant Alice`)
600601
- [x] Participant aliases (`participant A as Alice`)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sequenceDiagram
2+
participant A
3+
participant B
4+
A-)B: solid point
5+
B--)A: dotted point
6+
---
7+
+---+ +---+
8+
| A | | B |
9+
+-+-+ +-+-+
10+
| |
11+
| solid point
12+
+--------)|
13+
| |
14+
| dotted point
15+
|(........+
16+
| |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
sequenceDiagram
2+
participant A
3+
participant B
4+
A<<->>B: solid bidirectional
5+
A<<-->>B: dotted bidirectional
6+
B<<->>A: reverse solid
7+
---
8+
+---+ +---+
9+
| A | | B |
10+
+-+-+ +-+-+
11+
| |
12+
| solid bidirectional
13+
+<------->|
14+
| |
15+
| dotted bidirectional
16+
+<.......>|
17+
| |
18+
| reverse solid
19+
|<------->+
20+
| |
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sequenceDiagram
2+
participant A
3+
participant B
4+
A-xB: solid cross
5+
B--xA: dotted cross
6+
---
7+
+---+ +---+
8+
| A | | B |
9+
+-+-+ +-+-+
10+
| |
11+
| solid cross
12+
+--------x|
13+
| |
14+
| dotted cross
15+
|x........+
16+
| |
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
sequenceDiagram
2+
participant A
3+
A-xA: self cross
4+
A-)A: self point
5+
A<<->>A: self bidirectional
6+
---
7+
+---+
8+
| A |
9+
+-+-+
10+
|
11+
| self cross
12+
+--+
13+
| |
14+
|x-+
15+
|
16+
| self point
17+
+--+
18+
| |
19+
|(-+
20+
|
21+
| self bidirectional
22+
+--+
23+
| |
24+
|<-+
25+
|
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sequenceDiagram
2+
participant A
3+
participant B
4+
A-)B: solid point
5+
B--)A: dotted point
6+
---
7+
┌───┐ ┌───┐
8+
│ A │ │ B │
9+
└─┬─┘ └─┬─┘
10+
│ │
11+
│ solid point
12+
├────────)│
13+
│ │
14+
│ dotted point
15+
│(┈┈┈┈┈┈┈┈┤
16+
│ │
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
sequenceDiagram
2+
participant A
3+
participant B
4+
A<<->>B: solid bidirectional
5+
A<<-->>B: dotted bidirectional
6+
B<<->>A: reverse solid
7+
---
8+
┌───┐ ┌───┐
9+
│ A │ │ B │
10+
└─┬─┘ └─┬─┘
11+
│ │
12+
│ solid bidirectional
13+
├◄───────►│
14+
│ │
15+
│ dotted bidirectional
16+
├◄┈┈┈┈┈┈┈►│
17+
│ │
18+
│ reverse solid
19+
│◄───────►┤
20+
│ │
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sequenceDiagram
2+
participant A
3+
participant B
4+
A-xB: solid cross
5+
B--xA: dotted cross
6+
---
7+
┌───┐ ┌───┐
8+
│ A │ │ B │
9+
└─┬─┘ └─┬─┘
10+
│ │
11+
│ solid cross
12+
├────────×│
13+
│ │
14+
│ dotted cross
15+
│×┈┈┈┈┈┈┈┈┤
16+
│ │
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
sequenceDiagram
2+
participant A
3+
A-xA: self cross
4+
A-)A: self point
5+
A<<->>A: self bidirectional
6+
---
7+
┌───┐
8+
│ A │
9+
└─┬─┘
10+
11+
│ self cross
12+
├──┐
13+
│ │
14+
│×─┘
15+
16+
│ self point
17+
├──┐
18+
│ │
19+
│(─┘
20+
21+
│ self bidirectional
22+
├──┐
23+
│ │
24+
│◄─┘
25+

pkg/sequence/arrows_test.go

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,85 @@ func TestArrowTypes(t *testing.T) {
3333
if got.isDotted() != tt.wantDotted {
3434
t.Errorf("isDotted() = %v, want %v", got.isDotted(), tt.wantDotted)
3535
}
36-
if got.hasHead() != tt.wantHead {
37-
t.Errorf("hasHead() = %v, want %v", got.hasHead(), tt.wantHead)
36+
if _, hasHead := got.head(Unicode, true); hasHead != tt.wantHead {
37+
t.Errorf("head() present = %v, want %v", hasHead, tt.wantHead)
3838
}
3939
})
4040
}
4141
}
4242

43-
// TestUnsupportedArrowsRejected documents that arrow types we don't yet support
44-
// (async -x/-), cross, and bidirectional <<->>) are rejected rather than
45-
// silently mis-parsed. mermaid supports these; adding them is future work.
46-
func TestUnsupportedArrowsRejected(t *testing.T) {
43+
// TestArrowSpecParityForms pins the exact input forms mermaid's own test
44+
// suites use for these arrows (sequenceDiagram.spec.js and the cypress
45+
// rendering spec): no spaces around the arrow or after the colon, punctuation
46+
// in labels, asymmetric spacing, and both message directions.
47+
func TestArrowSpecParityForms(t *testing.T) {
48+
tests := []struct {
49+
in string
50+
want ArrowType
51+
}{
52+
{"sequenceDiagram\nAlice-xBob:Hello Bob, how are you?", SolidCross},
53+
{"sequenceDiagram\nAlice--xBob:Hello Bob, how are you?", DottedCross},
54+
{"sequenceDiagram\nAlice-)Bob:Hello Bob, how are you?", SolidPoint},
55+
{"sequenceDiagram\nAlice--)Bob:Hello Bob, how are you?", DottedPoint},
56+
{"sequenceDiagram\nAlice<<->>Bob:Hello Bob, how are you?", BidirectionalSolid},
57+
{"sequenceDiagram\nAlice<<-->>Bob:Hello Bob, how are you?", BidirectionalDotted},
58+
{"sequenceDiagram\n Bob--x Alice: I am good thanks!", DottedCross},
59+
{"sequenceDiagram\n Alice --x Ola1: Bye!", DottedCross},
60+
{"sequenceDiagram\n John<<->>Alice: This also works the other way", BidirectionalSolid},
61+
}
62+
for _, tt := range tests {
63+
sd, err := Parse(tt.in)
64+
if err != nil {
65+
t.Errorf("Parse(%q): %v", tt.in, err)
66+
continue
67+
}
68+
if len(sd.Messages) != 1 || sd.Messages[0].ArrowType != tt.want {
69+
t.Errorf("Parse(%q): expected 1 message with ArrowType %v, got %+v", tt.in, tt.want, sd.Messages)
70+
}
71+
}
72+
}
73+
74+
// TestCentralConnectionsRejected documents that mermaid's central-connection
75+
// syntax (circle markers at the lifeline: "A ()->>() B", released in mermaid
76+
// 11.16) is rejected loudly rather than silently mis-parsed. It composes with
77+
// every arrow type, so supporting it is its own follow-up.
78+
func TestCentralConnectionsRejected(t *testing.T) {
4779
for _, in := range []string{
48-
"sequenceDiagram\n A-xB: cross",
49-
"sequenceDiagram\n A-)B: async",
50-
"sequenceDiagram\n A--xB: dotted cross",
51-
"sequenceDiagram\n A--)B: dotted async",
52-
"sequenceDiagram\n A<<->>B: bidirectional",
80+
"sequenceDiagram\n Alice ()->>() Bob: dual",
81+
"sequenceDiagram\n Alice ()-x() Bob: cross dual",
82+
"sequenceDiagram\n Alice ()<<->>() Bob: bidirectional dual",
83+
"sequenceDiagram\n Alice ->>() Bob: forward",
84+
"sequenceDiagram\n Alice ()->> Bob: reverse",
5385
} {
5486
if _, err := Parse(in); err == nil {
55-
t.Errorf("expected error for unsupported arrow in %q, got none", in)
87+
t.Errorf("expected error for central-connection syntax %q, got none", in)
88+
}
89+
}
90+
}
91+
92+
// TestCrossPointBidirectionalArrows checks that mermaid's remaining message
93+
// arrows — cross (-x/--x), async point (-)/--)) and bidirectional
94+
// (<<->>/<<-->>) — parse to the right ArrowType.
95+
func TestCrossPointBidirectionalArrows(t *testing.T) {
96+
tests := []struct {
97+
in string
98+
want ArrowType
99+
}{
100+
{"sequenceDiagram\n A-xB: cross", SolidCross},
101+
{"sequenceDiagram\n A--xB: dotted cross", DottedCross},
102+
{"sequenceDiagram\n A-)B: async", SolidPoint},
103+
{"sequenceDiagram\n A--)B: dotted async", DottedPoint},
104+
{"sequenceDiagram\n A<<->>B: bidirectional", BidirectionalSolid},
105+
{"sequenceDiagram\n A<<-->>B: dotted bidirectional", BidirectionalDotted},
106+
}
107+
for _, tt := range tests {
108+
sd, err := Parse(tt.in)
109+
if err != nil {
110+
t.Errorf("Parse(%q): %v", tt.in, err)
111+
continue
112+
}
113+
if len(sd.Messages) != 1 || sd.Messages[0].ArrowType != tt.want {
114+
t.Errorf("Parse(%q): expected 1 message with ArrowType %v, got %+v", tt.in, tt.want, sd.Messages)
56115
}
57116
}
58117
}

0 commit comments

Comments
 (0)