From c040cb2d6cb6e84b3d850539749a8dcabb5e9657 Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Thu, 15 Aug 2024 10:13:48 +1000 Subject: [PATCH] Make messaging/relink mock test more reliable Co-authored-by: Fedor Indutny --- package-lock.json | 8 ++--- package.json | 2 +- ts/background.ts | 50 +++++++++++++++++++++------ ts/test-mock/bootstrap.ts | 5 +++ ts/test-mock/messaging/relink_test.ts | 13 +++++-- ts/test-mock/playwright.ts | 4 +++ 6 files changed, 63 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1be71addf3..f26f0cfd26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -128,7 +128,7 @@ "@indutny/parallel-prettier": "3.0.0", "@indutny/rezip-electron": "1.3.1", "@indutny/symbolicate-mac": "2.3.0", - "@signalapp/mock-server": "6.7.0", + "@signalapp/mock-server": "6.8.1", "@storybook/addon-a11y": "8.1.11", "@storybook/addon-actions": "8.1.11", "@storybook/addon-controls": "8.1.11", @@ -7253,9 +7253,9 @@ } }, "node_modules/@signalapp/mock-server": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@signalapp/mock-server/-/mock-server-6.7.0.tgz", - "integrity": "sha512-ueF3RTp07Y3kxdIg3un3dyE87VdA3y+E37wNxG9HbAb8fk5WP4LYlRwa7VvJBRuI28IU8LbrrC0d7ItXGdN3sA==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@signalapp/mock-server/-/mock-server-6.8.1.tgz", + "integrity": "sha512-RYAaNoCMuIPoMTAuvgEwMh8D12pdvpjOA/qfEOnwXRRLJU1XWXKuAHBc0uJ7deZWLM6qbC/egST/hXImLcsV7Q==", "dev": true, "dependencies": { "@signalapp/libsignal-client": "^0.45.0", diff --git a/package.json b/package.json index 67975f6d08..e0583250fa 100644 --- a/package.json +++ b/package.json @@ -210,7 +210,7 @@ "@indutny/parallel-prettier": "3.0.0", "@indutny/rezip-electron": "1.3.1", "@indutny/symbolicate-mac": "2.3.0", - "@signalapp/mock-server": "6.7.0", + "@signalapp/mock-server": "6.8.1", "@storybook/addon-a11y": "8.1.11", "@storybook/addon-actions": "8.1.11", "@storybook/addon-controls": "8.1.11", diff --git a/ts/background.ts b/ts/background.ts index dfe0599ac6..dddf8c56e7 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -35,6 +35,7 @@ import { ChallengeHandler } from './challenge'; import * as durations from './util/durations'; import { drop } from './util/drop'; import { explodePromise } from './util/explodePromise'; +import type { ExplodePromiseResultType } from './util/explodePromise'; import { isWindowDragElement } from './util/isWindowDragElement'; import { assertDev, strictAssert } from './util/assert'; import { filter } from './util/iterables'; @@ -1462,7 +1463,7 @@ export async function startApp(): Promise { log.info(`Startup/syncTasks: Queueing ${syncTasks.length} sync tasks`); await queueSyncTasks(syncTasks, DataWriter.removeSyncTaskById); - log.info('`Startup/syncTasks: Done'); + log.info('Startup/syncTasks: Done'); } log.info('listening for registration events'); @@ -1708,16 +1709,31 @@ export async function startApp(): Promise { } let connectCount = 0; - let connecting = false; + let connectPromise: ExplodePromiseResultType | undefined; let remotelyExpired = false; async function connect(firstRun?: boolean) { - if (connecting) { + if (connectPromise && !firstRun) { log.warn('background: connect already running', { connectCount, firstRun, }); return; } + if (connectPromise && firstRun) { + while (connectPromise) { + log.warn( + 'background: connect already running; waiting for previous run', + { + connectCount, + firstRun, + } + ); + // eslint-disable-next-line no-await-in-loop + await connectPromise.promise; + } + await connect(firstRun); + return; + } if (remotelyExpired) { log.warn('background: remotely expired, not reconnecting'); @@ -1727,8 +1743,7 @@ export async function startApp(): Promise { strictAssert(server !== undefined, 'WebAPI not connected'); try { - connecting = true; - + connectPromise = explodePromise(); // Reset the flag and update it below if needed setIsInitialSync(false); @@ -1804,12 +1819,13 @@ export async function startApp(): Promise { window.textsecure.storage.user.getDeviceId() !== 1 ) { log.info('Boot after upgrading. Requesting contact sync'); - window.getSyncRequest(); - - void StorageService.reprocessUnknownFields(); - void runStorageService(); try { + window.getSyncRequest(); + + void StorageService.reprocessUnknownFields(); + void runStorageService(); + const manager = window.getAccountManager(); await Promise.all([ manager.maybeUpdateDeviceName(), @@ -1817,7 +1833,7 @@ export async function startApp(): Promise { ]); } catch (e) { log.error( - 'Problem with account manager updates after starting new version: ', + "Problem with 'boot after upgrade' tasks: ", Errors.toLogFormat(e) ); } @@ -1982,7 +1998,15 @@ export async function startApp(): Promise { reconnectBackOff.reset(); } finally { - connecting = false; + if (connectPromise) { + connectPromise.resolve(); + connectPromise = undefined; + } else { + log.warn('background connect: in finally, no connectPromise!', { + connectCount, + firstRun, + }); + } } } @@ -3082,6 +3106,10 @@ export async function startApp(): Promise { ); } finally { await Registration.markEverDone(); + + if (window.SignalCI) { + window.SignalCI.handleEvent('unlinkCleanupComplete', null); + } } } diff --git a/ts/test-mock/bootstrap.ts b/ts/test-mock/bootstrap.ts index 92cd24bc3c..519e12619b 100644 --- a/ts/test-mock/bootstrap.ts +++ b/ts/test-mock/bootstrap.ts @@ -305,6 +305,8 @@ export class Bootstrap { const app = await this.startApp(extraConfig); const window = await app.getWindow(); + + debug('looking for QR code or relink button'); const qrCode = window.locator( '.module-InstallScreenQrCodeNotScannedStep__qr-code__code' ); @@ -316,10 +318,13 @@ export class Bootstrap { await qrCode.waitFor(); } + debug('waiting for provision'); const provision = await this.server.waitForProvision(); + debug('waiting for provision URL'); const provisionURL = await app.waitForProvisionURL(); + debug('completing provision'); this.privDesktop = await provision.complete({ provisionURL, primaryDevice: this.phone, diff --git a/ts/test-mock/messaging/relink_test.ts b/ts/test-mock/messaging/relink_test.ts index c4243901a7..b38cfe4f64 100644 --- a/ts/test-mock/messaging/relink_test.ts +++ b/ts/test-mock/messaging/relink_test.ts @@ -9,7 +9,7 @@ import type { App } from '../playwright'; import { Bootstrap } from '../bootstrap'; import { expectSystemMessages } from '../helpers'; -export const debug = createDebug('mock:test:stories'); +export const debug = createDebug('mock:test:relink'); describe('messaging/relink', function (this: Mocha.Suite) { this.timeout(durations.MINUTE); @@ -70,9 +70,10 @@ describe('messaging/relink', function (this: Mocha.Suite) { it('updates pin state on relink', async () => { const { - phone, - desktop, contacts: [first, second], + desktop, + phone, + server, } = bootstrap; { @@ -88,7 +89,10 @@ describe('messaging/relink', function (this: Mocha.Suite) { .waitFor(); await app.unlink(); + await app.waitForUnlink(); await phone.unlink(desktop); + await server.removeDevice(desktop.number, desktop.deviceId); + await app.close(); debug('change pinned contact, identity key'); @@ -133,6 +137,9 @@ describe('messaging/relink', function (this: Mocha.Suite) { timestamp: bootstrap.getTimestamp(), }); + // Wait for that storage service version to be processed + await app.waitForManifestVersion(state.version); + debug('open old pinned contact'); await leftPane .locator( diff --git a/ts/test-mock/playwright.ts b/ts/test-mock/playwright.ts index 7c5a90fbf9..a183fa562d 100644 --- a/ts/test-mock/playwright.ts +++ b/ts/test-mock/playwright.ts @@ -180,6 +180,10 @@ export class App extends EventEmitter { return window.evaluate('window.SignalCI.unlink()'); } + public async waitForUnlink(): Promise { + return this.waitForEvent('unlinkCleanupComplete'); + } + // EventEmitter types public override on(type: 'close', callback: () => void): this;