-
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
fix: support snapshots of xhr/fetch and other logs generated from the primary #21552
Conversation
Thanks for taking the time to open a PR!
|
Test summaryRun details
View run in Cypress Dashboard ➡️ FlakinessThis 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 |
function fireXHRAndFetchRequests() { | ||
|
||
xhr = new XMLHttpRequest(); | ||
xhr.open("GET", "https://jsonplaceholder.cypress.io/todos/1"); |
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 make a fetch request to our local server instead of to .cypress.io? I see us using this in a couple of other places already, but the seems simple enough that we could add it to the server.
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.
Made a fixture and stubbed the body out with cy.intercept
in 265617f. Seems to do what we want?
packages/driver/src/cypress/log.ts
Outdated
// insert at index 'at' or whatever is the next position | ||
snapshots[options.at || snapshots.length] = snapshot | ||
if (options.next && shouldRebindSnapshotFn) { | ||
const fn = this.snapshot |
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.
Could we rename fn to be more descriptive?
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.
how is something like 5df6787? I changed the name to originalLogSnapshotFn
.
packages/driver/src/cypress/log.ts
Outdated
this.set('snapshots', snapshots) | ||
if (this.config('experimentalSessionAndOrigin') && !Cypress.isCrossOriginSpecBridge) { | ||
// @ts-ignore | ||
const { originPolicy: activeSpecBridgeOriginPolicyIfApplicable } = this.state('currentActiveOriginPolicy') ? Cypress.Location.create(this.state('currentActiveOriginPolicy')) : { |
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 think the currentActiveOriginPolicy, if present, already is an originPolicy so you shouldn't have to re-create 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.
addressed in 2ee5441.
|
||
if (options.next) { | ||
const fn = this.snapshot | ||
if (activeSpecBridgeOriginPolicyIfApplicable && activeSpecBridgeOriginPolicyIfApplicable === originPolicyThatIsSoonToBeOrIsActive) { |
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.
In what scenarios is this not true? If we are in a cy.origin block but have begun navigating to another origin? Does it make a difference if it's the top origin or another cross origin?
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.
Mainly the error case/operator error. If a user navigates to an origin that doesn't match the spec bridge origin, like
cy.get('[href="https://www.foobar.com"]').click()
cy.origin('https://www.barbaz.com', () => {
// wrong origin, don't snapshot this
})
I added a test here to make sure this fails gracefully.
@@ -0,0 +1,89 @@ | |||
// import to bind shouldWithTimeout into global cy 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.
What do you mean by this? isn't this picked up in the the global via the support 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.
It is not. We don't import utils
inside the support directory in the index
or defaults
. Not entirely sure why, because this seems like it should be included there...
} | ||
|
||
this.set('snapshots', snapshots) | ||
if (this.config('experimentalSessionAndOrigin') && !Cypress.isCrossOriginSpecBridge) { |
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.
Would it be possible to somehow tie this to the command group the log is part of? Like add the originPolicy to the command group and use it for any events generated within that group? @emilyrohrbough, is something like that possible (or better)?
cy.origin('http://foobar.com:3500', () => { | ||
cy.get(`[data-cy="assertion-header"]`).should('exist') | ||
// have some wait time to allow for the xhr/fetch requests to settle | ||
cy.wait(200) |
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.
Once #21579 merges, you can wait for the actual request instead of having an arbitrary wait time. You may be able to do it now if you don't wait inside of cy.origin
.
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 gave it a try waiting outside. The test seems to flake about 50/50, I am guessing due to the time for the log to come back and be searchable after the alias resolves takes longer than 250ms.
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.
Would it make sense to increase the timeout in shouldWithTimeout
?
packages/driver/src/cypress/log.ts
Outdated
return fn.call(this, options.next) | ||
Cypress.primaryOriginCommunicator.toSpecBridge(activeSpecBridgeOriginPolicyIfApplicable, 'generate:snapshot:for:log', { | ||
name, | ||
id: eventID, |
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 can't the log's id be used? We can associate multiple snapshots to a log so I would expect this to be fine / no need to manage another unique eventID.
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.
After revisiting, I removed the date.now()
and opted for just going with the log ID, which the event handling now lives in the event manager to ask the spec bridge for the log snapshot.
After talking with @emilyrohrbough , I am going to move this back to draft to see if I can figure out a better pattern then just baking the snapshot behavior into the log manager itself. |
dbc3106
to
d90da5c
Compare
…en XHR requests are made, as well as used aliases for requests over arbitrary waits
@@ -191,8 +191,9 @@ export class SpecBridgeCommunicator extends EventEmitter { | |||
data = preprocessLogForSerialization(data as any) | |||
} | |||
|
|||
// If requested by the runner, preprocess the final snapshot before sending through postMessage() to attempt to serialize the DOM body of the snapshot. | |||
if (FINAL_SNAPSHOT_EVENT === eventName) { | |||
// If requested by the runner, preprocess the snapshot before sending through postMessage() to attempt to serialize the DOM body of the snapshot. |
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.
nit: lets specify @packages/runner since the driver has a Runner class 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.
sorry this was confusing...more like, we should specific which runner. it seems like it's this runner:
but our code base also has these runners:
Cypress.primaryOriginCommunicator.once(`snapshot:for:log:generated:${eventID}`, (generatedCrossOriginSnapshot) => { | ||
const snapshot = generatedCrossOriginSnapshot.body ? generatedCrossOriginSnapshot : null | ||
|
||
addSnapshot.apply(log, [snapshot, options, false]) | ||
}) | ||
|
||
Cypress.primaryOriginCommunicator.toSpecBridge(specBridge, 'generate:snapshot:for:log', { | ||
name, | ||
id: eventID, | ||
}) |
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 might be one of those cases where adding a promise-based API to the communicator would be useful. Then it could be something like:
const generatedCrossOriginSnapshot = await
Cypress.primaryOriginCommunicator.toSpecBridgeAsync(specBridge, 'generate:snapshot:for:log')
const snapshot = generatedCrossOriginSnapshot.body ? generatedCrossOriginSnapshot : null
addSnapshot.apply(log, [snapshot, options, false])
I'm not suggesting adding it in this PR, but wanted to call it out as an example. Maybe when we have another use-case, we could add that and refactor this one.
Co-authored-by: Matt Schile <mschile@cypress.io>
Co-authored-by: Matt Schile <mschile@cypress.io>
that need screenshots of the secondary
User facing changelog
Additional details
The goal of this PR is to have snapshots reflect the current active origin for logs generated in the primary domain. Currently, logs generated in the primary domain, such as xhr/fetch requests, show snapshots of the primary stale domain when a secondary domain is active. This should only mainly impact xhr/fetch requests as the logs are generated in the primary, but there is potential impact elsewhere as there are changes to the snapshot function inside the log. This is gated behind the
experimentalSessionAndOrigin
flag, so any regressions, if any, should be behind the feature flag.How has the user experience changed?
-- example using a site with a lot of requests
before
after
PR Tasks
cypress-documentation
?type definitions
?cypress.schema.json
?