-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
feat: add subscription for specs changing #20657
feat: add subscription for specs changing #20657
Conversation
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 |
* add an extra test for migration * refactor: use async tools to deal with files Co-authored-by: Barthélémy Ledoux <bart@cypress.io>
* feat: rename __socket.io -> __socket, add __socket-graphql for graphql-ws * fix: remove currentTestingType from Query type * feat: add subscription to refresh when auth state changes * Update packages/frontend-shared/src/gql-components/HeaderBarContent.vue * PR review updates, add docs, tests for authChange subscription * remove login/logout toApp/toLaunchpad calls * remove login/logout/devChange toApp/toLaunchpad calls * fix, getCtx lazily to fix proxy performance spec * Fix, thanks @JessicaSachs * test fixes, remove flash of missing content in wizard Co-authored-by: Ryan Manuel <ryanm@cypress.io> Co-authored-by: Jess <jess@jessicasachs.io> Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
* remove pluginsFile references * fix all tests relying on this system test * fix broken tests * fix more broken tests * one more * relative path * pr feedbkac * fix vite-dev-server broken configuration * PR feedback on error message * update errors snaphsot * bring back error in gql * fix snapshot * fix snapshot. * fix merge issues Co-authored-by: ElevateBart <ledouxb@gmail.com>
…is removed (#20515) * add terminal warning for experimental studio * add to errors old * add warnings to main * debug onWarning callback * show error in open mode * update snapshot * update tests * validate config earlier * remove from types and schema * use on link * refactor getError * update types Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com> * add unit test for validateNoBreakingConfigLaunchpad * fix types * merge test files * update types Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com>
…e specific" This reverts commit c002011.
9dc99f8
to
a17c97f
Compare
.should('contain', 'new-file.spec.js') | ||
}) | ||
|
||
it('handles removing the last file', () => { |
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 this test be expanded so as to verify that once you get redirected to the "No Specs Page", adding a file takes you back to the SpecsList. We fixed that bug by moving the subscription up a level but would be good to cover that case.
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.
@ZachJW34, the test before this one accomplishes that.
if (done) { | ||
return { done: true, value: undefined } | ||
} | ||
|
||
if (!hasSentInitial && sendInitial) { | ||
hasSentInitial = true | ||
|
||
return { done: false, value: {} } |
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.
@tgriesser are the values that we're emitting here being used? As I was working through this logic I was trying to figure out if {} was appropriate here, or undefined?
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.
The value here is what will flow into the first argument of the resolve
for the subscription. So if we want to have a more targeted subscription where we're not looking to merge with existing types, like notifying where the type is dependent on an individual file change (where there is no initial value), we can set sendInitial
to false, and just use the values that are sent into the emitter to determine the resolved value. Here's a rough example of what I mean:
type SpecEventType {
ADD
CHANGE
REMOVE
}
type SpecEvent {
event: SpecEventType
filePath: String
fileParts: FileParts
}
type Subscription {
"""Fired whenever a spec changes"""
specEvent: SpecEvent
}
subscribe: (source, args, ctx) => ctx.subscribeTo('specEvt', false)
resolve: (specEvt, args, ctx) => {
return {...specEvt, fileParts: {absolute: specEvt.filePath}}
}
on.all('evt', (event, filePath) => {
ctx.emitter.specEvt({
event,
filePath
})
}
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 a few comments, but otherwise looks pretty solid! Just kicked off the CI pipeline again to see if it will complete
@@ -81,7 +81,8 @@ useSubscription({ query: OnSpecChangeDocument }, (prev, next) => { | |||
- [API Docs for useSubscription](https://formidable.com/open-source/urql/docs/api/vue/#usesubscription) | |||
- [Subscriptions overview](https://formidable.com/open-source/urql/docs/advanced/subscriptions/) | |||
|
|||
One thing to be aware of, is the subscription is only mounted/responded to when the containing component is mounted on the page. | |||
One thing to be aware of, is the subscription is only mounted/responded to when the containing component is mounted on the page. Therefore, one rule of thumb when using subscriptions is to ensure that they are declared in the subscription dependent view that is highest in the hierarchy so that the subscription can be active when it needs to be. This location is often alongside a query rather than a fragment. | |||
|
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.
Great addition here!
throw: async (error: Error) => { | ||
throw 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.
Does adding throw
here make a difference? Or was this more useful while debugging the timing issue with the deferreds?
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 to complete the expected type for the async generator. From what I could tell in the graphql-ws an async generator seemed to be what they were expecting if you were going to expose return
like we are:
Declaring it as an async generator like I am now, allows me to iterate like I am in the test i wrote but it also necessitates adding the throw function.
@@ -21,7 +21,7 @@ export class ServerCt extends ServerBase<SocketCt> { | |||
this.server.on('connect', this.onConnect.bind(this)) | |||
this.server.on('upgrade', (req, socket, head) => this.onUpgrade(req, socket, head, socketIoRoute)) | |||
|
|||
graphqlWS(this.server, `${socketIoRoute}-graphql`) | |||
this._graphqlWS = graphqlWS(this.server, `${socketIoRoute}-graphql`) |
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.
Nice catch!
if (Cypress.platform === 'win32') return posixPath.replaceAll('/', '\\') | ||
|
||
return posixPath | ||
} |
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 helper has been propagated a few times already, but you could import it from here instead: https://github.com/cypress-io/cypress/blob/10.0-release/packages/app/src/paths.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.
supportFile: false, | ||
}, | ||
}`) | ||
}, { path: getPathForPlatform('cypress/e2e/dom-list.spec.js') }) |
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.
Doesn't look like the path is being used here (or with the other config writes)
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.
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.
Works good! My comments are small.
Not sure if you've done much testing on windows, but I'm curious if this might have an impact on https://cypress-io.atlassian.net/browse/UNIFY-1221 as well.
574a705
User facing changelog
Ensure that when the spec pattern changes inside of the cypress config, we start watching the new spec pattern in the file system for changes
Additional details
In addition to fixing the spec pattern watching logic, we are also converting specs to use the gql subscription system. In the process of working on this, I realized that we had a couple of race conditions involving the subscription async iterator, where we might get events while we're not actually awaiting them yet and thus they get lost. Also, when stepping through the
graphql-ws
code, I realized that when we are "returning" out of the async iterator, so I am fixing that as well by ensuring we always resolve the promise we are waiting on in the subscription.How has the user experience changed?
PR Tasks
cypress-documentation
?type definitions
?cypress.schema.json
?