@@ -4,6 +4,7 @@ import { copyFile, mkdir, readFile, rm } from 'node:fs/promises';
4
4
import type { Command , CommanderError , OutputConfiguration } from '@commander-js/extra-typings' ;
5
5
import { MermaidChart } from '@mermaidchart/sdk' ;
6
6
7
+ import confirm from '@inquirer/confirm' ;
7
8
import input from '@inquirer/input' ;
8
9
import select from '@inquirer/select' ;
9
10
import type { MCDocument , MCProject , MCUser } from '@mermaidchart/sdk/dist/types.js' ;
@@ -186,9 +187,15 @@ describe('logout', () => {
186
187
187
188
describe ( 'link' , ( ) => {
188
189
const diagram = 'test/output/unsynced.mmd' ;
190
+ const diagram2 = 'test/output/unsynced2.mmd' ;
191
+ const diagram3 = 'test/output/unsynced3.mmd' ;
189
192
190
193
beforeEach ( async ( ) => {
191
- await copyFile ( 'test/fixtures/unsynced.mmd' , diagram ) ;
194
+ await Promise . all ( [
195
+ copyFile ( 'test/fixtures/unsynced.mmd' , diagram ) ,
196
+ copyFile ( 'test/fixtures/unsynced.mmd' , diagram2 ) ,
197
+ copyFile ( 'test/fixtures/unsynced.mmd' , diagram3 ) ,
198
+ ] ) ;
192
199
} ) ;
193
200
194
201
it ( 'should create a new diagram on MermaidChart and add id to frontmatter' , async ( ) => {
@@ -214,13 +221,65 @@ describe('link', () => {
214
221
`id: ${ mockedEmptyDiagram . documentID } ` ,
215
222
) ;
216
223
} ) ;
224
+
225
+ for ( const rememberProjectId of [ true , false ] ) {
226
+ it ( `should link multiple diagrams ${
227
+ rememberProjectId ? 'and remember project id' : ''
228
+ } `, async ( ) => {
229
+ const { program } = mockedProgram ( ) ;
230
+
231
+ vi . mock ( '@inquirer/confirm' ) ;
232
+ vi . mock ( '@inquirer/select' ) ;
233
+ vi . mocked ( confirm ) . mockResolvedValue ( rememberProjectId ) ;
234
+ vi . mocked ( select ) . mockResolvedValue ( mockedProjects [ 0 ] . id ) ;
235
+
236
+ vi . mocked ( MermaidChart . prototype . createDocument ) . mockResolvedValue ( mockedEmptyDiagram ) ;
237
+
238
+ await expect ( readFile ( diagram , { encoding : 'utf8' } ) ) . resolves . not . toContain ( / ^ i d : / ) ;
239
+
240
+ await program . parseAsync ( [ '--config' , CONFIG_AUTHED , 'link' , diagram , diagram2 , diagram3 ] , {
241
+ from : 'user' ,
242
+ } ) ;
243
+
244
+ if ( rememberProjectId ) {
245
+ expect ( vi . mocked ( confirm ) ) . toHaveBeenCalledOnce ( ) ;
246
+ expect ( vi . mocked ( select ) ) . toHaveBeenCalledOnce ( ) ;
247
+ } else {
248
+ // if the user didn't allow using the same project id for all diagrams,
249
+ // ask every time
250
+ expect ( vi . mocked ( confirm ) ) . toHaveBeenCalledOnce ( ) ;
251
+ expect ( vi . mocked ( select ) ) . toHaveBeenCalledTimes ( 3 ) ;
252
+ }
253
+
254
+ // should have uploaded and created three files
255
+ expect ( vi . mocked ( MermaidChart . prototype . setDocument ) ) . toHaveBeenCalledTimes ( 3 ) ;
256
+ expect ( vi . mocked ( MermaidChart . prototype . setDocument ) ) . toHaveBeenCalledWith (
257
+ expect . objectContaining ( {
258
+ code : expect . not . stringContaining ( 'id:' ) , // id: field should not be uploaded
259
+ title : diagram , // title should default to file name
260
+ } ) ,
261
+ ) ;
262
+
263
+ await Promise . all (
264
+ [ diagram , diagram2 , diagram3 ] . map ( async ( file ) => {
265
+ await expect ( readFile ( file , { encoding : 'utf8' } ) ) . resolves . toContain (
266
+ `id: ${ mockedEmptyDiagram . documentID } ` ,
267
+ ) ;
268
+ } ) ,
269
+ ) ;
270
+ } ) ;
271
+ }
217
272
} ) ;
218
273
219
274
describe ( 'pull' , ( ) => {
220
275
const diagram = 'test/output/connected-diagram.mmd' ;
276
+ const diagram2 = 'test/output/connected-diagram-2.mmd' ;
221
277
222
278
beforeEach ( async ( ) => {
223
- await copyFile ( 'test/fixtures/connected-diagram.mmd' , diagram ) ;
279
+ await Promise . all ( [
280
+ copyFile ( 'test/fixtures/connected-diagram.mmd' , diagram ) ,
281
+ copyFile ( 'test/fixtures/connected-diagram.mmd' , diagram2 ) ,
282
+ ] ) ;
224
283
} ) ;
225
284
226
285
it ( 'should fail if MermaidChart document has not yet been linked' , async ( ) => {
@@ -243,7 +302,7 @@ describe('pull', () => {
243
302
) . rejects . toThrowError ( `Diagram at ${ diagram } has no code` ) ;
244
303
} ) ;
245
304
246
- it ( 'should pull document and add a `id:` field to frontmatter' , async ( ) => {
305
+ it ( 'should pull documents and add a `id:` field to frontmatter' , async ( ) => {
247
306
const { program } = mockedProgram ( ) ;
248
307
249
308
const mockedDiagram = {
@@ -255,22 +314,30 @@ title: My cool flowchart
255
314
A[I've been updated!]` ,
256
315
} ;
257
316
258
- vi . mocked ( MermaidChart . prototype . getDocument ) . mockResolvedValueOnce ( mockedDiagram ) ;
317
+ vi . mocked ( MermaidChart . prototype . getDocument ) . mockResolvedValue ( mockedDiagram ) ;
259
318
260
- await program . parseAsync ( [ '--config' , CONFIG_AUTHED , 'pull' , diagram ] , { from : 'user' } ) ;
319
+ await program . parseAsync ( [ '--config' , CONFIG_AUTHED , 'pull' , diagram , diagram2 ] , {
320
+ from : 'user' ,
321
+ } ) ;
261
322
262
- const diagramContents = await readFile ( diagram , { encoding : 'utf8' } ) ;
323
+ for ( const file of [ diagram , diagram2 ] ) {
324
+ const diagramContents = await readFile ( file , { encoding : 'utf8' } ) ;
263
325
264
- expect ( diagramContents ) . toContain ( `id: ${ mockedDiagram . documentID } ` ) ;
265
- expect ( diagramContents ) . toContain ( "flowchart TD\n A[I've been updated!]" ) ;
326
+ expect ( diagramContents ) . toContain ( `id: ${ mockedDiagram . documentID } ` ) ;
327
+ expect ( diagramContents ) . toContain ( "flowchart TD\n A[I've been updated!]" ) ;
328
+ }
266
329
} ) ;
267
330
} ) ;
268
331
269
332
describe ( 'push' , ( ) => {
270
333
const diagram = 'test/output/connected-diagram.mmd' ;
334
+ const diagram2 = 'test/output/connected-diagram-2.mmd' ;
271
335
272
336
beforeEach ( async ( ) => {
273
- await copyFile ( 'test/fixtures/connected-diagram.mmd' , diagram ) ;
337
+ await Promise . all ( [
338
+ copyFile ( 'test/fixtures/connected-diagram.mmd' , diagram ) ,
339
+ copyFile ( 'test/fixtures/connected-diagram.mmd' , diagram2 ) ,
340
+ ] ) ;
274
341
} ) ;
275
342
276
343
it ( 'should fail if MermaidChart document has not yet been linked' , async ( ) => {
@@ -283,16 +350,18 @@ describe('push', () => {
283
350
) . rejects . toThrowError ( 'Diagram at test/fixtures/unsynced.mmd has no id' ) ;
284
351
} ) ;
285
352
286
- it ( 'should push document and remove the `id:` field front frontmatter' , async ( ) => {
353
+ it ( 'should push documents and remove the `id:` field front frontmatter' , async ( ) => {
287
354
const { program } = mockedProgram ( ) ;
288
355
289
- vi . mocked ( MermaidChart . prototype . getDocument ) . mockResolvedValueOnce ( mockedEmptyDiagram ) ;
356
+ vi . mocked ( MermaidChart . prototype . getDocument ) . mockResolvedValue ( mockedEmptyDiagram ) ;
290
357
291
358
await expect ( readFile ( diagram , { encoding : 'utf8' } ) ) . resolves . not . toContain ( / ^ i d : / ) ;
292
359
293
- await program . parseAsync ( [ '--config' , CONFIG_AUTHED , 'push' , diagram ] , { from : 'user' } ) ;
360
+ await program . parseAsync ( [ '--config' , CONFIG_AUTHED , 'push' , diagram , diagram2 ] , {
361
+ from : 'user' ,
362
+ } ) ;
294
363
295
- expect ( vi . mocked ( MermaidChart . prototype . setDocument ) ) . toHaveBeenCalledOnce ( ) ;
364
+ expect ( vi . mocked ( MermaidChart . prototype . setDocument ) ) . toHaveBeenCalledTimes ( 2 ) ;
296
365
expect ( vi . mocked ( MermaidChart . prototype . setDocument ) ) . toHaveBeenCalledWith (
297
366
expect . objectContaining ( {
298
367
code : expect . not . stringContaining ( 'id:' ) ,
0 commit comments