async_expectations.spec.ts (5087B)
1 /* eslint-disable @typescript-eslint/require-await */ 2 export const description = ` 3 Tests for eventualAsyncExpectation and immediateAsyncExpectation. 4 `; 5 6 import { makeTestGroup } from '../common/framework/test_group.js'; 7 import { makeTestGroupForUnitTesting } from '../common/internal/test_group.js'; 8 import { assert, objectEquals, rejectOnTimeout, resolveOnTimeout } from '../common/util/util.js'; 9 10 import { TestGroupTest } from './test_group_test.js'; 11 import { UnitTest } from './unit_test.js'; 12 13 class FixtureToTest extends UnitTest { 14 public override immediateAsyncExpectation<T>(fn: () => Promise<T>): Promise<T> { 15 return super.immediateAsyncExpectation(fn); 16 } 17 public override eventualAsyncExpectation<T>(fn: (niceStack: Error) => Promise<T>): void { 18 super.eventualAsyncExpectation(fn); 19 } 20 } 21 22 export const g = makeTestGroup(TestGroupTest); 23 24 g.test('eventual').fn(async t0 => { 25 const g = makeTestGroupForUnitTesting(FixtureToTest); 26 27 const runState = [0, 0, 0, 0]; 28 let runStateIndex = 0; 29 30 // Should pass in state 3 31 g.test('noawait,resolve').fn(t => { 32 const idx = runStateIndex++; 33 34 runState[idx] = 1; 35 t.eventualAsyncExpectation(async () => { 36 runState[idx] = 2; 37 await resolveOnTimeout(50); 38 runState[idx] = 3; 39 }); 40 runState[idx] = 4; 41 }); 42 43 // Should fail in state 4 44 g.test('noawait,reject').fn(t => { 45 const idx = runStateIndex++; 46 47 runState[idx] = 1; 48 t.eventualAsyncExpectation(async () => { 49 runState[idx] = 2; 50 await rejectOnTimeout(50, 'rejected 1'); 51 runState[idx] = 3; 52 }); 53 runState[idx] = 4; 54 }); 55 56 // Should fail in state 3 57 g.test('nested,2').fn(t => { 58 const idx = runStateIndex++; 59 60 runState[idx] = 1; 61 t.eventualAsyncExpectation(async () => { 62 runState[idx] = 2; 63 await resolveOnTimeout(50); // Wait a bit before adding a new eventualAsyncExpectation 64 t.eventualAsyncExpectation(() => rejectOnTimeout(100, 'inner rejected 1')); 65 runState[idx] = 3; 66 }); 67 runState[idx] = 4; 68 }); 69 70 // Should fail in state 3 71 g.test('nested,4').fn(t => { 72 const idx = runStateIndex++; 73 74 runState[idx] = 1; 75 t.eventualAsyncExpectation(async () => { 76 t.eventualAsyncExpectation(async () => { 77 t.eventualAsyncExpectation(async () => { 78 runState[idx] = 2; 79 await resolveOnTimeout(50); // Wait a bit before adding a new eventualAsyncExpectation 80 t.eventualAsyncExpectation(() => rejectOnTimeout(100, 'inner rejected 2')); 81 runState[idx] = 3; 82 }); 83 }); 84 }); 85 runState[idx] = 4; 86 }); 87 88 const resultsPromise = t0.run(g); 89 assert(objectEquals(runState, [0, 0, 0, 0])); 90 91 const statuses = Array.from(await resultsPromise).map(([, v]) => v.status); 92 assert(objectEquals(runState, [3, 4, 3, 3]), () => runState.toString()); 93 assert(objectEquals(statuses, ['pass', 'fail', 'fail', 'fail']), () => statuses.toString()); 94 }); 95 96 g.test('immediate').fn(async t0 => { 97 const g = makeTestGroupForUnitTesting(FixtureToTest); 98 99 const runState = [0, 0, 0, 0, 0]; 100 101 g.test('noawait,resolve').fn(t => { 102 runState[0] = 1; 103 void t.immediateAsyncExpectation(async () => { 104 runState[0] = 2; 105 await resolveOnTimeout(50); 106 runState[0] = 3; 107 }); 108 runState[0] = 4; 109 }); 110 111 // (Can't g.test('noawait,reject') because it causes a top-level Promise 112 // rejection which crashes Node.) 113 114 g.test('await,resolve').fn(async t => { 115 runState[1] = 1; 116 await t.immediateAsyncExpectation(async () => { 117 runState[1] = 2; 118 await resolveOnTimeout(50); 119 runState[1] = 3; 120 }); 121 }); 122 123 g.test('await,reject').fn(async t => { 124 runState[2] = 1; 125 await t.immediateAsyncExpectation(async () => { 126 runState[2] = 2; 127 await rejectOnTimeout(50, 'rejected 3'); 128 runState[2] = 3; 129 }); 130 }); 131 132 // (Similarly can't test 'nested,noawait'.) 133 134 g.test('nested,await,2').fn(t => { 135 runState[3] = 1; 136 t.eventualAsyncExpectation(async () => { 137 runState[3] = 2; 138 await resolveOnTimeout(50); // Wait a bit before adding a new immediateAsyncExpectation 139 runState[3] = 3; 140 await t.immediateAsyncExpectation(() => rejectOnTimeout(100, 'inner rejected 3')); 141 runState[3] = 5; 142 }); 143 runState[3] = 4; 144 }); 145 146 g.test('nested,await,4').fn(t => { 147 runState[4] = 1; 148 t.eventualAsyncExpectation(async () => { 149 t.eventualAsyncExpectation(async () => { 150 t.eventualAsyncExpectation(async () => { 151 runState[4] = 2; 152 await resolveOnTimeout(50); // Wait a bit before adding a new immediateAsyncExpectation 153 runState[4] = 3; 154 await t.immediateAsyncExpectation(() => rejectOnTimeout(100, 'inner rejected 3')); 155 runState[4] = 5; 156 }); 157 }); 158 }); 159 runState[4] = 4; 160 }); 161 162 const resultsPromise = t0.run(g); 163 assert(objectEquals(runState, [0, 0, 0, 0, 0])); 164 165 const statuses = Array.from(await resultsPromise).map(([, v]) => v.status); 166 assert(objectEquals(runState, [3, 3, 2, 3, 3])); 167 assert(objectEquals(statuses, ['fail', 'pass', 'fail', 'fail', 'fail'])); 168 });