Skip to content

Commit

Permalink
fix(testing): avoid overwriting environment variables in nx cypress p…
Browse files Browse the repository at this point in the history
…reset (#20748)
  • Loading branch information
AgentEnder authored and jaysoo committed Dec 14, 2023
1 parent e2f8b96 commit 012190a
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 21 deletions.
10 changes: 10 additions & 0 deletions e2e/cypress/src/cypress.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ export default defineConfig({
...nxE2EPreset(__dirname),
fixturesFolder: undefined,
},
env: {
fromCyConfig: 'i am from the cypress config file'
}
});`
);

Expand Down Expand Up @@ -144,6 +147,13 @@ describe('env vars', () => {
'i am from the nx project json file'
);
});
it('should have cypress config vars', () => {
assert.equal(
Cypress.env('fromCyConfig'),
'i am from the cypress config file'
);
});
});`
);
const run3 = runCLI(`e2e ${myapp}-e2e --no-watch`);
Expand Down
39 changes: 35 additions & 4 deletions packages/cypress/plugins/cypress-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ import { dirname, join, relative } from 'path';
import { lstatSync } from 'fs';

import vitePreprocessor from '../src/plugins/preprocessor-vite';
import { NX_PLUGIN_OPTIONS } from '../src/utils/symbols';

import { exec } from 'child_process';
import { request as httpRequest } from 'http';
import { request as httpsRequest } from 'https';

// Importing the cypress type here causes the angular and next unit
// tests to fail when transpiling, it seems like the cypress types are
// clobbering jest's types. A bit weird. Leaving the commented out import
// and usage, as its helpful when modifying this code.
//
// import type * as Cypress from 'cypress';

interface BaseCypressPreset {
videosFolder: string;
screenshotsFolder: string;
Expand Down Expand Up @@ -86,25 +95,35 @@ export function nxE2EPreset(
options?: NxCypressE2EPresetOptions
) {
const basePath = options?.cypressDir || 'src';
const baseConfig: any /** Cypress.EndToEndConfigOptions */ = {

const baseConfig: any /*Cypress.EndToEndConfigOptions & {
[NX_PLUGIN_OPTIONS]: unknown;
}*/ = {
...nxBaseCypressPreset(pathToConfig),
fileServerFolder: '.',
supportFile: `${basePath}/support/e2e.ts`,
specPattern: `${basePath}/**/*.cy.{js,jsx,ts,tsx}`,
fixturesFolder: `${basePath}/fixtures`,
env: {

[NX_PLUGIN_OPTIONS]: {
webServerCommand: options?.webServerCommands?.default,
webServerCommands: options?.webServerCommands,
ciWebServerCommand: options?.ciWebServerCommand,
},

async setupNodeEvents(on, config) {
const webServerCommands =
config.env?.webServerCommands ?? options?.webServerCommands;
const webServerCommand =
config.env?.webServerCommand ?? webServerCommands?.default;

if (options?.bundler === 'vite') {
on('file:preprocessor', vitePreprocessor());
}
if (!config.env.webServerCommands) {

if (!options?.webServerCommands) {
return;
}
const webServerCommand = config.env.webServerCommand;

if (!webServerCommand) {
return;
Expand Down Expand Up @@ -216,7 +235,19 @@ export type NxCypressE2EPresetOptions = {
**/
cypressDir?: string;

/**
* A map of commandName -> command to start the web server for testing.
* Currently only default is read.
*/
webServerCommands?: Record<string, string>;

/**
* A command to start the web server - used for e2e tests distributed by Nx.
*/
ciWebServerCommand?: string;

/**
* Configures how the web server command is started and monitored.
*/
webServerConfig?: WebServerConfig;
};
30 changes: 16 additions & 14 deletions packages/cypress/src/plugins/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { defineConfig } from 'cypress';
import { createNodes } from './plugin';
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
import { join } from 'path';
import { nxE2EPreset } from '../../plugins/cypress-preset';

describe('@nx/cypress/plugin', () => {
let createNodesFunction = createNodes[1];
Expand All @@ -15,8 +16,9 @@ describe('@nx/cypress/plugin', () => {

await tempFs.createFiles({
'package.json': '{}',
'test.cy.ts': '',
'src/test.cy.ts': '',
});
process.chdir(tempFs.tempDir);
context = {
nxJsonConfiguration: {
// These defaults should be overridden by plugin
Expand Down Expand Up @@ -44,12 +46,12 @@ describe('@nx/cypress/plugin', () => {
mockCypressConfig(
defineConfig({
e2e: {
env: {
...nxE2EPreset('.', {
webServerCommands: {
default: 'nx run my-app:serve',
production: 'nx run my-app:serve:production',
},
},
}),
videosFolder: './dist/videos',
screenshotsFolder: './dist/screenshots',
},
Expand Down Expand Up @@ -162,13 +164,13 @@ describe('@nx/cypress/plugin', () => {
specPattern: '**/*.cy.ts',
videosFolder: './dist/videos',
screenshotsFolder: './dist/screenshots',
env: {
...nxE2EPreset('.', {
webServerCommands: {
default: 'my-app:serve',
production: 'my-app:serve:production',
},
ciWebServerCommand: 'my-app:serve-static',
},
}),
},
})
);
Expand Down Expand Up @@ -207,8 +209,8 @@ describe('@nx/cypress/plugin', () => {
"cwd": ".",
},
"outputs": [
"{projectRoot}/dist/videos",
"{projectRoot}/dist/screenshots",
"{projectRoot}/dist/cypress/videos",
"{projectRoot}/dist/cypress/screenshots",
],
},
"e2e-ci": {
Expand All @@ -217,7 +219,7 @@ describe('@nx/cypress/plugin', () => {
{
"params": "forward",
"projects": "self",
"target": "e2e-ci--test.cy.ts",
"target": "e2e-ci--src/test.cy.ts",
},
],
"executor": "nx:noop",
Expand All @@ -231,13 +233,13 @@ describe('@nx/cypress/plugin', () => {
},
],
"outputs": [
"{projectRoot}/dist/videos",
"{projectRoot}/dist/screenshots",
"{projectRoot}/dist/cypress/videos",
"{projectRoot}/dist/cypress/screenshots",
],
},
"e2e-ci--test.cy.ts": {
"e2e-ci--src/test.cy.ts": {
"cache": true,
"command": "cypress run --config-file cypress.config.js --e2e --env webServerCommand="my-app:serve-static" --spec test.cy.ts",
"command": "cypress run --config-file cypress.config.js --e2e --env webServerCommand="my-app:serve-static" --spec src/test.cy.ts",
"inputs": [
"default",
"^production",
Expand All @@ -251,8 +253,8 @@ describe('@nx/cypress/plugin', () => {
"cwd": ".",
},
"outputs": [
"{projectRoot}/dist/videos",
"{projectRoot}/dist/screenshots",
"{projectRoot}/dist/cypress/videos",
"{projectRoot}/dist/cypress/screenshots",
],
},
},
Expand Down
8 changes: 5 additions & 3 deletions packages/cypress/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { existsSync, readdirSync } from 'fs';
import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context';
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';
import { NX_PLUGIN_OPTIONS } from '../utils/symbols';

export interface CypressPluginOptions {
ciTargetName?: string;
Expand Down Expand Up @@ -147,13 +148,14 @@ function buildCypressTargets(
) {
const cypressConfig = getCypressConfig(configFilePath, context);

const cypressEnv = {
const pluginPresetOptions = {
...cypressConfig.e2e?.[NX_PLUGIN_OPTIONS],
...cypressConfig.env,
...cypressConfig.e2e?.env,
};

const webServerCommands: Record<string, string> =
cypressEnv?.webServerCommands;
pluginPresetOptions?.webServerCommands;

const relativeConfigPath = relative(projectRoot, configFilePath);

Expand Down Expand Up @@ -185,7 +187,7 @@ function buildCypressTargets(
}
}

const ciWebServerCommand: string = cypressEnv?.ciWebServerCommand;
const ciWebServerCommand: string = pluginPresetOptions?.ciWebServerCommand;
if (ciWebServerCommand) {
const specPatterns = Array.isArray(cypressConfig.e2e.specPattern)
? cypressConfig.e2e.specPattern.map((p) => join(projectRoot, p))
Expand Down
4 changes: 4 additions & 0 deletions packages/cypress/src/utils/symbols.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* Key used to store options used by the nx plugin for @nx/cypress.
*/
export const NX_PLUGIN_OPTIONS = Symbol('Nx Plugin Options');

0 comments on commit 012190a

Please sign in to comment.