Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(webpack-dev-server): touch component-index during onSpecsChange to avoid writing to app file #25861

Merged
merged 11 commits into from
Feb 20, 2023
2 changes: 1 addition & 1 deletion .circleci/workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ commands:
- run:
name: Check current branch to persist artifacts
command: |
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "fix-duplicate-and-expired-cookies" ]]; then
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "astone123/ventura-webpack-permission-testing" ]]; then
echo "Not uploading artifacts or posting install comment for this branch."
circleci-agent step halt
fi
Expand Down
18 changes: 18 additions & 0 deletions npm/webpack-dev-server/cypress/e2e/webpack-dev-server.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,22 @@ describe('Config options', () => {
expect(verifyFile).to.eq('OK')
})
})

it('recompiles with new spec and custom indexHtmlFile', () => {
cy.scaffoldProject('webpack5_wds4-react')
cy.openProject('webpack5_wds4-react', ['--config-file', 'cypress-webpack-dev-server-custom-index.config.ts'])
cy.startAppServer('component')

cy.visitApp()

cy.withCtx(async (ctx) => {
await ctx.actions.file.writeFileInProject(
ctx.path.join('src', 'New.cy.js'),
await ctx.file.readFileInProject(ctx.path.join('src', 'App.cy.jsx')),
)
})

cy.contains('New.cy.js').click()
cy.waitForSpecToFinish({ passCount: 2 })
})
})
21 changes: 15 additions & 6 deletions npm/webpack-dev-server/src/CypressCTWebpackPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface CypressCTWebpackPluginOptions {
supportFile: string | false
devServerEvents: EventEmitter
webpack: Function
indexHtmlFile: string
}

export type CypressCTContextOptions = Omit<CypressCTWebpackPluginOptions, 'devServerEvents' | 'webpack'>
Expand Down Expand Up @@ -47,6 +48,7 @@ export class CypressCTWebpackPlugin {
private supportFile: string | false
private compilation: Webpack45Compilation | null = null
private webpack: Function
private indexHtmlFile: string

private readonly projectRoot: string
private readonly devServerEvents: EventEmitter
Expand All @@ -57,13 +59,15 @@ export class CypressCTWebpackPlugin {
this.projectRoot = options.projectRoot
this.devServerEvents = options.devServerEvents
this.webpack = options.webpack
this.indexHtmlFile = options.indexHtmlFile
}

private addLoaderContext = (loaderContext: object, module: any) => {
(loaderContext as CypressCTWebpackContext)._cypress = {
files: this.files,
projectRoot: this.projectRoot,
supportFile: this.supportFile,
indexHtmlFile: this.indexHtmlFile,
}
};

Expand Down Expand Up @@ -93,11 +97,16 @@ export class CypressCTWebpackPlugin {
}

/*
* `webpack --watch` watches the existing specs and their dependencies for changes,
* but we also need to add additional dependencies to our dynamic "browser.js" (generated
* using loader.ts) when new specs are created. This hook informs webpack that browser.js
* has been "updated on disk", causing a recompliation (and pulling the new specs in as
* dependencies).
* `webpack --watch` watches the existing specs and their dependencies for changes.
* When new specs are created, we need to trigger a recompilation to add the new specs
* as dependencies. This hook informs webpack that `component-index.html` has been "updated on disk",
* causing a recompilation (and pulling the new specs in as dependencies). We use the component
* index file because we know that it will be there since the project is using Component Testing.
*
* We were using `browser.js` before to cause a recompilation but we ran into an
* issue with MacOS Ventura that will not allow us to write to files inside of our application bundle.
*
* See https://github.com/cypress-io/cypress/issues/24398
*/
private onSpecsChange = async (specs: Cypress.Cypress['spec'][]) => {
if (!this.compilation || _.isEqual(specs, this.files)) {
Expand All @@ -110,7 +119,7 @@ export class CypressCTWebpackPlugin {
// eslint-disable-next-line no-restricted-syntax
const utimesSync: UtimesSync = inputFileSystem.fileSystem.utimesSync ?? fs.utimesSync

utimesSync(path.resolve(__dirname, 'browser.js'), new Date(), new Date())
utimesSync(path.join(this.projectRoot, this.indexHtmlFile), new Date(), new Date())
}

/**
Expand Down
1 change: 1 addition & 0 deletions npm/webpack-dev-server/src/makeDefaultWebpackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export function makeCypressWebpackConfig (
devServerEvents,
supportFile,
webpack,
indexHtmlFile,
}),
],
devtool: 'inline-source-map',
Expand Down
8 changes: 4 additions & 4 deletions npm/webpack-dev-server/test/devServer-e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const cypressConfig = {
supportFile: '',
isTextTerminal: true,
devServerPublicPathRoute: root,
indexHtmlFile: path.join(__dirname, 'component-index.html'),
indexHtmlFile: 'test/component-index.html',
} as any as Cypress.PluginConfigOptions

describe('#devServer', () => {
Expand Down Expand Up @@ -170,7 +170,7 @@ describe('#devServer', () => {
await closeServer(close)
})

it('touches browser.js when a spec file is added and recompile', async function () {
it('touches component index when a spec file is added and recompile', async function () {
// File watching only enabled when running in `open` mode
cypressConfig.isTextTerminal = false
const devServerEvents = new EventEmitter()
Expand All @@ -187,13 +187,13 @@ describe('#devServer', () => {
absolute: `${root}/test/fixtures/bar.spec.js`,
}

const oldmtime = fs.statSync('./dist/browser.js').mtimeMs
const oldmtime = fs.statSync(cypressConfig.indexHtmlFile).mtimeMs

await once(devServerEvents, 'dev-server:compile:success')
devServerEvents.emit('dev-server:specs:changed', [newSpec])

await once(devServerEvents, 'dev-server:compile:success')
const updatedmtime = fs.statSync('./dist/browser.js').mtimeMs
const updatedmtime = fs.statSync(cypressConfig.indexHtmlFile).mtimeMs

expect(oldmtime).to.not.equal(updatedmtime)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from 'cypress'
import defaultConfig from './cypress-webpack.config'

export default defineConfig({
...defaultConfig,
component: {
...defaultConfig.component as Cypress.Config['component'],
indexHtmlFile: 'my-component-index.html',
},
})
12 changes: 12 additions & 0 deletions system-tests/project-fixtures/react/my-component-index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>