@@ -1280,6 +1280,100 @@ flowchart TD
12801280 ] )
12811281 } )
12821282
1283+ test ( "expands & node groups into fan-in and fan-out edges" , ( ) => {
1284+ const diagram = parseMermaidFlowchartDiagram ( `flowchart LR
1285+ N[Native] & M[Mapped] & O --> LM["LanguageModel"]
1286+ LM -->|prepare| REQ & LOG` )
1287+
1288+ expect ( diagram . nodes ) . toEqual ( [
1289+ { id : "N" , label : "Native" , shape : "box" } ,
1290+ { id : "M" , label : "Mapped" , shape : "box" } ,
1291+ { id : "O" , label : "O" , shape : "box" } ,
1292+ { id : "LM" , label : "LanguageModel" , shape : "box" } ,
1293+ { id : "REQ" , label : "REQ" , shape : "box" } ,
1294+ { id : "LOG" , label : "LOG" , shape : "box" } ,
1295+ ] )
1296+ expect ( diagram . edges ) . toEqual ( [
1297+ { from : "N" , to : "LM" , label : "" } ,
1298+ { from : "M" , to : "LM" , label : "" } ,
1299+ { from : "O" , to : "LM" , label : "" } ,
1300+ { from : "LM" , to : "REQ" , label : "prepare" } ,
1301+ { from : "LM" , to : "LOG" , label : "prepare" } ,
1302+ ] )
1303+ } )
1304+
1305+ test ( "expands & groups on both sides of an edge and through a chain" , ( ) => {
1306+ const diagram = parseMermaidFlowchartDiagram ( `flowchart LR
1307+ A & B --> C & D --> E` )
1308+
1309+ expect ( diagram . edges ) . toEqual ( [
1310+ { from : "A" , to : "C" , label : "" } ,
1311+ { from : "A" , to : "D" , label : "" } ,
1312+ { from : "B" , to : "C" , label : "" } ,
1313+ { from : "B" , to : "D" , label : "" } ,
1314+ { from : "C" , to : "E" , label : "" } ,
1315+ { from : "D" , to : "E" , label : "" } ,
1316+ ] )
1317+ } )
1318+
1319+ test ( "declares every node of a bare & group inside the current subgraph" , ( ) => {
1320+ const diagram = parseMermaidFlowchartDiagram ( `flowchart TD
1321+ subgraph Runtime
1322+ A[Alpha] & B[Beta]:::focus
1323+ end
1324+ A --> B` )
1325+
1326+ expect ( diagram . nodes ) . toEqual ( [
1327+ { id : "A" , label : "Alpha" , shape : "box" } ,
1328+ { id : "B" , label : "Beta" , shape : "box" } ,
1329+ ] )
1330+ expect ( diagram . subgraphs ?. [ 0 ] ?. nodeIds ) . toEqual ( [ "A" , "B" ] )
1331+ } )
1332+
1333+ test ( "keeps & inside quoted or bracketed labels as label text" , ( ) => {
1334+ const diagram = parseMermaidFlowchartDiagram ( `flowchart LR
1335+ A["Fetch & parse"] & B[R&D] --> C[Done & dusted]` )
1336+
1337+ expect ( diagram . nodes ) . toEqual ( [
1338+ { id : "A" , label : "Fetch & parse" , shape : "box" } ,
1339+ { id : "B" , label : "R&D" , shape : "box" } ,
1340+ { id : "C" , label : "Done & dusted" , shape : "box" } ,
1341+ ] )
1342+ expect ( diagram . edges ) . toEqual ( [
1343+ { from : "A" , to : "C" , label : "" } ,
1344+ { from : "B" , to : "C" , label : "" } ,
1345+ ] )
1346+ } )
1347+
1348+ test ( "keeps & inside edge labels as label text" , ( ) => {
1349+ const diagram = parseMermaidFlowchartDiagram ( `flowchart LR
1350+ X[a & b] -->|x & y| Y` )
1351+
1352+ expect ( diagram . nodes . find ( ( node ) => node . id === "X" ) ?. label ) . toBe ( "a & b" )
1353+ expect ( diagram . edges ) . toEqual ( [ { from : "X" , to : "Y" , label : "x & y" } ] )
1354+ } )
1355+
1356+ test ( "rejects empty & group members" , ( ) => {
1357+ for ( const statement of [ "A & --> B" , "& A --> B" , "A --> B &" , "A &" ] ) {
1358+ expect ( ( ) => parseMermaidFlowchartDiagram ( `flowchart LR\n ${ statement } ` ) ) . toThrow (
1359+ `Unsupported syntax in flowchart diagram at line 2: "${ statement } "` ,
1360+ )
1361+ }
1362+ } )
1363+
1364+ test ( "renders a fan-in expressed with & the same as separate edge statements" , ( ) => {
1365+ const grouped = renderFlowchartDiagram ( `flowchart LR
1366+ N & M & O --> LM[LanguageModel] --> REQ[LLMRequest]` )
1367+ const separate = renderFlowchartDiagram ( `flowchart LR
1368+ N --> LM[LanguageModel]
1369+ M --> LM
1370+ O --> LM
1371+ LM --> REQ[LLMRequest]` )
1372+
1373+ expect ( grouped ) . toBe ( separate )
1374+ expect ( grouped ) . toContain ( "LanguageModel" )
1375+ } )
1376+
12831377 test ( "parses chained undirected solid edges" , ( ) => {
12841378 const diagram = parseMermaidFlowchartDiagram ( `flowchart LR
12851379 A --- B --- C` )
0 commit comments