Skip to content
Vitaliy Potapov edited this page Nov 13, 2015 · 2 revisions

What is it?

Mocks for chrome.* extensions api via sinon stubs.

Why this is needed?

To run unit tests for chrome extensions in node or browser

Features

  1. Stubs for all chrome.* methods and properties
  2. Manual events triggering
  3. Plugins to emulate cookies storage, opened tabs, etc

How to install

Npm:

npm install sinon-chrome

Direct download:
sinon-chrome.js

How to use

1.Make chrome global

Node

before(function() {
   global.chrome = require('sinon-chrome');
});

Browser

<script src="...sinon-chrome.js">

2.Write tests

You can use all sinon stub api to create chrome methods behavior.

For example

var domainACookies = [
   {
      name: 'a',
      value: 'b',
      domain: 'domainA.com'
   }
];

var domainBCookies = [
   {
      name: 'b',
      value: 'c',
      domain: 'domainB.com'
   }
];

var allCookies = domainACookies.concat(domainBCookies);

before(function () {
   chrome.cookies.getAll.withArgs({domain: 'domainA.com'}).yields(domainACookies);
   chrome.cookies.getAll.withArgs({domain: 'domainB.com'}).yields(domainBCookies);
   chrome.cookies.getAll.withArgs({}).yields(allCookies);
});

it('should return correct cookies for domain A', function () {
   chrome.cookies.getAll({domain: 'domainA.com'}, function (list) {
      assert.deepEqual(list, domainACookies);
   });
});

it('should return correct cookies for domain B', function () {
   chrome.cookies.getAll({domain: 'domainB.com'}, function (list) {
      assert.deepEqual(list, domainBCookies);
   });
});

it('should return correct cookies for all domains', function () {
   chrome.cookies.getAll({}, function (list) {
      assert.deepEqual(list, allCookies);
   });
});

Properties

You can define chrome api property values.

For example

chrome.runtime.id = 'test';
chrome.runtime.lastError = new Error('some error');
chrome.windows.WINDOW_ID_CURRENT = 100;

console.log(chrome.runtime.id); // test
console.log(chrome.runtime.lastError); // Error: some error(…)
console.log(chrome.windows.WINDOW_ID_CURRENT); // 100

chrome.reset(); // or chrome.flush();

console.log(chrome.runtime.id); // undefined
console.log(chrome.runtime.lastError); // undefined
console.log(chrome.windows.WINDOW_ID_CURRENT); // undefined

Events

You can can manipulate by chrome events by manual triggering with custom params.

For example

var handler = sinon.spy();
chrome.cookies.onChanged.addListener(handler);

chrome.cookies.onChanged.trigger(1, 2, 3);
handler.withArgs(1, 2, 3).callCount; // 1

chrome.cookies.onChanged.trigger(1, 2, 3);
handler.withArgs(1, 2, 3).callCount; // 2

// remove listener
chrome.cookies.onChanged.removeListener(handler);
chrome.cookies.onChanged.trigger(1, 2, 3);
chrome.cookies.onChanged.trigger(1, 2, 3);
handler.withArgs(1, 2, 3).callCount; // 2

To reset stubs data and properties values, you should call chrome.reset.

For example

chrome.tabs.getAll();
chrome.tabs.getAll();

chrome.runtime.id = 'test_id';

console.log(chrome.tabs.getAll.callCount); // 2
console.log(chrome.runtime.id); // test_id

chrome.reset();
console.log(chrome.tabs.getAll.callCount); // 0
console.log(chrome.runtime.id); // undefined

To reset stubs behavior, you should call chrome.flush.

For example

chrome.runtime.getURL.returns('url');
chrome.tabs.query.yields([1, 2, 3]);
console.log(chrome.runtime.getURL()); // url
chrome.tabs.query({}, function tabsHandler(list) {
   console.log(list); // [1, 2, 3]
});

chrome.flush();
console.log(chrome.runtime.getURL()); // undefined
chrome.tabs.query({}, function tabsHandler(list) {
   // unreachable point. Function tabsHandler will never be called
});

Difference from 0.2 version

We remove all predefined properties and behavior. You must define all stubs behavior by your self.

For example

before(function () {
   chrome.runtime.id = 'my_test_id';
   chrome.runtime.getURL = function (path) {
      return 'chrome-extension://' + chrome.runtime.id + '/' + path;
   };
});

Supported namespaces

  1. chrome.alarms
  2. chrome.bookmarks
  3. chrome.browserAction
  4. chrome.browsingData
  5. chrome.certificateProvider
  6. chrome.commands
  7. chrome.contentSettings
  8. chrome.contextMenus
  9. chrome.cookies
  10. chrome.debugger
  11. chrome.declarativeContent
  12. chrome.desktopCapture
  13. chrome.devtools.inspectedWindow
  14. chrome.devtools.network
  15. chrome.devtools.panels
  16. chrome.downloads
  17. chrome.extension
  18. chrome.extensionTypes
  19. chrome.fontSettings
  20. chrome.gcm
  21. chrome.history
  22. chrome.i18n
  23. chrome.identity
  24. chrome.idle
  25. chrome.instanceID
  26. chrome.management
  27. chrome.notifications
  28. chrome.omnibox
  29. chrome.pageAction
  30. chrome.pageCapture
  31. chrome.permissions
  32. chrome.printerProvider
  33. chrome.privacy
  34. chrome.proxy
  35. chrome.runtime
  36. chrome.sessions
  37. chrome.storage
  38. chrome.system.cpu
  39. chrome.system.memory
  40. chrome.system.storage
  41. chrome.tabCapture
  42. chrome.tabs
  43. chrome.topSites
  44. chrome.tts
  45. chrome.ttsEngine
  46. chrome.webNavigation
  47. chrome.webRequest
  48. chrome.windows

Development and pull request.

Fork this repo and install all dependencies. Don't forget check your code style and run tests before send pull request.

code checking

npm run code

run tests

npm test

Any questions?

Feel free to open issue.