-
Notifications
You must be signed in to change notification settings - Fork 48
Usage example
Aleksey Tsvetkov edited this page Jan 6, 2016
·
1 revision
Let's create simple chrome extension, that displays opened tabs count.
We need create simple background.js
script for main logic and popup.js
, that displays current tabs count on badge.
Create manifest.json
{
"name": "Opened Tabs List",
"description": "A browser action that displays opened tabs list",
"version": "1.0",
"permissions": [
"tabs"
],
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_popup": "popup.html",
"default_icon": "icon.png"
},
"manifest_version": 2
}
Main logic background.js
/**
* Retrieves opened tabs list
* @param {Function} callback
*/
function getOpenedTabs(callback) {
var params = {
windowId: chrome.windows.WINDOW_ID_CURRENT
};
chrome.tabs.query(params, callback);
}
/**
* Updates browserAction badge
* @param {Array} tabs
*/
function updateBadge(tabs) {
chrome.browserAction.setBadgeText({
text: String(tabs.length)
});
}
/**
* Listen messages from popup
*/
chrome.runtime.onMessage.addListener(function (data, sender, sendResponse) {
if (data === 'get-tabs') {
getOpenedTabs(sendResponse);
return true;
}
});
/**
* listen to new tab creation and update badge counter
*/
chrome.tabs.onCreated.addListener(function () {
getOpenedTabs(updateBadge);
});
/**
* listen tab onRemoved and update badge counter
*/
chrome.tabs.onRemoved.addListener(function () {
getOpenedTabs(updateBadge);
});
/**
* update badge counter on startup
*/
getOpenedTabs(updateBadge);
Create popup page popup.html
<!doctype html>
<html>
<head>
<title></title>
<style>
body {width: 400px;}
</style>
</head>
<body>
<ul id="tabs">
</ul>
<script src="popup.js"></script>
</body>
</html>
And popup logic script popup.js
// request background for opened tabs list
chrome.runtime.sendMessage('get-tabs', function(data) {
var html = [];
var maxLength = 40;
data.forEach(function(tab) {
var title = tab.title.length > maxLength ? tab.title.substring(0, maxLength) + '...' : tab.title;
html.push('<li><a href="#" data-id="' + tab.id + '">' + title + '</a></li>');
});
document.getElementById('tabs').innerHTML = html.join('');
});
// listen click on title to activate tab
document.getElementById('tabs').addEventListener('click', function(e) {
if (e.target.tagName === 'A') {
e.preventDefault();
var tabId = parseInt(e.target.getAttribute('data-id'), 10);
chrome.tabs.update(tabId, {active: true});
}
});
Now we have working extension, that watches user tabs.
Let's test it with sinon-chrome
.
Background specs background.test.js
var fs = require('fs');
var sinon = require('sinon');
var chrome = require('sinon-chrome');
var assert = require('chai').assert;
var jsdom = require('jsdom');
sinon.assert.expose(global.assert, {prefix: ''});
describe('background page', function () {
var window;
beforeEach(function (done) {
jsdom.env({
// generated background page
html: '<html></html>',
// js source
src: [fs.readFileSync('src/background.js', 'utf-8')],
created: function (errors, wnd) {
// attach `chrome` to window
wnd.chrome = chrome;
wnd.console = console;
},
done: function (errors, wnd) {
if (errors) {
console.log(errors);
done(true);
} else {
window = wnd;
done();
}
}
});
});
afterEach(function () {
chrome.reset();
window.close();
});
it('should attach listeners on startup', function () {
assert.calledOnce(chrome.runtime.onMessage.addListener);
assert.calledOnce(chrome.tabs.onCreated.addListener);
assert.calledOnce(chrome.tabs.onRemoved.addListener);
});
it('should update badge on startup', function () {
assert.calledOnce(chrome.tabs.query);
assert.calledOnce(chrome.browserAction.setBadgeText);
assert.calledWithMatch(chrome.browserAction.setBadgeText, {
text: '4'
});
});
it('should return tabs by request from popup', function () {
chrome.tabs.query.reset();
var sendResponse = sinon.spy();
chrome.runtime.onMessage.trigger('get-tabs', {}, sendResponse);
assert.calledOnce(chrome.tabs.query);
assert.calledOnce(sendResponse);
assert.calledWith(sendResponse, sinon.match.array);
assert.calledWith(sendResponse, sinon.match(function (value) {
return value.length === 4;
}));
});
});
And popup.test.js
var fs = require('fs');
var sinon = require('sinon');
var chrome = require('sinon-chrome');
var jsdom = require('jsdom');
var assert = require('chai').assert;
var window;
describe('popup page', function() {
beforeEach(function(done) {
jsdom.env({
// popup
file: 'src/popup.html',
// js source
src: [fs.readFileSync('src/popup.js', 'utf-8')],
created: function (errors, wnd) {
if (errors) {
console.log(errors);
return done(true);
}
// attach `chrome` to window
wnd.chrome = chrome;
wnd.console = console;
// fake tabs response
chrome.runtime.sendMessage.yields([
{id: 1, title: 'tab 1'},
{id: 2, title: 'tab 2'}
]);
},
done: function (errors, wnd) {
if (errors) {
console.log(errors);
return done(true);
}
window = wnd;
done();
}
});
});
afterEach(function() {
chrome.reset();
window.close();
});
it('should request tabs and render response on startup', function() {
assert.calledOnce(chrome.runtime.sendMessage);
var html = '<li><a href="#" data-id="1">tab 1</a></li><li><a href="#" data-id="2">tab 2</a></li>';
assert.equal(window.document.getElementById('tabs').innerHTML, html);
});
});
Test with pleasure :)