From f9a5867786217a08d2322d9606f1bb8aef45b11d Mon Sep 17 00:00:00 2001 From: Sergey Petushkov Date: Thu, 24 Oct 2024 14:35:57 +0200 Subject: [PATCH] chore(e2e): refactor context to use yargs parser --- .depalignrc.json | 3 + .evergreen/functions.yml | 19 +- package-lock.json | 144 +++++- .../helpers/commands/connect-form.ts | 11 +- .../helpers/commands/screenshot.ts | 2 +- packages/compass-e2e-tests/helpers/compass.ts | 56 +-- .../helpers/test-runner-context.ts | 443 ++++++++++++------ .../helpers/test-runner-global-fixtures.ts | 33 +- .../helpers/test-runner-paths.ts | 36 ++ packages/compass-e2e-tests/index.ts | 31 +- packages/compass-e2e-tests/package.json | 11 +- .../tests/collection-bulk-delete.test.ts | 3 +- .../tests/collection-documents-tab.test.ts | 3 +- .../tests/connection-form.test.ts | 3 +- .../tests/connection.test.ts | 10 +- .../tests/my-queries-tab.test.ts | 6 +- .../tests/protect-connection-strings.test.ts | 3 +- 17 files changed, 563 insertions(+), 254 deletions(-) create mode 100644 packages/compass-e2e-tests/helpers/test-runner-paths.ts diff --git a/.depalignrc.json b/.depalignrc.json index 277dbf7ce19..1ba9475076f 100644 --- a/.depalignrc.json +++ b/.depalignrc.json @@ -26,6 +26,9 @@ ], "js-yaml": [ "^3.13.1" + ], + "yargs": [ + "^4.8.1" ] } } \ No newline at end of file diff --git a/.evergreen/functions.yml b/.evergreen/functions.yml index b5a67ece2ac..915011c5569 100644 --- a/.evergreen/functions.yml +++ b/.evergreen/functions.yml @@ -597,10 +597,9 @@ functions: DEBUG: ${debug|} MONGODB_VERSION: ${mongodb_version|} MONGODB_RUNNER_VERSION: ${mongodb_version|} - E2E_TEST_GROUPS: ${e2e_test_groups} - E2E_TEST_GROUP: ${e2e_test_group} + COMPASS_E2E_TEST_GROUPS: ${e2e_test_groups} + COMPASS_E2E_TEST_GROUP: ${e2e_test_group} ATLAS_LOCAL_VERSION: latest - HADRON_DISTRIBUTION: compass script: | set -e # Load environment variables @@ -629,8 +628,8 @@ functions: DEBUG: ${debug|} MONGODB_VERSION: ${mongodb_version|} MONGODB_RUNNER_VERSION: ${mongodb_version|} - E2E_TEST_GROUPS: ${e2e_test_groups} - E2E_TEST_GROUP: ${e2e_test_group} + COMPASS_E2E_TEST_GROUPS: ${e2e_test_groups} + COMPASS_E2E_TEST_GROUP: ${e2e_test_group} script: | set -e # Load environment variables @@ -648,7 +647,7 @@ functions: export COMPASS_E2E_DISABLE_CLIPBOARD_USAGE="true" fi - npm run --unsafe-perm --workspace compass-e2e-tests test-packaged-ci + npm run --unsafe-perm --workspace compass-e2e-tests test-ci -- --test-packaged-app test-web-sandbox: - command: shell.exec @@ -664,14 +663,14 @@ functions: DEBUG: ${debug|} MONGODB_VERSION: ${mongodb_version|} MONGODB_RUNNER_VERSION: ${mongodb_version|} - COMPASS_WEB_BROWSER_NAME: ${browser_name} - E2E_TEST_GROUPS: ${e2e_test_groups} - E2E_TEST_GROUP: ${e2e_test_group} + COMPASS_E2E_BROWSER_NAME: ${browser_name} + COMPASS_E2E_TEST_GROUPS: ${e2e_test_groups} + COMPASS_E2E_TEST_GROUP: ${e2e_test_group} script: | set -e # Load environment variables eval $(.evergreen/print-compass-env.sh) - npm run --unsafe-perm --workspace compass-e2e-tests test-web + npm run --unsafe-perm --workspace compass-e2e-tests test-ci web test-connectivity: - command: shell.exec diff --git a/package-lock.json b/package-lock.json index 72363fe5b31..cdedcf9f9b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13961,6 +13961,16 @@ "@types/node": "*" } }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", @@ -44529,6 +44539,9 @@ }, "packages/compass-e2e-tests": { "version": "1.27.3", + "bin": { + "compass-e2e-tests": "index.ts" + }, "devDependencies": { "@electron/rebuild": "^3.7.0", "@mongodb-js/compass-test-server": "^0.1.22", @@ -44540,6 +44553,7 @@ "@types/chai-as-promised": "^7.1.4", "@types/cross-spawn": "^6.0.2", "@types/puppeteer": "^5.4.4", + "@types/yargs": "^17.0.33", "@wdio/types": "^8.32.2", "bson": "^6.8.0", "chai": "^4.3.4", @@ -44572,7 +44586,18 @@ "ts-node": "^10.9.1", "webdriverio": "^8.40.0", "why-is-node-running": "^2.3.0", - "xvfb-maybe": "^0.2.1" + "xvfb-maybe": "^0.2.1", + "yargs": "^17.7.2" + } + }, + "packages/compass-e2e-tests/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, "packages/compass-e2e-tests/node_modules/brace-expansion": { @@ -44598,6 +44623,21 @@ "node": ">=8" } }, + "packages/compass-e2e-tests/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "packages/compass-e2e-tests/node_modules/electron-to-chromium": { "version": "1.5.41", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.41.tgz", @@ -44831,6 +44871,19 @@ "node": ">=0.10.0" } }, + "packages/compass-e2e-tests/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "packages/compass-e2e-tests/node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -44870,6 +44923,35 @@ "node": ">=8" } }, + "packages/compass-e2e-tests/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/compass-e2e-tests/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "packages/compass-editor": { "name": "@mongodb-js/compass-editor", "version": "0.31.1", @@ -64861,6 +64943,15 @@ "@types/node": "*" } }, + "@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, "@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", @@ -68166,6 +68257,7 @@ "@types/chai-as-promised": "^7.1.4", "@types/cross-spawn": "^6.0.2", "@types/puppeteer": "^5.4.4", + "@types/yargs": "^17.0.33", "@wdio/types": "^8.32.2", "bson": "^6.8.0", "chai": "^4.3.4", @@ -68198,9 +68290,16 @@ "ts-node": "^10.9.1", "webdriverio": "^8.40.0", "why-is-node-running": "^2.3.0", - "xvfb-maybe": "^0.2.1" + "xvfb-maybe": "^0.2.1", + "yargs": "^17.7.2" }, "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -68221,6 +68320,17 @@ "is-wsl": "^2.1.1" } }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "electron-to-chromium": { "version": "1.5.41", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.41.tgz", @@ -68380,6 +68490,15 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -68411,6 +68530,27 @@ "siginfo": "^2.0.0", "stackback": "0.0.2" } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true } } }, diff --git a/packages/compass-e2e-tests/helpers/commands/connect-form.ts b/packages/compass-e2e-tests/helpers/commands/connect-form.ts index f47505af19e..fa1e52d5967 100644 --- a/packages/compass-e2e-tests/helpers/commands/connect-form.ts +++ b/packages/compass-e2e-tests/helpers/commands/connect-form.ts @@ -4,7 +4,10 @@ import type { CompassBrowser } from '../compass-browser'; import * as Selectors from '../selectors'; import type { ConnectFormState } from '../connect-form-state'; import Debug from 'debug'; -import { DEFAULT_CONNECTIONS } from '../test-runner-context'; +import { + DEFAULT_CONNECTIONS, + isTestingAtlasCloudExternal, +} from '../test-runner-context'; import { getConnectionTitle } from '@mongodb-js/connection-info'; const debug = Debug('compass-e2e-tests'); @@ -925,6 +928,12 @@ export async function saveConnection( } export async function setupDefaultConnections(browser: CompassBrowser) { + // When running tests against Atlas Cloud, connections can't be added or + // removed from the UI manually, so we skip setup for default connections + if (isTestingAtlasCloudExternal()) { + return; + } + /* This is intended to be used by most test files (ones that don't care too much about the intricacies about connections) in a before() hook after starting diff --git a/packages/compass-e2e-tests/helpers/commands/screenshot.ts b/packages/compass-e2e-tests/helpers/commands/screenshot.ts index 5b01dc7ae4f..8e840db9200 100644 --- a/packages/compass-e2e-tests/helpers/commands/screenshot.ts +++ b/packages/compass-e2e-tests/helpers/commands/screenshot.ts @@ -1,6 +1,6 @@ import path from 'path'; import type { CompassBrowser } from '../compass-browser'; -import { LOG_SCREENSHOTS_PATH } from '../test-runner-context'; +import { LOG_SCREENSHOTS_PATH } from '../test-runner-paths'; const withTimeout = (millis: number, promise: Promise) => { let timeoutPid: NodeJS.Timeout; diff --git a/packages/compass-e2e-tests/helpers/compass.ts b/packages/compass-e2e-tests/helpers/compass.ts index 71800865a86..6f518bdd516 100644 --- a/packages/compass-e2e-tests/helpers/compass.ts +++ b/packages/compass-e2e-tests/helpers/compass.ts @@ -29,25 +29,21 @@ import { DEFAULT_CONNECTION_STRINGS, DEFAULT_CONNECTION_NAMES, DEFAULT_CONNECTIONS_SERVER_INFO, + isTestingWeb, + isTestingDesktop, + context, + assertTestingWeb, + isTestingAtlasCloudExternal, +} from './test-runner-context'; +import { ELECTRON_CHROMIUM_VERSION, - TEST_COMPASS_WEB as _TEST_COMPASS_WEB, LOG_PATH, LOG_COVERAGE_PATH, COMPASS_DESKTOP_PATH, LOG_OUTPUT_PATH, LOG_SCREENSHOTS_PATH, - WEBDRIVER_DEFAULT_WAITFOR_TIMEOUT, - WEBDRIVER_DEFAULT_WAITFOR_INTERVAL, - TEST_COMPASS_DESKTOP_PACKAGED_APP, ELECTRON_PATH, - COMPASS_WEB_BROWSER_NAME, - COMPASS_WEB_BROWSER_VERSION, - TEST_ATLAS_CLOUD_EXTERNAL, - TEST_ATLAS_CLOUD_EXTERNAL_COOKIES_FILE, - TEST_ATLAS_CLOUD_EXTERNAL_URL, - TEST_ATLAS_CLOUD_EXTERNAL_GROUP_ID, - COMPASS_WEB_SANDBOX_URL, -} from './test-runner-context'; +} from './test-runner-paths'; const debug = Debug('compass-e2e-tests'); @@ -57,7 +53,7 @@ const { Z_SYNC_FLUSH } = zlib.constants; const packageCompassAsync = promisify(packageCompass); // should we test compass-web (true) or compass electron (false)? -export const TEST_COMPASS_WEB = _TEST_COMPASS_WEB; +export const TEST_COMPASS_WEB = isTestingWeb(); /* A helper so we can easily find all the tests we're skipping in compass-web. @@ -75,10 +71,6 @@ export function skipForWeb( } } -export const MONGODB_TEST_SERVER_PORT = Number( - process.env.MONGODB_TEST_SERVER_PORT ?? 27091 -); - export const DEFAULT_CONNECTION_STRING_1 = DEFAULT_CONNECTION_STRINGS[0]; // NOTE: in browser.setupDefaultConnections() we don't give the first connection an // explicit name, so it gets a calculated one based off the connection string @@ -435,7 +427,7 @@ async function getCompassExecutionParameters(): Promise<{ testPackagedApp: boolean; binary: string; }> { - const testPackagedApp = TEST_COMPASS_DESKTOP_PACKAGED_APP; + const testPackagedApp = isTestingDesktop(context) && context.testPackagedApp; const binary = testPackagedApp ? getCompassBinPath(await getCompassBuildMetadata()) : ELECTRON_PATH; @@ -554,8 +546,8 @@ async function processCommonOpts({ // https://webdriver.io/docs/options/#webdriverio const wdioOptions = { - waitforTimeout: WEBDRIVER_DEFAULT_WAITFOR_TIMEOUT, - waitforInterval: WEBDRIVER_DEFAULT_WAITFOR_INTERVAL, + waitforTimeout: context.webdriverWaitforTimeout, + waitforInterval: context.webdriverWaitforInterval, }; process.env.DEBUG = `${process.env.DEBUG ?? ''},mongodb-compass:main:logging`; @@ -727,14 +719,16 @@ export async function startBrowser( // eslint-disable-next-line @typescript-eslint/no-unused-vars opts: StartCompassOptions = {} ) { + assertTestingWeb(context); + runCounter++; const { webdriverOptions, wdioOptions } = await processCommonOpts(); const options: RemoteOptions = { capabilities: { - browserName: COMPASS_WEB_BROWSER_NAME, - ...(COMPASS_WEB_BROWSER_VERSION && { - browserVersion: COMPASS_WEB_BROWSER_VERSION, + browserName: context.browserName, + ...(context.browserVersion && { + browserVersion: context.browserVersion, }), }, ...webdriverOptions, @@ -746,11 +740,17 @@ export async function startBrowser( const browser: CompassBrowser = (await remote(options)) as CompassBrowser; - if (TEST_ATLAS_CLOUD_EXTERNAL) { + if (isTestingAtlasCloudExternal(context)) { + const { + atlasCloudExternalCookiesFile, + atlasCloudExternalUrl, + atlasCloudExternalProjectId, + } = context; + // To be able to use `setCookies` method, we need to first open any page on // the same domain as the cookies we are going to set // https://webdriver.io/docs/api/browser/setCookies/ - await browser.navigateTo(`${TEST_ATLAS_CLOUD_EXTERNAL_URL!}/404`); + await browser.navigateTo(`${atlasCloudExternalUrl}/404`); type StoredAtlasCloudCookies = { name: string; @@ -763,7 +763,7 @@ export async function startBrowser( }[]; const cookies: StoredAtlasCloudCookies = JSON.parse( - await fs.readFile(TEST_ATLAS_CLOUD_EXTERNAL_COOKIES_FILE!, 'utf8') + await fs.readFile(atlasCloudExternalCookiesFile, 'utf8') ); await browser.setCookies( @@ -788,10 +788,10 @@ export async function startBrowser( ); await browser.navigateTo( - `${TEST_ATLAS_CLOUD_EXTERNAL_URL!}/v2/${TEST_ATLAS_CLOUD_EXTERNAL_GROUP_ID!}#/explorer` + `${atlasCloudExternalUrl}/v2/${atlasCloudExternalProjectId}#/explorer` ); } else { - await browser.navigateTo(COMPASS_WEB_SANDBOX_URL); + await browser.navigateTo(context.sandboxUrl); } const compass = new Compass(name, browser, { diff --git a/packages/compass-e2e-tests/helpers/test-runner-context.ts b/packages/compass-e2e-tests/helpers/test-runner-context.ts index 3464c11bbbc..f76a729dd31 100644 --- a/packages/compass-e2e-tests/helpers/test-runner-context.ts +++ b/packages/compass-e2e-tests/helpers/test-runner-context.ts @@ -2,145 +2,313 @@ import { getConnectionTitle, type ConnectionInfo, } from '@mongodb-js/connection-info'; -import path from 'path'; -import electronPath from 'electron'; -import electronPackageJson from 'electron/package.json'; -// @ts-expect-error no types for this package -import { electronToChromium } from 'electron-to-chromium'; import type { MongoClusterOptions } from 'mongodb-runner'; +import yargs from 'yargs'; +import type { Argv } from 'yargs'; +import { hideBin } from 'yargs/helpers'; +import Debug from 'debug'; +import fs from 'fs'; -if (typeof electronPath !== 'string') { - throw new Error( - 'Running e2e tests in an unsupported runtime: `electronPath` is not a string' - ); +const debug = Debug('compass-e2e-tests:context'); + +function buildCommonArgs(yargs: Argv) { + return yargs + .option('disable-start-stop', { + type: 'boolean', + description: + 'Disables automatically starting (and stopping) default local test mongodb servers and compass-web sandbox', + }) + .option('test-groups', { + type: 'number', + description: + 'Run tests in batches. Sets the total number of test groups to have', + default: 1, + }) + .option('test-group', { + type: 'number', + description: + 'Run tests in batches. Sets the current test group from the total number', + default: 1, + }) + .option('test-filter', { + type: 'string', + description: 'Filter the spec files picked up for testing', + default: '*', + }) + .option('webdriver-waitfor-timeout', { + type: 'number', + description: 'Set a custom default webdriver waitFor timeout', + default: 120_000, // webdriver default is 3000ms + }) + .option('webdriver-waitfor-interval', { + type: 'number', + description: 'Set a custom default webdriver waitFor interval', + default: 100, // webdriver default is 500ms + }) + .option('mocha-timeout', { + type: 'number', + description: 'Set a custom default mocha timeout', + // Kinda arbitrary, but longer than webdriver-waitfor-timeout so the test + // can fail before Mocha times out + default: 240_000, + }) + .option('mocha-bail', { + type: 'boolean', + description: 'Bail on the first failing test instead of continuing', + }) + .option('hadron-distribution', { + type: 'string', + description: + 'Configure hadron distribution that will be used when packaging compass for tests (has no effect when testing packaged app)', + default: 'compass', + }) + .option('disable-clipboard-usage', { + type: 'boolean', + description: 'Disable tests that are relying on clipboard', + default: false, + }); } -// TODO: Probably time to use some arg parser for this already -export const ALLOWED_RUNNER_ARGS = [ - '--test-compass-web', - '--no-compile', - '--no-native-modules', - '--test-packaged-app', - '--disable-start-stop', - '--bail', -]; +function buildDesktopArgs(yargs: Argv) { + return ( + yargs + .option('test-packaged-app', { + type: 'boolean', + description: + 'Test a packaged binary instead of running compiled assets directly with electron binary', + default: false, + }) + // Skip this step if you are running tests consecutively and don't need to + // rebuild modules all the time. Also no need to ever recompile when testing + // compass-web. + .option('compile', { + type: 'boolean', + description: + 'When not testing a packaged app, re-compile assets before running tests', + default: true, + }) + .option('native-modules', { + type: 'boolean', + describe: + 'When not testing a packaaged app, re-compile native modules before running tests', + default: true, + }) + .epilogue( + 'All command line arguments can be also provided as env vars with `COMPASS_E2E_` prefix:\n\n COMPASS_E2E_TEST_PACKAGED_APP=true compass-e2e-tests desktop' + ) + ); +} /** * Variables used by a special use-case of running e2e tests against a * cloud(-dev).mongodb.com URL. If you're changing anything related to these, * make sure that the tests in mms are also updated to account for that */ -export const TEST_ATLAS_CLOUD_EXTERNAL_URL = - process.env.TEST_ATLAS_CLOUD_EXTERNAL_URL; -export const TEST_ATLAS_CLOUD_EXTERNAL_COOKIES_FILE = - process.env.TEST_ATLAS_CLOUD_EXTERNAL_COOKIES_FILE; -export const TEST_ATLAS_CLOUD_EXTERNAL_GROUP_ID = - process.env.TEST_ATLAS_CLOUD_EXTERNAL_GROUP_ID; -const TEST_ATLAS_CLOUD_EXTERNAL_DEFAULT_CONNECTIONS: ConnectionInfo[] | null = - JSON.parse(process.env.TEST_ATLAS_CLOUD_DEFAULT_CONNECTIONS ?? 'null'); - -const ALL_ATLAS_CLOUD_EXTERNAL_VARS = [ - TEST_ATLAS_CLOUD_EXTERNAL_URL, - TEST_ATLAS_CLOUD_EXTERNAL_COOKIES_FILE, - TEST_ATLAS_CLOUD_EXTERNAL_GROUP_ID, - TEST_ATLAS_CLOUD_EXTERNAL_DEFAULT_CONNECTIONS, -]; - -export const TEST_ATLAS_CLOUD_EXTERNAL = ALL_ATLAS_CLOUD_EXTERNAL_VARS.some( - (val) => { - return !!val; - } -); +const atlasCloudExternalArgs = [ + 'test-atlas-cloud-external', + 'atlas-cloud-external-url', + 'atlas-cloud-external-project-id', + 'atlas-cloud-external-cookies-file', + 'atlas-cloud-external-default-connections-file', +] as const; -if ( - TEST_ATLAS_CLOUD_EXTERNAL && - ALL_ATLAS_CLOUD_EXTERNAL_VARS.some((val) => { - return !val; - }) -) { - throw new Error( - 'Trying to test Atlas Cloud external URL but some required variables are missing' +let testEnv: 'desktop' | 'web' | undefined; + +function buildWebArgs(yargs: Argv) { + return ( + yargs + .option('browser-name', { + choices: ['chrome', 'firefox'] as const, + description: 'Test runner browser name', + default: 'chrome', + }) + // https://webdriver.io/docs/driverbinaries/ + // + // If you leave out browserVersion it will try and find the browser binary + // on your system. If you specify it it will download that version. The + // main limitation then is that 'latest' is the only 'semantic' version + // that is supported for Firefox. + // https://github.com/puppeteer/puppeteer/blob/ab5d4ac60200d1cea5bcd4910f9ccb323128e79a/packages/browsers/src/browser-data/browser-data.ts#L66 + // + // Alternatively we can download it ourselves and specify the path to the + // binary or we can even start and stop chromedriver/geckodriver manually. + // + // NOTE: The version of chromedriver or geckodriver in play might also be + // relevant. + .option('browser-version', { + type: 'string', + description: + 'Test runner browser version (`unset` will not provide an explicit version to webdriver)', + default: 'latest', + }) + .option('sandbox-url', { + type: 'string', + description: 'Set compass-web sandbox URL', + default: 'http://localhost:7777', + }) + .option('test-atlas-cloud-external', { + type: 'boolean', + description: + 'Run compass-web tests against an external Atlas Cloud URL (e.g., https://cloud-dev.mongodb.com)', + }) + .option('atlas-cloud-external-url', { + type: 'string', + description: 'External URL to run the tests against', + }) + .option('atlas-cloud-external-project-id', { + type: 'string', + description: 'Atlas `projectId` value', + }) + .option('atlas-cloud-external-cookies-file', { + type: 'string', + description: + 'File with a JSON array of cookie values that should contain Atlas Cloud auth cookies', + }) + .option('atlas-cloud-external-default-connections-file', { + type: 'string', + description: + 'File with JSON array of connections (following ConnectionInfo schema) that are expected to be available in the Atlas project', + }) + .implies( + Object.fromEntries( + atlasCloudExternalArgs.map((arg) => { + return [arg, atlasCloudExternalArgs]; + }) + ) + ) + .epilogue( + 'All command line arguments can be also provided as env vars with `COMPASS_E2E_` prefix:\n\n COMPASS_E2E_TEST_ATLAS_CLOUD_EXTERNAL=true compass-e2e-tests web' + ) ); } -export const TEST_COMPASS_WEB = - process.argv.includes('--test-compass-web') || TEST_ATLAS_CLOUD_EXTERNAL; -export const TEST_COMPASS_DESKTOP = !TEST_COMPASS_WEB; -export const TEST_COMPASS_DESKTOP_PACKAGED_APP = process.argv.includes( - '--test-packaged-app' -); -// Skip this step if you are running tests consecutively and don't need to -// rebuild modules all the time. Also no need to ever recompile when testing -// compass-web. -export const SKIP_COMPASS_DESKTOP_COMPILE = - process.argv.includes('--no-compile') && !TEST_COMPASS_WEB; -// Skip this step if you want to run tests against your own compilation (e.g, a -// dev build or a build running in watch mode that autorecompiles). Also no need -// to recompile when testing compass-web. -export const SKIP_NATIVE_MODULE_REBUILD = - process.argv.includes('--no-native-modules') && !TEST_COMPASS_WEB; -export const DISABLE_START_STOP = process.argv.includes('--disable-start-stop'); -export const MOCHA_BAIL = process.argv.includes('--bail'); - -export const COMPASS_WEB_BROWSER_NAME = - process.env.COMPASS_WEB_BROWSER_NAME ?? 'chrome'; -// https://webdriver.io/docs/driverbinaries/ -// -// If you leave out browserVersion it will try and find the browser binary on -// your system. If you specify it it will download that version. The main -// limitation then is that 'latest' is the only 'semantic' version that is -// supported for Firefox. -// https://github.com/puppeteer/puppeteer/blob/ab5d4ac60200d1cea5bcd4910f9ccb323128e79a/packages/browsers/src/browser-data/browser-data.ts#L66 -// -// Alternatively we can download it ourselves and specify the path to the binary -// or we can even start and stop chromedriver/geckodriver manually. -// -// NOTE: The version of chromedriver or geckodriver in play might also be -// relevant. -export const COMPASS_WEB_BROWSER_VERSION = - process.env.COMPASS_WEB_BROWSER_VERSION === 'unset' - ? undefined - : process.env.BROWSER_VERSION ?? 'latest'; -export const COMPASS_WEB_SANDBOX_URL = 'http://localhost:7777'; - -const MONGODB_TESTSERVER_VERSION = +const argv = yargs(hideBin(process.argv)) + .scriptName('compass-e2e-tests') + .env('COMPASS_E2E') + .detectLocale(false) + .version(false) + .strict(); + +const parsedArgs = buildCommonArgs(argv) + .command( + ['$0', 'desktop'], + 'Run e2e tests against Compass desktop', + buildDesktopArgs, + () => { + testEnv = 'desktop'; + } + ) + .command('web', 'Run e2e tests against Compass web', buildWebArgs, () => { + testEnv = 'web'; + }) + .parse(); + +type BuilderCallbackParsedArgs Argv> = + ReturnType['parseSync']>; + +type CommonParsedArgs = BuilderCallbackParsedArgs; + +type DesktopParsedArgs = CommonParsedArgs & + BuilderCallbackParsedArgs; + +type WebParsedArgs = CommonParsedArgs & + BuilderCallbackParsedArgs; + +if (!testEnv) { + throw new Error('Test env was not selected'); +} + +if ('then' in parsedArgs && typeof parsedArgs.then === 'function') { + throw new Error('Async args parser is not allowed'); +} + +export const context = parsedArgs as CommonParsedArgs & + Partial; + +export function isTestingDesktop(ctx = context): ctx is DesktopParsedArgs { + return testEnv === 'desktop'; +} + +export function assertTestingDesktop( + ctx = context +): asserts ctx is DesktopParsedArgs { + if (!isTestingDesktop(ctx)) { + throw new Error( + `Expected tested runtime to be desktop, but got ${String(testEnv)}` + ); + } +} + +export function isTestingWeb(ctx = context): ctx is WebParsedArgs { + return testEnv === 'web'; +} + +export function assertTestingWeb(ctx = context): asserts ctx is WebParsedArgs { + if (!isTestingWeb(ctx)) { + throw new Error( + `Expected tested runtime to be web, but got ${String(testEnv)}` + ); + } +} + +export function isTestingAtlasCloudExternal( + ctx = context +): ctx is WebParsedArgs & { + [K in + | 'testAtlasCloudExternal' + | 'atlasCloudExternalUrl' + | 'atlasCloudExternalProjectId' + | 'atlasCloudExternalCookiesFile' + | 'atlasCloudExternalDefaultConnectionsFile']: NonNullable< + WebParsedArgs[K] + >; +} { + return isTestingWeb(ctx) && !!ctx.testAtlasCloudExternal; +} + +debug('Running tests with the following arguments:', context); + +process.env.HADRON_DISTRIBUTION ??= context.hadronDistribution; + +const testServerVersion = process.env.MONGODB_VERSION ?? process.env.MONGODB_RUNNER_VERSION; export const DEFAULT_CONNECTIONS: (ConnectionInfo & { testServer?: Partial; -})[] = - TEST_ATLAS_CLOUD_EXTERNAL && TEST_ATLAS_CLOUD_EXTERNAL_DEFAULT_CONNECTIONS - ? TEST_ATLAS_CLOUD_EXTERNAL_DEFAULT_CONNECTIONS - : [ - { - id: 'test-connection-1', - connectionOptions: { - connectionString: 'mongodb://127.0.0.1:27091/test', - }, - testServer: { - version: MONGODB_TESTSERVER_VERSION, - topology: 'replset', - secondaries: 0, - args: ['--port', '27091'], - }, +})[] = isTestingAtlasCloudExternal(context) + ? JSON.parse( + fs.readFileSync(context.atlasCloudExternalDefaultConnectionsFile, 'utf-8') + ) + : [ + { + id: 'test-connection-1', + connectionOptions: { + connectionString: 'mongodb://127.0.0.1:27091/test', }, - { - id: 'test-connection-2', - connectionOptions: { - connectionString: 'mongodb://127.0.0.1:27092/test', - }, - favorite: { - name: 'connection-2', - color: 'Iris', - }, - testServer: { - version: MONGODB_TESTSERVER_VERSION, - topology: 'replset', - secondaries: 0, - args: ['--port', '27092'], - }, + testServer: { + version: testServerVersion, + topology: 'replset', + secondaries: 0, + args: ['--port', '27091'], }, - ]; + }, + { + id: 'test-connection-2', + connectionOptions: { + connectionString: 'mongodb://127.0.0.1:27092/test', + }, + favorite: { + name: 'connection-2', + color: 'Iris', + }, + testServer: { + version: testServerVersion, + topology: 'replset', + secondaries: 0, + args: ['--port', '27092'], + }, + }, + ]; export const DEFAULT_CONNECTION_STRINGS = DEFAULT_CONNECTIONS.map((info) => { return info.connectionOptions.connectionString; @@ -154,40 +322,3 @@ export const DEFAULT_CONNECTIONS_SERVER_INFO: { version: string; enterprise: boolean; }[] = []; - -export const E2E_WORKSPACE_PATH = path.dirname( - require.resolve('compass-e2e-tests/package.json') -); -// /packages/compass-e2e-tests -// /packages -// -export const MONOREPO_ROOT_PATH = path.resolve(E2E_WORKSPACE_PATH, '..', '..'); -export const COMPASS_DESKTOP_PATH = path.dirname( - require.resolve('mongodb-compass/package.json') -); -export const COMPASS_WEB_PATH = path.dirname( - require.resolve('@mongodb-js/compass-web/package.json') -); -export const LOG_PATH = path.resolve(E2E_WORKSPACE_PATH, '.log'); -export const LOG_OUTPUT_PATH = path.join(LOG_PATH, 'output'); -export const LOG_SCREENSHOTS_PATH = path.join(LOG_PATH, 'screenshots'); -export const LOG_COVERAGE_PATH = path.join(LOG_PATH, 'coverage'); -// Set coverage to the root of the monorepo so it will be generated for -// everything and not just packages/compass -export const COVERAGE_PATH = (process.env.COVERAGE = MONOREPO_ROOT_PATH); - -export const ELECTRON_PATH = electronPath; -export const ELECTRON_VERSION = electronPackageJson.version; -export const ELECTRON_CHROMIUM_VERSION = electronToChromium(ELECTRON_VERSION); - -export const WEBDRIVER_DEFAULT_WAITFOR_TIMEOUT = process.env - .COMPASS_TEST_DEFAULT_WAITFOR_TIMEOUT - ? Number(process.env.COMPASS_TEST_DEFAULT_WAITFOR_TIMEOUT) - : 120_000; // default is 3000ms -export const WEBDRIVER_DEFAULT_WAITFOR_INTERVAL = process.env - .COMPASS_TEST_DEFAULT_WAITFOR_INTERVAL - ? Number(process.env.COMPASS_TEST_DEFAULT_WAITFOR_INTERVAL) - : 100; // default is 500ms -// Kinda arbitrary, but longer than WEBDRIVER_DEFAULT_WAITFOR_TIMEOUT so the -// test can fail before Mocha times out -export const MOCHA_DEFAULT_TIMEOUT = WEBDRIVER_DEFAULT_WAITFOR_TIMEOUT * 2; 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 8fd8e030921..108d1283bb5 100644 --- a/packages/compass-e2e-tests/helpers/test-runner-global-fixtures.ts +++ b/packages/compass-e2e-tests/helpers/test-runner-global-fixtures.ts @@ -1,19 +1,14 @@ import gunzip from './gunzip'; import fs from 'fs'; import { - COMPASS_WEB_SANDBOX_URL, + context, DEFAULT_CONNECTIONS, DEFAULT_CONNECTIONS_SERVER_INFO, - DISABLE_START_STOP, - E2E_WORKSPACE_PATH, - LOG_PATH, - SKIP_COMPASS_DESKTOP_COMPILE, - SKIP_NATIVE_MODULE_REBUILD, - TEST_ATLAS_CLOUD_EXTERNAL, - TEST_COMPASS_DESKTOP, - TEST_COMPASS_DESKTOP_PACKAGED_APP, - TEST_COMPASS_WEB, + isTestingAtlasCloudExternal, + isTestingDesktop, + isTestingWeb, } from './test-runner-context'; +import { E2E_WORKSPACE_PATH, LOG_PATH } from './test-runner-paths'; import Debug from 'debug'; import { startTestServer } from '@mongodb-js/compass-test-server'; import crossSpawn from 'cross-spawn'; @@ -76,7 +71,7 @@ export async function mochaGlobalSetup(this: Mocha.Runner) { debug('X DISPLAY', process.env.DISPLAY); - if (!DISABLE_START_STOP) { + if (!context.disableStartStop) { for (const connectionInfo of DEFAULT_CONNECTIONS) { if (connectionInfo.testServer) { debug( @@ -95,7 +90,7 @@ export async function mochaGlobalSetup(this: Mocha.Runner) { throwIfAborted(); } - if (TEST_COMPASS_WEB && !TEST_ATLAS_CLOUD_EXTERNAL) { + if (isTestingWeb(context) && !isTestingAtlasCloudExternal(context)) { debug('Starting Compass Web server ...'); const compassWeb = spawnCompassWeb(); cleanupFns.push(() => { @@ -106,7 +101,7 @@ export async function mochaGlobalSetup(this: Mocha.Runner) { debug('No pid for compass-web'); } }); - await waitForCompassWebToBeReady(); + await waitForCompassWebToBeReady(context.sandboxUrl); } } @@ -124,19 +119,19 @@ export async function mochaGlobalSetup(this: Mocha.Runner) { fs.mkdirSync(LOG_PATH, { recursive: true }); - if (TEST_COMPASS_DESKTOP) { - if (TEST_COMPASS_DESKTOP_PACKAGED_APP) { + if (isTestingDesktop(context)) { + if (context.testPackagedApp) { debug('Building Compass before running the tests ...'); await buildCompass(); } else { debug('Preparing Compass before running the tests'); - if (!SKIP_NATIVE_MODULE_REBUILD) { + if (!context.nativeModules) { debug('Rebuilding native modules ...'); await rebuildNativeModules(); } - if (!SKIP_COMPASS_DESKTOP_COMPILE) { + if (!context.compile) { debug('Compiling Compass assets ...'); await compileCompassAssets(); } @@ -183,7 +178,7 @@ function spawnCompassWeb() { return proc; } -async function waitForCompassWebToBeReady() { +async function waitForCompassWebToBeReady(sandboxUrl: string) { let serverReady = false; const start = Date.now(); while (!serverReady) { @@ -194,7 +189,7 @@ async function waitForCompassWebToBeReady() { ); } try { - const res = await fetch(COMPASS_WEB_SANDBOX_URL); + const res = await fetch(sandboxUrl); serverReady = res.ok; debug('Web server ready:', serverReady); } catch (err) { diff --git a/packages/compass-e2e-tests/helpers/test-runner-paths.ts b/packages/compass-e2e-tests/helpers/test-runner-paths.ts new file mode 100644 index 00000000000..19b835abe7b --- /dev/null +++ b/packages/compass-e2e-tests/helpers/test-runner-paths.ts @@ -0,0 +1,36 @@ +import path from 'path'; +import electronPath from 'electron'; +import electronPackageJson from 'electron/package.json'; +// @ts-expect-error no types for this package +import { electronToChromium } from 'electron-to-chromium'; + +if (typeof electronPath !== 'string') { + throw new Error( + 'Running e2e tests in an unsupported runtime: `electronPath` is not a string' + ); +} + +export const E2E_WORKSPACE_PATH = path.dirname( + require.resolve('compass-e2e-tests/package.json') +); +// /packages/compass-e2e-tests +// /packages +// +export const MONOREPO_ROOT_PATH = path.resolve(E2E_WORKSPACE_PATH, '..', '..'); +export const COMPASS_DESKTOP_PATH = path.dirname( + require.resolve('mongodb-compass/package.json') +); +export const COMPASS_WEB_PATH = path.dirname( + require.resolve('@mongodb-js/compass-web/package.json') +); +export const LOG_PATH = path.resolve(E2E_WORKSPACE_PATH, '.log'); +export const LOG_OUTPUT_PATH = path.join(LOG_PATH, 'output'); +export const LOG_SCREENSHOTS_PATH = path.join(LOG_PATH, 'screenshots'); +export const LOG_COVERAGE_PATH = path.join(LOG_PATH, 'coverage'); +// Set coverage to the root of the monorepo so it will be generated for +// everything and not just packages/compass +export const COVERAGE_PATH = (process.env.COVERAGE = MONOREPO_ROOT_PATH); + +export const ELECTRON_PATH = electronPath; +export const ELECTRON_VERSION = electronPackageJson.version; +export const ELECTRON_CHROMIUM_VERSION = electronToChromium(ELECTRON_VERSION); diff --git a/packages/compass-e2e-tests/index.ts b/packages/compass-e2e-tests/index.ts index 7efbb9710b8..86a31aec1a1 100644 --- a/packages/compass-e2e-tests/index.ts +++ b/packages/compass-e2e-tests/index.ts @@ -2,14 +2,9 @@ import path from 'path'; import { glob } from 'glob'; import crossSpawn from 'cross-spawn'; - import Mocha from 'mocha'; import Debug from 'debug'; -import { - ALLOWED_RUNNER_ARGS, - MOCHA_BAIL, - MOCHA_DEFAULT_TIMEOUT, -} from './helpers/test-runner-context'; +import { context } from './helpers/test-runner-context'; import { abortRunner, mochaGlobalSetup, @@ -21,16 +16,6 @@ import logRunning from 'why-is-node-running'; const debug = Debug('compass-e2e-tests'); -for (const arg of process.argv) { - if (arg.startsWith('--') && !ALLOWED_RUNNER_ARGS.includes(arg)) { - throw Error( - `Unknown command argument "${arg}". Usage:\n\n npm run test ${ALLOWED_RUNNER_ARGS.map( - (arg) => `[${arg}]` - ).join(' ')}\n` - ); - } -} - const FIRST_TEST = 'tests/time-to-first-query.test.ts'; // Trigger a mocha abort on interrupt. This doesn't stop the test runner @@ -65,9 +50,9 @@ function terminateOnTimeout() { let runnerPromise: Promise | undefined; async function main() { - const e2eTestGroupsAmount = parseInt(process.env.E2E_TEST_GROUPS || '1'); - const e2eTestGroup = parseInt(process.env.E2E_TEST_GROUP || '1'); - const e2eTestFilter = process.env.E2E_TEST_FILTER || '*'; + const e2eTestGroupsAmount = context.testGroups; + const e2eTestGroup = context.testGroup; + const e2eTestFilter = context.testFilter; const tests = ( await glob(`tests/**/${e2eTestFilter}.{test,spec}.ts`, { @@ -99,9 +84,13 @@ async function main() { debug('Test files:', tests); + if (tests.length === 0) { + throw new Error('No tests to run'); + } + const mocha = new Mocha({ - timeout: MOCHA_DEFAULT_TIMEOUT, - bail: MOCHA_BAIL, + timeout: context.mochaTimeout, + bail: context.mochaBail, reporter: require.resolve('@mongodb-js/mocha-config-compass/reporter'), }); diff --git a/packages/compass-e2e-tests/package.json b/packages/compass-e2e-tests/package.json index 555dcc7d950..8cf111bbc2b 100644 --- a/packages/compass-e2e-tests/package.json +++ b/packages/compass-e2e-tests/package.json @@ -5,9 +5,10 @@ "description": "E2E test suite for Compass app that follows smoke tests / feature testing matrix", "scripts": { "clean": "node -e \"try { fs.rmdirSync('.mongodb', { recursive: true }); } catch (e) {}\" && node -e \"try { fs.rmdirSync('.log', { recursive: true }); } catch (e) {}\"", + "typecheck": "tsc -p tsconfig-lint.json --noEmit", "eslint": "eslint", "prettier": "prettier", - "lint": "npm run eslint . && npm run prettier -- --check .", + "lint": "npm run typecheck && npm run eslint . && npm run prettier -- --check .", "depcheck": "depcheck", "check": "npm run lint && npm run depcheck", "test": "xvfb-maybe --auto-servernum --server-args=\"-screen 0 1432x840x24\" -- ts-node index.ts", @@ -24,8 +25,8 @@ "stop-servers": "npm run stop-server-1 && npm run stop-server-2", "test-noserver": "env DEBUG=hadron*,mongo*,compass*,xvfb-maybe* npm run test -- --disable-start-stop --bail", "test-noserver-nocompile": "env DEBUG=hadron*,mongo*,compass*,xvfb-maybe* npm run test -- --no-native-modules --no-compile --disable-start-stop --bail", - "test-web": "env DEBUG=hadron*,mongo*,compass*,xvfb-maybe* npm run test -- --test-compass-web", - "test-web-noserver": "env DEBUG=hadron*,mongo*,compass*,xvfb-maybe* npm run test -- --test-compass-web --disable-start-stop --bail", + "test-web": "env DEBUG=hadron*,mongo*,compass*,xvfb-maybe* npm run test web", + "test-web-noserver": "env DEBUG=hadron*,mongo*,compass*,xvfb-maybe* npm run test web -- --disable-start-stop --bail", "coverage-merge": "nyc merge .log/coverage .nyc_output/coverage.json", "coverage-report": "npm run coverage-merge && nyc report" }, @@ -40,6 +41,7 @@ "@types/chai-as-promised": "^7.1.4", "@types/cross-spawn": "^6.0.2", "@types/puppeteer": "^5.4.4", + "@types/yargs": "^17.0.33", "@wdio/types": "^8.32.2", "bson": "^6.8.0", "chai": "^4.3.4", @@ -72,6 +74,7 @@ "ts-node": "^10.9.1", "webdriverio": "^8.40.0", "why-is-node-running": "^2.3.0", - "xvfb-maybe": "^0.2.1" + "xvfb-maybe": "^0.2.1", + "yargs": "^17.7.2" } } diff --git a/packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts b/packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts index e1a1934a635..eb93e94a822 100644 --- a/packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts +++ b/packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts @@ -11,6 +11,7 @@ import { import type { Compass } from '../helpers/compass'; import * as Selectors from '../helpers/selectors'; import { createNumbersCollection } from '../helpers/insert-data'; +import { context } from '../helpers/test-runner-context'; describe('Bulk Delete', function () { let compass: Compass; @@ -157,7 +158,7 @@ describe('Bulk Delete', function () { }); it('can export a delete query', async function () { - if (process.env.COMPASS_E2E_DISABLE_CLIPBOARD_USAGE === 'true') { + if (context.disableClipboardUsage) { this.skip(); } diff --git a/packages/compass-e2e-tests/tests/collection-documents-tab.test.ts b/packages/compass-e2e-tests/tests/collection-documents-tab.test.ts index b590acb7a0d..d662acc2afc 100644 --- a/packages/compass-e2e-tests/tests/collection-documents-tab.test.ts +++ b/packages/compass-e2e-tests/tests/collection-documents-tab.test.ts @@ -17,6 +17,7 @@ import { createNestedDocumentsCollection, createNumbersCollection, } from '../helpers/insert-data'; +import { context } from '../helpers/test-runner-context'; const { expect } = chai; @@ -559,7 +560,7 @@ FindIterable result = collection.find(filter);`); }); it('can copy a document from the contextual toolbar', async function () { - if (process.env.COMPASS_E2E_DISABLE_CLIPBOARD_USAGE === 'true') { + if (context.disableClipboardUsage) { this.skip(); } diff --git a/packages/compass-e2e-tests/tests/connection-form.test.ts b/packages/compass-e2e-tests/tests/connection-form.test.ts index afd961b8be6..111c074f761 100644 --- a/packages/compass-e2e-tests/tests/connection-form.test.ts +++ b/packages/compass-e2e-tests/tests/connection-form.test.ts @@ -12,6 +12,7 @@ import { import type { Compass } from '../helpers/compass'; import * as Selectors from '../helpers/selectors'; import type { ConnectFormState } from '../helpers/connect-form-state'; +import { context } from '../helpers/test-runner-context'; const DEFAULT_FLE_ENCRYPTED_FIELDS_MAP = "{\n/**\n * // Client-side encrypted fields map configuration:\n * 'database.collection': {\n * fields: [\n * {\n * keyId: UUID(\"...\"),\n * path: '...',\n * bsonType: '...',\n * queries: [{ queryType: 'equality' }]\n * }\n * ]\n * }\n */\n}\n"; @@ -618,7 +619,7 @@ describe('Connection form', function () { // save await browser.saveFavorite(favoriteName, 'Green'); - if (process.env.COMPASS_E2E_DISABLE_CLIPBOARD_USAGE !== 'true') { + if (!context.disableClipboardUsage) { // copy the connection string await browser.selectConnectionMenuItem( favoriteName, diff --git a/packages/compass-e2e-tests/tests/connection.test.ts b/packages/compass-e2e-tests/tests/connection.test.ts index 36b7fdc725b..5a431454de3 100644 --- a/packages/compass-e2e-tests/tests/connection.test.ts +++ b/packages/compass-e2e-tests/tests/connection.test.ts @@ -15,7 +15,7 @@ import { TEST_COMPASS_WEB, connectionNameFromString, DEFAULT_CONNECTION_NAME_1, - MONGODB_TEST_SERVER_PORT, + DEFAULT_CONNECTION_STRING_1, } from '../helpers/compass'; import type { Compass } from '../helpers/compass'; import type { ConnectFormState } from '../helpers/connect-form-state'; @@ -317,11 +317,11 @@ describe('Connection string', function () { }); it('fails for authentication errors', async function () { + const [protocol, url] = DEFAULT_CONNECTION_STRING_1.split('://'); // connect - await browser.connectWithConnectionString( - `mongodb://a:b@127.0.0.1:${MONGODB_TEST_SERVER_PORT}/test`, - { connectionStatus: 'failure' } - ); + await browser.connectWithConnectionString(`${protocol}://a:b@${url}`, { + connectionStatus: 'failure', + }); // check the error const toastTitle = await browser.$(Selectors.LGToastTitle).getText(); diff --git a/packages/compass-e2e-tests/tests/my-queries-tab.test.ts b/packages/compass-e2e-tests/tests/my-queries-tab.test.ts index 891577ab9ae..58d833dfdf1 100644 --- a/packages/compass-e2e-tests/tests/my-queries-tab.test.ts +++ b/packages/compass-e2e-tests/tests/my-queries-tab.test.ts @@ -15,8 +15,8 @@ import type { QueryOptions } from '../helpers/commands'; import type { Compass } from '../helpers/compass'; import * as Selectors from '../helpers/selectors'; import { createNumbersCollection } from '../helpers/insert-data'; - import { MongoClient } from 'mongodb'; +import { context as runnerContext } from '../helpers/test-runner-context'; async function openMenuForQueryItem( browser: CompassBrowser, @@ -221,7 +221,7 @@ describe('My Queries tab', function () { // copy to clipboard await browser.clickVisible(Selectors.SavedItemMenuItemCopy); - if (process.env.COMPASS_E2E_DISABLE_CLIPBOARD_USAGE !== 'true') { + if (!runnerContext.disableClipboardUsage) { await browser.waitUntil( async () => { const text = (await clipboard.read()) @@ -368,7 +368,7 @@ describe('My Queries tab', function () { // copy to clipboard await browser.clickVisible(Selectors.SavedItemMenuItemCopy); - if (process.env.COMPASS_E2E_DISABLE_CLIPBOARD_USAGE !== 'true') { + if (!runnerContext.disableClipboardUsage) { await browser.waitUntil( async () => { const text = (await clipboard.read()) diff --git a/packages/compass-e2e-tests/tests/protect-connection-strings.test.ts b/packages/compass-e2e-tests/tests/protect-connection-strings.test.ts index 111a57fb19a..c20ebc3476f 100644 --- a/packages/compass-e2e-tests/tests/protect-connection-strings.test.ts +++ b/packages/compass-e2e-tests/tests/protect-connection-strings.test.ts @@ -10,6 +10,7 @@ import clipboard from 'clipboardy'; import { expect } from 'chai'; import * as Selectors from '../helpers/selectors'; import type { ConnectFormState } from '../helpers/connect-form-state'; +import { context } from '../helpers/test-runner-context'; async function expectCopyConnectionStringToClipboard( browser: CompassBrowser, @@ -17,7 +18,7 @@ async function expectCopyConnectionStringToClipboard( expected: string ): Promise { const Sidebar = Selectors.Multiple; - if (process.env.COMPASS_E2E_DISABLE_CLIPBOARD_USAGE !== 'true') { + if (!context.disableClipboardUsage) { await browser.selectConnectionMenuItem( favoriteName, Sidebar.CopyConnectionStringItem