diff --git a/src/cache_test.ts b/src/cache_test.ts index 5b2f890e412..8bb11206930 100644 --- a/src/cache_test.ts +++ b/src/cache_test.ts @@ -10,6 +10,7 @@ import { ListPromise } from './informer.js'; import { MockAgent, setGlobalDispatcher, getGlobalDispatcher } from 'undici'; import { Watch } from './watch.js'; +import { deferred } from './test/deferred.js'; const server = 'https://foo.company.com'; @@ -1442,14 +1443,11 @@ describe('ListWatchCache', () => { await informer.start(); - let doneResolve: any; - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const done = deferred(); - informer.on('add', doneResolve); + informer.on('add', done.resolve); - const value = await donePromise; + const value = await done.promise; deepStrictEqual(value, { metadata: { @@ -1716,12 +1714,6 @@ describe('ListWatchCache', () => { deepStrictEqual(errors, [error]); }); - function deferred() { - let resolve!: (value: T | PromiseLike) => void; - const promise = new Promise((done) => (resolve = done)); - return { promise, resolve }; - } - function lifecycleCache( t: TestContext, options: { diff --git a/src/test/deferred.ts b/src/test/deferred.ts new file mode 100644 index 00000000000..330fd2d03b2 --- /dev/null +++ b/src/test/deferred.ts @@ -0,0 +1,3 @@ +export function deferred() { + return Promise.withResolvers(); +} diff --git a/src/test/integration/informerReconnect.ts b/src/test/integration/informerReconnect.ts index 53e74f1798c..5da48acdf59 100644 --- a/src/test/integration/informerReconnect.ts +++ b/src/test/integration/informerReconnect.ts @@ -4,6 +4,7 @@ import { Watch } from '../../watch.js'; import { ListWatch } from '../../cache.js'; import { generateName } from './name.js'; import { withTimeout } from './helpers.js'; +import { deferred } from '../deferred.js'; export default async function informerReconnect() { const kc = new KubeConfig(); @@ -37,35 +38,25 @@ export default async function informerReconnect() { let connectCount = 0; let errorCount = 0; - let cm1AddResolve: () => void; - const cm1AddPromise = new Promise((resolve) => { - cm1AddResolve = resolve; - }); - - let cm2AddResolve: () => void; - const cm2AddPromise = new Promise((resolve) => { - cm2AddResolve = resolve; - }); + const cm1Add = deferred(); + const cm2Add = deferred(); const initialConnects = 0; - let reconnectResolve: () => void; - const reconnectPromise = new Promise((resolve) => { - reconnectResolve = resolve; - }); + const reconnect = deferred(); informer.on('add', (obj: V1ConfigMap) => { const name = obj.metadata?.name ?? 'unknown'; console.log(`Informer event: add ${name}`); addedNames.push(name); - if (name === cm1Name) cm1AddResolve(); - if (name === cm2Name) cm2AddResolve(); + if (name === cm1Name) cm1Add.resolve(); + if (name === cm2Name) cm2Add.resolve(); }); informer.on('connect', () => { connectCount++; console.log(`Informer event: connect (#${connectCount})`); - if (connectCount > initialConnects + 1) reconnectResolve(); + if (connectCount > initialConnects + 1) reconnect.resolve(); }); informer.on('error', (err: any) => { @@ -89,12 +80,12 @@ export default async function informerReconnect() { }, }); - await withTimeout(cm1AddPromise, 15000, 'Timed out waiting for cm1 add event'); + await withTimeout(cm1Add.promise, 15000, 'Timed out waiting for cm1 add event'); assert.ok(addedNames.includes(cm1Name), 'Should have received add event for cm1'); console.log('✓ Received add event for cm1'); console.log(`Waiting for watch reconnection (up to 45s)...`); - await withTimeout(reconnectPromise, 45000, 'Timed out waiting for informer reconnect'); + await withTimeout(reconnect.promise, 45000, 'Timed out waiting for informer reconnect'); assert.ok(connectCount > initialConnects + 1, 'Informer should have reconnected'); console.log(`✓ Informer reconnected (connect count: ${connectCount})`); @@ -107,7 +98,7 @@ export default async function informerReconnect() { }, }); - await withTimeout(cm2AddPromise, 15000, 'Timed out waiting for cm2 add event'); + await withTimeout(cm2Add.promise, 15000, 'Timed out waiting for cm2 add event'); assert.ok(addedNames.includes(cm2Name), 'Should have received add event for cm2 after reconnect'); console.log('✓ Received add event for cm2 after reconnection'); diff --git a/src/test/integration/watchPods.ts b/src/test/integration/watchPods.ts index 3ede5f18467..7a2a5d2e765 100644 --- a/src/test/integration/watchPods.ts +++ b/src/test/integration/watchPods.ts @@ -3,6 +3,7 @@ import { CoreV1Api, KubeConfig, V1Pod } from '../../index.js'; import { Watch } from '../../watch.js'; import { generateName } from './name.js'; import { withTimeout } from './helpers.js'; +import { deferred } from '../deferred.js'; export default async function watchPods() { const kc = new KubeConfig(); @@ -19,15 +20,8 @@ export default async function watchPods() { const receivedEvents: { type: string; name: string }[] = []; - let addResolve: () => void; - const addPromise = new Promise((resolve) => { - addResolve = resolve; - }); - - let deleteResolve: () => void; - const deletePromise = new Promise((resolve) => { - deleteResolve = resolve; - }); + const added = deferred(); + const deleted = deferred(); const controller = await watch.watch( `/api/v1/namespaces/${namespace}/pods`, @@ -37,8 +31,8 @@ export default async function watchPods() { console.log(`Watch event: ${phase} ${name}`); receivedEvents.push({ type: phase, name }); - if (phase === 'ADDED') addResolve(); - if (phase === 'DELETED') deleteResolve(); + if (phase === 'ADDED') added.resolve(); + if (phase === 'DELETED') deleted.resolve(); }, (err: any) => { if (err && err.name !== 'AbortError') console.log('Watch done with error:', err); @@ -56,7 +50,7 @@ export default async function watchPods() { }; await coreV1Client.createNamespacedPod({ namespace, body: pod }); - await withTimeout(addPromise, 15000, 'Timed out waiting for ADDED event'); + await withTimeout(added.promise, 15000, 'Timed out waiting for ADDED event'); const addEvent = receivedEvents.find((e) => e.type === 'ADDED' && e.name === podName); assert.ok(addEvent, 'Should have received ADDED event for pod'); @@ -65,7 +59,7 @@ export default async function watchPods() { console.log(`Deleting pod ${podName}`); await coreV1Client.deleteNamespacedPod({ name: podName, namespace }); - await withTimeout(deletePromise, 15000, 'Timed out waiting for DELETED event'); + await withTimeout(deleted.promise, 15000, 'Timed out waiting for DELETED event'); const deleteEvent = receivedEvents.find((e) => e.type === 'DELETED' && e.name === podName); assert.ok(deleteEvent, 'Should have received DELETED event for pod'); diff --git a/src/watch_test.ts b/src/watch_test.ts index 0b953b1787b..974bacaf36c 100644 --- a/src/watch_test.ts +++ b/src/watch_test.ts @@ -6,6 +6,7 @@ import { Cluster, Context, User } from './config_types.js'; import { Watch } from './watch.js'; import { IncomingMessage, ServerResponse, createServer } from 'node:http'; import { AddressInfo } from 'node:net'; +import { deferred } from './test/deferred.js'; const server = 'https://foo.company.com'; @@ -110,15 +111,8 @@ describe('Watch', () => { let doneCalled = 0; let doneErr: any; - let handledAllObjectsResolve: any; - const handledAllObjectsPromise = new Promise((resolve) => { - handledAllObjectsResolve = resolve; - }); - - let doneResolve: any; - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const handledAllObjects = deferred(); + const done = deferred(); await watch.watch( path, @@ -129,24 +123,24 @@ describe('Watch', () => { receivedTypes.push(phase); receivedObjects.push(obj); if (receivedObjects.length === 2) { - handledAllObjectsResolve(); + handledAllObjects.resolve(); } }, (err: any) => { doneCalled += 1; doneErr = err; - doneResolve(); + done.resolve(); }, ); - await handledAllObjectsPromise; + await handledAllObjects.promise; deepStrictEqual(receivedTypes, [obj1.type, obj2.type]); deepStrictEqual(receivedObjects, [obj1.object, obj2.object]); strictEqual(doneCalled, 0); response!.destroy(); - await donePromise; + await done.promise; strictEqual(doneCalled, 1); strictEqual(doneErr?.name, 'TypeError'); strictEqual(doneErr?.message, 'terminated'); @@ -170,11 +164,7 @@ describe('Watch', () => { const watch = new Watch(kc); let doneCalled = 0; - let doneResolve: () => void; - - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const done = deferred(); await watch.watch( '/some/path/to/object', @@ -182,11 +172,11 @@ describe('Watch', () => { () => {}, () => { doneCalled += 1; - doneResolve(); + done.resolve(); }, ); - await donePromise; + await done.promise; strictEqual(doneCalled, 1); }); @@ -209,15 +199,8 @@ describe('Watch', () => { const receivedObjects: string[] = []; const doneErr: any[] = []; - let handledAllObjectsResolve: any; - const handledAllObjectsPromise = new Promise((resolve) => { - handledAllObjectsResolve = resolve; - }); - - let doneResolve: any; - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const handledAllObjects = deferred(); + const done = deferred(); await watch.watch( path, @@ -226,16 +209,16 @@ describe('Watch', () => { receivedTypes.push(phase); receivedObjects.push(obj); if (receivedObjects.length === 1) { - handledAllObjectsResolve(); + handledAllObjects.resolve(); } }, (err: any) => { doneErr.push(err); - doneResolve(); + done.resolve(); }, ); - await handledAllObjectsPromise; + await handledAllObjects.promise; deepStrictEqual(receivedTypes, [obj1.type]); deepStrictEqual(receivedObjects, [obj1.object]); @@ -245,7 +228,7 @@ describe('Watch', () => { const errIn = new Error('err'); response!.destroy(errIn); - await donePromise; + await done.promise; strictEqual(doneErr.length, 1); strictEqual(doneErr[0]?.name, 'TypeError'); @@ -272,15 +255,8 @@ describe('Watch', () => { const receivedObjects: string[] = []; const doneErr: any[] = []; - let handledAllObjectsResolve: any; - const handledAllObjectsPromise = new Promise((resolve) => { - handledAllObjectsResolve = resolve; - }); - - let doneResolve: any; - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const handledAllObjects = deferred(); + const done = deferred(); await watch.watch( path, @@ -289,22 +265,22 @@ describe('Watch', () => { receivedTypes.push(phase); receivedObjects.push(obj); if (receivedObjects.length === 1) { - handledAllObjectsResolve(); + handledAllObjects.resolve(); } }, (err: any) => { doneErr.push(err); - doneResolve(); + done.resolve(); }, ); - await handledAllObjectsPromise; + await handledAllObjects.promise; deepStrictEqual(receivedTypes, [obj1.type]); deepStrictEqual(receivedObjects, [obj1.object]); strictEqual(doneErr.length, 0); - await donePromise; + await done.promise; strictEqual(doneErr.length, 1); strictEqual(doneErr[0], null); @@ -330,10 +306,7 @@ describe('Watch', () => { const receivedTypes: string[] = []; const receivedObjects: string[] = []; - let doneResolve: any; - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const done = deferred(); await watch.watch( path, @@ -343,11 +316,11 @@ describe('Watch', () => { receivedObjects.push(recievedObject); }, () => { - doneResolve(); + done.resolve(); }, ); - await donePromise; + await done.promise; deepStrictEqual(receivedTypes, [obj.type]); deepStrictEqual(receivedObjects, [obj.object]); @@ -364,10 +337,7 @@ describe('Watch', () => { let doneErr: any; - let doneResolve: () => void; - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const done = deferred(); await watch.watch( '/some/path/to/object', @@ -377,11 +347,11 @@ describe('Watch', () => { }, (err: any) => { doneErr = err; - doneResolve(); + done.resolve(); }, ); - await donePromise; + await done.promise; strictEqual(doneErr.name, 'TimeoutError'); }); @@ -410,10 +380,7 @@ describe('Watch', () => { const receivedObjects: any[] = []; let doneErr: any; - let doneResolve: () => void; - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const done = deferred(); await watch.watch( '/some/path/to/object', @@ -423,11 +390,11 @@ describe('Watch', () => { }, (err: any) => { doneErr = err; - doneResolve(); + done.resolve(); }, ); - await donePromise; + await done.promise; // The stream lived well past requestTimeoutMs because every event reset the timeout. strictEqual(receivedObjects.length, eventCount); @@ -447,10 +414,7 @@ describe('Watch', () => { const receivedObjects: any[] = []; let doneErr: any; - let doneResolve: () => void; - const donePromise = new Promise((resolve) => { - doneResolve = resolve; - }); + const done = deferred(); await watch.watch( '/some/path/to/object', @@ -460,11 +424,11 @@ describe('Watch', () => { }, (err: any) => { doneErr = err; - doneResolve(); + done.resolve(); }, ); - await donePromise; + await done.promise; deepStrictEqual(receivedObjects, [{ name: 'obj' }]); strictEqual(doneErr.name, 'TimeoutError'); diff --git a/tsconfig-with-tests.json b/tsconfig-with-tests.json index 98928a3edd2..479792f0c48 100644 --- a/tsconfig-with-tests.json +++ b/tsconfig-with-tests.json @@ -1,4 +1,7 @@ { "extends": "./tsconfig.json", + "compilerOptions": { + "lib": ["es2024"] + }, "exclude": [] }