How do I add and use Chrome Extensions with Cypress.io programmatically?
Close to duplicating this but solution cannot be manual.
I'm running npx cypress open
, clicking "E2E Testing", then clicking "Chrome v112", then running my spec.
The extension is not modifying the page or appearing in chrome://extensions
I have tried manually adding my extension to Cypress chrome as mentioned here
But I would like to do it programmatically so I can use it in github workflows etc.
I see one answer that points to the docs and I have copied it to cypress.config.ts
(and replaced the path with the one that works when loading manually). But the extension doesn't load on my page when I call cy.visit()
in Cypress and isn't listed in chrome://extensions within Cypress Chrome.
I also notice the docs say:
launchOptions.extensions.push('Users/jane/path/to/extension')
which is missing the beginning /
. I'm not sure if that's intentional so I have tried both with and without it.
Would love to hear any suggestions!
Add eg:
launchOptions.extensions.push(
'/Users/me/git_projects/xxx/extension/dist'
)
to your cypress.config.ts
This should already load the extension (check console for any errors) which you can find in the opened Chrome instance's chrome://extensions
tab.
However, a point worth noting is that the extension runs in the Cypress's own window scope - not the one inside your test page's iframe. This makes running test commands quite tricky. If you want to access the test instance from the extension you should query the Cypress test <iframe>
element separately. And vice versa, if you want to access the extension's DOM (if it injected something) inside a test should use window.parent.document.querySelector(<my-extension>)
eg:
cy.window().then(async window => {
const el = window.parent.document.querySelector('my-extension') as HTMLElement
expect(el).to.not.be.null
})
Rather than doing this querying mess, it might be better to hook up to the extension's own messages (incase it's passing those) and checking them against your fixtures eg:
cy.window().then(async window => {
cy.stub(window.console, 'warn').as('consoleWarn')
cy.stub(window.console, 'error').as('consoleError')
window.msgs = []
window.addEventListener('message', event => {
console.log('msg', event)
if (
typeof event.data !== 'object' ||
!('source' in event.data) ||
event.data.source !== 'my-extension'
) {
return
}
window.msgs.push(event.data)
})
})
which you can deep equal with eg: cy.window().its('msgs').should('deep.equal', data1)
But anyway, good luck. It's not easy and apparently you can't load the extensions in headless mode (although I haven't tried). (For full disclosure, I myself author an extension https://github.com/TeemuKoivisto/prosemirror-dev-toolkit for which I want to add some tests)