Skip to content

Commit 139fa5d

Browse files
authored
feat(smoke-tests): test auto-updating from the version of Compass that was just packaged COMPASS-8536 (#6629)
* Test auto-updating from the version of Compass that was just packaged
1 parent 08818fd commit 139fa5d

File tree

14 files changed

+342
-62
lines changed

14 files changed

+342
-62
lines changed

.evergreen/functions.yml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,13 @@ functions:
649649
npm run --unsafe-perm --workspace compass-e2e-tests test-packaged-ci
650650
651651
smoketest-packaged-app:
652+
- command: github.generate_token
653+
params:
654+
owner: 10gen
655+
repo: compass-mongodb-com
656+
expansion_name: generated_token
657+
permissions: # optional
658+
contents: read
652659
- command: shell.exec
653660
# Fail the task if it's idle for 10 mins
654661
timeout_secs: 600
@@ -667,16 +674,22 @@ functions:
667674
# Load environment variables
668675
eval $(.evergreen/print-compass-env.sh)
669676
677+
npm i -w packages/compass-smoke-tests https://x-access-token:${generated_token}@github.com/10gen/compass-mongodb-com --engine-strict=false
678+
670679
if [[ "$IS_WINDOWS" == "true" ]]; then
671-
npm run --unsafe-perm --workspace @mongodb-js/compass-smoke-tests start -- --package=windows_zip
672-
npm run --unsafe-perm --workspace @mongodb-js/compass-smoke-tests start -- --package=windows_msi
680+
# TODO: windows_setup
681+
npm run --unsafe-perm --workspace @mongodb-js/compass-smoke-tests start -- --package=windows_zip --tests=auto-update-from
682+
npm run --unsafe-perm --workspace @mongodb-js/compass-smoke-tests start -- --package=windows_msi --tests=auto-update-from
673683
fi
674684
675685
if [[ "$IS_OSX" == "true" ]]; then
676686
echo "Disabling clipboard usage in e2e tests (TODO: https://jira.mongodb.org/browse/BUILD-14780)"
677687
export COMPASS_E2E_DISABLE_CLIPBOARD_USAGE="true"
678-
npm run --unsafe-perm --workspace @mongodb-js/compass-smoke-tests start -- --package=osx_dmg
679-
npm run --unsafe-perm --workspace @mongodb-js/compass-smoke-tests start -- --package=osx_zip
688+
# NOTE: We're also skipping auto-update of the macOS app in CI
689+
# because it doesn't work. Running a different test to make sure it
690+
# can install and run successfully at least.
691+
npm run --unsafe-perm --workspace @mongodb-js/compass-smoke-tests start -- --package=osx_zip --tests=time-to-first-query
692+
npm run --unsafe-perm --workspace @mongodb-js/compass-smoke-tests start -- --package=osx_dmg --tests=time-to-first-query
680693
fi
681694
682695
#if [[ "$IS_UBUNTU" == "true" ]]; then

.evergreen/preinstall.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ echo "APPDATA: $APPDATA"
1313
echo "PATH: $PATH"
1414

1515
# these are super useful if you want to run the smoke tests locally
16-
echo "DEV_VERSION_IDENTIFIER: $DEV_VERSION_IDENTIFIER"
17-
echo "EVERGREEN_BUCKET_NAME: $EVERGREEN_BUCKET_NAME"
18-
echo "EVERGREEN_BUCKET_KEY_PREFIX: $EVERGREEN_BUCKET_KEY_PREFIX"
16+
echo "export DEV_VERSION_IDENTIFIER=$DEV_VERSION_IDENTIFIER"
17+
echo "export EVERGREEN_BUCKET_KEY_PREFIX=$EVERGREEN_BUCKET_KEY_PREFIX"
18+
echo "export EVERGREEN_BUCKET_NAME=$EVERGREEN_BUCKET_NAME"
1919

2020
echo "IS_OSX: $IS_OSX"
2121
echo "IS_LINUX: $IS_LINUX"

packages/compass-e2e-tests/helpers/selectors.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,3 +1380,12 @@ export const GlobalWrites = {
13801380
SampleFindingDocuments: '[data-testid="sample-finding-documents"]',
13811381
SampleInsertingDocuments: '[data-testid="sample-inserting-documents"]',
13821382
};
1383+
1384+
// Auto-update toasts
1385+
export const AutoUpdateToast = '[data-testid="toast-compass-update"]';
1386+
export const AutoUpdateRestartButton =
1387+
'[data-testid="auto-update-restart-button"]';
1388+
export const AutoUpdateDownloadLink =
1389+
'[data-testid="auto-update-download-link"]';
1390+
export const AutoUpdateReleaseNotesLink =
1391+
'[data-testid="auto-update-release-notes-link"]';
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { expect } from 'chai';
2+
import {
3+
init,
4+
cleanup,
5+
Selectors,
6+
screenshotPathName,
7+
} from '../helpers/compass';
8+
9+
function wait(ms: number) {
10+
return new Promise((resolve) => {
11+
setTimeout(resolve, ms);
12+
});
13+
}
14+
15+
describe('Auto-update', function () {
16+
it('auto-update from', async function () {
17+
if (process.env.TEST_NAME !== 'auto-update-from') {
18+
// we don't want this test to execute along with all the others under
19+
// normal circumstances because it is destructive - it overwrites Compass
20+
// itself
21+
this.skip();
22+
}
23+
24+
// run the app and wait for it to auto-update
25+
console.log('starting compass the first time');
26+
const compass = await init('auto-update from', { firstRun: true });
27+
const { browser } = compass;
28+
try {
29+
await browser.$(Selectors.AutoUpdateToast).waitForDisplayed();
30+
31+
if (process.env.AUTO_UPDATE_UPDATABLE === 'true') {
32+
const restartButton = browser.$(Selectors.AutoUpdateRestartButton);
33+
await restartButton.waitForDisplayed();
34+
35+
// We could click the restart button to apply the update and restart the
36+
// app, but restarting the app confuses webdriverio or at least our test
37+
// helpers. So we're going to just restart the app manually.
38+
await browser.pause(1000);
39+
} else {
40+
// When auto-update is not supported the toast contains a link to
41+
// download
42+
const linkElement = browser.$(Selectors.AutoUpdateDownloadLink);
43+
await linkElement.waitForDisplayed();
44+
expect(await linkElement.getAttribute('href')).to.equal(
45+
'https://www.mongodb.com/try/download/compass?utm_source=compass&utm_medium=product'
46+
);
47+
}
48+
} finally {
49+
await browser.screenshot(screenshotPathName('auto-update-from'));
50+
await cleanup(compass);
51+
}
52+
53+
if (process.env.AUTO_UPDATE_UPDATABLE === 'true') {
54+
console.log(
55+
'pause to make sure the app properly exited before starting again'
56+
);
57+
await wait(10_000);
58+
59+
console.log('starting compass a second time');
60+
// run the app again and check that the version changed
61+
const compass = await init('auto-update from restart', {
62+
firstRun: false,
63+
});
64+
const { browser } = compass;
65+
try {
66+
await browser.$(Selectors.AutoUpdateToast).waitForDisplayed();
67+
await browser
68+
.$(Selectors.AutoUpdateReleaseNotesLink)
69+
.waitForDisplayed();
70+
} finally {
71+
await browser.screenshot(
72+
screenshotPathName('auto-update-from-restart')
73+
);
74+
await cleanup(compass);
75+
}
76+
}
77+
});
78+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
ignores:
22
- '@mongodb-js/prettier-config-compass'
33
- '@mongodb-js/tsconfig-compass'
4+
- compass-mongodb-com

packages/compass-smoke-tests/src/cli.ts

Lines changed: 123 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
import assert from 'node:assert/strict';
33
import fs from 'node:fs';
44
import path from 'node:path';
5+
import { once } from 'node:events';
56

67
import yargs from 'yargs';
78
import { hideBin } from 'yargs/helpers';
89
import { pick } from 'lodash';
9-
import { execute } from './execute';
10+
import { execute, executeAsync } from './execute';
1011
import {
1112
type PackageDetails,
1213
readPackageDetails,
@@ -25,6 +26,8 @@ import { installWindowsMSI } from './installers/windows-msi';
2526
const SUPPORTED_PLATFORMS = ['win32', 'darwin', 'linux'] as const;
2627
const SUPPORTED_ARCHS = ['x64', 'arm64'] as const;
2728

29+
const SUPPORTED_TESTS = ['time-to-first-query', 'auto-update-from'] as const;
30+
2831
function isSupportedPlatform(
2932
value: unknown
3033
): value is typeof SUPPORTED_PLATFORMS[number] {
@@ -104,7 +107,14 @@ const argv = yargs(hideBin(process.argv))
104107
type: 'boolean',
105108
description: 'Do not delete the sandbox after a run',
106109
default: false,
107-
});
110+
})
111+
.option('tests', {
112+
type: 'array',
113+
string: true,
114+
choices: SUPPORTED_TESTS,
115+
description: 'Which tests to run',
116+
})
117+
.default('tests', SUPPORTED_TESTS.slice());
108118

109119
type TestSubject = PackageDetails & {
110120
filepath: string;
@@ -184,23 +194,47 @@ async function run() {
184194
'platform',
185195
'arch',
186196
'package',
197+
'tests',
187198
])
188199
);
189200

190-
const { kind, filepath, appName } = await getTestSubject(context);
201+
const { kind, appName, filepath, autoUpdatable } = await getTestSubject(
202+
context
203+
);
191204
const install = getInstaller(kind);
192205

193206
try {
194-
const { appPath, uninstall } = install({
195-
appName,
196-
filepath,
197-
destinationPath: context.sandboxPath,
198-
});
207+
if (context.tests.length === 0) {
208+
console.log('Warning: not performing any tests. Pass --tests.');
209+
}
199210

200-
try {
201-
runTest({ appName, appPath });
202-
} finally {
203-
await uninstall();
211+
for (const testName of context.tests) {
212+
const { appPath, uninstall } = install({
213+
appName,
214+
filepath,
215+
destinationPath: context.sandboxPath,
216+
});
217+
218+
try {
219+
if (testName === 'time-to-first-query') {
220+
// Auto-update does not work on mac in CI at the moment. So in that case
221+
// we just run the E2E tests to make sure the app at least starts up.
222+
runTimeToFirstQuery({
223+
appName,
224+
appPath,
225+
});
226+
}
227+
if (testName === 'auto-update-from') {
228+
await runUpdateTest({
229+
appName,
230+
appPath,
231+
autoUpdatable,
232+
testName,
233+
});
234+
}
235+
} finally {
236+
await uninstall();
237+
}
204238
}
205239
} finally {
206240
if (context.skipCleanup) {
@@ -212,12 +246,30 @@ async function run() {
212246
}
213247
}
214248

215-
type RunTestOptions = {
249+
async function importUpdateServer() {
250+
try {
251+
return (await import('compass-mongodb-com')).default;
252+
} catch (err: unknown) {
253+
console.log('Remember to npm link compass-mongodb-com');
254+
throw err;
255+
}
256+
}
257+
258+
async function startAutoUpdateServer() {
259+
console.log('Starting auto-update server');
260+
const { httpServer, updateChecker, start } = (await importUpdateServer())();
261+
start();
262+
await once(updateChecker, 'refreshed');
263+
264+
return httpServer;
265+
}
266+
267+
type RunE2ETestOptions = {
216268
appName: string;
217269
appPath: string;
218270
};
219271

220-
function runTest({ appName, appPath }: RunTestOptions) {
272+
function runTimeToFirstQuery({ appName, appPath }: RunE2ETestOptions) {
221273
execute(
222274
'npm',
223275
[
@@ -241,6 +293,63 @@ function runTest({ appName, appPath }: RunTestOptions) {
241293
);
242294
}
243295

296+
type RunUpdateTestOptions = {
297+
appName: string;
298+
appPath: string;
299+
autoUpdatable?: boolean;
300+
testName: string;
301+
};
302+
303+
async function runUpdateTest({
304+
appName,
305+
appPath,
306+
autoUpdatable,
307+
testName,
308+
}: RunUpdateTestOptions) {
309+
process.env.PORT = '0'; // dynamic port
310+
process.env.UPDATE_CHECKER_ALLOW_DOWNGRADES = 'true';
311+
312+
const server = await startAutoUpdateServer();
313+
314+
const address = server.address();
315+
assert(typeof address === 'object' && address !== null);
316+
const port = address.port;
317+
const HADRON_AUTO_UPDATE_ENDPOINT_OVERRIDE = `http://localhost:${port}`;
318+
console.log({ HADRON_AUTO_UPDATE_ENDPOINT_OVERRIDE });
319+
320+
try {
321+
// must be async because the update server is running in the same process
322+
await executeAsync(
323+
'npm',
324+
[
325+
'run',
326+
'--unsafe-perm',
327+
'test-packaged',
328+
'--workspace',
329+
'compass-e2e-tests',
330+
'--',
331+
'--test-filter=auto-update',
332+
],
333+
{
334+
// We need to use a shell to get environment variables setup correctly
335+
shell: true,
336+
env: {
337+
...process.env,
338+
HADRON_AUTO_UPDATE_ENDPOINT_OVERRIDE,
339+
AUTO_UPDATE_UPDATABLE: (!!autoUpdatable).toString(),
340+
TEST_NAME: testName,
341+
COMPASS_APP_NAME: appName,
342+
COMPASS_APP_PATH: appPath,
343+
},
344+
}
345+
);
346+
} finally {
347+
console.log('Stopping auto-update server');
348+
server.close();
349+
delete process.env.UPDATE_CHECKER_ALLOW_DOWNGRADES;
350+
}
351+
}
352+
244353
run()
245354
.then(function () {
246355
console.log('done');
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
declare module 'compass-mongodb-com' {
2+
import type http from 'http';
3+
function updateServer(): {
4+
start: () => void;
5+
httpServer: http.Server;
6+
updateChecker: NodeJS.EventEmitter;
7+
};
8+
export = updateServer;
9+
}

packages/compass-smoke-tests/src/context.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ export type SmokeTestsContext = {
99
forceDownload?: boolean;
1010
localPackage?: boolean;
1111
sandboxPath: string;
12+
tests: string[];
1213
skipCleanup: boolean;
1314
};

0 commit comments

Comments
 (0)