Skip to content

Commit 466be9f

Browse files
astone123ZachJW34warrensplayer
authored
fix: force Webpack to emit assets on error (#23844)
Co-authored-by: Zachary Williams <[email protected]> Co-authored-by: Stokes Player <[email protected]>
1 parent a7945e8 commit 466be9f

File tree

10 files changed

+158
-59
lines changed

10 files changed

+158
-59
lines changed

npm/webpack-dev-server/__snapshots__/makeWebpackConfig.spec.ts.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ exports['makeWebpackConfig ignores userland webpack `output.publicPath` and `dev
1212
},
1313
"mode": "development",
1414
"optimization": {
15+
"emitOnErrors": true,
1516
"splitChunks": {
1617
"chunks": "all"
1718
}
@@ -33,6 +34,7 @@ exports['makeWebpackConfig ignores userland webpack `output.publicPath` and `dev
3334
},
3435
"mode": "development",
3536
"optimization": {
37+
"noEmitOnErrors": false,
3638
"splitChunks": {
3739
"chunks": "all"
3840
}

npm/webpack-dev-server/cypress/e2e/angular.cy.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ for (const project of WEBPACK_REACT) {
2222
it('should mount a passing test', () => {
2323
cy.visitApp()
2424
cy.contains('app.component.cy.ts').click()
25-
cy.waitForSpecToFinish()
26-
cy.get('.passed > .num').should('contain', 1)
25+
cy.waitForSpecToFinish({ passCount: 1 })
26+
2727
cy.get('li.command').first().within(() => {
2828
cy.get('.command-method').should('contain', 'mount')
2929
cy.get('.command-message').should('contain', 'AppComponent')
@@ -33,8 +33,7 @@ for (const project of WEBPACK_REACT) {
3333
it('should live-reload on src changes', () => {
3434
cy.visitApp()
3535
cy.contains('app.component.cy.ts').click()
36-
cy.waitForSpecToFinish()
37-
cy.get('.passed > .num').should('contain', 1)
36+
cy.waitForSpecToFinish({ passCount: 1 })
3837

3938
cy.withCtx(async (ctx) => {
4039
await ctx.actions.file.writeFileInProject(
@@ -43,7 +42,7 @@ for (const project of WEBPACK_REACT) {
4342
)
4443
})
4544

46-
cy.get('.failed > .num').should('contain', 1)
45+
cy.waitForSpecToFinish({ failCount: 1 })
4746

4847
cy.withCtx(async (ctx) => {
4948
await ctx.actions.file.writeFileInProject(
@@ -52,7 +51,28 @@ for (const project of WEBPACK_REACT) {
5251
)
5352
})
5453

55-
cy.get('.passed > .num').should('contain', 1)
54+
cy.waitForSpecToFinish({ passCount: 1 })
55+
})
56+
57+
it('should show compilation errors on src changes', () => {
58+
cy.visitApp()
59+
60+
cy.contains('app.component.cy.ts').click()
61+
cy.waitForSpecToFinish({ passCount: 1 })
62+
63+
// Create compilation error
64+
cy.withCtx(async (ctx) => {
65+
const componentFilePath = ctx.path.join('src', 'app', 'app.component.ts')
66+
67+
await ctx.actions.file.writeFileInProject(
68+
componentFilePath,
69+
(await ctx.file.readFileInProject(componentFilePath)).replace('class', 'classaaaaa'),
70+
)
71+
})
72+
73+
// The test should fail and the stack trace should appear in the command log
74+
cy.waitForSpecToFinish({ failCount: 1 })
75+
cy.contains('The following error originated from your test code, not from Cypress.').should('exist')
5676
})
5777

5878
// TODO: fix flaky test https://github.com/cypress-io/cypress/issues/23455
@@ -67,8 +87,7 @@ for (const project of WEBPACK_REACT) {
6787
})
6888

6989
cy.contains('new.component.cy.ts').click()
70-
cy.waitForSpecToFinish()
71-
cy.get('.passed > .num').should('contain', 1)
90+
cy.waitForSpecToFinish({ passCount: 1 })
7291
})
7392
})
7493
}

npm/webpack-dev-server/cypress/e2e/create-react-app.cy.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@ for (const project of WEBPACK_REACT) {
2121
it('should mount a passing test', () => {
2222
cy.visitApp()
2323
cy.contains('App.cy.js').click()
24-
cy.waitForSpecToFinish()
25-
cy.get('.passed > .num').should('contain', 1)
24+
cy.waitForSpecToFinish({ passCount: 1 })
2625
})
2726

2827
it('should live-reload on src changes', () => {
2928
cy.visitApp()
3029

3130
cy.contains('App.cy.js').click()
32-
cy.waitForSpecToFinish()
33-
cy.get('.passed > .num').should('contain', 1)
31+
cy.waitForSpecToFinish({ passCount: 1 })
3432

3533
cy.withCtx(async (ctx) => {
3634
await ctx.actions.file.writeFileInProject(
@@ -39,7 +37,7 @@ for (const project of WEBPACK_REACT) {
3937
)
4038
})
4139

42-
cy.get('.failed > .num').should('contain', 1)
40+
cy.waitForSpecToFinish({ failCount: 1 })
4341

4442
cy.withCtx(async (ctx) => {
4543
await ctx.actions.file.writeFileInProject(
@@ -48,7 +46,25 @@ for (const project of WEBPACK_REACT) {
4846
)
4947
})
5048

51-
cy.get('.passed > .num').should('contain', 1)
49+
cy.waitForSpecToFinish({ passCount: 1 })
50+
})
51+
52+
it('should show compilation errors on src changes', () => {
53+
cy.visitApp()
54+
55+
cy.contains('App.cy.js').click()
56+
cy.waitForSpecToFinish({ passCount: 1 })
57+
58+
cy.withCtx(async (ctx) => {
59+
await ctx.actions.file.writeFileInProject(
60+
ctx.path.join('src', 'App.js'),
61+
(await ctx.file.readFileInProject(ctx.path.join('src', 'App.js'))).replace('export', 'expart'),
62+
)
63+
})
64+
65+
// The test should fail and the stack trace should appear in the command log
66+
cy.waitForSpecToFinish({ failCount: 1 })
67+
cy.contains('The following error originated from your test code, not from Cypress.').should('exist')
5268
})
5369

5470
it('should detect new spec', () => {
@@ -62,8 +78,7 @@ for (const project of WEBPACK_REACT) {
6278
})
6379

6480
cy.contains('New.cy.js').click()
65-
cy.waitForSpecToFinish()
66-
cy.get('.passed > .num').should('contain', 1)
81+
cy.waitForSpecToFinish({ passCount: 1 })
6782
})
6883
})
6984
}

npm/webpack-dev-server/cypress/e2e/next.cy.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@ for (const project of WEBPACK_REACT) {
2121
it('should mount a passing test', () => {
2222
cy.visitApp()
2323
cy.contains('index.cy.js').click()
24-
cy.waitForSpecToFinish()
25-
cy.get('.passed > .num').should('contain', 1)
24+
cy.waitForSpecToFinish({ passCount: 1 })
2625
})
2726

2827
it('should live-reload on src changes', () => {
2928
cy.visitApp()
3029

3130
cy.contains('index.cy.js').click()
32-
cy.waitForSpecToFinish()
33-
cy.get('.passed > .num').should('contain', 1)
31+
cy.waitForSpecToFinish({ passCount: 1 })
3432

3533
cy.withCtx(async (ctx) => {
3634
const indexPath = ctx.path.join('pages', 'index.js')
@@ -41,7 +39,7 @@ for (const project of WEBPACK_REACT) {
4139
)
4240
})
4341

44-
cy.get('.failed > .num', { timeout: 10000 }).should('contain', 1)
42+
cy.waitForSpecToFinish({ failCount: 1 })
4543

4644
cy.withCtx(async (ctx) => {
4745
const indexTestPath = ctx.path.join('pages', 'index.cy.js')
@@ -52,7 +50,28 @@ for (const project of WEBPACK_REACT) {
5250
)
5351
})
5452

55-
cy.get('.passed > .num').should('contain', 1)
53+
cy.waitForSpecToFinish({ passCount: 1 })
54+
})
55+
56+
it('should show compilation errors on src changes', () => {
57+
cy.visitApp()
58+
59+
cy.contains('index.cy.js').click()
60+
cy.waitForSpecToFinish({ passCount: 1 })
61+
62+
// Create compilation error
63+
cy.withCtx(async (ctx) => {
64+
const indexPath = ctx.path.join('pages', 'index.js')
65+
66+
await ctx.actions.file.writeFileInProject(
67+
indexPath,
68+
(await ctx.file.readFileInProject(indexPath)).replace('export', 'expart'),
69+
)
70+
})
71+
72+
// The test should fail and the stack trace should appear in the command log
73+
cy.waitForSpecToFinish({ failCount: 1 })
74+
cy.contains('The following error originated from your test code, not from Cypress.').should('exist')
5675
})
5776

5877
// TODO: fix flaky test https://github.com/cypress-io/cypress/issues/23417
@@ -70,16 +89,14 @@ for (const project of WEBPACK_REACT) {
7089
})
7190

7291
cy.contains('New.cy.js').click()
73-
cy.waitForSpecToFinish()
74-
cy.get('.passed > .num').should('contain', 1)
92+
cy.waitForSpecToFinish({ passCount: 1 })
7593
})
7694

7795
// TODO: fix flaky test https://github.com/cypress-io/cypress/issues/23417
7896
it.skip('should allow import of global styles in support file', () => {
7997
cy.visitApp()
8098
cy.contains('styles.cy.js').click()
81-
cy.waitForSpecToFinish()
82-
cy.get('.passed > .num').should('contain', 1)
99+
cy.waitForSpecToFinish({ passCount: 1 })
83100
})
84101
})
85102
}

npm/webpack-dev-server/cypress/e2e/nuxt.cy.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ for (const project of PROJECTS) {
2323
it('should mount a passing test and live-reload', () => {
2424
cy.visitApp()
2525
cy.contains('Tutorial.cy.js').click()
26-
cy.waitForSpecToFinish()
27-
cy.get('.passed > .num').should('contain', 1)
26+
cy.waitForSpecToFinish({ passCount: 1 })
2827

2928
cy.withCtx(async (ctx) => {
3029
const tutorialVuePath = ctx.path.join('components', 'Tutorial.vue')
@@ -35,7 +34,7 @@ for (const project of PROJECTS) {
3534
)
3635
})
3736

38-
cy.get('.failed > .num').should('contain', 1)
37+
cy.waitForSpecToFinish({ failCount: 1 })
3938

4039
cy.withCtx(async (ctx) => {
4140
const tutorialCyPath = ctx.path.join('components', 'Tutorial.cy.js')
@@ -46,7 +45,28 @@ for (const project of PROJECTS) {
4645
)
4746
})
4847

49-
cy.get('.passed > .num').should('contain', 1)
48+
cy.waitForSpecToFinish({ passCount: 1 })
49+
})
50+
51+
it('should show compilation errors on src changes', () => {
52+
cy.visitApp()
53+
54+
cy.contains('Tutorial.cy.js').click()
55+
cy.waitForSpecToFinish({ passCount: 1 })
56+
57+
// Create compilation error
58+
cy.withCtx(async (ctx) => {
59+
const tutorialVuePath = ctx.path.join('components', 'Tutorial.vue')
60+
61+
await ctx.actions.file.writeFileInProject(
62+
tutorialVuePath,
63+
(await ctx.file.readFileInProject(tutorialVuePath)).replace('export', 'expart'),
64+
)
65+
})
66+
67+
// The test should fail and the stack trace should appear in the command log
68+
cy.waitForSpecToFinish({ failCount: 1 })
69+
cy.contains('The following error originated from your test code, not from Cypress.').should('exist')
5070
})
5171

5272
// TODO: fix flaky test https://github.com/cypress-io/cypress/issues/23455
@@ -64,8 +84,7 @@ for (const project of PROJECTS) {
6484
})
6585

6686
cy.contains('New.cy.js').click()
67-
cy.waitForSpecToFinish()
68-
cy.get('.passed > .num').should('contain', 1)
87+
cy.waitForSpecToFinish({ passCount: 1 })
6988
})
7089
})
7190
}

npm/webpack-dev-server/cypress/e2e/vue-cli.cy.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,32 @@ for (const project of PROJECTS) {
2121
it('should mount a passing test', () => {
2222
cy.visitApp()
2323
cy.contains('HelloWorld.cy.js').click()
24-
cy.waitForSpecToFinish()
25-
cy.get('.passed > .num').should('contain', 1)
24+
cy.waitForSpecToFinish({ passCount: 1 })
2625
cy.get('.commands-container').within(() => {
2726
cy.contains('mount')
2827
cy.contains('<HelloWorld ... />')
2928
})
3029
})
30+
31+
it('should show compilation errors on src changes', () => {
32+
cy.visitApp()
33+
34+
cy.contains('HelloWorld.cy.js').click()
35+
cy.waitForSpecToFinish({ passCount: 1 })
36+
37+
// Create compilation error
38+
cy.withCtx(async (ctx) => {
39+
const helloWorldVuePath = ctx.path.join('src', 'components', 'HelloWorld.vue')
40+
41+
await ctx.actions.file.writeFileInProject(
42+
helloWorldVuePath,
43+
(await ctx.file.readFileInProject(helloWorldVuePath)).replace('export', 'expart'),
44+
)
45+
})
46+
47+
// The test should fail and the stack trace should appear in the command log
48+
cy.waitForSpecToFinish({ failCount: 1 })
49+
cy.contains('The following error originated from your test code, not from Cypress.').should('exist')
50+
})
3151
})
3252
}
Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/// <reference types="cypress" />
2+
import type { ExpectedResults } from '@packages/app/cypress/e2e/support/execute-spec'
3+
import { waitForSpecToFinish } from '@packages/app/cypress/e2e/support/execute-spec'
24

35
declare global {
46
namespace Cypress {
@@ -11,24 +13,9 @@ declare global {
1113
* 3. Waits (with a timeout of 30s) for the Rerun all tests button to be present. This ensures all tests have completed
1214
*
1315
*/
14-
waitForSpecToFinish()
16+
waitForSpecToFinish(expectedResults?: ExpectedResults): void
1517
}
1618
}
1719
}
1820

19-
// Here we export the function with no intention to import it
20-
// This only tells the typescript type checker that this definitely is a module
21-
// This way, we are allowed to use the global namespace declaration
22-
export const waitForSpecToFinish = () => {
23-
// First ensure the test is loaded
24-
cy.get('.passed > .num').should('contain', '--')
25-
cy.get('.failed > .num').should('contain', '--')
26-
27-
// Then ensure the tests are running
28-
cy.contains('Your tests are loading...').should('not.exist')
29-
30-
// Then ensure the tests have finished
31-
cy.get('[aria-label="Rerun all tests"]', { timeout: 30000 })
32-
}
33-
3421
Cypress.Commands.add('waitForSpecToFinish', waitForSpecToFinish)

npm/webpack-dev-server/src/makeDefaultWebpackConfig.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,18 @@ export function makeDefaultWebpackConfig (
2424

2525
debug(`Using HtmlWebpackPlugin version ${version} from ${importPath}`)
2626

27+
const optimization = <Record<string, any>>{}
28+
29+
if (config.sourceWebpackModulesResult.webpack.majorVersion === 5) {
30+
optimization.emitOnErrors = true
31+
} else {
32+
optimization.noEmitOnErrors = false
33+
}
34+
2735
const finalConfig = {
2836
mode: 'development',
2937
optimization: {
38+
...optimization,
3039
splitChunks: {
3140
chunks: 'all',
3241
},

0 commit comments

Comments
 (0)