diff options
Diffstat (limited to 'e2e')
-rw-r--r-- | e2e/ambassador/manifest.json | 28 | ||||
-rw-r--r-- | e2e/ambassador/src/background/index.js | 42 | ||||
-rw-r--r-- | e2e/ambassador/src/background/ipc.js | 7 | ||||
-rw-r--r-- | e2e/ambassador/src/background/tabs.js | 26 | ||||
-rw-r--r-- | e2e/ambassador/src/client/ipc.js | 29 | ||||
-rw-r--r-- | e2e/ambassador/src/client/keys.js | 31 | ||||
-rw-r--r-- | e2e/ambassador/src/client/scrolls.js | 20 | ||||
-rw-r--r-- | e2e/ambassador/src/client/tabs.js | 37 | ||||
-rw-r--r-- | e2e/ambassador/src/client/windows.js | 27 | ||||
-rw-r--r-- | e2e/ambassador/src/content/events.js | 31 | ||||
-rw-r--r-- | e2e/ambassador/src/content/index.js | 30 | ||||
-rw-r--r-- | e2e/ambassador/src/content/ipc.js | 40 | ||||
-rw-r--r-- | e2e/ambassador/src/content/scrolls.js | 20 | ||||
-rw-r--r-- | e2e/ambassador/src/shared/messages.js | 34 | ||||
-rw-r--r-- | e2e/ambassador/webpack.config.js | 24 | ||||
-rw-r--r-- | e2e/contents/scroll.test.js | 151 | ||||
-rw-r--r-- | e2e/contents/tab.test.js | 216 | ||||
-rw-r--r-- | e2e/contents/zoom.test.js | 72 | ||||
-rw-r--r-- | e2e/karma-delay.js | 10 | ||||
-rw-r--r-- | e2e/karma-webext-launcher.js | 53 | ||||
-rw-r--r-- | e2e/karma.conf.js | 51 | ||||
-rw-r--r-- | e2e/web-server/index.js | 14 |
22 files changed, 993 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..db2deb3 --- /dev/null +++ b/e2e/ambassador/src/background/index.js @@ -0,0 +1,42 @@ +import { + WINDOWS_CREATE, WINDOWS_REMOVE, WINDOWS_GET, + TABS_CREATE, TABS_SELECT_AT, TABS_GET_ZOOM, TABS_SET_ZOOM, + EVENT_KEYPRESS, EVENT_KEYDOWN, EVENT_KEYUP, + SCROLL_GET, SCROLL_SET, +} 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, + }); + case TABS_SELECT_AT: + return tabs.selectAt({ + windowId: message.windowId, + index: message.index, + }); + case TABS_GET_ZOOM: + return browser.tabs.getZoom(message.tabId); + case TABS_SET_ZOOM: + return browser.tabs.setZoom(message.tabId, message.factor); + case EVENT_KEYPRESS: + case EVENT_KEYDOWN: + case EVENT_KEYUP: + case SCROLL_GET: + case SCROLL_SET: + 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..d049500 --- /dev/null +++ b/e2e/ambassador/src/background/tabs.js @@ -0,0 +1,26 @@ +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); + }); + }); +}; + +const selectAt = (props = {}) => { + return browser.tabs.query({ windowId: props.windowId }).then((tabs) => { + let target = tabs[props.index]; + return browser.tabs.update(target.id, { active: true }); + }); +}; + + +export { + create, selectAt +}; 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..37b9c0a --- /dev/null +++ b/e2e/ambassador/src/client/keys.js @@ -0,0 +1,31 @@ +import { EVENT_KEYPRESS, EVENT_KEYDOWN, EVENT_KEYUP } from '../shared/messages'; +import * as ipc from './ipc'; + +const NEUTRAL_MODIFIERS = { shiftKey: false, altKey: false, ctrlKey: false }; + +const press = (tabId, key, modifiers = NEUTRAL_MODIFIERS) => { + return ipc.send(Object.assign({}, modifiers, { + type: EVENT_KEYPRESS, + tabId, + key, + })); +}; + +const down = (tabId, key, modifiers = NEUTRAL_MODIFIERS) => { + return ipc.send(Object.assign({}, modifiers, { + type: EVENT_KEYDOWN, + tabId, + key, + })); +}; + + +const up = (tabId, key, modifiers = NEUTRAL_MODIFIERS) => { + return ipc.send(Object.assign({}, modifiers, { + type: EVENT_KEYUP, + tabId, + key, + })); +}; + +export { press, down, up }; diff --git a/e2e/ambassador/src/client/scrolls.js b/e2e/ambassador/src/client/scrolls.js new file mode 100644 index 0000000..f8f82e9 --- /dev/null +++ b/e2e/ambassador/src/client/scrolls.js @@ -0,0 +1,20 @@ +import { SCROLL_GET, SCROLL_SET } from '../shared/messages'; +import * as ipc from './ipc'; + +const get = (tabId) => { + return ipc.send({ + type: SCROLL_GET, + tabId, + }); +}; + +const set = (tabId, x, y) => { + return ipc.send({ + type: SCROLL_SET, + tabId, + x, + y, + }); +}; + +export { get, set }; diff --git a/e2e/ambassador/src/client/tabs.js b/e2e/ambassador/src/client/tabs.js new file mode 100644 index 0000000..c7b1340 --- /dev/null +++ b/e2e/ambassador/src/client/tabs.js @@ -0,0 +1,37 @@ +import { + TABS_CREATE, TABS_SELECT_AT, TABS_GET_ZOOM, TABS_SET_ZOOM, +} from '../shared/messages'; +import * as ipc from './ipc'; + +const create = (windowId, url) => { + return ipc.send({ + type: TABS_CREATE, + windowId, + url, + }); +}; + +const selectAt = (windowId, index) => { + return ipc.send({ + type: TABS_SELECT_AT, + windowId, + index, + }); +}; + +const getZoom = (tabId) => { + return ipc.send({ + tabId, + type: TABS_GET_ZOOM, + }); +}; + +const setZoom = (tabId, factor) => { + return ipc.send({ + type: TABS_SET_ZOOM, + tabId, + factor, + }); +}; + +export { create, selectAt, getZoom, setZoom }; 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/events.js b/e2e/ambassador/src/content/events.js new file mode 100644 index 0000000..1e45909 --- /dev/null +++ b/e2e/ambassador/src/content/events.js @@ -0,0 +1,31 @@ +const keypress = (opts) => { + let event = new KeyboardEvent('keypress', { + key: opts.key, + altKey: opts.altKey, + shiftKey: opts.shiftKey, + ctrlKey: opts.ctrlKey + }); + document.body.dispatchEvent(event); +}; + +const keydown = (opts) => { + let event = new KeyboardEvent('keydown', { + key: opts.key, + altKey: opts.altKey, + shiftKey: opts.shiftKey, + ctrlKey: opts.ctrlKey + }); + document.body.dispatchEvent(event); +}; + +const keyup = (opts) => { + let event = new KeyboardEvent('keyup', { + key: opts.key, + altKey: opts.altKey, + shiftKey: opts.shiftKey, + ctrlKey: opts.ctrlKey + }); + document.body.dispatchEvent(event); +}; + +export { keypress, keydown, keyup }; diff --git a/e2e/ambassador/src/content/index.js b/e2e/ambassador/src/content/index.js new file mode 100644 index 0000000..fd19136 --- /dev/null +++ b/e2e/ambassador/src/content/index.js @@ -0,0 +1,30 @@ +import { + EVENT_KEYPRESS, EVENT_KEYDOWN, EVENT_KEYUP, + SCROLL_GET, SCROLL_SET, +} from '../shared/messages'; +import * as ipc from './ipc'; +import * as events from './events'; +import * as scrolls from './scrolls'; + +ipc.receivePageMessage((message) => { + return ipc.sendToBackground(message); +}); + +ipc.receiveBackgroundMesssage((message) => { + switch (message.type) { + case EVENT_KEYPRESS: + events.keypress(message); + break; + case EVENT_KEYDOWN: + events.keydown(message); + break; + case EVENT_KEYUP: + events.keyup(message); + break; + case SCROLL_GET: + return Promise.resolve(scrolls.get()); + case SCROLL_SET: + return Promise.resolve(scrolls.set(message.x, message.y)); + } + 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/content/scrolls.js b/e2e/ambassador/src/content/scrolls.js new file mode 100644 index 0000000..4227cf7 --- /dev/null +++ b/e2e/ambassador/src/content/scrolls.js @@ -0,0 +1,20 @@ +const get = () => { + let element = document.documentElement; + return { + xMax: element.scrollWidth - element.clientWidth, + yMax: element.scrollHeight - element.clientHeight, + x: element.scrollLeft, + y: element.scrollTop, + frameWidth: element.clientWidth, + frameHeight: element.clientHeight, + }; +}; + +const set = (x, y) => { + let element = document.documentElement; + element.scrollLeft = x; + element.scrollTop = y; + return get(); +}; + +export { get, set }; diff --git a/e2e/ambassador/src/shared/messages.js b/e2e/ambassador/src/shared/messages.js new file mode 100644 index 0000000..1fc47d2 --- /dev/null +++ b/e2e/ambassador/src/shared/messages.js @@ -0,0 +1,34 @@ +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 TABS_SELECT_AT = 'tabs.selectAt'; +const TABS_GET_ZOOM = 'tabs.get.zoom'; +const TABS_SET_ZOOM = 'tabs.set.zoom'; +const EVENT_KEYPRESS = 'event.keypress'; +const EVENT_KEYDOWN = 'event.keydown'; +const EVENT_KEYUP = 'event.keyup'; +const SCROLL_GET = 'scroll.get'; +const SCROLL_SET = 'scroll.set'; + +export { + METHOD_REQUEST, + METHOD_RESPONSE, + + WINDOWS_CREATE, + WINDOWS_REMOVE, + WINDOWS_GET, + + TABS_CREATE, + TABS_SELECT_AT, + TABS_GET_ZOOM, + TABS_SET_ZOOM, + + EVENT_KEYPRESS, + EVENT_KEYDOWN, + EVENT_KEYUP, + SCROLL_GET, + SCROLL_SET, +}; diff --git a/e2e/ambassador/webpack.config.js b/e2e/ambassador/webpack.config.js new file mode 100644 index 0000000..d292317 --- /dev/null +++ b/e2e/ambassador/webpack.config.js @@ -0,0 +1,24 @@ +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' + }, + + resolve: { + extensions: [ '.js' ], + modules: [path.join(__dirname, 'src'), 'node_modules'] + } +}; + +module.exports = config + diff --git a/e2e/contents/scroll.test.js b/e2e/contents/scroll.test.js new file mode 100644 index 0000000..070529a --- /dev/null +++ b/e2e/contents/scroll.test.js @@ -0,0 +1,151 @@ +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"; +import * as scrolls from "../ambassador/src/client/scrolls"; + +const SERVER_URL = "localhost:11111"; + +describe("scroll test", () => { + let targetWindow; + let targetTab; + + before(() => { + return windows.create().then((win) => { + targetWindow = win; + return tabs.create(targetWindow.id, SERVER_URL); + }).then((tab) => { + targetTab = tab; + }); + }); + + after(() => { + return windows.remove(targetWindow.id); + }); + + it('scrolls up by k', () => { + let before + return scrolls.set(targetTab.id, 100, 100).then((scroll) => { + before = scroll; + return keys.press(targetTab.id, 'k'); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.y).to.be.lessThan(before.y); + }); + }); + + it('scrolls down by j', () => { + let before + return scrolls.set(targetTab.id, 100, 100).then((scroll) => { + before = scroll; + return keys.press(targetTab.id, 'j'); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.y).to.be.greaterThan(before.y); + }); + }); + + it('scrolls left by h', () => { + let before + return scrolls.set(targetTab.id, 100, 100).then((scroll) => { + before = scroll; + return keys.press(targetTab.id, 'h'); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.x).to.be.lessThan(before.x); + }); + }); + + it('scrolls top by gg', () => { + return scrolls.set(targetTab.id, 100, 100).then((scroll) => { + return keys.press(targetTab.id, 'g'); + }).then(() => { + return keys.press(targetTab.id, 'g'); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.y).to.be.equals(0); + }); + }); + + it('scrolls bottom by G', () => { + return scrolls.set(targetTab.id, 100, 100).then((scroll) => { + return keys.press(targetTab.id, 'G', { shiftKey: true }); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.y).to.be.equals(actual.yMax); + }); + }); + + it('scrolls bottom by 0', () => { + return scrolls.set(targetTab.id, 100, 100).then((scroll) => { + return keys.press(targetTab.id, '0'); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.x).to.be.equals(0); + }); + }); + + it('scrolls bottom by $', () => { + return scrolls.set(targetTab.id, 100, 100).then((scroll) => { + return keys.press(targetTab.id, '$'); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.x).to.be.equals(actual.xMax); + }); + }); + + it('scrolls bottom by <C-U>', () => { + let before + return scrolls.set(targetTab.id, 5000, 5000).then((scroll) => { + before = scroll; + return keys.press(targetTab.id, 'u', { ctrlKey: true }); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.y).to.closeTo(before.y - before.frameHeight / 2, 1); + }); + }); + + it('scrolls bottom by <C-D>', () => { + let before + return scrolls.set(targetTab.id, 5000, 5000).then((scroll) => { + before = scroll; + return keys.press(targetTab.id, 'd', { ctrlKey: true }); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.y).to.closeTo(before.y + before.frameHeight / 2, 1); + }); + }); + + it('scrolls bottom by <C-B>', () => { + let before + return scrolls.set(targetTab.id, 5000, 5000).then((scroll) => { + before = scroll; + return keys.press(targetTab.id, 'b', { ctrlKey: true }); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.y).to.equals(before.y - before.frameHeight); + }); + }); + + it('scrolls bottom by <C-F>', () => { + let before + return scrolls.set(targetTab.id, 5000, 5000).then((scroll) => { + before = scroll; + return keys.press(targetTab.id, 'f', { ctrlKey: true }); + }).then(() => { + return scrolls.get(targetTab.id); + }).then((actual) => { + expect(actual.y).to.equals(before.y + before.frameHeight); + }); + }); +}); diff --git a/e2e/contents/tab.test.js b/e2e/contents/tab.test.js new file mode 100644 index 0000000..4374907 --- /dev/null +++ b/e2e/contents/tab.test.js @@ -0,0 +1,216 @@ +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; + + beforeEach(() => { + return windows.create(SERVER_URL).then((win) => { + targetWindow = win; + }); + }); + + afterEach(() => { + return windows.remove(targetWindow.id); + }); + + it('deletes tab by d', () => { + let before; + let targetTab; + return tabs.create(targetWindow.id, SERVER_URL).then((tab) => { + targetTab = tab; + return windows.get(targetWindow.id); + }).then((win) => { + before = win; + return keys.press(targetTab.id, 'd'); + }).then(() => { + return windows.get(targetWindow.id); + }).then((actual) => { + expect(actual.tabs).to.have.lengthOf(before.tabs.length - 1); + }); + }); + + it('duplicates tab by zd', () => { + let before; + let targetTab; + return tabs.create(targetWindow.id, SERVER_URL).then((tab) => { + targetTab = tab; + return windows.get(targetWindow.id) + }).then((win) => {; + before = win; + return keys.press(targetTab.id, 'z'); + }).then(() => { + return keys.press(targetTab.id, 'd'); + }).then(() => { + return windows.get(targetWindow.id); + }).then((actual) => { + expect(actual.tabs).to.have.lengthOf(before.tabs.length + 1); + }); + }) + + it('makes pinned by zp', () => { + let before; + let targetTab; + return tabs.create(targetWindow.id, SERVER_URL).then((tab) => { + targetTab = tab; + return windows.get(targetWindow.id) + }).then((win) => {; + before = win; + return keys.press(targetTab.id, 'z'); + }).then(() => { + return keys.press(targetTab.id, 'p'); + }).then(() => { + return windows.get(targetWindow.id); + }).then((actual) => { + expect(actual.tabs[0].pinned).to.be.true; + }); + }) + + it('selects previous tab by K', () => { + return Promise.resolve().then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#1') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#2') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#3'); + }).then(() => { + return tabs.selectAt(targetWindow.id, 2); + }).then((tab) => { + return keys.press(tab.id, 'K', { shiftKey: true }); + }).then(() => { + return windows.get(targetWindow.id); + }).then((win) => { + expect(win.tabs[1].active).to.be.true; + }); + }); + + it('selects previous tab by K rotatory', () => { + return Promise.resolve().then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#1') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#2') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#3'); + }).then(() => { + return tabs.selectAt(targetWindow.id, 0); + }).then((tab) => { + return keys.press(tab.id, 'K', { shiftKey: true }); + }).then(() => { + return windows.get(targetWindow.id); + }).then((win) => { + expect(win.tabs[3].active).to.be.true; + }); + }); + + it('selects next tab by J', () => { + return Promise.resolve().then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#1') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#2') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#3'); + }).then(() => { + return tabs.selectAt(targetWindow.id, 2); + }).then((tab) => { + return keys.press(tab.id, 'J', { shiftKey: true }); + }).then(() => { + return windows.get(targetWindow.id); + }).then((win) => { + expect(win.tabs[3].active).to.be.true; + }); + }); + + it('selects previous tab by J rotatory', () => { + return Promise.resolve().then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#1') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#2') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#3'); + }).then(() => { + return tabs.selectAt(targetWindow.id, 3); + }).then((tab) => { + return keys.press(tab.id, 'J', { shiftKey: true }); + }).then(() => { + return windows.get(targetWindow.id); + }).then((win) => { + expect(win.tabs[0].active).to.be.true; + }); + }); + + it('selects first tab by g0', () => { + return Promise.resolve().then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#1') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#2') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#3'); + }).then(() => { + return tabs.selectAt(targetWindow.id, 2); + }).then((tab) => { + return keys.press(tab.id, 'g').then(() => tab); + }).then((tab) => { + return keys.press(tab.id, '0'); + }).then(() => { + return windows.get(targetWindow.id); + }).then((win) => { + expect(win.tabs[0].active).to.be.true; + }); + }); + + it('selects last tab by g$', () => { + return Promise.resolve().then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#1') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#2') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#3'); + }).then(() => { + return tabs.selectAt(targetWindow.id, 2); + }).then((tab) => { + return keys.press(tab.id, 'g').then(() => tab); + }).then((tab) => { + return keys.press(tab.id, '$'); + }).then(() => { + return windows.get(targetWindow.id); + }).then((win) => { + expect(win.tabs[3].active).to.be.true; + }); + }); + + it('selects last selected tab by <C-6>', () => { + return Promise.resolve().then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#1') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#2') + }).then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#3'); + }).then(() => { + return tabs.selectAt(targetWindow.id, 1); + }).then(() => { + return tabs.selectAt(targetWindow.id, 3); + }).then((tab) => { + return keys.press(tab.id, '6', { ctrlKey: true }); + }).then(() => { + return windows.get(targetWindow.id); + }).then((win) => { + expect(win.tabs[1].active).to.be.true; + }); + }); + + it('deletes tab by d', () => { + return Promise.resolve().then(() => { + return tabs.create(targetWindow.id, SERVER_URL + '#1'); + }).then((tab) => { + return keys.press(tab.id, 'd'); + }).then(() => { + return windows.get(targetWindow.id); + }).then((win) => { + expect(win.tabs).to.have.lengthOf(1); + }); + }); +}); diff --git a/e2e/contents/zoom.test.js b/e2e/contents/zoom.test.js new file mode 100644 index 0000000..603e0b6 --- /dev/null +++ b/e2e/contents/zoom.test.js @@ -0,0 +1,72 @@ +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("zoom test", () => { + let targetWindow; + let targetTab; + + before(() => { + return windows.create(SERVER_URL).then((win) => { + targetWindow = win; + }); + }); + + after(() => { + return windows.remove(targetWindow.id); + }); + + beforeEach(() => { + return tabs.create(targetWindow.id, SERVER_URL).then((tab) => { + targetTab = tab; + }); + }); + + it('zooms-in by zi', () => { + let before; + return tabs.getZoom(targetTab.id).then((zoom) => { + before = zoom; + return keys.press(targetTab.id, 'z'); + }).then(() => { + return keys.press(targetTab.id, 'i'); + }).then(() => { + return tabs.getZoom(targetTab.id); + }).then((actual) => { + expect(actual).to.be.greaterThan(before); + }); + }); + + it('zooms-in by zo', () => { + let before; + return tabs.getZoom(targetTab.id).then((zoom) => { + before = zoom; + return keys.press(targetTab.id, 'z'); + }).then(() => { + return keys.press(targetTab.id, 'o'); + }).then(() => { + return tabs.getZoom(targetTab.id); + }).then((actual) => { + expect(actual).to.be.lessThan(before); + }); + }); + + it('zooms-in by zz', () => { + let before; + tabs.setZoom(targetTab.id, 1.5).then(() => { + return tabs.getZoom(targetTab.id); + }).then((zoom) => { + before = zoom; + return keys.press(targetTab.id, 'z'); + }).then(() => { + return keys.press(targetTab.id, 'z'); + }).then(() => { + return tabs.getZoom(targetTab.id); + }).then((actual) => { + expect(actual).to.be.lessThan(before); + expect(actual).to.be.be(1); + }); + }); +}); 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..5ef4646 --- /dev/null +++ b/e2e/karma.conf.js @@ -0,0 +1,51 @@ +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', + ], + + client: { + mocha: { + timeout: 5000 + } + } + }) +} 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'); |