diff options
Diffstat (limited to 'e2e')
-rw-r--r-- | e2e/ambassador/manifest.json | 28 | ||||
-rw-r--r-- | e2e/ambassador/src/background/index.js | 36 | ||||
-rw-r--r-- | e2e/ambassador/src/background/ipc.js | 7 | ||||
-rw-r--r-- | e2e/ambassador/src/background/tabs.js | 18 | ||||
-rw-r--r-- | e2e/ambassador/src/client/ipc.js | 29 | ||||
-rw-r--r-- | e2e/ambassador/src/client/keys.js | 29 | ||||
-rw-r--r-- | e2e/ambassador/src/client/tabs.js | 12 | ||||
-rw-r--r-- | e2e/ambassador/src/client/windows.js | 27 | ||||
-rw-r--r-- | e2e/ambassador/src/content/index.js | 37 | ||||
-rw-r--r-- | e2e/ambassador/src/content/ipc.js | 40 | ||||
-rw-r--r-- | e2e/ambassador/src/shared/messages.js | 24 | ||||
-rw-r--r-- | e2e/ambassador/webpack.config.js | 37 | ||||
-rw-r--r-- | e2e/contents/tab.test.js | 48 | ||||
-rw-r--r-- | e2e/karma-delay.js | 10 | ||||
-rw-r--r-- | e2e/karma-webext-launcher.js | 53 | ||||
-rw-r--r-- | e2e/karma.conf.js | 45 | ||||
-rw-r--r-- | e2e/web-server/index.js | 14 |
17 files changed, 494 insertions, 0 deletions
diff --git a/e2e/ambassador/manifest.json b/e2e/ambassador/manifest.json new file mode 100644 index 0000000..d2253f6 --- /dev/null +++ b/e2e/ambassador/manifest.json @@ -0,0 +1,28 @@ +{ + "manifest_version": 2, + "name": "ambassador", + "description": "WebExtension test helper", + "version": "0.1", + "content_scripts": [ + { + "all_frames": true, + "matches": [ "<all_urls>" ], + "js": [ "build/content.js" ], + "run_at": "document_start", + "match_about_blank": true + } + ], + "background": { + "scripts": [ + "build/background.js" + ] + }, + "permissions": [ + "history", + "sessions", + "storage", + "tabs", + "clipboardRead", + "activeTab" + ] +} diff --git a/e2e/ambassador/src/background/index.js b/e2e/ambassador/src/background/index.js new file mode 100644 index 0000000..f9fda7e --- /dev/null +++ b/e2e/ambassador/src/background/index.js @@ -0,0 +1,36 @@ +import { + WINDOWS_CREATE, WINDOWS_REMOVE, WINDOWS_GET, + TABS_CREATE, + EVENT_KEYPRESS, EVENT_KEYDOWN, EVENT_KEYUP, +} from '../shared/messages'; +import * as tabs from './tabs'; +import { receiveContentMessage } from './ipc'; + +receiveContentMessage((message) => { + switch (message.type) { + case WINDOWS_CREATE: + return browser.windows.create({ url: message.url }); + case WINDOWS_REMOVE: + return browser.windows.remove(message.windowId); + case WINDOWS_GET: + return browser.windows.get(message.windowId, { populate: true }); + case TABS_CREATE: + return tabs.create({ + url: message.url, + windowId: message.windowId, + }); + } +}); + + +receiveContentMessage((message) => { + switch (message.type) { + case EVENT_KEYPRESS: + case EVENT_KEYDOWN: + case EVENT_KEYUP: + return browser.tabs.sendMessage( + message.tabId, + message + ); + } +}); diff --git a/e2e/ambassador/src/background/ipc.js b/e2e/ambassador/src/background/ipc.js new file mode 100644 index 0000000..95d2164 --- /dev/null +++ b/e2e/ambassador/src/background/ipc.js @@ -0,0 +1,7 @@ +const receiveContentMessage = (func) => { + browser.runtime.onMessage.addListener((message) => { + return func(message); + }); +}; + +export { receiveContentMessage }; diff --git a/e2e/ambassador/src/background/tabs.js b/e2e/ambassador/src/background/tabs.js new file mode 100644 index 0000000..93d47a3 --- /dev/null +++ b/e2e/ambassador/src/background/tabs.js @@ -0,0 +1,18 @@ +const create = (props = {}) => { + return new Promise((resolve) => { + browser.tabs.create(props).then((createdTab) => { + let callback = (tabId, changeInfo, tab) => { + if (tab.url !== 'about:blank' && tabId === createdTab.id && + changeInfo.status === 'complete') { + browser.tabs.onUpdated.removeListener(callback); + resolve(tab); + } + }; + browser.tabs.onUpdated.addListener(callback); + }); + }); +}; + +export { + create, +}; diff --git a/e2e/ambassador/src/client/ipc.js b/e2e/ambassador/src/client/ipc.js new file mode 100644 index 0000000..9f232ea --- /dev/null +++ b/e2e/ambassador/src/client/ipc.js @@ -0,0 +1,29 @@ +import { METHOD_REQUEST, METHOD_RESPONSE } from '../shared/messages'; + +const generateId = () => { + return Math.random().toString(); +}; + +const send = (message) => { + return new Promise((resolve) => { + let id = generateId(); + let callback = (e) => { + let packet = e.data; + if (e.source !== window || packet.method !== METHOD_RESPONSE || + packet.id !== id) { + return; + } + window.removeEventListener('message', callback); + resolve(packet.message); + }; + window.addEventListener('message', callback); + + window.postMessage({ + id, + method: METHOD_REQUEST, + message + }, window.origin); + }); +}; + +export { send }; diff --git a/e2e/ambassador/src/client/keys.js b/e2e/ambassador/src/client/keys.js new file mode 100644 index 0000000..af0fb3d --- /dev/null +++ b/e2e/ambassador/src/client/keys.js @@ -0,0 +1,29 @@ +import { EVENT_KEYPRESS, EVENT_KEYDOWN, EVENT_KEYUP } from '../shared/messages'; +import * as ipc from './ipc'; + +const press = (tabId, key) => { + return ipc.send({ + type: EVENT_KEYPRESS, + tabId, + key, + }); +}; + +const down = (tabId, key) => { + return ipc.send({ + type: EVENT_KEYDOWN, + tabId, + key, + }); +}; + + +const up = (tabId, key) => { + return ipc.send({ + type: EVENT_KEYUP, + tabId, + key, + }); +}; + +export { press, down, up }; diff --git a/e2e/ambassador/src/client/tabs.js b/e2e/ambassador/src/client/tabs.js new file mode 100644 index 0000000..4db3c11 --- /dev/null +++ b/e2e/ambassador/src/client/tabs.js @@ -0,0 +1,12 @@ +import { TABS_CREATE } from '../shared/messages'; +import * as ipc from './ipc'; + +const create = (windowId, url) => { + return ipc.send({ + type: TABS_CREATE, + windowId, + url, + }); +}; + +export { create }; diff --git a/e2e/ambassador/src/client/windows.js b/e2e/ambassador/src/client/windows.js new file mode 100644 index 0000000..f92405a --- /dev/null +++ b/e2e/ambassador/src/client/windows.js @@ -0,0 +1,27 @@ +import { + WINDOWS_CREATE, WINDOWS_REMOVE, WINDOWS_GET +} from '../shared/messages'; +import * as ipc from './ipc'; + +const create = (url) => { + return ipc.send({ + type: WINDOWS_CREATE, + url, + }); +}; + +const remove = (windowId) => { + return ipc.send({ + type: WINDOWS_REMOVE, + windowId, + }); +}; + +const get = (windowId) => { + return ipc.send({ + type: WINDOWS_GET, + windowId, + }); +}; + +export { create, remove, get }; diff --git a/e2e/ambassador/src/content/index.js b/e2e/ambassador/src/content/index.js new file mode 100644 index 0000000..8573d66 --- /dev/null +++ b/e2e/ambassador/src/content/index.js @@ -0,0 +1,37 @@ +import { + WINDOWS_CREATE, WINDOWS_REMOVE, WINDOWS_GET, + TABS_CREATE, + EVENT_KEYPRESS, EVENT_KEYDOWN, EVENT_KEYUP, +} from '../shared/messages'; +import * as ipc from './ipc'; + +ipc.receivePageMessage((message) => { + switch (message.type) { + case WINDOWS_CREATE: + case WINDOWS_REMOVE: + case WINDOWS_GET: + case TABS_CREATE: + case EVENT_KEYPRESS: + case EVENT_KEYDOWN: + case EVENT_KEYUP: + return ipc.sendToBackground(message); + } +}); + +ipc.receiveBackgroundMesssage((message) => { + switch (message.type) { + case EVENT_KEYPRESS: + document.body.dispatchEvent( + new KeyboardEvent('keypress', { 'key': message.key })); + break; + case EVENT_KEYDOWN: + document.body.dispatchEvent( + new KeyboardEvent('keydown', { 'key': message.key })); + break; + case EVENT_KEYUP: + document.body.dispatchEvent( + new KeyboardEvent('keyup', { 'key': message.key })); + break; + } + return Promise.resolve({}); +}); diff --git a/e2e/ambassador/src/content/ipc.js b/e2e/ambassador/src/content/ipc.js new file mode 100644 index 0000000..917623c --- /dev/null +++ b/e2e/ambassador/src/content/ipc.js @@ -0,0 +1,40 @@ +import { METHOD_REQUEST, METHOD_RESPONSE } from '../shared/messages'; + +const sendToBackground = (message) => { + return browser.runtime.sendMessage(message); +}; + +const receiveBackgroundMesssage = (func) => { + return browser.runtime.onMessage.addListener((message) => { + return Promise.resolve(func(message)); + }); +}; + +const receivePageMessage = (func) => { + window.addEventListener('message', (e) => { + let packet = e.data; + if (e.origin !== window.origin || packet.method !== METHOD_REQUEST) { + return; + } + + let resp = { + id: packet.id, + method: METHOD_RESPONSE, + }; + let respMessage = func(packet.message); + if (respMessage instanceof Promise) { + return respMessage.then((data) => { + resp.message = data; + e.source.postMessage(resp, e.origin); + }); + } else if (respMessage) { + resp.message = respMessage; + } + e.source.postMessage(resp, e.origin); + }); +}; + +export { + sendToBackground, receiveBackgroundMesssage, + receivePageMessage, +}; diff --git a/e2e/ambassador/src/shared/messages.js b/e2e/ambassador/src/shared/messages.js new file mode 100644 index 0000000..32b7aa2 --- /dev/null +++ b/e2e/ambassador/src/shared/messages.js @@ -0,0 +1,24 @@ +const METHOD_REQUEST = 'request'; +const METHOD_RESPONSE = 'response'; +const WINDOWS_CREATE = 'windows.create'; +const WINDOWS_REMOVE = 'windows.remove'; +const WINDOWS_GET = 'windows.get'; +const TABS_CREATE = 'tabs.create'; +const EVENT_KEYPRESS = 'event.keypress'; +const EVENT_KEYDOWN = 'event.keydown'; +const EVENT_KEYUP = 'event.keyup'; + +export { + METHOD_REQUEST, + METHOD_RESPONSE, + + WINDOWS_CREATE, + WINDOWS_REMOVE, + WINDOWS_GET, + + TABS_CREATE, + + EVENT_KEYPRESS, + EVENT_KEYDOWN, + EVENT_KEYUP, +}; diff --git a/e2e/ambassador/webpack.config.js b/e2e/ambassador/webpack.config.js new file mode 100644 index 0000000..2a544bf --- /dev/null +++ b/e2e/ambassador/webpack.config.js @@ -0,0 +1,37 @@ +const path = require('path'); + +const src = path.resolve(__dirname, 'src'); +const dist = path.resolve(__dirname, 'build'); + +config = { + entry: { + content: path.join(src, 'content'), + background: path.join(src, 'background') + }, + + output: { + path: dist, + filename: '[name].js' + }, + + module: { + loaders: [ + { + test: [ /\.js$/ ], + exclude: /node_modules/, + loader: 'babel-loader', + query: { + presets: ['es2015'] + } + } + ] + }, + + resolve: { + extensions: [ '.js' ], + modules: [path.join(__dirname, 'src'), 'node_modules'] + } +}; + +module.exports = config + diff --git a/e2e/contents/tab.test.js b/e2e/contents/tab.test.js new file mode 100644 index 0000000..198bf0a --- /dev/null +++ b/e2e/contents/tab.test.js @@ -0,0 +1,48 @@ +import { expect } from "chai"; +import * as windows from "../ambassador/src/client/windows"; +import * as tabs from "../ambassador/src/client/tabs"; +import * as keys from "../ambassador/src/client/keys"; + +const SERVER_URL = "localhost:11111"; + +describe("tab test", () => { + let targetWindow; + + before(() => { + return windows.create().then((win) => { + targetWindow = win; + }); + }); + + after(() => { + return windows.remove(targetWindow.id); + }); + + describe('press d', () => { + it('deletes tab', () => { + return tabs.create(targetWindow.id, SERVER_URL).then((tab) => { + return keys.press(tab.id, 'd'); + }).then(() => { + return windows.get(targetWindow.id); + }).then((after) => { + expect(after.tabs).to.have.lengthOf(1); + }); + }); + }); + + describe('press zd', () => { + it('duplicates tab', () => { + let targetTab = 0; + return tabs.create(targetWindow.id, SERVER_URL).then((tab) => { + targetTab = tab; + return keys.press(targetTab.id, 'z'); + }).then(() => { + return keys.press(targetTab.id, 'd'); + }).then(() => { + return windows.get(targetWindow.id); + }).then((after) => { + expect(after.tabs).to.have.lengthOf(3); + }); + }); + }) +}); diff --git a/e2e/karma-delay.js b/e2e/karma-delay.js new file mode 100644 index 0000000..7d18c4a --- /dev/null +++ b/e2e/karma-delay.js @@ -0,0 +1,10 @@ +'use strict'; + +window.__karma__.start = (function(start){ +return function(){ + var args = arguments + setTimeout(() => { + start(args) + }, 3000); +}; +}(window.__karma__.start)); diff --git a/e2e/karma-webext-launcher.js b/e2e/karma-webext-launcher.js new file mode 100644 index 0000000..e0a3e42 --- /dev/null +++ b/e2e/karma-webext-launcher.js @@ -0,0 +1,53 @@ +'use strict' + +var fs = require('fs') +var path = require('path') + +var PREFS = { + 'browser.shell.checkDefaultBrowser': 'false', + 'browser.bookmarks.restore_default_bookmarks': 'false', + 'dom.disable_open_during_load': 'false', + 'dom.max_script_run_time': '0', + 'dom.min_background_timeout_value': '10', + 'extensions.autoDisableScopes': '0', + 'extensions.enabledScopes': '15', +} + +var FirefoxWebExt = function (id, baseBrowserDecorator, args) { + baseBrowserDecorator(this) + + this._start = function (url) { + var self = this + var command = this._getCommand() + + let prefArgs = [].concat(...Object.keys(PREFS).map((key) => { + return ['--pref', key + '=' + PREFS[key]]; + })); + let sourceDirArgs = [].concat(...args.sourceDirs.map((dir) => { + return ['--source-dir', dir]; + })); + + self._execCommand( + command, + ['run', '--start-url', url, '--no-input'].concat(sourceDirArgs, prefArgs) + ) + } +} + +FirefoxWebExt.prototype = { + name: 'FirefoxWebExt', + + DEFAULT_CMD: { + linux: 'node_modules/web-ext/bin/web-ext', + darwin: 'node_modules/web-ext/bin/web-ext', + win32: 'node_modules/web-ext/bin/web-ext', + } +} + +FirefoxWebExt.$inject = ['id', 'baseBrowserDecorator', 'args'] + +// PUBLISH DI MODULE +module.exports = { + 'launcher:FirefoxWebExt': ['type', FirefoxWebExt], +} + diff --git a/e2e/karma.conf.js b/e2e/karma.conf.js new file mode 100644 index 0000000..2b60ca9 --- /dev/null +++ b/e2e/karma.conf.js @@ -0,0 +1,45 @@ +module.exports = function (config) { + + config.set({ + basePath: '', + frameworks: ['mocha'], + files: [ + 'karma-delay.js', + '**/*.test.js' + ], + + preprocessors: { + '**/*.test.js': ['webpack'] + }, + + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + + customLaunchers: { + FirefoxWebExtRunner: { + base: 'FirefoxWebExt', + sourceDirs: [ '.', 'e2e/ambassador'], + }, + }, + browsers: ['FirefoxWebExtRunner'], + sauceLabs: { + username: 'michael_jackson' + }, + + singleRun: true, + + webpackMiddleware: { + noInfo: true + }, + + reporters: ['mocha'], + + plugins: [ + require('./karma-webext-launcher'), + 'karma-mocha', + 'karma-webpack', + 'karma-mocha-reporter', + ], + }) +} diff --git a/e2e/web-server/index.js b/e2e/web-server/index.js new file mode 100644 index 0000000..81e11c1 --- /dev/null +++ b/e2e/web-server/index.js @@ -0,0 +1,14 @@ +var http = require('http'); + +const content = +'<!DOCTYPE html>' + +'<html lang="en">' + + '<body style="width:10000px; height:10000px">' + + '</body>' + +'</html">' ; + + +http.createServer(function (req, res) { + res.writeHead(200, {'Content-Type': 'text/html'}); + res.end(content); +}).listen(11111, '127.0.0.1'); |