Skip to content

Commit 07d4340

Browse files
Barthélémy Ledouxjennifer-shehane
andauthored
feat: allow cypress.config.js to be a default config file (#18221)
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
1 parent 2caa5de commit 07d4340

File tree

28 files changed

+754
-617
lines changed

28 files changed

+754
-617
lines changed

packages/desktop-gui/cypress/integration/settings_spec.js

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -358,34 +358,52 @@ describe('Settings', () => {
358358
})
359359

360360
describe('project id panel', () => {
361-
beforeEach(function () {
362-
this.openProject.resolve(this.config)
363-
this.projectStatuses[0].id = this.config.projectId
364-
this.getProjectStatus.resolve(this.projectStatuses[0])
361+
context('with json file', () => {
362+
beforeEach(function () {
363+
this.openProject.resolve(this.config)
364+
this.projectStatuses[0].id = this.config.projectId
365+
this.getProjectStatus.resolve(this.projectStatuses[0])
365366

366-
this.goToSettings()
367-
cy.contains('Project ID').click()
368-
})
367+
this.goToSettings()
368+
cy.contains('Project ID').click()
369+
})
369370

370-
it('displays project id section', function () {
371-
cy.contains(this.config.projectId)
372-
cy.percySnapshot()
373-
})
371+
it('displays project id section', function () {
372+
cy.contains(this.config.projectId)
373+
cy.percySnapshot()
374+
})
375+
376+
it('shows tooltip on hover of copy to clipboard', () => {
377+
cy.get('.action-copy').trigger('mouseover')
378+
cy.get('.cy-tooltip').should('contain', 'Copy to clipboard')
379+
})
374380

375-
it('shows tooltip on hover of copy to clipboard', () => {
376-
cy.get('.action-copy').trigger('mouseover')
377-
cy.get('.cy-tooltip').should('contain', 'Copy to clipboard')
381+
it('copies project id config to clipboard', function () {
382+
cy.get('.action-copy').click()
383+
.then(() => {
384+
const expectedJsonConfig = {
385+
projectId: this.config.projectId,
386+
}
387+
const expectedCopyCommand = JSON.stringify(expectedJsonConfig, null, 2)
388+
389+
expect(this.ipc.setClipboardText).to.be.calledWith(expectedCopyCommand)
390+
})
391+
})
378392
})
379393

380-
it('copies project id config to clipboard', function () {
381-
cy.get('.action-copy').click()
382-
.then(() => {
383-
const expectedJsonConfig = {
384-
projectId: this.config.projectId,
385-
}
386-
const expectedCopyCommand = JSON.stringify(expectedJsonConfig, null, 2)
394+
context('with js file', () => {
395+
beforeEach(function () {
396+
this.openProject.resolve({ ...this.config, configFile: 'custom.cypress.js' })
397+
this.projectStatuses[0].id = this.config.projectId
398+
this.getProjectStatus.resolve(this.projectStatuses[0])
399+
400+
this.goToSettings()
401+
cy.contains('Project ID').click()
402+
})
387403

388-
expect(this.ipc.setClipboardText).to.be.calledWith(expectedCopyCommand)
404+
it('displays project id section', function () {
405+
cy.get('[data-cy="project-id"] pre').contains('module.exports = {')
406+
cy.percySnapshot()
389407
})
390408
})
391409
})
@@ -586,6 +604,17 @@ describe('Settings', () => {
586604
.should('contain', systemNodeVersion)
587605
.should('not.contain', bundledNodeVersion)
588606
})
607+
608+
it('should display an additional line when configFile is not JSON', function () {
609+
const configFile = 'notjson.js'
610+
611+
this.navigateWithConfig({
612+
configFile,
613+
})
614+
615+
cy.contains(`Node.js Version (${bundledNodeVersion})`).click()
616+
cy.get('.node-version li').should('contain', configFile)
617+
})
589618
})
590619

591620
describe('proxy settings panel', () => {

packages/desktop-gui/src/lib/config-file-formatted.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ const configFileFormatted = (configFile) => {
66
return <><code>cypress.json</code> file (currently disabled by <code>--config-file false</code>)</>
77
}
88

9-
if (isUndefined(configFile) || configFile === 'cypress.json') {
9+
if (isUndefined(configFile)) {
1010
return <><code>cypress.json</code> file</>
1111
}
1212

13+
if (['cypress.json', 'cypress.config.js'].includes(configFile)) {
14+
return <><code>{configFile}</code> file</>
15+
}
16+
1317
return <>custom config file <code>{configFile}</code></>
1418
}
1519

packages/desktop-gui/src/lib/utils.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,5 @@ export function stripSharedDirsFromDir2 (dir1, dir2, osName) {
103103
.join(sep)
104104
.value()
105105
}
106+
107+
export const isFileJSON = (file) => file && /\.json$/.test(file)

packages/desktop-gui/src/settings/node-version.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { observer } from 'mobx-react'
33
import React from 'react'
44

55
import ipc from '../lib/ipc'
6+
import { isFileJSON } from '../lib/utils'
7+
import { configFileFormatted } from '../lib/config-file-formatted'
68

79
const openHelp = (e) => {
810
e.preventDefault()
@@ -89,6 +91,9 @@ const NodeVersion = observer(({ project }) => {
8991
<div className='well text-muted'>
9092
This Node.js version is used to:
9193
<ul>
94+
{isFileJSON(project.configFile)
95+
? undefined
96+
: <li>Execute code in the {configFileFormatted(project.configFile)}.</li>}
9297
<li>Build files in the {formatIntegrationFolder()} folder.</li>
9398
<li>Build files in the <code>cypress/support</code> folder.</li>
9499
<li>Execute code in the {formatPluginsFile() ? formatPluginsFile() : 'plugins'} file.</li>

packages/desktop-gui/src/settings/project-id.jsx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React from 'react'
33
import Tooltip from '@cypress/react-tooltip'
44

55
import ipc from '../lib/ipc'
6+
import { isFileJSON } from '../lib/utils'
67
import { configFileFormatted } from '../lib/config-file-formatted'
78

89
const openProjectIdHelp = (e) => {
@@ -19,10 +20,6 @@ const openProjectIdHelp = (e) => {
1920
const ProjectId = observer(({ project }) => {
2021
if (!project.id) return null
2122

22-
const projectIdJsonConfig = {
23-
projectId: project.id,
24-
}
25-
2623
return (
2724
<div data-cy="project-id">
2825
<a href='#' className='learn-more' onClick={openProjectIdHelp}>
@@ -33,7 +30,7 @@ const ProjectId = observer(({ project }) => {
3330
It identifies your project and should not be changed.
3431
</p>
3532
<pre className='line-nums copy-to-clipboard'>
36-
<a className="action-copy" onClick={() => ipc.setClipboardText(JSON.stringify(projectIdJsonConfig, null, 2))}>
33+
<a className="action-copy" onClick={() => ipc.setClipboardText(document.querySelector('[data-cy="project-id"] pre').innerText)}>
3734
<Tooltip
3835
title='Copy to clipboard'
3936
placement='top'
@@ -42,9 +39,20 @@ const ProjectId = observer(({ project }) => {
4239
<i className='fas fa-clipboard' />
4340
</Tooltip>
4441
</a>
45-
<span>{'{'}</span>
46-
<span>{` "projectId": "${project.id}"`}</span>
47-
<span>{'}'}</span>
42+
{
43+
isFileJSON(project.configFile) ?
44+
<>
45+
<span>{'{'}</span>
46+
<span>{` "projectId": "${project.id}"`}</span>
47+
<span>{'}'}</span>
48+
</>
49+
:
50+
<>
51+
<span>{'module.exports = {'}</span>
52+
<span>{` projectId: "${project.id}"`}</span>
53+
<span>{'}'}</span>
54+
</>
55+
}
4856
</pre>
4957
</div>
5058
)

packages/desktop-gui/src/settings/project-id_spec.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,14 @@ describe('ProjectId', () => {
4444

4545
cy.get('@externalOpen').should('have.been.called')
4646
})
47+
48+
it('shows a different output when configFile is js', () => {
49+
mount(<ProjectId project={{ ...project, configFile: 'cypress.config.js' }} />, {
50+
stylesheets: '/__root/dist/app.css',
51+
})
52+
53+
cy.get('[data-cy=project-id] pre').then(($pre) => {
54+
expect($pre.text()).to.contain('module.exports = ')
55+
})
56+
})
4757
})

packages/server/lib/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import scaffold from './scaffold'
99
import { fs } from './util/fs'
1010
import keys from './util/keys'
1111
import origin from './util/origin'
12-
import settings from './util/settings'
12+
import * as settings from './util/settings'
1313
import Debug from 'debug'
1414
import pathHelpers from './util/path_helpers'
1515
import findSystemNode from './util/find_system_node'

packages/server/lib/configFiles.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// the first file is the default created file
2+
export const CYPRESS_CONFIG_FILES = ['cypress.json', 'cypress.config.js']

packages/server/lib/errors.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,20 @@ const getMsgByType = function (type, arg1 = {}, arg2, arg3) {
694694
${chalk.yellow(arg1.error)}
695695
696696
Learn more at https://on.cypress.io/reporters`
697+
// TODO: update with vetted cypress language
698+
case 'NO_DEFAULT_CONFIG_FILE_FOUND':
699+
return stripIndent`\
700+
Could not find a Cypress configuration file, exiting.
701+
702+
We looked but did not find a default config file in this folder: ${chalk.blue(arg1)}`
703+
// TODO: update with vetted cypress language
704+
case 'CONFIG_FILES_LANGUAGE_CONFLICT':
705+
return stripIndent`
706+
There is both a \`${arg2}\` and a \`${arg3}\` at the location below:
707+
${arg1}
708+
709+
Cypress does not know which one to read for config. Please remove one of the two and try again.
710+
`
697711
case 'CONFIG_FILE_NOT_FOUND':
698712
return stripIndent`\
699713
Could not find a Cypress configuration file, exiting.

packages/server/lib/gui/events.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-disable no-case-declarations */
22
const _ = require('lodash')
3+
const path = require('path')
34
const ipc = require('electron').ipcMain
45
const { clipboard } = require('electron')
56
const debug = require('debug')('cypress:server:events')
@@ -323,6 +324,20 @@ const handleEvent = function (options, bus, event, id, type, arg) {
323324
onWarning,
324325
})
325326
}).call('getConfig')
327+
.then((config) => {
328+
if (config.configFile && path.isAbsolute(config.configFile)) {
329+
config.configFile = path.relative(arg, config.configFile)
330+
}
331+
332+
// those two values make no sense to display in
333+
// the GUI
334+
if (config.resolved) {
335+
config.resolved.configFile = undefined
336+
config.resolved.testingType = undefined
337+
}
338+
339+
return config
340+
})
326341
.then(send)
327342
.catch(sendErr)
328343

0 commit comments

Comments
 (0)