My latest project involves creating a simple chrome extension that utilizes message passing. The goal of the extension is to listen for messages from a specific website (in this case, localhost:8080/*
) and respond with a simple "Bye". To test this functionality, Selenium opens a locally served page in Chrome, attempts to send a message to the extension, and then displays the response in the console:
$ tree -I node_modules
.
├── extension
│ ├── background.js
│ └── manifest.json
├── package.json
└── test
├── index.html
└── selenium-test.js
2 directories, 5 files
background.js
chrome.runtime.onMessage.addListener(
function (req, sender, sendResp) {
sendResp('Bye');
});
manifest.json
{
"name": "chrome-test",
"version": "0.1",
"manifest_version": 2,
"key": "pcoogjpilcclcmejpkmbifdbihomlgec",
"description": "Test extension.",
"app": {
"background": {
"scripts": ["background.js"],
"persistent": true
}
},
"externally_connectable": {
"matches": [
"http://localhost:8080/*"
],
"accepts_tls_channel_id": false
},
"permissions": [
"http://localhost:8080/*"
]
}
package.json
{
"name": "chrome-test",
"version": "0.0.5",
"description": "Chrome API sucks.",
"keywords": [ "" ],
"author": "Chris Perivolaropoulos",
"contributors": [],
"dependencies": {
"selenium-webdriver": "*",
"mocha": "*",
"chai": "*"
},
"scripts": {
"test": "mocha test/selenium-test.js"
}
}
index.html
<html>
<head>
<title>Test page</title>
</head>
<body>
<h1>Test page</h1>
<div id="echo"></div>
<script type="text/javascript">
chrome.runtime.sendMessage('pcoogjpilcclcmejpkmbifdbihomlgec', 'hello',
function (msg) {
console.log("Received! " + msg);
});
</script>
</body>
</html>
selenium-test.js
var assert = require('chai').assert,
test = require('selenium-webdriver/testing'),
webdriver = require('selenium-webdriver'),
chromedriver = require('selenium-webdriver/chrome');
// @param extensions: string of unpacked extension path to install.
function chrome_driver(extension) {
var logperfs = new webdriver.logging.Preferences(),
opts = new chromedriver.Options().
addArguments("--load-extension=" + extension ||
'../extension');
logperfs.setLevel(webdriver.logging.Type.BROWSER,
webdriver.logging.Level.ALL);
var chrome = new webdriver.Builder().
withCapabilities(webdriver.Capabilities.chrome()).
setChromeOptions(opts).
setLoggingPrefs(logperfs).
build();
chrome.manage().timeouts().pageLoadTimeout(5000);
return chrome;
}
function browser_logs(driver, callback) {
driver.manage().logs().
get(webdriver.logging.Type.BROWSER).then(callback);
}
test.describe('Test', function() {
var chrome;
this.timeout(10000);
test.before(function() {
chrome = chrome_driver("extension");
});
test.it("Test messages", function () {
chrome.get("http://localhost:8080/test/index.html").then(function () {
browser_logs(chrome, function (entries) {
entries.forEach(function (e) {console.log("BrowserLog: " + e.message);});
assert.equal(entries.pop().message,
"hello", "Bus not echoing.");
});
});
});
test.after(function() {
chrome.quit();
});
});
To run a test first run a local http server
$ python -m SimpleHTTPServer 8080
Serving HTTP on 0.0.0.0 port 8080 ...
and from another console run the tests
$ npm test
> <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="27444f55484a420a53425453671709170912">[email protected]</a> test /path/to/project
> mocha test/selenium-test.js
Test
BrowserLog: http://localhost:8080/test/index.html 11:15 Received! undefined
[2K[0G 1) Test messages
0 passing (1s)
1 failing
1) Test Test messages:
Bus not echoing.
+ expected - actual
+hello
-http://localhost:8080/test/index.html 11:15 Receviced! undefined
at /path/to/project/test/selenium-test.js:43:12
at /path/to/project/node_modules/selenium-webdriver/lib/goog/base.js:1582:15
at webdriver.promise.ControlFlow.runInNewFrame_ (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:1640:20)
at notify (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:444:12)
at notifyAll (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:422:7)
at resolve (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:400:7)
at fulfill (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:512:5)
at Object.webdriver.promise.asap (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:758:5)
at webdriver.promise.ControlFlow.runInNewFrame_ (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:1651:25)
at notify (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:444:12)
at notifyAll (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:422:7)
at resolve (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:400:7)
at fulfill (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:512:5)
at Object.webdriver.promise.asap (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/promise.js:758:5)
at webdriver.promise.ControlFlow.runInNewFrame_ (/path/to/project/node_modules/selenium-webdriver/lib/webdriver/prompt...
npm ERR! Test failed. See above for more details.
The extension always responds undefined
instead of 'Bye'
as instructed in background.js.