Skip to content

Commit

Permalink
fix(webpack-dev-server): touch component-index during onSpecsChange t…
Browse files Browse the repository at this point in the history
…o avoid writing to app file (#25861)

* testing: try disabling uTimesSync and see what happens

* build binaries [run ci]

* fix: touch component index file instead of browser.js

* build binaries [run ci]

* update test

* fix test

* add test for custom HTML file in config

* use existing component index in webpack-dev-server unit tests

---------

Co-authored-by: Lachlan Miller <[email protected]>
  • Loading branch information
astone123 and lmiller1990 authored Feb 20, 2023
1 parent 9e059d0 commit 87816de
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 11 deletions.
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>

6 comments on commit 87816de

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 87816de Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.7.0/linux-arm64/develop-87816de1b7c4c3873ad791d71ac2af5aaa88e889/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 87816de Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.7.0/linux-x64/develop-87816de1b7c4c3873ad791d71ac2af5aaa88e889/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 87816de Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.7.0/darwin-x64/develop-87816de1b7c4c3873ad791d71ac2af5aaa88e889/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 87816de Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.7.0/win32-x64/develop-87816de1b7c4c3873ad791d71ac2af5aaa88e889/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 87816de Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.7.0/darwin-arm64/develop-87816de1b7c4c3873ad791d71ac2af5aaa88e889/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 87816de Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.7.0/linux-x64/develop-87816de1b7c4c3873ad791d71ac2af5aaa88e889/cypress.tgz

Please sign in to comment.