Skip to content
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

Merged
merged 12 commits into from
Aug 17, 2022

Conversation

AtofStryker
Copy link
Contributor

@AtofStryker AtofStryker commented May 18, 2022

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

request-behavior-old

after

new-request-behavior

PR Tasks

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

@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

37840 0 615 0Flakiness 7


Run details

Project cypress
Status Passed
Commit 4d2e378
Started Aug 17, 2022 3:07 PM
Ended Aug 17, 2022 3:23 PM
Duration 15:26 💡
OS Linux Debian - 11.3
Browser Multiple

View run in Cypress Dashboard ➡️


Flakiness

cypress/e2e/commands/net_stubbing.cy.ts Flakiness
1 network stubbing > intercepting request > can add a body to a request that does not have one
2 network stubbing > intercepting request > can delay with deprecated delayMs param
3 network stubbing > intercepting request > can delay with deprecated delayMs param
4 network stubbing > intercepting request > can delay with deprecated delayMs param
5 network stubbing > intercepting request > can delay with deprecated delayMs param
This comment includes only the first 5 flaky tests. See all 7 flaky tests in the 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

@AtofStryker AtofStryker marked this pull request as ready for review May 19, 2022 16:09
@AtofStryker AtofStryker requested a review from a team as a code owner May 19, 2022 16:09
@AtofStryker AtofStryker requested review from jennifer-shehane and removed request for a team May 19, 2022 16:09
@jennifer-shehane jennifer-shehane removed their request for review May 19, 2022 16:10
@AtofStryker AtofStryker changed the title support snapshots of xhr/fetch and other logs generated from the primary fix: support snapshots of xhr/fetch and other logs generated from the primary May 19, 2022
function fireXHRAndFetchRequests() {

xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.cypress.io/todos/1");
Copy link
Member

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.

Copy link
Contributor Author

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?

// insert at index 'at' or whatever is the next position
snapshots[options.at || snapshots.length] = snapshot
if (options.next && shouldRebindSnapshotFn) {
const fn = this.snapshot
Copy link
Member

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?

Copy link
Contributor Author

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.

this.set('snapshots', snapshots)
if (this.config('experimentalSessionAndOrigin') && !Cypress.isCrossOriginSpecBridge) {
// @ts-ignore
const { originPolicy: activeSpecBridgeOriginPolicyIfApplicable } = this.state('currentActiveOriginPolicy') ? Cypress.Location.create(this.state('currentActiveOriginPolicy')) : {
Copy link
Member

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?

https://github.com/cypress-io/cypress/blob/develop/packages/driver/src/cy/commands/origin/index.ts#L119

Copy link
Contributor Author

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) {
Copy link
Member

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?

Copy link
Contributor Author

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
Copy link
Member

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?

Copy link
Contributor Author

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) {
Copy link
Member

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)
Copy link
Contributor

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.

Copy link
Contributor Author

@AtofStryker AtofStryker May 23, 2022

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.

Copy link
Contributor

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/cross-origin/cypress.ts Outdated Show resolved Hide resolved
packages/driver/src/cross-origin/cypress.ts Outdated Show resolved Hide resolved
@AtofStryker AtofStryker requested a review from mschile May 23, 2022 16:22
return fn.call(this, options.next)
Cypress.primaryOriginCommunicator.toSpecBridge(activeSpecBridgeOriginPolicyIfApplicable, 'generate:snapshot:for:log', {
name,
id: eventID,
Copy link
Member

@emilyrohrbough emilyrohrbough May 24, 2022

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.

Copy link
Contributor Author

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.

@AtofStryker
Copy link
Contributor Author

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.

@AtofStryker AtofStryker marked this pull request as draft May 24, 2022 16:21
@AtofStryker AtofStryker marked this pull request as ready for review July 26, 2022 15:16
@@ -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.
Copy link
Member

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

Copy link
Member

Choose a reason for hiding this comment

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

Comment on lines +615 to +624
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,
})
Copy link
Contributor

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.

AtofStryker and others added 3 commits August 17, 2022 10:32
Co-authored-by: Matt Schile <mschile@cypress.io>
Co-authored-by: Matt Schile <mschile@cypress.io>
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.

Snapshot's in xhr requests for absolute URLs take a snapshot of the primary instead of the current domain
5 participants