22import assert from 'node:assert/strict' ;
33import fs from 'node:fs' ;
44import path from 'node:path' ;
5+ import { once } from 'node:events' ;
56
67import yargs from 'yargs' ;
78import { hideBin } from 'yargs/helpers' ;
89import { pick } from 'lodash' ;
9- import { execute } from './execute' ;
10+ import { execute , executeAsync } from './execute' ;
1011import {
1112 type PackageDetails ,
1213 readPackageDetails ,
@@ -25,6 +26,8 @@ import { installWindowsMSI } from './installers/windows-msi';
2526const SUPPORTED_PLATFORMS = [ 'win32' , 'darwin' , 'linux' ] as const ;
2627const SUPPORTED_ARCHS = [ 'x64' , 'arm64' ] as const ;
2728
29+ const SUPPORTED_TESTS = [ 'time-to-first-query' , 'auto-update-from' ] as const ;
30+
2831function 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
109119type 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+
244353run ( )
245354 . then ( function ( ) {
246355 console . log ( 'done' ) ;
0 commit comments