From 768ea0266dda0a6999af21dc1dfde522d33324e4 Mon Sep 17 00:00:00 2001 From: Sergey Petushkov Date: Fri, 7 Nov 2025 10:08:03 +0100 Subject: [PATCH 1/3] chore(e2e): make sure setEnv works the same way in browser and desktop --- .../helpers/commands/set-env.ts | 76 +++++++++++++------ packages/compass-e2e-tests/helpers/compass.ts | 8 +- .../helpers/test-runner-global-fixtures.ts | 4 - .../compass-web/polyfills/process/index.ts | 13 ---- packages/compass-web/sandbox/index.tsx | 1 + .../compass-web/sandbox/sandbox-process.ts | 7 ++ packages/compass-web/webpack.config.js | 8 -- packages/compass/src/main/application.ts | 8 ++ 8 files changed, 73 insertions(+), 52 deletions(-) create mode 100644 packages/compass-web/sandbox/sandbox-process.ts diff --git a/packages/compass-e2e-tests/helpers/commands/set-env.ts b/packages/compass-e2e-tests/helpers/commands/set-env.ts index 40ca31ae95b..c80dbf95370 100644 --- a/packages/compass-e2e-tests/helpers/commands/set-env.ts +++ b/packages/compass-e2e-tests/helpers/commands/set-env.ts @@ -1,9 +1,11 @@ import type { CompassBrowser } from '../compass-browser'; -import { isTestingWeb } from '../test-runner-context'; +import { inspect } from 'util'; /** - * Sets an environment variable override in Compass Web. - * This is only supported in Compass Web tests, not in Compass Desktop. + * Sets an environment variable override in Compass, both web and desktop. + * Requires an application to be running already to be used, so make sure that + * the env variables you are changing are accessed dynamically in the + * application runtime after initialization * * @example * // Set the Atlas service URL override in a test @@ -12,32 +14,60 @@ import { isTestingWeb } from '../test-runner-context'; * mockAtlasServer.endpoint * ); * - * @param browser - The CompassBrowser instance - * @param key - The environment variable name - * @param value - The environment variable value + * @param browser The CompassBrowser instance + * @param key The environment variable name + * @param value The environment variable value */ export async function setEnv( browser: CompassBrowser, key: string, value: string ): Promise { - if (isTestingWeb()) { - // When running in Compass web we use a global function to set env vars - await browser.execute( - (_key, _value) => { - const kSandboxSetEnvFn = Symbol.for('@compass-web-sandbox-set-env'); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (globalThis as any)[kSandboxSetEnvFn]?.(_key, _value); - }, - key, - value + let latestValue: string | undefined; + try { + await browser.waitUntil(async () => { + try { + latestValue = await browser.execute( + async (_key, _value) => { + // If process is available in global scope, we're in desktop + if ('process' in globalThis) { + process.env[_key] = _value; + // eslint-disable-next-line @typescript-eslint/no-require-imports + return await require('electron').ipcRenderer.invoke( + 'compass:set-process-env', + _key, + _value + ); + } else { + const kProcessEnv = Symbol.for( + '@compass-web-sandbox-process-env' + ); + (globalThis as any)[kProcessEnv][_key] = _value; + return (globalThis as any)[kProcessEnv][_key]; + } + }, + key, + value + ); + // null and undefined are the same when sending values through + // browser.execute + // eslint-disable-next-line eqeqeq + return latestValue == value; + } catch { + // Either ipcRenderer.invoke or trying to set the value on undefined + // will fail inside browser.execute, this is a good indicator that the + // app is not ready yet for setEnv to be called. Return `false` to wait + // a bit more + return false; + } + }); + } catch (err) { + throw new Error( + `Failed to set process.env.${key}: expected new value to be ${inspect( + value + )}, got ${inspect(latestValue)}. Original error:\n\n${ + (err as Error).message + }` ); - return; } - - // When running in Compass desktop, we can't dynamically change env vars - // after the process has started, so we throw an error - throw new Error( - 'setEnv is only supported in Compass web. For Compass desktop, set environment variables before starting the app.' - ); } diff --git a/packages/compass-e2e-tests/helpers/compass.ts b/packages/compass-e2e-tests/helpers/compass.ts index d2f6938667b..48e5d852195 100644 --- a/packages/compass-e2e-tests/helpers/compass.ts +++ b/packages/compass-e2e-tests/helpers/compass.ts @@ -655,10 +655,6 @@ async function startCompassElectron( process.env.HADRON_PRODUCT_NAME_OVERRIDE = 'MongoDB Compass WebdriverIO'; } - // TODO(COMPASS-9977) Turn off virtual scrolling in e2e tests until we can fix - // browser.scrollToVirtualItem() to work with it - process.env.COMPASS_DISABLE_VIRTUAL_TABLE_RENDERING = 'true'; - const options = { automationProtocol: 'webdriver' as const, capabilities: { @@ -1094,6 +1090,10 @@ async function setSharedConfigOnStart(browser: CompassBrowser) { // Compass in a way where changing this config is not allowed return true; }); + + // TODO(COMPASS-9977) Turn off virtual scrolling in e2e tests until we can fix + // browser.scrollToVirtualItem() to work with it + await browser.setEnv('COMPASS_DISABLE_VIRTUAL_TABLE_RENDERING', 'true'); } export async function init( diff --git a/packages/compass-e2e-tests/helpers/test-runner-global-fixtures.ts b/packages/compass-e2e-tests/helpers/test-runner-global-fixtures.ts index 50d6fdd520a..8a6def6ee32 100644 --- a/packages/compass-e2e-tests/helpers/test-runner-global-fixtures.ts +++ b/packages/compass-e2e-tests/helpers/test-runner-global-fixtures.ts @@ -93,10 +93,6 @@ export async function mochaGlobalSetup(this: Mocha.Runner) { if (isTestingWeb(context) && !isTestingAtlasCloudExternal(context)) { debug('Starting Compass Web server ...'); - // TODO(COMPASS-9977) Turn off virtual scrolling in e2e tests until we can fix - // browser.scrollToVirtualItem() to work with it - process.env.COMPASS_DISABLE_VIRTUAL_TABLE_RENDERING = 'true'; - if (isTestingAtlasCloudSandbox(context)) { const compassWeb = await spawnCompassWebSandboxAndSignInToAtlas( { diff --git a/packages/compass-web/polyfills/process/index.ts b/packages/compass-web/polyfills/process/index.ts index 009fd9e5af2..0a446bd6b7f 100644 --- a/packages/compass-web/polyfills/process/index.ts +++ b/packages/compass-web/polyfills/process/index.ts @@ -6,17 +6,4 @@ import hrtime from 'browser-process-hrtime'; (process as any).platform = 'Unknown'; (process as any).arch = 'Unknown'; -// Allow e2e tests to override environment variables -if (process.env.APP_ENV === 'webdriverio') { - const kSandboxSetEnvFn = Symbol.for('@compass-web-sandbox-set-env'); - // eslint-disable-next-line no-console - console.info( - `[compass-web sandbox] call window[Symbol.for('@compass-web-sandbox-set-env')]('KEY', 'value') to dynamically set environment variables` - ); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (globalThis as any)[kSandboxSetEnvFn] = (key: string, value: string) => { - process.env[key] = value; - }; -} - export { process }; diff --git a/packages/compass-web/sandbox/index.tsx b/packages/compass-web/sandbox/index.tsx index 55c0529036e..816143d5a0c 100644 --- a/packages/compass-web/sandbox/index.tsx +++ b/packages/compass-web/sandbox/index.tsx @@ -14,6 +14,7 @@ import { useAtlasProxySignIn } from './sandbox-atlas-sign-in'; import { sandboxConnectionStorage } from './sandbox-connection-storage'; import { useWorkspaceTabRouter } from './sandbox-workspace-tab-router'; import { SandboxPreferencesGlobalAccessProvider } from '../src/preferences'; +import './sandbox-process'; const sandboxContainerStyles = css({ width: '100%', diff --git a/packages/compass-web/sandbox/sandbox-process.ts b/packages/compass-web/sandbox/sandbox-process.ts new file mode 100644 index 00000000000..44318b2b0cb --- /dev/null +++ b/packages/compass-web/sandbox/sandbox-process.ts @@ -0,0 +1,7 @@ +const kSandboxProcessEnv = Symbol.for('@compass-web-sandbox-process-env'); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +(globalThis as any)[kSandboxProcessEnv] = process.env; +// eslint-disable-next-line no-console +console.info( + `[compass-web sandbox] call window[Symbol.for('@compass-web-sandbox-process-env')] to get access to process.env` +); diff --git a/packages/compass-web/webpack.config.js b/packages/compass-web/webpack.config.js index 93cbc21d1ef..ef12b44bdfd 100644 --- a/packages/compass-web/webpack.config.js +++ b/packages/compass-web/webpack.config.js @@ -165,14 +165,6 @@ module.exports = (env, args) => { ), } : {}), - ...(process.env.COMPASS_DISABLE_VIRTUAL_TABLE_RENDERING - ? { - 'process.env.COMPASS_DISABLE_VIRTUAL_TABLE_RENDERING': - JSON.stringify( - process.env.COMPASS_DISABLE_VIRTUAL_TABLE_RENDERING - ), - } - : {}), }), new webpack.ProvidePlugin({ diff --git a/packages/compass/src/main/application.ts b/packages/compass/src/main/application.ts index 17b44e9d0bc..57fade7fe03 100644 --- a/packages/compass/src/main/application.ts +++ b/packages/compass/src/main/application.ts @@ -295,6 +295,14 @@ class CompassApplication { ipcMain?.handle('compass:mainProcessPid', () => { return process.pid; }); + + ipcMain?.handle( + 'compass:set-process-env', + (_evt, key: string, value: string) => { + process.env[key] = value; + return process.env[key]; + } + ); } private static async setupLogging(): Promise { From cfd737c2c118732cb91c4a695b3b6d08c7a644d1 Mon Sep 17 00:00:00 2001 From: Sergey Petushkov Date: Fri, 7 Nov 2025 14:28:58 +0100 Subject: [PATCH 2/3] chore(e2e): account for smoke tests not having new ipc event handler --- .../helpers/commands/set-env.ts | 8 ++++++-- packages/compass-e2e-tests/helpers/compass.ts | 17 ++++++++++++++--- .../compass-e2e-tests/tests/auto-update.test.ts | 4 ++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/compass-e2e-tests/helpers/commands/set-env.ts b/packages/compass-e2e-tests/helpers/commands/set-env.ts index c80dbf95370..9dc68a47725 100644 --- a/packages/compass-e2e-tests/helpers/commands/set-env.ts +++ b/packages/compass-e2e-tests/helpers/commands/set-env.ts @@ -17,11 +17,15 @@ import { inspect } from 'util'; * @param browser The CompassBrowser instance * @param key The environment variable name * @param value The environment variable value + * @param dangerouslySkipWaitFor If true will not wait for process.env value in the app to + * equal requested value. This is not recommended, don't use it unless you know + * what you're doing */ export async function setEnv( browser: CompassBrowser, key: string, - value: string + value: string, + dangerouslySkipWaitFor?: boolean ): Promise { let latestValue: string | undefined; try { @@ -58,7 +62,7 @@ export async function setEnv( // will fail inside browser.execute, this is a good indicator that the // app is not ready yet for setEnv to be called. Return `false` to wait // a bit more - return false; + return dangerouslySkipWaitFor ?? false; } }); } catch (err) { diff --git a/packages/compass-e2e-tests/helpers/compass.ts b/packages/compass-e2e-tests/helpers/compass.ts index 48e5d852195..42227ad9562 100644 --- a/packages/compass-e2e-tests/helpers/compass.ts +++ b/packages/compass-e2e-tests/helpers/compass.ts @@ -425,6 +425,7 @@ interface StartCompassOptions { firstRun?: boolean; extraSpawnArgs?: string[]; wrapBinary?: (binary: string) => Promise | string; + dangerouslySkipSharedConfigWaitFor?: boolean; } let defaultUserDataDir: string | undefined; @@ -1072,7 +1073,10 @@ function augmentError(error: Error, stack: string) { error.stack = `${error.stack ?? ''}\nvia ${strippedLines.join('\n')}`; } -async function setSharedConfigOnStart(browser: CompassBrowser) { +async function setSharedConfigOnStart( + browser: CompassBrowser, + dangerouslySkipSharedConfigWaitFor = false +) { // Guide cues might affect too many tests in a way where the auto showing of // the cue prevents clicks from working on elements. Dealing with this // case-by-case is way too much work, so we disable the cues completely for @@ -1093,7 +1097,11 @@ async function setSharedConfigOnStart(browser: CompassBrowser) { // TODO(COMPASS-9977) Turn off virtual scrolling in e2e tests until we can fix // browser.scrollToVirtualItem() to work with it - await browser.setEnv('COMPASS_DISABLE_VIRTUAL_TABLE_RENDERING', 'true'); + await browser.setEnv( + 'COMPASS_DISABLE_VIRTUAL_TABLE_RENDERING', + 'true', + dangerouslySkipSharedConfigWaitFor + ); } export async function init( @@ -1112,7 +1120,10 @@ export async function init( const { browser } = compass; - await setSharedConfigOnStart(browser); + await setSharedConfigOnStart( + browser, + opts.dangerouslySkipSharedConfigWaitFor + ); if (TEST_COMPASS_WEB) { // larger window for more consistent results diff --git a/packages/compass-e2e-tests/tests/auto-update.test.ts b/packages/compass-e2e-tests/tests/auto-update.test.ts index 36cbe9fe4f9..e2f6ad225b2 100644 --- a/packages/compass-e2e-tests/tests/auto-update.test.ts +++ b/packages/compass-e2e-tests/tests/auto-update.test.ts @@ -77,6 +77,10 @@ describe('Auto-update', function () { // run the app again and check that the version changed const compass = await init(`${testName} restart`, { firstRun: false, + // smoketests that are running this suite are using the version of the + // compass that doesn't have the methods needed to set env in shared + // config. It's safe to skip taking into account the test being used + dangerouslySkipSharedConfigWaitFor: true, }); const { browser } = compass; try { From 4dbdebcdef78ba3fc06685dc991885e96419cd59 Mon Sep 17 00:00:00 2001 From: Sergey Petushkov Date: Mon, 10 Nov 2025 09:35:58 +0100 Subject: [PATCH 3/3] fix(e2e): add skip in another init in autoupdate tests --- packages/compass-e2e-tests/tests/auto-update.test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/compass-e2e-tests/tests/auto-update.test.ts b/packages/compass-e2e-tests/tests/auto-update.test.ts index e2f6ad225b2..bf7117c4881 100644 --- a/packages/compass-e2e-tests/tests/auto-update.test.ts +++ b/packages/compass-e2e-tests/tests/auto-update.test.ts @@ -24,7 +24,13 @@ describe('Auto-update', function () { // run the app and wait for it to auto-update console.log('starting compass the first time'); - const compass = await init(testName, { firstRun: true }); + const compass = await init(testName, { + firstRun: true, + // smoketests that are running this suite are using the version of the + // compass that doesn't have the methods needed to set env in shared + // config. It's safe to skip taking into account the test being used + dangerouslySkipSharedConfigWaitFor: true, + }); const { browser } = compass; try { await browser.$(Selectors.AutoUpdateToast).waitForDisplayed();