@fluidframework/azure-end-to-end-tests 2.70.0 → 2.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,7 +43,7 @@ const debuggerAttached = inspector.url() !== undefined;
43
43
  /**
44
44
  * Set this to a high number when debugging to avoid timeouts from debugging time.
45
45
  */
46
- const timeoutMultiplier = debuggerAttached ? 1000 : useAzure ? 3 : 1;
46
+ const timeoutMultiplier = debuggerAttached ? 1000 : useAzure ? 5 : 1;
47
47
 
48
48
  /**
49
49
  * Sets the timeout for the given test context.
@@ -131,11 +131,12 @@ describe(`Presence with AzureClient`, () => {
131
131
  const allAttendeesFullyJoinedTimeoutMs = (2000 + 300 * numClients) * timeoutMultiplier;
132
132
 
133
133
  for (const writeClients of [numClients, 1]) {
134
- it(`announces 'attendeeConnected' when remote client joins session [${numClients} clients, ${writeClients} writers]`, async function () {
134
+ it(`announces 'attendeeConnected' when remote client joins session [${numClients} clients, ${writeClients} writers]`, async function testAnnouncesAttendeeConnected() {
135
135
  setTestTimeout(this, childConnectTimeoutMs + allAttendeesJoinedTimeoutMs + 1000);
136
136
 
137
137
  // Setup
138
138
  const { children, childErrorPromise } = await forkChildProcesses(
139
+ this.test?.title ?? "",
139
140
  numClients,
140
141
  afterCleanUp,
141
142
  );
@@ -153,7 +154,7 @@ describe(`Presence with AzureClient`, () => {
153
154
  );
154
155
  });
155
156
 
156
- it(`announces 'attendeeDisconnected' when remote client disconnects [${numClients} clients, ${writeClients} writers]`, async function () {
157
+ it(`announces 'attendeeDisconnected' when remote client disconnects [${numClients} clients, ${writeClients} writers]`, async function testAnnouncesAttendeeDisconnected() {
157
158
  if (useAzure && numClients > 50) {
158
159
  // Even with increased timeouts, more than 50 clients can be too large for AFR.
159
160
  // This may be due to slow responses/inactivity from the clients that are
@@ -173,6 +174,7 @@ describe(`Presence with AzureClient`, () => {
173
174
 
174
175
  // Setup
175
176
  const { children, childErrorPromise } = await forkChildProcesses(
177
+ this.test?.title ?? "",
176
178
  numClients,
177
179
  afterCleanUp,
178
180
  );
@@ -335,78 +337,95 @@ describe(`Presence with AzureClient`, () => {
335
337
  /**
336
338
  * Timeout for child processes to connect to container ({@link ConnectedEvent})
337
339
  */
338
- const childConnectTimeoutMs = 1000 * numClients * timeoutMultiplier;
339
-
340
- let children: ChildProcess[];
341
- let childErrorPromise: Promise<never>;
342
- let containerCreatorAttendeeId: AttendeeId;
343
- let attendeeIdPromises: Promise<AttendeeId>[];
344
- let remoteClients: ChildProcess[];
345
- const testValue = "testValue";
346
- const workspaceId = "presenceTestWorkspace";
347
-
348
- beforeEach(async () => {
349
- ({ children, childErrorPromise } = await forkChildProcesses(
350
- numClients,
351
- afterCleanUp,
352
- ));
353
- ({ containerCreatorAttendeeId, attendeeIdPromises } = await connectChildProcesses(
354
- children,
355
- { writeClients: numClients, readyTimeoutMs: childConnectTimeoutMs },
356
- ));
357
- await Promise.all(attendeeIdPromises);
358
- remoteClients = children.filter((_, index) => index !== 0);
359
- // NOTE: For testing purposes child clients will expect a Latest value of type string (StateFactory.latest<{ value: string }>).
360
- await registerWorkspaceOnChildren(children, workspaceId, {
361
- latest: true,
362
- timeoutMs: workspaceRegisterTimeoutMs,
363
- });
364
- });
365
-
366
- it(`allows clients to read Latest state from other clients [${numClients} clients]`, async function () {
367
- // Setup
368
- const updateEventsPromise = waitForLatestValueUpdates(
369
- remoteClients,
370
- workspaceId,
371
- childErrorPromise,
372
- stateUpdateTimeoutMs,
373
- { fromAttendeeId: containerCreatorAttendeeId, expectedValue: testValue },
374
- );
340
+ const childConnectTimeoutMs = (4000 + 1000 * numClients) * timeoutMultiplier;
341
+ const testCaseTimeoutMs = 1000;
342
+ const testSetupAndActTimeoutMs = childConnectTimeoutMs + testCaseTimeoutMs;
343
+
344
+ // These tests use beforeEach to setup complex state that takes a lot of time
345
+ // and is dependent on number of clients. Keeping the work in beforeEach
346
+ // allows time reporting to report the tested scenario apart from the setup time.
347
+ // So this describe block isolates those beforeEach setups from each distinct
348
+ // client count. Test cases descriptions also have the client count for clarity.
349
+ describe(`with ${numClients} clients`, () => {
350
+ let children: ChildProcess[];
351
+ let childErrorPromise: Promise<never>;
352
+ let containerCreatorAttendeeId: AttendeeId;
353
+ let attendeeIdPromises: Promise<AttendeeId>[];
354
+ let remoteClients: ChildProcess[];
355
+ const testValue = "testValue";
356
+ const workspaceId = "presenceTestWorkspace";
357
+
358
+ beforeEach(async function usingLatestStateObject_beforeEach(): Promise<void> {
359
+ const startTime = performance.now();
360
+ setTestTimeout(this, testSetupAndActTimeoutMs);
361
+
362
+ ({ children, childErrorPromise } = await forkChildProcesses(
363
+ this.currentTest?.title ?? "",
364
+ numClients,
365
+ afterCleanUp,
366
+ ));
367
+ ({ containerCreatorAttendeeId, attendeeIdPromises } = await connectChildProcesses(
368
+ children,
369
+ { writeClients: numClients, readyTimeoutMs: childConnectTimeoutMs },
370
+ ));
371
+ await Promise.all(attendeeIdPromises);
372
+ remoteClients = children.filter((_, index) => index !== 0);
373
+ // NOTE: For testing purposes child clients will expect a Latest value of type string (StateFactory.latest<{ value: string }>).
374
+ await registerWorkspaceOnChildren(children, workspaceId, {
375
+ latest: true,
376
+ timeoutMs: workspaceRegisterTimeoutMs,
377
+ });
375
378
 
376
- // Act - Trigger the update
377
- children[0].send({
378
- command: "setLatestValue",
379
- workspaceId,
380
- value: testValue,
379
+ testConsole.log(
380
+ ` Setup for "${this.currentTest?.title}" completed in ${performance.now() - startTime}ms`,
381
+ );
381
382
  });
382
- const updateEvents = await updateEventsPromise;
383
383
 
384
- // Verify all events are from the expected attendee
385
- for (const updateEvent of updateEvents) {
386
- assert.strictEqual(updateEvent.attendeeId, containerCreatorAttendeeId);
387
- assert.deepStrictEqual(updateEvent.value, testValue);
388
- }
384
+ it(`allows clients to read Latest state from other clients [${numClients} clients]`, async function () {
385
+ // Setup
386
+ const updateEventsPromise = waitForLatestValueUpdates(
387
+ remoteClients,
388
+ workspaceId,
389
+ childErrorPromise,
390
+ stateUpdateTimeoutMs,
391
+ { fromAttendeeId: containerCreatorAttendeeId, expectedValue: testValue },
392
+ );
389
393
 
390
- // Act - Request each remote client to read latest state from container creator
391
- for (const child of remoteClients) {
392
- child.send({
393
- command: "getLatestValue",
394
+ // Act - Trigger the update
395
+ children[0].send({
396
+ command: "setLatestValue",
394
397
  workspaceId,
395
- attendeeId: containerCreatorAttendeeId,
398
+ value: testValue,
396
399
  });
397
- }
400
+ const updateEvents = await updateEventsPromise;
398
401
 
399
- const getResponses = await getLatestValueResponses(
400
- remoteClients,
401
- workspaceId,
402
- childErrorPromise,
403
- getStateTimeoutMs,
404
- );
402
+ // Verify all events are from the expected attendee
403
+ for (const updateEvent of updateEvents) {
404
+ assert.strictEqual(updateEvent.attendeeId, containerCreatorAttendeeId);
405
+ assert.deepStrictEqual(updateEvent.value, testValue);
406
+ }
405
407
 
406
- // Verify - all responses should contain the expected value
407
- for (const getResponse of getResponses) {
408
- assert.deepStrictEqual(getResponse.value, testValue);
409
- }
408
+ // Act - Request each remote client to read latest state from container creator
409
+ for (const child of remoteClients) {
410
+ child.send({
411
+ command: "getLatestValue",
412
+ workspaceId,
413
+ attendeeId: containerCreatorAttendeeId,
414
+ });
415
+ }
416
+
417
+ const getResponses = await getLatestValueResponses(
418
+ remoteClients,
419
+ workspaceId,
420
+ childErrorPromise,
421
+ getStateTimeoutMs,
422
+ );
423
+
424
+ // Verify - all responses should contain the expected value
425
+ for (const getResponse of getResponses) {
426
+ assert.deepStrictEqual(getResponse.value, testValue);
427
+ }
428
+ });
410
429
  });
411
430
  }
412
431
  });
@@ -419,193 +438,211 @@ describe(`Presence with AzureClient`, () => {
419
438
  /**
420
439
  * Timeout for child processes to connect to container ({@link ConnectedEvent})
421
440
  */
422
- const childConnectTimeoutMs = 1000 * numClients * timeoutMultiplier;
423
-
424
- let children: ChildProcess[];
425
- let childErrorPromise: Promise<never>;
426
- let containerCreatorAttendeeId: AttendeeId;
427
- let attendeeIdPromises: Promise<AttendeeId>[];
428
- let remoteClients: ChildProcess[];
429
- const workspaceId = "presenceTestWorkspace";
430
- const key1 = "player1";
431
- const key2 = "player2";
432
- const value1 = { name: "Alice", score: 100 };
433
- const value2 = { name: "Bob", score: 200 };
434
-
435
- beforeEach(async () => {
436
- ({ children, childErrorPromise } = await forkChildProcesses(
437
- numClients,
438
- afterCleanUp,
439
- ));
440
- ({ containerCreatorAttendeeId, attendeeIdPromises } = await connectChildProcesses(
441
- children,
442
- { writeClients: numClients, readyTimeoutMs: childConnectTimeoutMs },
443
- ));
444
- await Promise.all(attendeeIdPromises);
445
- remoteClients = children.filter((_, index) => index !== 0);
446
- // NOTE: For testing purposes child clients will expect a LatestMap value of type Record<string, string | number> (StateFactory.latestMap<{ value: Record<string, string | number> }, string>).
447
- await registerWorkspaceOnChildren(children, workspaceId, {
448
- latestMap: true,
449
- timeoutMs: workspaceRegisterTimeoutMs,
450
- });
451
- });
452
-
453
- it(`allows clients to read LatestMap values from other clients [${numClients} clients]`, async () => {
454
- // Setup
455
- const testKey = "cursor";
456
- const testValue = { x: 150, y: 300 };
457
- const updateEventsPromise = waitForLatestMapValueUpdates(
458
- remoteClients,
459
- workspaceId,
460
- testKey,
461
- childErrorPromise,
462
- stateUpdateTimeoutMs,
463
- { fromAttendeeId: containerCreatorAttendeeId, expectedValue: testValue },
464
- );
441
+ const childConnectTimeoutMs = (4000 + 1000 * numClients) * timeoutMultiplier;
442
+ const testCaseTimeoutMs = 1000;
443
+ const testSetupAndActTimeoutMs = childConnectTimeoutMs + testCaseTimeoutMs;
444
+
445
+ // These tests use beforeEach to setup complex state that takes a lot of time
446
+ // and is dependent on number of clients. Keeping the work in beforeEach
447
+ // allows time reporting to report the tested scenario apart from the setup time.
448
+ // So this describe block isolates those beforeEach setups from each distinct
449
+ // client count. Test cases descriptions also have the client count for clarity.
450
+ describe(`with ${numClients} clients`, () => {
451
+ let children: ChildProcess[];
452
+ let childErrorPromise: Promise<never>;
453
+ let containerCreatorAttendeeId: AttendeeId;
454
+ let attendeeIdPromises: Promise<AttendeeId>[];
455
+ let remoteClients: ChildProcess[];
456
+ const workspaceId = "presenceTestWorkspace";
457
+ const key1 = "player1";
458
+ const key2 = "player2";
459
+ const value1 = { name: "Alice", score: 100 };
460
+ const value2 = { name: "Bob", score: 200 };
461
+
462
+ beforeEach(async function usingLatestMapStateObject_beforeEach(): Promise<void> {
463
+ const startTime = performance.now();
464
+
465
+ setTestTimeout(this, testSetupAndActTimeoutMs);
466
+
467
+ ({ children, childErrorPromise } = await forkChildProcesses(
468
+ this.currentTest?.title ?? "",
469
+ numClients,
470
+ afterCleanUp,
471
+ ));
472
+ ({ containerCreatorAttendeeId, attendeeIdPromises } = await connectChildProcesses(
473
+ children,
474
+ { writeClients: numClients, readyTimeoutMs: childConnectTimeoutMs },
475
+ ));
476
+ await Promise.all(attendeeIdPromises);
477
+ remoteClients = children.filter((_, index) => index !== 0);
478
+ // NOTE: For testing purposes child clients will expect a LatestMap value of type Record<string, string | number> (StateFactory.latestMap<{ value: Record<string, string | number> }, string>).
479
+ await registerWorkspaceOnChildren(children, workspaceId, {
480
+ latestMap: true,
481
+ timeoutMs: workspaceRegisterTimeoutMs,
482
+ });
465
483
 
466
- // Act
467
- children[0].send({
468
- command: "setLatestMapValue",
469
- workspaceId,
470
- key: testKey,
471
- value: testValue,
484
+ testConsole.log(
485
+ ` Setup for "${this.currentTest?.title}" completed in ${performance.now() - startTime}ms`,
486
+ );
472
487
  });
473
- const updateEvents = await updateEventsPromise;
474
488
 
475
- // Check all events are from the expected attendee
476
- for (const updateEvent of updateEvents) {
477
- assert.strictEqual(updateEvent.attendeeId, containerCreatorAttendeeId);
478
- assert.strictEqual(updateEvent.key, testKey);
479
- assert.deepStrictEqual(updateEvent.value, testValue);
480
- }
489
+ it(`allows clients to read LatestMap values from other clients [${numClients} clients]`, async () => {
490
+ // Setup
491
+ const testKey = "cursor";
492
+ const testValue = { x: 150, y: 300 };
493
+ const updateEventsPromise = waitForLatestMapValueUpdates(
494
+ remoteClients,
495
+ workspaceId,
496
+ testKey,
497
+ childErrorPromise,
498
+ stateUpdateTimeoutMs,
499
+ { fromAttendeeId: containerCreatorAttendeeId, expectedValue: testValue },
500
+ );
481
501
 
482
- for (const child of remoteClients) {
483
- child.send({
484
- command: "getLatestMapValue",
502
+ // Act
503
+ children[0].send({
504
+ command: "setLatestMapValue",
485
505
  workspaceId,
486
506
  key: testKey,
487
- attendeeId: containerCreatorAttendeeId,
507
+ value: testValue,
488
508
  });
489
- }
490
- const getResponses = await getLatestMapValueResponses(
491
- remoteClients,
492
- workspaceId,
493
- testKey,
494
- childErrorPromise,
495
- getStateTimeoutMs,
496
- );
509
+ const updateEvents = await updateEventsPromise;
497
510
 
498
- // Verify
499
- for (const getResponse of getResponses) {
500
- assert.deepStrictEqual(getResponse.value, testValue);
501
- }
502
- });
511
+ // Check all events are from the expected attendee
512
+ for (const updateEvent of updateEvents) {
513
+ assert.strictEqual(updateEvent.attendeeId, containerCreatorAttendeeId);
514
+ assert.strictEqual(updateEvent.key, testKey);
515
+ assert.deepStrictEqual(updateEvent.value, testValue);
516
+ }
503
517
 
504
- it(`returns per-key values on read [${numClients} clients]`, async function () {
505
- // Setup
506
- const allAttendeeIds = await Promise.all(attendeeIdPromises);
507
- const attendee0Id = containerCreatorAttendeeId;
508
- const attendee1Id = allAttendeeIds[1];
509
-
510
- const key1Recipients = children.filter((_, index) => index !== 0);
511
- const key2Recipients = children.filter((_, index) => index !== 1);
512
- const key1UpdateEventsPromise = waitForLatestMapValueUpdates(
513
- key1Recipients,
514
- workspaceId,
515
- key1,
516
- childErrorPromise,
517
- stateUpdateTimeoutMs,
518
- { fromAttendeeId: attendee0Id, expectedValue: value1 },
519
- );
520
- const key2UpdateEventsPromise = waitForLatestMapValueUpdates(
521
- key2Recipients,
522
- workspaceId,
523
- key2,
524
- childErrorPromise,
525
- stateUpdateTimeoutMs,
526
- { fromAttendeeId: attendee1Id, expectedValue: value2 },
527
- );
518
+ for (const child of remoteClients) {
519
+ child.send({
520
+ command: "getLatestMapValue",
521
+ workspaceId,
522
+ key: testKey,
523
+ attendeeId: containerCreatorAttendeeId,
524
+ });
525
+ }
526
+ const getResponses = await getLatestMapValueResponses(
527
+ remoteClients,
528
+ workspaceId,
529
+ testKey,
530
+ childErrorPromise,
531
+ getStateTimeoutMs,
532
+ );
528
533
 
529
- // Act
530
- children[0].send({
531
- command: "setLatestMapValue",
532
- workspaceId,
533
- key: key1,
534
- value: value1,
535
- });
536
- const key1UpdateEvents = await key1UpdateEventsPromise;
537
- children[1].send({
538
- command: "setLatestMapValue",
539
- workspaceId,
540
- key: key2,
541
- value: value2,
534
+ // Verify
535
+ for (const getResponse of getResponses) {
536
+ assert.deepStrictEqual(getResponse.value, testValue);
537
+ }
542
538
  });
543
- const key2UpdateEvents = await key2UpdateEventsPromise;
544
539
 
545
- // Verify all events are from the expected attendees
546
- for (const updateEvent of key1UpdateEvents) {
547
- assert.strictEqual(updateEvent.attendeeId, attendee0Id);
548
- assert.strictEqual(updateEvent.key, key1);
549
- assert.deepStrictEqual(updateEvent.value, value1);
550
- }
551
- for (const updateEvent of key2UpdateEvents) {
552
- assert.strictEqual(updateEvent.attendeeId, attendee1Id);
553
- assert.strictEqual(updateEvent.key, key2);
554
- assert.deepStrictEqual(updateEvent.value, value2);
555
- }
540
+ it(`returns per-key values on read [${numClients} clients]`, async function () {
541
+ // Setup
542
+ const allAttendeeIds = await Promise.all(attendeeIdPromises);
543
+ const attendee0Id = containerCreatorAttendeeId;
544
+ const attendee1Id = allAttendeeIds[1];
556
545
 
557
- // Read key1 of attendee0 from all children
558
- for (const child of children) {
559
- child.send({
560
- command: "getLatestMapValue",
546
+ const key1Recipients = children.filter((_, index) => index !== 0);
547
+ const key2Recipients = children.filter((_, index) => index !== 1);
548
+ const key1UpdateEventsPromise = waitForLatestMapValueUpdates(
549
+ key1Recipients,
550
+ workspaceId,
551
+ key1,
552
+ childErrorPromise,
553
+ stateUpdateTimeoutMs,
554
+ { fromAttendeeId: attendee0Id, expectedValue: value1 },
555
+ );
556
+ const key2UpdateEventsPromise = waitForLatestMapValueUpdates(
557
+ key2Recipients,
558
+ workspaceId,
559
+ key2,
560
+ childErrorPromise,
561
+ stateUpdateTimeoutMs,
562
+ { fromAttendeeId: attendee1Id, expectedValue: value2 },
563
+ );
564
+
565
+ // Act
566
+ children[0].send({
567
+ command: "setLatestMapValue",
561
568
  workspaceId,
562
569
  key: key1,
563
- attendeeId: attendee0Id,
570
+ value: value1,
564
571
  });
565
- }
566
- const key1Responses = await getLatestMapValueResponses(
567
- children,
568
- workspaceId,
569
- key1,
570
- childErrorPromise,
571
- getStateTimeoutMs,
572
- );
573
-
574
- // Read key2 of attendee1 from all children
575
- for (const child of children) {
576
- child.send({
577
- command: "getLatestMapValue",
572
+ const key1UpdateEvents = await key1UpdateEventsPromise;
573
+ children[1].send({
574
+ command: "setLatestMapValue",
578
575
  workspaceId,
579
576
  key: key2,
580
- attendeeId: attendee1Id,
577
+ value: value2,
581
578
  });
582
- }
583
- const key2Responses = await getLatestMapValueResponses(
584
- children,
585
- workspaceId,
586
- key2,
587
- childErrorPromise,
588
- getStateTimeoutMs,
589
- );
579
+ const key2UpdateEvents = await key2UpdateEventsPromise;
590
580
 
591
- // Verify
592
- assert.strictEqual(
593
- key1Responses.length,
594
- numClients,
595
- "Expected responses from all clients for key1",
596
- );
597
- assert.strictEqual(
598
- key2Responses.length,
599
- numClients,
600
- "Expected responses from all clients for key2",
601
- );
581
+ // Verify all events are from the expected attendees
582
+ for (const updateEvent of key1UpdateEvents) {
583
+ assert.strictEqual(updateEvent.attendeeId, attendee0Id);
584
+ assert.strictEqual(updateEvent.key, key1);
585
+ assert.deepStrictEqual(updateEvent.value, value1);
586
+ }
587
+ for (const updateEvent of key2UpdateEvents) {
588
+ assert.strictEqual(updateEvent.attendeeId, attendee1Id);
589
+ assert.strictEqual(updateEvent.key, key2);
590
+ assert.deepStrictEqual(updateEvent.value, value2);
591
+ }
602
592
 
603
- for (const response of key1Responses) {
604
- assert.deepStrictEqual(response.value, value1, "Key1 value should match");
605
- }
606
- for (const response of key2Responses) {
607
- assert.deepStrictEqual(response.value, value2, "Key2 value should match");
608
- }
593
+ // Read key1 of attendee0 from all children
594
+ for (const child of children) {
595
+ child.send({
596
+ command: "getLatestMapValue",
597
+ workspaceId,
598
+ key: key1,
599
+ attendeeId: attendee0Id,
600
+ });
601
+ }
602
+ const key1Responses = await getLatestMapValueResponses(
603
+ children,
604
+ workspaceId,
605
+ key1,
606
+ childErrorPromise,
607
+ getStateTimeoutMs,
608
+ );
609
+
610
+ // Read key2 of attendee1 from all children
611
+ for (const child of children) {
612
+ child.send({
613
+ command: "getLatestMapValue",
614
+ workspaceId,
615
+ key: key2,
616
+ attendeeId: attendee1Id,
617
+ });
618
+ }
619
+ const key2Responses = await getLatestMapValueResponses(
620
+ children,
621
+ workspaceId,
622
+ key2,
623
+ childErrorPromise,
624
+ getStateTimeoutMs,
625
+ );
626
+
627
+ // Verify
628
+ assert.strictEqual(
629
+ key1Responses.length,
630
+ numClients,
631
+ "Expected responses from all clients for key1",
632
+ );
633
+ assert.strictEqual(
634
+ key2Responses.length,
635
+ numClients,
636
+ "Expected responses from all clients for key2",
637
+ );
638
+
639
+ for (const response of key1Responses) {
640
+ assert.deepStrictEqual(response.value, value1, "Key1 value should match");
641
+ }
642
+ for (const response of key2Responses) {
643
+ assert.deepStrictEqual(response.value, value2, "Key2 value should match");
644
+ }
645
+ });
609
646
  });
610
647
  }
611
648
  });