-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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: issue with compilation failures in component testing #21599
Conversation
…ue-with-compilation
…ue-with-compilation # Conflicts: # npm/webpack-dev-server/cypress/e2e/react.cy.ts # npm/webpack-dev-server/src/CypressCTWebpackPlugin.ts # npm/webpack-dev-server/src/devServer.ts
Thanks for taking the time to open a PR!
|
Test summaryRun details
View run in Cypress Dashboard ➡️ Flakiness
This comment has been generated by cypress-bot as a result of this project's GitHub integration settings. You can manage this integration in this project's settings in the Cypress Dashboard |
This reverts commit 98b2f26.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One change for the merging of the webpackConfig, the rest are minor. Tested and it works great, HUGE improvement
incremental: true, | ||
plugins: [ | ||
{ | ||
name: 'esbuild-plugin', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change this to cypress-esbuild-plugin
. Also, how did you debug this plugin? I tried logging and throwing errors inside the setup
function but I never saw any logs inside the terminal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: fd175c8
(#21599)
@@ -4,5 +4,5 @@ import { App } from './App' | |||
|
|||
it('renders hello world', () => { | |||
mount(<App />) | |||
cy.get('h1').contains('Hello World') | |||
cy.get('h1').contains('Hello World').click() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this click()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Without it, if we are displaying an overlay the tests will pass (even though they shouldn't). I can maybe throw a comment on there to make that more clear why I'm doing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment added here: fd175c8
(#21599)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.should('be.visible')
btw is more "explicit" about what you're testing. Though .click()
's actionability checks are more aggressive (and will cover more failure cases)
system-tests/lib/system-tests.ts
Outdated
@@ -296,12 +296,13 @@ Bluebird.config({ | |||
longStackTraces: true, | |||
}) | |||
|
|||
let cacheNodeModulesDir |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why were these changes needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. These were needed at one point to standardize output, but I refactored a few things and missed these. They are now removed:
cy.withCtx(async (ctx) => { | ||
await ctx.actions.file.writeFileInProject( | ||
`src/AppCompilationError.cy.jsx`, | ||
` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use dedent
here to indent the app code alongside the test without affecting the final file output if you like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to use dedent on the latest commit
name: 'esbuild-plugin', | ||
setup (build) { | ||
build.onEnd(function (result) { | ||
// We don't want to completely fail the build here on errors so we treat the errors as warnings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add link to #21599? I'd normally suggest linking the issue, but in this case it's in Jira and I prefer to link to github when possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added here: fd175c8
(#21599)
@@ -93,42 +93,6 @@ export class CypressCTWebpackPlugin { | |||
callback() | |||
} | |||
|
|||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we removing the code to inform Cypress that there's a compilation error / success? It seems like this is an event we might want to react to in the UI in some way.
I'm thinking specifically of "compilation is done, rerun the spec" - right now we rely on webpack-dev-server's hot reload functionality, but I'd rather remove that and have Cypress do the hot reloading at some point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment below: #21599 (comment)
@@ -179,74 +178,6 @@ describe('#devServer', () => { | |||
}) | |||
}) | |||
|
|||
it('emits dev-server:compile:error event on error compilation', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(just another mention of the above question - if we put back the dev-server:compile:error
/ dev-server:compile:success
events, these tests would come back as well)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So there still is a dev-server:compile:success
event. It's just in a different spot, but as I was thinking about this, I like having all of the compilation hooks in one place (they were definitely spread out and confusing before). With how everything works together we don't need the error events in vite or in webpack (however, that could change as this evolves in the future).
Unified the location of the compilation hooks here:
@@ -19,6 +19,9 @@ describe('makeWebpackConfig', () => { | |||
output: { | |||
publicPath: '/this-will-be-ignored', | |||
}, | |||
devServer: { | |||
overlay: true, // This will be ignored as well |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overlay: true, // This will be ignored as well | |
overlay: true, // This will be overridden by makeWebpackConfig.ts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated: fd175c8
(#21599)
@@ -4,5 +4,5 @@ import { App } from './App' | |||
|
|||
it('renders hello world', () => { | |||
mount(<App />) | |||
cy.get('h1').contains('Hello World') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we clicking on hello world?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to ensure that the component is interactable (i.e. there's no overlay) I added a comment for this: fd175c8
(#21599)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes & rationale makes sense - good test coverage and it looks like the other review comments have been addressed, fine with me as long as tests look good 👍
export const run = (options: LaunchArgs, loadingPromise: Promise<void>) => { | ||
// TODO: make sure if we need to run this in electron by default to match e2e behavior? | ||
options.browser = options.browser || 'electron' | ||
options.runAllSpecsInSameBrowserSession = true | ||
|
||
require('../plugins/dev-server').emitter.on('dev-server:compile:error', (error: Error) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥 good riddance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
god bless
@@ -17,4 +17,4 @@ | |||
import '@packages/frontend-shared/cypress/e2e/support/e2eSupport' | |||
|
|||
// Alternatively you can use CommonJS syntax: | |||
// require('./commands') | |||
require('./commands') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like mixing these. Why would you require instead of import? Not gonna block, but we should stick to one way of importing. require is nonstandard in the browser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can update this. That was my bad. I had just uncommented what was commented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated here: dd566a0
(#21599)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concerned about magicHtml
usage. What's the deal with that?
publicPath: '/this-will-be-ignored', | ||
}, | ||
devServer: { | ||
magicHtml: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was added in Webpack 4.1 only. Will we break user config for Webpack 4? Is there a sys test for Webpack 4.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JessicaSachs this is a unit test. I'm just verifying that user defined config will be kept (other than the ones we care about)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I saw that was just like "why this flag?". Cool.
export const run = (options: LaunchArgs, loadingPromise: Promise<void>) => { | ||
// TODO: make sure if we need to run this in electron by default to match e2e behavior? | ||
options.browser = options.browser || 'electron' | ||
options.runAllSpecsInSameBrowserSession = true | ||
|
||
require('../plugins/dev-server').emitter.on('dev-server:compile:error', (error: Error) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
god bless
…pack * develop: fix: UNIFY-1408, warnings should be nested appropriately & clearable (#21630) chore: fix unit-tests-release job (#21652) chore(deps): update dependency eventsource to v2 [security] (#21639) fix: Add hover states for test titles in reporter (#21635) docs(CONTRIBUTING): Fix link to "good first issue" for newcomers (#21614) chore: compare `cy.screenshot` images in percy (#21598) fix: switching from ct to e2e (non-configured) does not go through setup (#21607) fix: issue with compilation failures in component testing (#21599) test: fix flaky launchpad test (#21637) docs: remove gitter link in contributing guide. (#21592) fix: order projects by most recently opened (#21589) fix: prevent crash on runs visit when offline (#21618) fix: pass family parameter to connect method (#21545) chore: clean up `debug` statements in preparation for 10.0 release, add `debug` docs (#21621) chore: add regression test for ts detection (#21578)
User facing changelog
Component specs with webpack compilation errors no longer exit the server process in run mode, their results get sent to the dashboard, and the exit code is specified properly. Component specs with vite compilation errors no longer hang in run or open mode.
Additional details
Each framework handles compilation and linting errors slightly differnently. This PR focuses on compilation errors. An explanation of the current, proposed interim (on this PR), and proposed ideal states can be found in this google doc
Compilation Errors when using the Webpack Framework
The main problem with this scenario is that we currently emit a webpack failure on compilation errors and in one of the handlers, we immediately exit the server process. This doesn't allow us to return the appropriate status codes, report to the dashboard appropriately, or continue running specs that don't have compilation errors.
The interim solution to this problem is to no longer exit the process. Webpack automatically injects the compilation error into the problematic module and Cypress's generic error mechanism handles this correctly.
Longer term, we could investigate displaying a custom error for this scenario rather than the generic uncaught exception message.
Compilation Errors when using the Vite Framework
The main problem with this scenario is that esbuild errors out during the optimization process and assets are not generated.
The interim solution to this problem is to add an esbuild plugin that changes the errors to warnings. Vite will then not end up generating an asset for the bad asset and we will get a 500 error whenever the asset is loaded. This will end up getting this scenario to an acceptable state for both open and run mode, however it won't allow for the compilation error message to be displayed to the user. Instead it will be a more generic error.
In the long run, we will try and make the error more user friendly and specific. Some investigation will be needed to figure out:
How has the user experience changed?
PR Tasks
cypress-documentation
?type definitions
?cypress.schema.json
?