Support cy.visit()
with protocols other than http
/https
such as:
chrome://
chrome-extension://
resource://
Most notably, chrome-extension://
will allow users to test the UI of a chrome extension.
There's also Add support for testing chrome extensions but it's closed.
I've added a comment because I believe the issue is still happening.
@JulianG that issue was for testing content scripts, which is currently possible. But yeah this is the other half of Chrome extensions
Would love to see support for this added!
I鈥檇 be very keen to see this - you can already make a fair bit of headway with extensions, but this would be the icing on the cake.
I would love to see this ability. It would be so great.
Curious, which pages are you most wanting to test? background.html? popup.html?
And you need access to the chrome.*
apis correct?
I'm trying to figure out the scope of work here, because embedding the page in an iframe while maintaining access to chrome.*
privileged apis might be tricky
@Bkucera For my own use case, I would be able to run Cypress on my extension's popup in order to see if:
I tried cy.visit('chrome-extension://.../popup.html')
but it doesn't work due to invalid protocol.
Also, background.html
is literally never used because it's a auto-generated page when you use a single background.js
(probably ~99% of the time), but it would be nice for running Cypress on options.html
page. :+1:
Having access to chrome*
API would be awesome (e.g.: to check if a notification has been triggered, sync, ...), or maybe we can manually stub chrome*
methods at the moment?
Thanks you for taking time on this. :slightly_smiling_face:
@Bkucera Exactly. My chrome extension uses chrome.windows.*
and chrome.tabs.*
and in order to display in a list and manipulate well... windows and tabs.
I'm currently in the process of writing a fake (as in not a mock nor stub) chrome api so I can test in Cypress, but I would very much prefer to test the real thing.
(In my case it's neither background.html
nor popup.html
. My background.js
uses chrome api to open a window containing index.html
.)
In my case I want to test via cy.visit('chrome-extension://.../popup.html')
or if possible by using the keyboard hotkeys to trigger the extension. In my case the hotkey causes the background.js
to run a script that attaches the HTML for the extension to the DOM. My extension is used to do tab switching so the user could switch to any tab they have open. I also use the history and sessions APIs.
One thing I had hoped to do was call cy.visit
a couple times to get cypress to load some browsing history and then run my extension to test the calls to the APIs but I would be willing to settle for stubbing their responses in cypress.
Thanks everyone for the input. I think the use case of @Kocal can currently be done by stubbing chrome.*
apis and running a simple http server in the folder with manifest.json
. Then you can just cy.visit
http://localhost:8080/popup.html
and this should be very similar to visiting chrome-extension://...
I have done this before and you can change the viewport to be something more similar to popup size
My popup is now successfuly tested, thanks you all! :sunglasses:
Some tips for people who wants to spec their extension's views and mocking chrome*
API:
dist
folder)dist
folder (serve is pretty nice){
"baseUrl": "http://localhost:5000"
}
describe('App', () => {
before(() => {
// Load your popup
cy.visit('/popup/popup.html', {
// If you need to stub `chrome*` API, you should do it there:
onBeforeLoad(win) {
win.chrome = win.chrome || {};
win.chrome.runtime = {
sendMessage(message, cb) {
// ...
cb(some_data);
},
};
},
});
});
});
Have you stubbed chrome.* in the end?
I started making a fake implementation of chrome.windows.*
and chrome tabs.*
which is what I use. Do you know if such thing already exists?
Well, I only use chrome.runtime.sendMessage
inside my popup view, I didn't take time for other methods :confused:
EDIT: some times ago I used jest-webextension-mock for mocking chrome.*
in Jest context. Maybe it can helps you
I have used sinon-chrome before, it works well for unit/IT testing. Not sure how it compares to jest-webextension-mock.
For me, the use case would not be testing an extension but testing our app with an extension I want to be able to click some buttons on the extension etc while navigating through our app
I can see both use cases being strong.
Say you're developing an extension that has some UI flows in the popup, it gets pretty annoying to manually test those each time by clicking the extension icon! Regressions are so hard to notice because of the nature of the popup. With Cypress interface, I'd spot the regressions by just running the test command, and notice exactly where it happens.
On the other side, you're obviously developing an extension to enhance a browser -- and websites as a result -- so running an "example site" inside Cypress with the extension loaded could be useful to notice things like what the extension might inject, etc. like what @Moejoe90 is suggesting.
@Bkucera is this being actively worked on? Is there anything the community can do to support?
@callmenick I'm working on testing a chrome extension that injects html into a third party site, but no Test Runner features are being developed yet.
Most likely I'll end up using something from here to allow the extension to detect content in the AUT (application under test), which cypress puts in an iframe
Cool, thanks for the update. I'm personally interested in the first point, supporting extension protocols so I can visit chrome-extension://id/index.html
and run tests from there. Is there any roadmap for that?
@callmenick you can check https://github.com/cypress-io/cypress/issues/1965#issuecomment-415796370 I guess
Yeah that's what we're doing now as well @Kocal. Thanks for that!
Hey everyone, I was able to set up a good workflow (see however below*) for testing chrome extensions that inject HTML onto third party sites.
For example, to test an extension that injects HTML inside of Gmail, there were a few things I had to do:
cypress/plugins/gmail/
, one of my pages is called gmail_home.html
)plugins/index.js
, and it needs to have a self-signed SSL cert: this requires launching cypress with sudo due to needing port 443 (google's port)plugins/index.js
code:const path = require('path');
module.exports = (on) => {
on('task', {
setUrlPath (url) {
console.log(url)
filepath = url
return null
}
})
}
let filepath = 'gmail/gmail_home.html'
const express = require('express')
const PORT = 443
const app = express()
const selfSignedHttps = require('self-signed-https')
app.get('/*', (req, res) => {
return res.sendFile(filepath, { root: __dirname })
})
selfSignedHttps(app).listen(PORT, () => console.log(`Server running on port ${PORT}`))
...
cypress.json
:"hosts": {
"mail.google.com": "127.0.0.1",
}
"all_frames":true
to extension's manifest.json
"content_scripts": [
{
"matches": [
"http://mail.google.com/*",
"https://mail.google.com/*"
],
"js": [
...
],
"css": [
...
],
"all_frames": true
}
plugins/index.js
file as shown here: https://docs.cypress.io/api/plugins/browser-launch-api.html#Usage:+1:
Cypress cy.route
stubbing will not affect traffic originating in a chrome extension, so there is more work to do before that can be used.
This will be fixed by Full Network stubbing, and is on our roadmap: #687
Similar to @callmenick above, I'm curious about whether or not Cypress can support simply visit a HTML page from a Chrome extension. If an extension has an HTML page listed in its web_accessible_resources
it can be loaded in an iframe without too much trouble. That manifest entry, coupled with the --load-extension=$folder
flag could allow a very basic UI test of a Chrome extension. Is this something Cypress could support?
@Bkucera any idea on when this might happen? Asking since it'll influence our testing roadmap.
Thanks for all your hard work :)
@bdresser the main hurdle to this is #687 , and I have no timeline for that; however I'm not exactly sure what you are testing. could you describe your use case like others have above?
Thanks for the information thread and guidance, @Bkucera , along with the example!
To fully test my Chrome extension, I want to be mocking out a variety of API responses, including 2xx, 4xx, and 5xx responses from my API. If I understand correctly, I cannot currently do this with Cypress by itself. There is also no way you can easily think of to use some other library to mock it out that will work with running tests in Cypress, correct?
I think I can accomplish this by using Puppeteer directly, as described in this SO answer and using nock to mock the API responses.
Is chrome-extension protocol working?
It fails with error > Error: Invalid protocol: chrome-extension:
I also have a use case where I would like to use Cypress, but looking at this issue, wont work. I would like to test a chrome extensions UI that communicates to a webpage using chrome.runtime.connect(extID, portName)
. The extension has a state stored in redux using webext-redux to share the store, which I think needs to run from within an extension and wont work by hosting the files locally. Being able to test pages starting with chrome-extension:// would be amazing.
I belive there should be way to test extension in real Chrome. Not under web server, not stubbing anything. With doing all this extra work, there is huge space to introduce new bugs and worse - to miss some real bugs.
I didn't check the source code of Cypress or Chrome so I'm really not sure how it is working under the hood. But isn't it possible to navigate to chrome://
and chrome-extension://
in exact same way as to http://
? Isn't it only alias to http and working over http protocol?
Btw. I started to play with Cypress only because I need to test extension, I wouldn't give it a try if it wouldn't look like it can do this from docs. As other tools are lacking in this area too, it my be great to provide better support for extension authors.
@Bkucera
the main hurdle to this is #687 , and I have no timeline for that; however I'm not exactly sure what you are testing. could you describe your use case like others have above?
Since #687 landed in the meantime, would you say there are other major blockers? I'd be interested in working on making this happen and some rough pointers would be appreciated.
https://github.com/cypress-io/cypress/issues/687 is actually not a prerequisite to delivering this feature. There was a misunderstanding previously on the scope of that issue.
@jennifer-shehane Thanks for the info. Do you by chance know if there's something important missing currently which would make implementing this feature especially hard? Asking because it's tagged with "difficulty 5".
As of now is there a robust and reliable method for testing a chrome extension - i.e. is it possible for Cypress to open the extension window/popup and interact with the UI?
I would require a test to initially start on a website and in the course of testing, it will send requests and receive responses from the extension based on user input on both the site and extension.
_Example scenario:_
Site: user clicks on a button
Extn: receives request from site
User: Navigates to extension to confirm/deny request
Extn: returns response based on user input
Site: handles response
Most helpful comment
I belive there should be way to test extension in real Chrome. Not under web server, not stubbing anything. With doing all this extra work, there is huge space to introduce new bugs and worse - to miss some real bugs.
I didn't check the source code of Cypress or Chrome so I'm really not sure how it is working under the hood. But isn't it possible to navigate to
chrome://
andchrome-extension://
in exact same way as tohttp://
? Isn't it only alias to http and working over http protocol?Btw. I started to play with Cypress only because I need to test extension, I wouldn't give it a try if it wouldn't look like it can do this from docs. As other tools are lacking in this area too, it my be great to provide better support for extension authors.