I am working on a Chrome Extension and it is working as expected locally. When I load the extension in the Cypress testing browser, and ensure that it is on, the extension does not seem to do anything.
Here is a MWE:
public/manifest.json
{
"manifest_version": 2,
"name": "name",
"version": "0.1.0",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"background": {
"scripts": ["background.js"]
},
"permissions": ["tabs", "http://*/"],
"browser_action": {
"default_icon": "logo192.png",
"default_title": "title"
}
}
public/content.js
// background script sends a response once it receives a message from App.js (see below)
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
window.postMessage({ msg: "hi" }, "http://localhost:3000");
});
src/App.js
import React, { useEffect } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Button } from "react-bootstrap";
export default function App() {
useEffect(() => {
function triggerEvent(e) {
if (e.source !== window) return;
alert("here");
}
window.addEventListener("message", (e) => triggerEvent(e));
// cleanup event listener
return () => {
window.removeEventListener("message", (e) => triggerEvent(e));
};
});
function sendMessage() {
chrome.runtime.sendMessage("extension_id", {msg: "hi"});
}
return (
<Button id="amazing-btn" variant="primary" type="button" onClick={()=>sendMessage()}>
button
</Button>
);
}
cypress.json
{
"baseUrl": "http://localhost:3000"
}
cypress/plugins/index.js
/// <reference types="cypress" />
module.exports = (on, config) => {
require("@cypress/code-coverage/task")(on, config);
// load extension into cypress browser
on("before:browser:launch", (browser, launchOptions) => {
launchOptions.extensions.push("full/path/to/my/public/folder");
return launchOptions;
});
return config;
};
I checked and this correctly loads and turns on the extension in Cypress' testing browser.
cypress/integration/App.spec.js
/// <reference types="cypress" />
describe("App Tests", () => {
beforeEach(() => {
cy.visit(Cypress.config().baseUrl);
});
it("renders everything", () => {
cy.get("#amazing-btn");
});
it("clicks button", () => {
// should see an alert in the Cypress timeline after click, but none is shown
cy.get("#amazing-btn").click();
});
});
Issue:
On the cypress browser (not locally) the content script does not seem to send the message to the react application properly as I do not see anything being alerted in from the application side (App.js).
What confuses me the most is that this works locally but not in the cypress browser. I do see that my background script is able to communicate with the content script (in cypress) but this final bridge between content and application is what prevents me from continuing with the testing.
Any idea why this is happening?
I figured out how to bypass the button click to directly send the message to my react application through Cypress with stubbed information and it works!
To complete the coverage I modified my code to not run the function if it the window that the message is sent from includes the cypress browser URL and simply added a click event in my test case.
Hope this helps someone who gets stuck in the same spot.