Skip to content

fix: Ensuring spec file presence prior to webpack-dev-server compilation #21550

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

Merged
merged 5 commits into from
May 20, 2022

Conversation

tbiethman
Copy link
Contributor

@tbiethman tbiethman commented May 18, 2022

User facing changelog

Additional details

There is a race condition between our webpack compilation and our emission of the dev-server:specs:changed event. When a spec file is removed from the file system, we attempt to compile prior to updating our internal files property within the plugin, causing the loader to reference files that no longer exist.

I updated the CypressCTWebpackPlugin to filter out files in state that no longer exist on the file system during the beforeCompile phase. This prevents both the initial error from being presented at file removal time and allows the file to be immediately executed when re-created.

How has the user experience changed?

webpack_delete_spec.mov

PR Tasks

  • Have tests been added/updated?
  • [n/a] Has the original issue (or this PR, if no issue exists) been tagged with a release in ZenHub? (user-facing changes only)
  • [n/a] Has a PR for user-facing changes been opened in cypress-documentation?
  • [n/a] Have API changes been updated in the type definitions?
  • [n/a] Have new configuration options been added to the cypress.schema.json?

@tbiethman tbiethman self-assigned this May 18, 2022
@cypress-bot
Copy link
Contributor

cypress-bot bot commented May 18, 2022

Thanks for taking the time to open a PR!

@cypress
Copy link

cypress bot commented May 18, 2022



Test summary

4855 0 58 0Flakiness 0


Run details

Project cypress
Status Passed
Commit b265ee9
Started May 19, 2022 9:08 PM
Ended May 19, 2022 9:22 PM
Duration 14:01 💡
OS Linux Debian - 10.11
Browser Chrome beta 102

View run in Cypress Dashboard ➡️


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

@tbiethman tbiethman marked this pull request as ready for review May 18, 2022 19:56
@tbiethman tbiethman requested a review from a team as a code owner May 18, 2022 19:56
@tbiethman tbiethman requested a review from ZachJW34 May 18, 2022 19:56
Copy link
Contributor

@ZachJW34 ZachJW34 left a comment

Choose a reason for hiding this comment

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

Works great!

@@ -8,4 +8,39 @@ describe('Config options', () => {
cy.contains('App.cy.jsx').click()
cy.get('.passed > .num').should('contain', 1)
})

// https://cypress-io.atlassian.net/browse/UNIFY-1697
it('filters missing spec files from loader during pre-compilation', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Awesome test, the cy-in-cy tests for the dev-servers are so darn cool.

Copy link
Contributor

@lmiller1990 lmiller1990 May 19, 2022

Choose a reason for hiding this comment

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

They are quite cool, but I wonder if a regression test would be best added in the actual npm/webpack-dev-server @tbiethman? This test is quite far away from the actual code it is related to. Not sure how practical it is to add unit/integration test inside of webpack-dev-server, though.

Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

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

Just a quick question around sync vs async!


// Ensure we don't try to load files that have been removed from the file system
// but have not yet been detected by the onSpecsChange handler
this.files = (this.files || []).filter((file) => fs.existsSync(file.absolute))
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure we want to use existsSync here, should we use the async pathExists from fs-extra and tapAsync?

Eg: https://github.com/cypress-io/cypress/compare/tbiethman/fix/unify-1697-ct-file-removed...lmiller1990/fix/unify-1697-ct-file-removed?expand=1

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Or - is the point we must do this async, so we avoid the race condition?

Copy link
Contributor Author

@tbiethman tbiethman May 19, 2022

Choose a reason for hiding this comment

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

We just need this to execute prior to the compile phase, which should happen regardless of whether we're sync/async here. Given that we're not actively manipulating the compile params here, we might as well use async and get whatever benefit that might have.

Your example branch was helpful, thank you. I thought about going with a Promise.all rather than running them in series. Something like:

    const foundFiles = await Promise.all(this.files.map(async (file) => {
      try {
        const exists = await fs.pathExists(file.absolute)

        return exists ? file : null
      } catch (e) {
        return null
      }
    }))

    this.files = foundFiles.filter((file) => file !== null)

Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems fine 💯

@tbiethman
Copy link
Contributor Author

I updated this to use an async beforeCompile implementation, seems to work great. I also added a mocha integration test to get slightly more granular coverage of this behavior. To help with this, I added a new event (dev-server:compile:done) to our existing done hook so I could more easily test that a failure is not occurring during the compile without relying on a timeout.

@tbiethman tbiethman requested review from lmiller1990 and ZachJW34 May 19, 2022 21:07
Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

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

Tests were improved, looks good. @ZachJW34 had previously QA'd so I'll merge this up.

@lmiller1990 lmiller1990 merged commit 87eec2b into 10.0-release May 20, 2022
@lmiller1990 lmiller1990 deleted the tbiethman/fix/unify-1697-ct-file-removed branch May 20, 2022 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants