diff --git a/circle.yml b/circle.yml index 4c1d01b60c4a..2456aced5c4b 100644 --- a/circle.yml +++ b/circle.yml @@ -29,7 +29,7 @@ mainBuildFilters: &mainBuildFilters only: - develop - 10.0-release - - marktnoonan/backmerge-develop-3-8-22 + - UNIFY-1294-specs-list-flake # usually we don't build Mac app - it takes a long time # but sometimes we want to really confirm we are doing the right thing @@ -39,7 +39,7 @@ macWorkflowFilters: &mac-workflow-filters or: - equal: [ develop, << pipeline.git.branch >> ] - equal: [ '10.0-release', << pipeline.git.branch >> ] - - equal: [ marktnoonan/backmerge-develop-3-8-22, << pipeline.git.branch >> ] + - equal: [ UNIFY-1294-specs-list-flake, << pipeline.git.branch >> ] - matches: pattern: "-release$" value: << pipeline.git.branch >> @@ -49,7 +49,7 @@ windowsWorkflowFilters: &windows-workflow-filters or: - equal: [ develop, << pipeline.git.branch >> ] - equal: [ '10.0-release', << pipeline.git.branch >> ] - - equal: [ marktnoonan/backmerge-develop-3-8-22, << pipeline.git.branch >> ] + - equal: [ UNIFY-1294-specs-list-flake, << pipeline.git.branch >> ] - matches: pattern: "-release$" value: << pipeline.git.branch >> @@ -1689,7 +1689,6 @@ jobs: steps: - clone-repo-and-checkout-branch: repo: cypress-example-kitchensink - pull_request_id: 524 - install-required-node - run: name: Remove cypress.json @@ -2005,7 +2004,6 @@ jobs: - test-binary-against-repo: repo: cypress-example-kitchensink browser: "electron" - pull_request_id: 524 test-binary-against-kitchensink-firefox: <<: *defaults @@ -2013,7 +2011,6 @@ jobs: - test-binary-against-repo: repo: cypress-example-kitchensink browser: firefox - pull_request_id: 524 test-binary-against-kitchensink-chrome: <<: *defaults @@ -2021,7 +2018,6 @@ jobs: - test-binary-against-repo: repo: cypress-example-kitchensink browser: chrome - pull_request_id: 524 test-binary-against-todomvc-firefox: <<: *defaults diff --git a/cli/__snapshots__/cli_spec.js b/cli/__snapshots__/cli_spec.js index a3ecb387346a..e9f539f87e70 100644 --- a/cli/__snapshots__/cli_spec.js +++ b/cli/__snapshots__/cli_spec.js @@ -26,8 +26,7 @@ exports['shows help for open --foo 1'] = ` cypress.config.{ts|js}. -C, --config-file path to script file where configuration values are set. defaults to - "cypress.config.{ts|js}". pass "false" to - disable. + "cypress.config.{ts|js}". -d, --detached [bool] runs Cypress application in detached mode --e2e runs end to end tests -e, --env sets environment variables. separate @@ -72,7 +71,7 @@ exports['shows help for run --foo 1'] = ` --ci-build-id the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers --component runs component tests -c, --config sets configuration values. separate multiple values with a comma. overrides any value in cypress.config.{ts|js}. - -C, --config-file path to script file where configuration values are set. defaults to "cypress.config.{ts|js}". pass "false" to disable. + -C, --config-file path to script file where configuration values are set. defaults to "cypress.config.{ts|js}". --e2e runs end to end tests -e, --env sets environment variables. separate multiple values with a comma. overrides any value in cypress.config.{ts|js} or cypress.env.json --group a named group for recorded runs in the Cypress Dashboard diff --git a/cli/__snapshots__/errors_spec.js b/cli/__snapshots__/errors_spec.js index e085d953df00..12048eb9a2de 100644 --- a/cli/__snapshots__/errors_spec.js +++ b/cli/__snapshots__/errors_spec.js @@ -83,6 +83,7 @@ exports['errors individual has the following errors 1'] = [ "incompatibleTestTypeFlags", "incompatibleTestingTypeAndFlag", "invalidCacheDirectory", + "invalidConfigFile", "invalidCypressEnv", "invalidOS", "invalidRunProjectPath", diff --git a/cli/__snapshots__/run_spec.js b/cli/__snapshots__/run_spec.js index 5889b5b1b55e..1d9b1bb4bf72 100644 --- a/cli/__snapshots__/run_spec.js +++ b/cli/__snapshots__/run_spec.js @@ -21,13 +21,6 @@ exports['exec run .processRunOptions passes --record option 1'] = [ "my record id" ] -exports['exec run .processRunOptions passes --config-file false option 1'] = [ - "--run-project", - null, - "--config-file", - false -] - exports['exec run .processRunOptions defaults to e2e testingType 1'] = [ "--run-project", null diff --git a/cli/lib/cli.js b/cli/lib/cli.js index b4ecf5de5297..8c473558452f 100644 --- a/cli/lib/cli.js +++ b/cli/lib/cli.js @@ -22,10 +22,6 @@ function unknownOption (flag, type = 'option') { } commander.Command.prototype.unknownOption = unknownOption -const coerceFalseOrString = (arg) => { - return arg !== 'false' ? arg : false -} - const coerceFalse = (arg) => { return arg !== 'false' } @@ -106,7 +102,7 @@ const descriptions = { ciBuildId: 'the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers', component: 'runs component tests', config: 'sets configuration values. separate multiple values with a comma. overrides any value in cypress.config.{ts|js}.', - configFile: 'path to script file where configuration values are set. defaults to "cypress.config.{ts|js}". pass "false" to disable.', + configFile: 'path to script file where configuration values are set. defaults to "cypress.config.{ts|js}".', detached: 'runs Cypress application in detached mode', dev: 'runs cypress in development and bypasses binary check', e2e: 'runs end to end tests', @@ -315,10 +311,6 @@ const castCypressOptions = (opts) => { castOpts.port = coerceAnyStringToInt(opts.port) } - if (_.has(opts, 'configFile')) { - castOpts.configFile = coerceFalseOrString(opts.configFile) - } - return castOpts } diff --git a/cli/lib/errors.js b/cli/lib/errors.js index 2530e231cf8b..941aa10fa125 100644 --- a/cli/lib/errors.js +++ b/cli/lib/errors.js @@ -230,6 +230,11 @@ const incompatibleTestingTypeAndFlag = { solution: 'Either set `testingType` or pass a testing type flag, but not both.', } +const invalidConfigFile = { + description: '`--config-file` cannot be false.', + solution: 'Either pass a relative path to a valid Cypress config file or remove this option.', +} + /** * This error happens when CLI detects that the child Test Runner process * was killed with a signal, like SIGBUS @@ -424,5 +429,6 @@ module.exports = { invalidTestingType, incompatibleTestTypeFlags, incompatibleTestingTypeAndFlag, + invalidConfigFile, }, } diff --git a/cli/lib/exec/open.js b/cli/lib/exec/open.js index 4708d276db4d..8765670b3685 100644 --- a/cli/lib/exec/open.js +++ b/cli/lib/exec/open.js @@ -2,7 +2,8 @@ const debug = require('debug')('cypress:cli') const util = require('../util') const spawn = require('./spawn') const verify = require('../tasks/verify') -const { processTestingType } = require('./shared') +const { processTestingType, checkConfigFile } = require('./shared') +const { exitWithError } = require('../errors') /** * Maps options collected by the CLI @@ -25,6 +26,7 @@ const processOpenOptions = (options = {}) => { } if (options.configFile !== undefined) { + checkConfigFile(options) args.push('--config-file', options.configFile) } @@ -67,14 +69,22 @@ const processOpenOptions = (options = {}) => { module.exports = { processOpenOptions, start (options = {}) { - const args = processOpenOptions(options) - function open () { - return spawn.start(args, { - dev: options.dev, - detached: Boolean(options.detached), - stdio: 'inherit', - }) + try { + const args = processOpenOptions(options) + + return spawn.start(args, { + dev: options.dev, + detached: Boolean(options.detached), + stdio: 'inherit', + }) + } catch (err) { + if (err.details) { + return exitWithError(err.details)() + } + + throw err + } } if (options.dev) { diff --git a/cli/lib/exec/run.js b/cli/lib/exec/run.js index b8644b7a2921..e070205901b1 100644 --- a/cli/lib/exec/run.js +++ b/cli/lib/exec/run.js @@ -5,7 +5,7 @@ const util = require('../util') const spawn = require('./spawn') const verify = require('../tasks/verify') const { exitWithError, errors } = require('../errors') -const { processTestingType, throwInvalidOptionError } = require('./shared') +const { processTestingType, throwInvalidOptionError, checkConfigFile } = require('./shared') /** * Typically a user passes a string path to the project. @@ -58,6 +58,7 @@ const processRunOptions = (options = {}) => { } if (options.configFile !== undefined) { + checkConfigFile(options) args.push('--config-file', options.configFile) } @@ -164,10 +165,14 @@ module.exports = { }) function run () { - let args - try { - args = processRunOptions(options) + const args = processRunOptions(options) + + debug('run to spawn.start args %j', args) + + return spawn.start(args, { + dev: options.dev, + }) } catch (err) { if (err.details) { return exitWithError(err.details)() @@ -175,12 +180,6 @@ module.exports = { throw err } - - debug('run to spawn.start args %j', args) - - return spawn.start(args, { - dev: options.dev, - }) } if (options.dev) { diff --git a/cli/lib/exec/shared.js b/cli/lib/exec/shared.js index b3723d195266..3be0243dd9db 100644 --- a/cli/lib/exec/shared.js +++ b/cli/lib/exec/shared.js @@ -47,7 +47,19 @@ const processTestingType = (options) => { return [] } +/** + * Throws an error if configFile is string 'false' or boolean false + * @param {*} options + */ +const checkConfigFile = (options) => { + // CLI will parse as string, module API can pass in boolean + if (options.configFile === 'false' || options.configFile === false) { + throwInvalidOptionError(errors.invalidConfigFile) + } +} + module.exports = { throwInvalidOptionError, processTestingType, + checkConfigFile, } diff --git a/cli/test/lib/cypress_spec.js b/cli/test/lib/cypress_spec.js index 829c42f3e492..44579d7ac926 100644 --- a/cli/test/lib/cypress_spec.js +++ b/cli/test/lib/cypress_spec.js @@ -53,18 +53,6 @@ describe('cypress', function () { expect(args).to.deep.eq({ config: JSON.stringify(config) }) }) }) - - it('passes configFile: false', () => { - const opts = { - configFile: false, - } - - return cypress.open(opts) - .then(getStartArgs) - .then((args) => { - expect(args).to.deep.eq(opts) - }) - }) }) context('.run fails to write results file', function () { @@ -152,18 +140,6 @@ describe('cypress', function () { return cypress.run().then(snapshot) }) - it('passes configFile: false', () => { - const opts = { - configFile: false, - } - - return cypress.run(opts) - .then(getStartArgs) - .then((args) => { - expect(args).to.deep.eq(opts) - }) - }) - it('rejects if project is an empty string', () => { return expect(cypress.run({ project: '' })).to.be.rejected }) @@ -223,15 +199,6 @@ describe('cypress', function () { }) }) - it('coerces --config-file false to boolean', async () => { - const args = 'cypress run --config-file false'.split(' ') - const options = await cypress.cli.parseRunArguments(args) - - expect(options).to.deep.equal({ - configFile: false, - }) - }) - it('coerces --config-file cypress.config.js to string', async () => { const args = 'cypress run --config-file cypress.config.js'.split(' ') const options = await cypress.cli.parseRunArguments(args) @@ -241,15 +208,6 @@ describe('cypress', function () { }) }) - it('parses config file false', async () => { - const args = 'cypress run --config-file false'.split(' ') - const options = await cypress.cli.parseRunArguments(args) - - expect(options).to.deep.equal({ - configFile: false, - }) - }) - it('parses config', async () => { const args = 'cypress run --config baseUrl=localhost,video=true'.split(' ') const options = await cypress.cli.parseRunArguments(args) diff --git a/cli/test/lib/exec/open_spec.js b/cli/test/lib/exec/open_spec.js index fcb975f8dd9c..d351771ce06c 100644 --- a/cli/test/lib/exec/open_spec.js +++ b/cli/test/lib/exec/open_spec.js @@ -56,15 +56,6 @@ describe('exec open', function () { }) }) - it('spawns with --config-file false', function () { - return open.start({ configFile: false }) - .then(() => { - expect(spawn.start).to.be.calledWith( - ['--config-file', false], - ) - }) - }) - it('spawns with --config-file set', function () { return open.start({ configFile: 'special-cypress.config.js' }) .then(() => { @@ -142,7 +133,11 @@ describe('exec open', function () { }) it('throws if --testing-type is invalid', () => { - expect(() => open.start({ testingType: 'randomTestingType' })).to.throw() + expect(() => open.processOpenOptions({ testingType: 'randomTestingType' })).to.throw() + }) + + it('throws if --config-file is false', () => { + expect(() => open.processOpenOptions({ configFile: 'false' })).to.throw() }) }) }) diff --git a/cli/test/lib/exec/run_spec.js b/cli/test/lib/exec/run_spec.js index 340330ec4d3e..a79d1a6e0067 100644 --- a/cli/test/lib/exec/run_spec.js +++ b/cli/test/lib/exec/run_spec.js @@ -53,14 +53,6 @@ describe('exec run', function () { snapshot(args) }) - it('passes --config-file false option', () => { - const args = run.processRunOptions({ - configFile: false, - }) - - snapshot(args) - }) - it('does not allow setting paradoxical --headed and --headless flags', () => { os.platform.returns('linux') process.exit.returns() @@ -112,6 +104,10 @@ describe('exec run', function () { it('throws if both testingType and component are set', () => { expect(() => run.processRunOptions({ testingType: 'component', component: true })).to.throw() }) + + it('throws if --config-file is false', () => { + expect(() => run.processRunOptions({ configFile: 'false' })).to.throw() + }) }) context('.start', function () { @@ -148,15 +144,6 @@ describe('exec run', function () { }) }) - it('spawns with --config-file false', function () { - return run.start({ configFile: false }) - .then(() => { - expect(spawn.start).to.be.calledWith( - ['--run-project', process.cwd(), '--config-file', false], - ) - }) - }) - it('spawns with --config-file set', function () { return run.start({ configFile: 'special-cypress.config.js' }) .then(() => { diff --git a/cli/types/cypress-npm-api.d.ts b/cli/types/cypress-npm-api.d.ts index 7d256f591d59..4647d6983306 100644 --- a/cli/types/cypress-npm-api.d.ts +++ b/cli/types/cypress-npm-api.d.ts @@ -142,11 +142,9 @@ declare namespace CypressCommandLine { /** * Path to the config file to be used. * - * If `false` is passed, no config file will be used. - * * @default "cypress.config.{ts|js}" */ - configFile: string | false + configFile: string /** * Specify environment variables. * TODO: isn't this duplicate of config.env?! diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index b9fe2a822538..195c0d8e798f 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -2882,9 +2882,9 @@ declare namespace Cypress { */ interface RuntimeConfigOptions extends Partial { /** - * Absolute path to the config file (default: /cypress.config.{ts|js}) or false + * Absolute path to the config file (default: /cypress.config.{ts|js}) */ - configFile: string | false + configFile: string /** * CPU architecture, from Node `os.arch()` * diff --git a/cli/types/tests/cypress-npm-api-test.ts b/cli/types/tests/cypress-npm-api-test.ts index d7979e17a39a..dd2bbd9f29f8 100644 --- a/cli/types/tests/cypress-npm-api-test.ts +++ b/cli/types/tests/cypress-npm-api-test.ts @@ -22,10 +22,6 @@ cypress.run().then(results => { cypress.open() // $ExpectType Promise cypress.run() // $ExpectType Promise -cypress.open({ - configFile: false -}) - cypress.run({ configFile: "abc123" }) diff --git a/cli/types/tests/plugins-config.ts b/cli/types/tests/plugins-config.ts index 1a86a0a3d110..2292a8e42fa4 100644 --- a/cli/types/tests/plugins-config.ts +++ b/cli/types/tests/plugins-config.ts @@ -6,7 +6,7 @@ const pluginConfig: Cypress.PluginConfig = (on, config) => {} // allows synchronous returns const pluginConfig2: Cypress.PluginConfig = (on, config) => { config // $ExpectType PluginConfigOptions - config.configFile // $ExpectType string | false + config.configFile // $ExpectType string config.fixturesFolder // $ExpectType string | false config.screenshotsFolder // $ExpectType string | false config.videoCompression // $ExpectType number | false diff --git a/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.test.ts b/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.test.ts index 0168ad9d95ef..c1a568ba0a06 100644 --- a/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.test.ts +++ b/npm/create-cypress-tests/src/component-testing/config-file-updater/configFileUpdater.test.ts @@ -44,21 +44,6 @@ const stripIndent = (strings: any, ...args: any) => { } describe('lib/util/config-file-updater', () => { - context('with configFile: false', () => { - beforeEach(function () { - this.projectRoot = path.join(projectRoot, '_test-output/path/to/project/') - }) - - it('.insertValuesInConfigFile does not create a file', function () { - return insertValuesInConfigFile(this.projectRoot, {}) - .then(() => { - throw Error('file shuold not have been created here') - }).catch((err) => { - expect(err.code).to.equal('ENOENT') - }) - }) - }) - context('with js files', () => { describe('#insertValueInJSString', () => { describe('es6 vs es5', () => { diff --git a/npm/cypress-schematic/src/builders/cypress/cypressBuilderOptions.ts b/npm/cypress-schematic/src/builders/cypress/cypressBuilderOptions.ts index bbbc51c88a97..9194fa1ba219 100644 --- a/npm/cypress-schematic/src/builders/cypress/cypressBuilderOptions.ts +++ b/npm/cypress-schematic/src/builders/cypress/cypressBuilderOptions.ts @@ -2,7 +2,7 @@ import { JsonObject } from '@angular-devkit/core' export interface CypressBuilderOptions extends JsonObject { baseUrl: string - configFile: string | false + configFile: string browser: 'electron' | 'chrome' | 'chromium' | 'canary' | 'firefox' | 'edge' | string devServerTarget: string env: Record diff --git a/npm/cypress-schematic/src/builders/cypress/schema.json b/npm/cypress-schematic/src/builders/cypress/schema.json index ea563eee0712..a09e8aee37c3 100644 --- a/npm/cypress-schematic/src/builders/cypress/schema.json +++ b/npm/cypress-schematic/src/builders/cypress/schema.json @@ -9,8 +9,7 @@ }, "configFile": { "type": [ - "string", - "boolean" + "string" ], "description": "Specify a path to a JSON file where configuration values are set or pass false to disable the use of a configuration file entirely." }, diff --git a/packages/app/README.md b/packages/app/README.md index 0ec237e9e18c..20309930bd23 100644 --- a/packages/app/README.md +++ b/packages/app/README.md @@ -30,7 +30,7 @@ Route configuration that might typically appear in `router.ts` can be set in a ` ```ts { - name: 'SpecsRunner', + name: 'SpecRunner', meta: { header: false, navBarExpandedAllowed: false diff --git a/packages/app/cypress/e2e/cypress-in-cypress-component.cy.ts b/packages/app/cypress/e2e/cypress-in-cypress-component.cy.ts index 50bff4857d29..35f5e81402e3 100644 --- a/packages/app/cypress/e2e/cypress-in-cypress-component.cy.ts +++ b/packages/app/cypress/e2e/cypress-in-cypress-component.cy.ts @@ -1,7 +1,8 @@ import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json' +import { getPathForPlatform } from '../../src/paths' import { snapshotAUTPanel } from './support/snapshot-aut-panel' -describe('Cypress In Cypress', { viewportWidth: 1500 }, () => { +describe('Cypress In Cypress CT', { viewportWidth: 1500, defaultCommandTimeout: 10000 }, () => { beforeEach(() => { cy.scaffoldProject('cypress-in-cypress') cy.findBrowsers() @@ -56,6 +57,7 @@ describe('Cypress In Cypress', { viewportWidth: 1500 }, () => { }) it('navigation between specs and other parts of the app works', () => { + cy.visitApp() cy.contains('TestComponent.spec').click() cy.get('[data-model-state="passed"]').should('contain', 'renders the test component') @@ -79,11 +81,11 @@ describe('Cypress In Cypress', { viewportWidth: 1500 }, () => { const { noSpecErrorTitle, noSpecErrorIntro, noSpecErrorExplainer } = defaultMessages.specPage const badFilePath = 'src/DoesNotExist.spec.js' - cy.visit(`http://localhost:4455/__/#/specs/runner?file=${badFilePath}`) + cy.visitApp(`/specs/runner?file=${getPathForPlatform(badFilePath)}`) cy.contains(noSpecErrorTitle).should('be.visible') cy.contains(noSpecErrorIntro).should('be.visible') cy.contains(noSpecErrorExplainer).should('be.visible') - cy.contains(badFilePath).should('be.visible') + cy.contains(getPathForPlatform(badFilePath)).should('be.visible') cy.location() .its('href') .should('eq', 'http://localhost:4455/__/#/specs') @@ -98,21 +100,21 @@ describe('Cypress In Cypress', { viewportWidth: 1500 }, () => { const goodFilePath = 'src/TestComponent.spec.jsx' - // TODO: Figure out why test is flaky without wait - // see: https://cypress-io.atlassian.net/browse/UNIFY-1294 - cy.wait(2000) - cy.visit(`http://localhost:4455/__/#/specs/runner?file=${goodFilePath}`) + cy.visitApp(`/specs/runner?file=${getPathForPlatform(goodFilePath)}`) cy.contains('renders the test component').should('be.visible') cy.withCtx((ctx) => { - ctx.actions.project.setSpecs([]) + // rename relative path for any specs that happen to be found + const specs = ctx.project.specs.map((spec) => ({ ...spec, relative: `${spec.relative}-updated` })) + + ctx.actions.project.setSpecs(specs) ctx.emitter.toApp() }).then(() => { cy.contains(noSpecErrorTitle).should('be.visible') cy.contains(noSpecErrorIntro).should('be.visible') cy.contains(noSpecErrorExplainer).should('be.visible') - cy.contains(goodFilePath).should('be.visible') + cy.contains(getPathForPlatform(goodFilePath)).should('be.visible') cy.location() .its('href') .should('eq', 'http://localhost:4455/__/#/specs') diff --git a/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts b/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts index e6d5bc15bc63..0f6b98e3db60 100644 --- a/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts +++ b/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts @@ -1,7 +1,8 @@ import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json' import { snapshotAUTPanel } from './support/snapshot-aut-panel' +import { getPathForPlatform } from '../../src/paths' -describe('Cypress In Cypress', { viewportWidth: 1500 }, () => { +describe('Cypress In Cypress E2E', { viewportWidth: 1500, defaultCommandTimeout: 10000 }, () => { beforeEach(() => { cy.scaffoldProject('cypress-in-cypress') cy.findBrowsers() @@ -99,11 +100,11 @@ describe('Cypress In Cypress', { viewportWidth: 1500 }, () => { const { noSpecErrorTitle, noSpecErrorIntro, noSpecErrorExplainer } = defaultMessages.specPage const badFilePath = 'cypress/e2e/does-not-exist.spec.js' - cy.visit(`http://localhost:4455/__/#/specs/runner?file=${badFilePath}`) + cy.visitApp(`/specs/runner?file=${getPathForPlatform(badFilePath)}`) cy.contains(noSpecErrorTitle).should('be.visible') cy.contains(noSpecErrorIntro).should('be.visible') cy.contains(noSpecErrorExplainer).should('be.visible') - cy.contains(badFilePath).should('be.visible') + cy.contains(getPathForPlatform(badFilePath)).should('be.visible') cy.location() .its('href') .should('eq', 'http://localhost:4455/__/#/specs') @@ -120,21 +121,22 @@ describe('Cypress In Cypress', { viewportWidth: 1500 }, () => { const goodFilePath = 'cypress/e2e/dom-content.spec.js' - // TODO: Figure out why test is flaky without wait - // see: https://cypress-io.atlassian.net/browse/UNIFY-1294 - cy.wait(2000) - cy.visit(`http://localhost:4455/__/#/specs/runner?file=${goodFilePath}`) + cy.visit(`http://localhost:4455/__/#/specs/runner?file=${getPathForPlatform(goodFilePath)}`) cy.contains('Dom Content').should('be.visible') cy.withCtx((ctx) => { - ctx.actions.project.setSpecs([]) + // rename relative path for any specs that happen to be found + + const specs = ctx.project.specs.map((spec) => ({ ...spec, relative: `${spec.relative}-updated` })) + + ctx.actions.project.setSpecs(specs) ctx.emitter.toApp() }).then(() => { cy.contains(noSpecErrorTitle).should('be.visible') cy.contains(noSpecErrorIntro).should('be.visible') cy.contains(noSpecErrorExplainer).should('be.visible') - cy.contains(goodFilePath).should('be.visible') + cy.contains(getPathForPlatform(goodFilePath)).should('be.visible') cy.location() .its('href') .should('eq', 'http://localhost:4455/__/#/specs') diff --git a/packages/app/cypress/e2e/settings.cy.ts b/packages/app/cypress/e2e/settings.cy.ts index 0f2222fa6961..849927a90558 100644 --- a/packages/app/cypress/e2e/settings.cy.ts +++ b/packages/app/cypress/e2e/settings.cy.ts @@ -104,6 +104,13 @@ describe('App: Settings', () => { cy.findByText('Project Settings').click() cy.get('[data-cy="file-match-indicator"]').contains('2 Matches') cy.get('[data-cy="spec-pattern"]').contains('**/*.cy.{js,jsx,ts,tsx}') + + cy.get('[data-cy="settings-specPatterns"').within(() => { + cy.validateExternalLink({ + name: 'Learn more.', + href: 'https://on.cypress.io/test-type-options', + }) + }) }) it('shows the Spec Patterns section (edited specPattern value)', () => { @@ -125,10 +132,53 @@ describe('App: Settings', () => { cy.findByText('Settings').click() cy.findByText('Project Settings').click() cy.get('[data-cy="settings-experiments"]').within(() => { - cy.get('[data-cy="experiment-experimentalFetchPolyfill"]') - cy.get('[data-cy="experiment-experimentalInteractiveRunEvents"]') - cy.get('[data-cy="experiment-experimentalSessionSupport"]') - cy.get('[data-cy="experiment-experimentalSourceRewriting"]') + cy.validateExternalLink({ + name: 'Learn more.', + href: 'https://on.cypress.io/experiments', + }) + + cy.get('[data-cy="experiment-experimentalFetchPolyfill"]').within(() => { + cy.validateExternalLink({ + name: 'cy.intercept()', + href: 'https://on.cypress.io/intercept', + }) + }) + + cy.get('[data-cy="experiment-experimentalInteractiveRunEvents"]').within(() => { + cy.validateExternalLink({ + name: 'before:run', + href: 'https://on.cypress.io/before-run', + }) + + cy.validateExternalLink({ + name: 'after:run', + href: 'https://on.cypress.io/after-run', + }) + + cy.validateExternalLink({ + name: 'before:spec', + href: 'https://on.cypress.io/before-spec', + }) + + cy.validateExternalLink({ + name: 'after:spec', + href: 'https://on.cypress.io/after-spec', + }) + }) + + cy.get('[data-cy="experiment-experimentalSessionSupport"]').within(() => { + cy.validateExternalLink({ + name: 'cy.session()', + href: 'https://on.cypress.io/session', + }) + }) + + cy.get('[data-cy="experiment-experimentalSourceRewriting"]').within(() => { + cy.validateExternalLink({ + name: '#5273', + href: 'https://github.com/cypress-io/cypress/issues/5273', + }) + }) }) }) diff --git a/packages/app/cypress/e2e/specs.cy.ts b/packages/app/cypress/e2e/specs.cy.ts index 4e050fa84579..5a190e9c10c3 100644 --- a/packages/app/cypress/e2e/specs.cy.ts +++ b/packages/app/cypress/e2e/specs.cy.ts @@ -1,10 +1,5 @@ import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json' - -function getPathForPlatform (posixPath: string) { - if (Cypress.platform === 'win32') return posixPath.replaceAll('/', '\\') - - return posixPath -} +import { getPathForPlatform } from '../../src/paths' function getRunnerHref (specPath: string) { specPath = getPathForPlatform(specPath) diff --git a/packages/app/src/pages/Specs/Runner.vue b/packages/app/src/pages/Specs/Runner.vue index dcfff8e0c0a7..0eac5b7e6be1 100644 --- a/packages/app/src/pages/Specs/Runner.vue +++ b/packages/app/src/pages/Specs/Runner.vue @@ -3,7 +3,7 @@ { - name: 'SpecsRunner', + name: 'SpecRunner', meta: { header: false, navBarExpandedAllowed: false diff --git a/packages/app/src/runner/SpecRunnerContainerOpenMode.vue b/packages/app/src/runner/SpecRunnerContainerOpenMode.vue index 7efc8980dbed..90cd60677a4b 100644 --- a/packages/app/src/runner/SpecRunnerContainerOpenMode.vue +++ b/packages/app/src/runner/SpecRunnerContainerOpenMode.vue @@ -1,19 +1,17 @@ diff --git a/packages/app/src/runner/unifiedRunner.ts b/packages/app/src/runner/unifiedRunner.ts index 3e0938e57920..c2228fe3f547 100644 --- a/packages/app/src/runner/unifiedRunner.ts +++ b/packages/app/src/runner/unifiedRunner.ts @@ -27,7 +27,7 @@ export function useUnifiedRunner () { const route = useRoute() const selectorPlaygroundStore = useSelectorPlaygroundStore() - watch(() => specs.value, () => { + watch(() => specs.value, (newVal) => { const fileParam = route.query.file if (!fileParam) { @@ -36,7 +36,7 @@ export function useUnifiedRunner () { return } - const activeSpecInSpecsList = specs.value.find((x) => x.relative === fileParam) + const activeSpecInSpecsList = newVal.find((x) => x.relative === fileParam) if (!activeSpecInSpecsList) { // the specs list no longer contains the spec being shown diff --git a/packages/app/src/runner/useEventManager.ts b/packages/app/src/runner/useEventManager.ts index f585ce4c4a5b..06f6be53b960 100644 --- a/packages/app/src/runner/useEventManager.ts +++ b/packages/app/src/runner/useEventManager.ts @@ -12,7 +12,7 @@ export function useEventManager () { function runSpec () { if (!specStore.activeSpec) { - throw Error(`Cannot run spec when specStore.active spec is null!`) + throw Error(`Cannot run spec when specStore.active spec is null or undefined!`) } autStore.setScriptError(null) @@ -54,7 +54,7 @@ export function useEventManager () { } const startSpecWatcher = () => { - return watch(() => specStore.activeSpec, (spec) => { + return watch(() => specStore.activeSpec, () => { runSpec() }, { immediate: true, flush: 'post' }) } diff --git a/packages/app/src/specs/generators/component/ComponentGeneratorStepOne.vue b/packages/app/src/specs/generators/component/ComponentGeneratorStepOne.vue index 37da995453ef..7c20b1d85f59 100644 --- a/packages/app/src/specs/generators/component/ComponentGeneratorStepOne.vue +++ b/packages/app/src/specs/generators/component/ComponentGeneratorStepOne.vue @@ -42,7 +42,7 @@ >