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

Expose and document Chrome DevTools Protocol #7942

Open
jennifer-shehane opened this issue Jul 10, 2020 · 12 comments
Open

Expose and document Chrome DevTools Protocol #7942

jennifer-shehane opened this issue Jul 10, 2020 · 12 comments
Labels
type: feature New feature that does not currently exist

Comments

@jennifer-shehane
Copy link
Member

Current behavior:

Currently there is no documented way to access the Chrome DevTools Protocol.

This actually is possible today, although it's undocumented using the method below.

Cypress.automation("remote:debugger:protocol", {

})

Desired behavior:

People have requested that they'd like direct access to the Chrome DevTools Protocol. Would want this documented so people could use it. Some examples of usage are below:

This feature needs to support:

  • Issuing commands
  • Receiving events

Additionally, there's no cross-browser support to this, so that's a challenge.

Versions

4.10.0

@cypress-bot cypress-bot bot added the stage: proposal 💡 No work has been done of this issue label Jul 10, 2020
@jennifer-shehane jennifer-shehane added the type: feature New feature that does not currently exist label Jul 13, 2020
@avallete
Copy link
Contributor

avallete commented Jul 13, 2020

I did used this into my cypress-nhover package. I could try to add some documentation about it.

PS: since Firefox seem to implement CDP as well (cf: https://github.com/firefox-devtools/rust-cdp, https://firefox-source-docs.mozilla.org/remote/) it may be worthy to create a new issue to be able to use it into cypress too.

@froatsnook
Copy link

Being able to run one test in American Samoa, the next in UK, and the next in Fiji would be useful for my use case (I had a regression where recurring events showed on the wrong dates in some time zones). Using the undocumented remote:debugger:protocol works great (although it seems you can only do Emulation.setTimezoneOverride once before you get a Unhandled rejection Error: Timezone override is already in effect error in $Cypress.automation).

@Sathish787
Copy link

Sathish787 commented May 27, 2021

Could suppress exception/unhandled rejection by placing code in support/command.js

Cypress.on('uncaught:exception', (err, runnable) => {
    return false
})

Mocking only timezone in cypress and not to mix with locale (mocking language). It is better to create separate custom command for locale to avoid error. Paste below code in support/command.js

Cypress.Commands.add('stubBrowserTimezone', timeZone) {
         return new Promise((resolve) => {
        return resolve(
            Cypress.automation("remote:debugger:protocol", {
                command: "Emulation.setTimezoneOverride",
                params: {
                    timezoneId: timeZone
                }                
            })
        )
    })
}

Then, in test file, use it like:

cy.stubBrowserTimezone("Europe/London").then(() => {
	cy.log(new Date().toString())
        test steps.... should be inside loop...
})

@flotwig
Copy link
Contributor

flotwig commented May 28, 2021

PS: since Firefox seem to implement CDP as well (cf: firefox-devtools/rust-cdp, firefox-source-docs.mozilla.org/remote) it may be worthy to create a new issue to be able to use it into cypress too.

@avallete now that CDP is available in FF stable as of FF86, look out for this coming soon

@flotwig
Copy link
Contributor

flotwig commented Jun 7, 2021

Here is an API that I think could work nicely for this:

/**
 * Send a CDP command with optional parameters and receive the result.
 */
Cypress.CDP.send = (method: string, params?: any) => Promise<CDPResult>
/**
 * Subscribe to a CDP event. Some events must be enabled before being listened to.
 */
Cypress.CDP.on = (method: string, cb: (params: any) => void)) => void

I don't see a need to integrate it with Cypress-isms like the chainable, since it is somewhat of a low-level API that may not make sense to write in that way. Any thoughts?

EDIT: Also, we probably need a way to select targets, or default to the test frame target.

@nileshgulia1
Copy link

Its now possible to simulate events like "copy to clipboard" using CDP : https://github.com/dmtrKovalenko/cypress-real-events

@shwarcu
Copy link

shwarcu commented Mar 3, 2022

@jennifer-shehane @flotwig is this topic parked/abandoned?

@flotwig
Copy link
Contributor

flotwig commented Mar 3, 2022

@shwarcu This is still something we'd like to add to Cypress, but it is not currently being worked on.

If you're interested in starting a PR to add this, this comment describes a partial API, but we'd also need some way to select Targets.

@BloodyRain2k
Copy link

Mocking only timezone in cypress and not to mix with locale (mocking language). It is better to create separate custom command for locale to avoid error. Paste below code in support/command.js

Cypress.Commands.add('stubBrowserTimezone', timeZone) {
         return new Promise((resolve) => {
        return resolve(
            Cypress.automation("remote:debugger:protocol", {
                command: "Emulation.setTimezoneOverride",
                params: {
                    timezoneId: timeZone
                }                
            })
        )
    })
}

This command has been a huge help with the project I'm working on. Thanks a lot for sharing it.
I was especially excited when I found out that it's not required to run the test commands inside the .then(), as that would have meant a major overhaul of my already existing tests.
Just calling the command in beforeEach() works just as well. And considering that the setting of the timezone is, for whatever reason, only allowed once anyways, it makes more sense this way too.

I did however seem to have found an edge-case where this might cause issues:

I had a literal unit-test set for my project, which are the only tests that can actually be measured in "ms" (avg. <100ms), unlike all others which could as well be just measured in 1/10ths of minutes.
After permutating the original ~300 tests to ~1100 by just running the original set in 4 different timezones, I started seeing random errors that said nothing more than "beforeEach() failed".

I tried finding an actual cause for this, but after an hour I just gave up because there was simply no pattern to be found, nor any details about what actually broke.
Sometimes it barely got past 100 before breaking, other times it got past 500 before throwing the first non-descriptive error.

I then went with a "gut feeling" and restructured the way the tests were grouped, so that beforeEach() would be called less than 10-20x a second, and after having now ~110 tests that take around 150-200ms each, the error has not yet appeared again.

In my case it would be ideal if the timezone would be just another "option" for describe/it, like "env" is.
So it would be possible to set up a set like describe("Timezone tests", { tz: "America/NewYork" }, () => { ... }) and just have the entire set run with that timezone.

But that's just QoL for "eventually". For now I just wanted to leave this here in case anyone else manages to run into this issue, so they at least have one approach of trying to prevent it.

@skitterm
Copy link

skitterm commented Nov 8, 2023

@jennifer-shehane while we await Cypress CDP wrappers, could you share an example of listening for a CDP event?

Use case
I'd like to intercept network requests using CDP (I know there's cy.intercept(), but I'd like to reuse this code across testing frameworks so CDP would be preferable). I can currently send the fetch.enable method

Cypress.automation("remote:debugger:protocol", {
    command: "Fetch.enable",
    params: {}
})

but I don't see a way to listen to events like Fetch.requestPaused or Network.responseReceived with the current API (to get the response status code and body, for example). Is there a way to receive CDP events currently, or is the current Cypress.automation('remote:debugger:protocol') approach only for calling CDP methods?

@fabianeichfeldt
Copy link

fabianeichfeldt commented Apr 18, 2024

Are there any news about listening to CDP events?

I would like to use CDP for memory analysis and taking HeapSnapshots, therefore I need to listen to events

@RomanDavlyatshin
Copy link

Are there any news about listening to CDP events?

I would like to use CDP for memory analysis and taking HeapSnapshots, therefore I need to listen to events

Hey Fabian,
its been a long time, so my memory on the issue is somewhat vague, but I have managed to use CDP without issue following the code sample provided by OP (although I may did some digging in Cypress sources)

Here is the example on some CDP calls I used:

// in supportfile.js  (utlized by Cypress to setup all kinds of stuff related to tests execution, including before/after hooks)

// before all tests - enable desired CDP domains
before((done) => {
  // ... some unrelated promises code above
  .then(() => Cypress.automation('remote:debugger:protocol', { command: 'Profiler.enable', params: {} }))
  .then(() => Cypress.automation('remote:debugger:protocol', { command: 'Profiler.startPreciseCoverage', params: {
    callCount: false,
    detailed: true
  }}))
  .then(()=>done());
});

// Take metrics after each test
afterEach(function (done) {
  const currentTest = this.currentTest;
  Cypress.automation('remote:debugger:protocol', { command: 'Profiler.takePreciseCoverage', params: {}})
    .then(async function (cdpCommandData) {
      // do something cool with the data
    })
    .then(()=>done());  
});

That should work in a similar fashion for Profiler heap usage and all other domains.
Hope that helps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature New feature that does not currently exist
Projects
None yet
Development

No branches or pull requests