commit
e9a6fb8558
13 changed files with 479 additions and 64 deletions
|
@ -4,7 +4,7 @@ jobs:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:9-stretch-browsers
|
- image: circleci/node:9-stretch-browsers
|
||||||
environment:
|
environment:
|
||||||
- FIREFOX_VERSION: "59.0b9"
|
- FIREFOX_VERSION: "59.0.3"
|
||||||
working_directory: ~
|
working_directory: ~
|
||||||
steps:
|
steps:
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
|
@ -42,4 +42,4 @@ jobs:
|
||||||
- run: npm run package
|
- run: npm run package
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: npm run ambassador:build
|
- run: npm run ambassador:build
|
||||||
- run: node e2e/web-server & npm run test:e2e
|
- run: node >/dev/null e2e/web-server & npm run test:e2e
|
||||||
|
|
14
QA.md
14
QA.md
|
@ -21,19 +21,9 @@ The behaviors of the console are tested in [Console section](#consoles).
|
||||||
|
|
||||||
#### Tabs
|
#### Tabs
|
||||||
|
|
||||||
- [ ] <kbd>!d</kbd>: delete current tab and pinned tab
|
|
||||||
- [ ] <kbd>u</kbd>: reopen close tab
|
|
||||||
- [ ] <kbd>r</kbd>: reload current tab
|
- [ ] <kbd>r</kbd>: reload current tab
|
||||||
- [ ] <kbd>R</kbd>: reload current tab without cache
|
- [ ] <kbd>R</kbd>: reload current tab without cache
|
||||||
|
|
||||||
#### Navigation
|
|
||||||
|
|
||||||
- [ ] <kbd>H</kbd>, <kbd>L</kbd>: go back and forward in history
|
|
||||||
- [ ] <kbd>[</kbd><kbd>[</kbd>, <kbd>]</kbd><kbd>]</kbd>: Open next/prev link in `<link>` tags.
|
|
||||||
- [ ] <kbd>[</kbd><kbd>[</kbd>, <kbd>]</kbd><kbd>]</kbd>: find prev and next links and open it
|
|
||||||
- [ ] <kbd>g</kbd><kbd>u</kbd>: go to parent directory
|
|
||||||
- [ ] <kbd>g</kbd><kbd>U</kbd>: go to root directory
|
|
||||||
|
|
||||||
#### Misc
|
#### Misc
|
||||||
|
|
||||||
- [ ] <kbd>y</kbd>: yank current URL and show a message
|
- [ ] <kbd>y</kbd>: yank current URL and show a message
|
||||||
|
@ -44,10 +34,6 @@ The behaviors of the console are tested in [Console section](#consoles).
|
||||||
|
|
||||||
### Following links
|
### Following links
|
||||||
|
|
||||||
- [ ] <kbd>f</kbd>: start following links
|
|
||||||
- [ ] <kbd>F</kbd>: start following links and open in new tab
|
|
||||||
- [ ] open link with target='_blank' in new tab by <kbd>f</kbd>
|
|
||||||
- [ ] open link with target='_blank' in new tab by <kbd>F</kbd>
|
|
||||||
- [ ] Show hints on following on a page containing `<frame>`/`<iframe>`
|
- [ ] Show hints on following on a page containing `<frame>`/`<iframe>`
|
||||||
- [ ] Show hints only inside viewport of the frame on following on a page containing `<frame>`/`<iframe>`
|
- [ ] Show hints only inside viewport of the frame on following on a page containing `<frame>`/`<iframe>`
|
||||||
- [ ] Show hints only inside top window on following on a page containing `<frame>`/`<iframe>`
|
- [ ] Show hints only inside top window on following on a page containing `<frame>`/`<iframe>`
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {
|
import {
|
||||||
WINDOWS_CREATE, WINDOWS_REMOVE, WINDOWS_GET,
|
WINDOWS_CREATE, WINDOWS_REMOVE, WINDOWS_GET,
|
||||||
TABS_CREATE, TABS_SELECT_AT, TABS_GET_ZOOM, TABS_SET_ZOOM,
|
TABS_CREATE, TABS_SELECT_AT, TABS_GET, TABS_UPDATE,
|
||||||
|
TABS_GET_ZOOM, TABS_SET_ZOOM,
|
||||||
EVENT_KEYPRESS, EVENT_KEYDOWN, EVENT_KEYUP,
|
EVENT_KEYPRESS, EVENT_KEYDOWN, EVENT_KEYUP,
|
||||||
SCROLL_GET, SCROLL_SET,
|
SCROLL_GET, SCROLL_SET,
|
||||||
} from '../shared/messages';
|
} from '../shared/messages';
|
||||||
|
@ -25,6 +26,10 @@ receiveContentMessage((message) => {
|
||||||
windowId: message.windowId,
|
windowId: message.windowId,
|
||||||
index: message.index,
|
index: message.index,
|
||||||
});
|
});
|
||||||
|
case TABS_GET:
|
||||||
|
return browser.tabs.get(message.tabId);
|
||||||
|
case TABS_UPDATE:
|
||||||
|
return browser.tabs.update(message.tabId, message.properties);
|
||||||
case TABS_GET_ZOOM:
|
case TABS_GET_ZOOM:
|
||||||
return browser.tabs.getZoom(message.tabId);
|
return browser.tabs.getZoom(message.tabId);
|
||||||
case TABS_SET_ZOOM:
|
case TABS_SET_ZOOM:
|
||||||
|
|
|
@ -5,7 +5,9 @@ const create = (props = {}) => {
|
||||||
if (tab.url !== 'about:blank' && tabId === createdTab.id &&
|
if (tab.url !== 'about:blank' && tabId === createdTab.id &&
|
||||||
changeInfo.status === 'complete') {
|
changeInfo.status === 'complete') {
|
||||||
browser.tabs.onUpdated.removeListener(callback);
|
browser.tabs.onUpdated.removeListener(callback);
|
||||||
resolve(tab);
|
|
||||||
|
// wait for 50 milliseconds to ensure plugin loaded;
|
||||||
|
setTimeout(() => resolve(tab), 50);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
browser.tabs.onUpdated.addListener(callback);
|
browser.tabs.onUpdated.addListener(callback);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
TABS_CREATE, TABS_SELECT_AT, TABS_GET_ZOOM, TABS_SET_ZOOM,
|
TABS_CREATE, TABS_SELECT_AT, TABS_GET, TABS_UPDATE,
|
||||||
|
TABS_GET_ZOOM, TABS_SET_ZOOM,
|
||||||
} from '../shared/messages';
|
} from '../shared/messages';
|
||||||
import * as ipc from './ipc';
|
import * as ipc from './ipc';
|
||||||
|
|
||||||
|
@ -19,6 +20,21 @@ const selectAt = (windowId, index) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const get = (tabId) => {
|
||||||
|
return ipc.send({
|
||||||
|
type: TABS_GET,
|
||||||
|
tabId,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const update = (tabId, properties) => {
|
||||||
|
return ipc.send({
|
||||||
|
type: TABS_UPDATE,
|
||||||
|
tabId,
|
||||||
|
properties,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getZoom = (tabId) => {
|
const getZoom = (tabId) => {
|
||||||
return ipc.send({
|
return ipc.send({
|
||||||
tabId,
|
tabId,
|
||||||
|
@ -34,4 +50,4 @@ const setZoom = (tabId, factor) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export { create, selectAt, getZoom, setZoom };
|
export { create, selectAt, get, update, getZoom, setZoom };
|
||||||
|
|
|
@ -5,6 +5,8 @@ const WINDOWS_REMOVE = 'windows.remove';
|
||||||
const WINDOWS_GET = 'windows.get';
|
const WINDOWS_GET = 'windows.get';
|
||||||
const TABS_CREATE = 'tabs.create';
|
const TABS_CREATE = 'tabs.create';
|
||||||
const TABS_SELECT_AT = 'tabs.selectAt';
|
const TABS_SELECT_AT = 'tabs.selectAt';
|
||||||
|
const TABS_GET = 'tabs.get';
|
||||||
|
const TABS_UPDATE = 'tabs.update';
|
||||||
const TABS_GET_ZOOM = 'tabs.get.zoom';
|
const TABS_GET_ZOOM = 'tabs.get.zoom';
|
||||||
const TABS_SET_ZOOM = 'tabs.set.zoom';
|
const TABS_SET_ZOOM = 'tabs.set.zoom';
|
||||||
const EVENT_KEYPRESS = 'event.keypress';
|
const EVENT_KEYPRESS = 'event.keypress';
|
||||||
|
@ -21,6 +23,8 @@ export {
|
||||||
WINDOWS_REMOVE,
|
WINDOWS_REMOVE,
|
||||||
WINDOWS_GET,
|
WINDOWS_GET,
|
||||||
|
|
||||||
|
TABS_GET,
|
||||||
|
TABS_UPDATE,
|
||||||
TABS_CREATE,
|
TABS_CREATE,
|
||||||
TABS_SELECT_AT,
|
TABS_SELECT_AT,
|
||||||
TABS_GET_ZOOM,
|
TABS_GET_ZOOM,
|
||||||
|
|
121
e2e/contents/follow.test.js
Normal file
121
e2e/contents/follow.test.js
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
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 { CLIENT_URL } from '../web-server/url';
|
||||||
|
|
||||||
|
describe("tab test", () => {
|
||||||
|
let targetWindow;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
return windows.create(CLIENT_URL).then((win) => {
|
||||||
|
targetWindow = win;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
return windows.remove(targetWindow.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('follows link by `f`', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/follow').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'f');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'a');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/follow#a');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('follows link into new tab by `F`', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/follow').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'F', { shiftKey: true });
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'a');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 500) });
|
||||||
|
}).then(() => {
|
||||||
|
return windows.get(targetWindow.id);
|
||||||
|
}).then((win) => {
|
||||||
|
let urls = win.tabs.map(t => t.url);
|
||||||
|
expect(urls).to.have.lengthOf(3);
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/');
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/follow');
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/follow#a');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('follows link with target=_blank into new tab by `f`', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/follow').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'f');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'b');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 500) });
|
||||||
|
}).then(() => {
|
||||||
|
return windows.get(targetWindow.id);
|
||||||
|
}).then((win) => {
|
||||||
|
let urls = win.tabs.map(t => t.url);
|
||||||
|
expect(urls).to.have.lengthOf(3);
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/');
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/follow');
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/follow#external');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('follows link with target=_blank into new tab by `F`', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/follow').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'F', { shiftKey: true });
|
||||||
|
}).then(() => {
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'b');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 500) });
|
||||||
|
}).then(() => {
|
||||||
|
return windows.get(targetWindow.id);
|
||||||
|
}).then((win) => {
|
||||||
|
let urls = win.tabs.map(t => t.url);
|
||||||
|
expect(urls).to.have.lengthOf(3);
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/');
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/follow');
|
||||||
|
expect(urls).to.include(CLIENT_URL + '/follow#external');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('follows area by `F`', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/follow').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'f');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'c');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/follow#area');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
156
e2e/contents/navigate.test.js
Normal file
156
e2e/contents/navigate.test.js
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
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";
|
||||||
|
import { CLIENT_URL } from '../web-server/url';
|
||||||
|
|
||||||
|
describe("navigate test", () => {
|
||||||
|
let targetWindow;
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
return windows.create().then((win) => {
|
||||||
|
targetWindow = win;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
return windows.remove(targetWindow.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('goes to parent', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/a/b/c').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'g');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'u');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/a/b/');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes hash', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/a/b/c#navigate').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'g');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'u');
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/a/b/c#');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('goes to root', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/a/b/c').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'g');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'U', { shiftKey: true });
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('goes back and forward in history', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/#navigate').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, 'g');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'u');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'H', { shiftKey: true });
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url, 'go back in history').to.be.equal(CLIENT_URL + '/#navigate');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, 'L', { shiftKey: true });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url, 'go next in history').to.be.equal(CLIENT_URL + '/#');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('goes previous page by <a>', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/a-pagenation?page=10').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, '[');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, '[');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/a-pagenation?page=9');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
it('goes next page by <a>', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/a-pagenation?page=10').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, ']');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, ']');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/a-pagenation?page=11');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
it('goes previous page by <link>', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/link-pagenation?page=10').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, '[');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, '[');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/link-pagenation?page=9');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
it('goes next page by <link>', () => {
|
||||||
|
let targetTab;
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '/link-pagenation?page=10').then((tab) => {
|
||||||
|
targetTab = tab;
|
||||||
|
return keys.press(targetTab.id, ']');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(targetTab.id, ']');
|
||||||
|
}).then(() => {
|
||||||
|
return new Promise(resolve => { setTimeout(() => resolve(), 10) });
|
||||||
|
}).then(() => {
|
||||||
|
return tabs.get(targetTab.id);
|
||||||
|
}).then((tab) => {
|
||||||
|
expect(tab.url).to.be.equal(CLIENT_URL + '/link-pagenation?page=11');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
|
@ -2,8 +2,7 @@ import * as windows from "../ambassador/src/client/windows";
|
||||||
import * as tabs from "../ambassador/src/client/tabs";
|
import * as tabs from "../ambassador/src/client/tabs";
|
||||||
import * as keys from "../ambassador/src/client/keys";
|
import * as keys from "../ambassador/src/client/keys";
|
||||||
import * as scrolls from "../ambassador/src/client/scrolls";
|
import * as scrolls from "../ambassador/src/client/scrolls";
|
||||||
|
import { CLIENT_URL } from '../web-server/url';
|
||||||
const SERVER_URL = "localhost:11111";
|
|
||||||
|
|
||||||
describe("scroll test", () => {
|
describe("scroll test", () => {
|
||||||
let targetWindow;
|
let targetWindow;
|
||||||
|
@ -12,7 +11,7 @@ describe("scroll test", () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
return windows.create().then((win) => {
|
return windows.create().then((win) => {
|
||||||
targetWindow = win;
|
targetWindow = win;
|
||||||
return tabs.create(targetWindow.id, SERVER_URL);
|
return tabs.create(targetWindow.id, CLIENT_URL + '/scroll');
|
||||||
}).then((tab) => {
|
}).then((tab) => {
|
||||||
targetTab = tab;
|
targetTab = tab;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import * as windows from "../ambassador/src/client/windows";
|
import * as windows from "../ambassador/src/client/windows";
|
||||||
import * as tabs from "../ambassador/src/client/tabs";
|
import * as tabs from "../ambassador/src/client/tabs";
|
||||||
import * as keys from "../ambassador/src/client/keys";
|
import * as keys from "../ambassador/src/client/keys";
|
||||||
|
import { CLIENT_URL } from '../web-server/url';
|
||||||
const SERVER_URL = "localhost:11111/";
|
|
||||||
|
|
||||||
describe("tab test", () => {
|
describe("tab test", () => {
|
||||||
let targetWindow;
|
let targetWindow;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
return windows.create(SERVER_URL).then((win) => {
|
return windows.create(CLIENT_URL).then((win) => {
|
||||||
targetWindow = win;
|
targetWindow = win;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -20,7 +19,7 @@ describe("tab test", () => {
|
||||||
it('deletes tab by d', () => {
|
it('deletes tab by d', () => {
|
||||||
let before;
|
let before;
|
||||||
let targetTab;
|
let targetTab;
|
||||||
return tabs.create(targetWindow.id, SERVER_URL).then((tab) => {
|
return tabs.create(targetWindow.id, CLIENT_URL).then((tab) => {
|
||||||
targetTab = tab;
|
targetTab = tab;
|
||||||
return windows.get(targetWindow.id);
|
return windows.get(targetWindow.id);
|
||||||
}).then((win) => {
|
}).then((win) => {
|
||||||
|
@ -36,7 +35,7 @@ describe("tab test", () => {
|
||||||
it('duplicates tab by zd', () => {
|
it('duplicates tab by zd', () => {
|
||||||
let before;
|
let before;
|
||||||
let targetTab;
|
let targetTab;
|
||||||
return tabs.create(targetWindow.id, SERVER_URL).then((tab) => {
|
return tabs.create(targetWindow.id, CLIENT_URL).then((tab) => {
|
||||||
targetTab = tab;
|
targetTab = tab;
|
||||||
return windows.get(targetWindow.id)
|
return windows.get(targetWindow.id)
|
||||||
}).then((win) => {;
|
}).then((win) => {;
|
||||||
|
@ -54,7 +53,7 @@ describe("tab test", () => {
|
||||||
it('makes pinned by zp', () => {
|
it('makes pinned by zp', () => {
|
||||||
let before;
|
let before;
|
||||||
let targetTab;
|
let targetTab;
|
||||||
return tabs.create(targetWindow.id, SERVER_URL).then((tab) => {
|
return tabs.create(targetWindow.id, CLIENT_URL).then((tab) => {
|
||||||
targetTab = tab;
|
targetTab = tab;
|
||||||
return windows.get(targetWindow.id)
|
return windows.get(targetWindow.id)
|
||||||
}).then((win) => {;
|
}).then((win) => {;
|
||||||
|
@ -71,11 +70,11 @@ describe("tab test", () => {
|
||||||
|
|
||||||
it('selects previous tab by K', () => {
|
it('selects previous tab by K', () => {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#1')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#2')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#2')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#3');
|
return tabs.create(targetWindow.id, CLIENT_URL + '#3');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.selectAt(targetWindow.id, 2);
|
return tabs.selectAt(targetWindow.id, 2);
|
||||||
}).then((tab) => {
|
}).then((tab) => {
|
||||||
|
@ -89,11 +88,11 @@ describe("tab test", () => {
|
||||||
|
|
||||||
it('selects previous tab by K rotatory', () => {
|
it('selects previous tab by K rotatory', () => {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#1')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#2')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#2')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#3');
|
return tabs.create(targetWindow.id, CLIENT_URL + '#3');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.selectAt(targetWindow.id, 0);
|
return tabs.selectAt(targetWindow.id, 0);
|
||||||
}).then((tab) => {
|
}).then((tab) => {
|
||||||
|
@ -107,11 +106,11 @@ describe("tab test", () => {
|
||||||
|
|
||||||
it('selects next tab by J', () => {
|
it('selects next tab by J', () => {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#1')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#2')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#2')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#3');
|
return tabs.create(targetWindow.id, CLIENT_URL + '#3');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.selectAt(targetWindow.id, 2);
|
return tabs.selectAt(targetWindow.id, 2);
|
||||||
}).then((tab) => {
|
}).then((tab) => {
|
||||||
|
@ -125,11 +124,11 @@ describe("tab test", () => {
|
||||||
|
|
||||||
it('selects previous tab by J rotatory', () => {
|
it('selects previous tab by J rotatory', () => {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#1')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#2')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#2')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#3');
|
return tabs.create(targetWindow.id, CLIENT_URL + '#3');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.selectAt(targetWindow.id, 3);
|
return tabs.selectAt(targetWindow.id, 3);
|
||||||
}).then((tab) => {
|
}).then((tab) => {
|
||||||
|
@ -143,11 +142,11 @@ describe("tab test", () => {
|
||||||
|
|
||||||
it('selects first tab by g0', () => {
|
it('selects first tab by g0', () => {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#1')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#2')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#2')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#3');
|
return tabs.create(targetWindow.id, CLIENT_URL + '#3');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.selectAt(targetWindow.id, 2);
|
return tabs.selectAt(targetWindow.id, 2);
|
||||||
}).then((tab) => {
|
}).then((tab) => {
|
||||||
|
@ -163,11 +162,11 @@ describe("tab test", () => {
|
||||||
|
|
||||||
it('selects last tab by g$', () => {
|
it('selects last tab by g$', () => {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#1')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#2')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#2')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#3');
|
return tabs.create(targetWindow.id, CLIENT_URL + '#3');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.selectAt(targetWindow.id, 2);
|
return tabs.selectAt(targetWindow.id, 2);
|
||||||
}).then((tab) => {
|
}).then((tab) => {
|
||||||
|
@ -183,11 +182,11 @@ describe("tab test", () => {
|
||||||
|
|
||||||
it('selects last selected tab by <C-6>', () => {
|
it('selects last selected tab by <C-6>', () => {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#1')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#2')
|
return tabs.create(targetWindow.id, CLIENT_URL + '#2')
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#3');
|
return tabs.create(targetWindow.id, CLIENT_URL + '#3');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return tabs.selectAt(targetWindow.id, 1);
|
return tabs.selectAt(targetWindow.id, 1);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
@ -203,7 +202,7 @@ describe("tab test", () => {
|
||||||
|
|
||||||
it('deletes tab by d', () => {
|
it('deletes tab by d', () => {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL + '#1');
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1');
|
||||||
}).then((tab) => {
|
}).then((tab) => {
|
||||||
return keys.press(tab.id, 'd');
|
return keys.press(tab.id, 'd');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
@ -212,4 +211,53 @@ describe("tab test", () => {
|
||||||
expect(win.tabs).to.have.lengthOf(1);
|
expect(win.tabs).to.have.lengthOf(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('reopen tab by u', () => {
|
||||||
|
return Promise.resolve().then(() => {
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_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);
|
||||||
|
return keys.press(win.tabs[0].id, 'u');
|
||||||
|
}).then(() => {
|
||||||
|
return windows.get(targetWindow.id);
|
||||||
|
}).then((win) => {
|
||||||
|
expect(win.tabs).to.have.lengthOf(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not delete pinned tab by d', () => {
|
||||||
|
return Promise.resolve().then(() => {
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1');
|
||||||
|
}).then((tab) => {
|
||||||
|
return tabs.update(tab.id, { pinned: true });
|
||||||
|
}).then((tab) => {
|
||||||
|
return keys.press(tab.id, 'd');
|
||||||
|
}).then(() => {
|
||||||
|
return windows.get(targetWindow.id);
|
||||||
|
}).then((win) => {
|
||||||
|
expect(win.tabs).to.have.lengthOf(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('deletes pinned tab by !d', () => {
|
||||||
|
let target;
|
||||||
|
return Promise.resolve().then(() => {
|
||||||
|
return tabs.create(targetWindow.id, CLIENT_URL + '#1');
|
||||||
|
}).then((tab) => {
|
||||||
|
return tabs.update(tab.id, { pinned: true });
|
||||||
|
}).then((tab) => {
|
||||||
|
target = tab;
|
||||||
|
return keys.press(target.id, '!');
|
||||||
|
}).then(() => {
|
||||||
|
return keys.press(target.id, 'd');
|
||||||
|
}).then(() => {
|
||||||
|
return windows.get(targetWindow.id);
|
||||||
|
}).then((win) => {
|
||||||
|
expect(win.tabs).to.have.lengthOf(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import * as windows from "../ambassador/src/client/windows";
|
import * as windows from "../ambassador/src/client/windows";
|
||||||
import * as tabs from "../ambassador/src/client/tabs";
|
import * as tabs from "../ambassador/src/client/tabs";
|
||||||
import * as keys from "../ambassador/src/client/keys";
|
import * as keys from "../ambassador/src/client/keys";
|
||||||
|
import { CLIENT_URL } from '../web-server/url';
|
||||||
const SERVER_URL = "localhost:11111/";
|
|
||||||
|
|
||||||
describe("zoom test", () => {
|
describe("zoom test", () => {
|
||||||
let targetWindow;
|
let targetWindow;
|
||||||
let targetTab;
|
let targetTab;
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
return windows.create(SERVER_URL).then((win) => {
|
return windows.create(CLIENT_URL).then((win) => {
|
||||||
targetWindow = win;
|
targetWindow = win;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -19,7 +18,7 @@ describe("zoom test", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
return tabs.create(targetWindow.id, SERVER_URL).then((tab) => {
|
return tabs.create(targetWindow.id, CLIENT_URL).then((tab) => {
|
||||||
targetTab = tab;
|
targetTab = tab;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,88 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var serverUrl = require('./url');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
|
var url = require('url');
|
||||||
|
|
||||||
const content =
|
const handleScroll = (req, res) => {
|
||||||
'<!DOCTYPE html>' +
|
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||||
'<html lang="en">' +
|
res.end('<!DOCTYPEhtml><html lang="en"><body style="width:10000px; height:10000px"></body></html">');
|
||||||
'<body style="width:10000px; height:10000px">' +
|
};
|
||||||
'</body>' +
|
|
||||||
'</html">' ;
|
|
||||||
|
|
||||||
|
const handleAPagenation = (req, res) => {
|
||||||
|
let u = url.parse(req.url);
|
||||||
|
let params = new url.URLSearchParams(u.search);
|
||||||
|
let page = params.get('page') === null ? null : Number(params.get('page'));
|
||||||
|
if (page === null || isNaN(page)) {
|
||||||
|
return handle404(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = '';
|
||||||
|
let nextLink = u.pathname + '?page=' + (page + 1);
|
||||||
|
let prevLink = u.pathname + '?page=' + (page - 1);
|
||||||
|
|
||||||
|
if (page > 1) {
|
||||||
|
body += '<a href="' + prevLink + '">prev</a> | ';
|
||||||
|
}
|
||||||
|
body += '<a href="' + nextLink + '">next</a>';
|
||||||
|
|
||||||
|
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||||
|
res.end('<!DOCTYPEhtml><html lang="en"><body">' + body + '</body></html">');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLinkPagenation = (req, res) => {
|
||||||
|
let u = url.parse(req.url);
|
||||||
|
let params = new url.URLSearchParams(u.search);
|
||||||
|
let page = params.get('page') === null ? null : Number(params.get('page'));
|
||||||
|
if (page === null || isNaN(page)) {
|
||||||
|
return handle404(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
let head = '';
|
||||||
|
let nextLink = u.pathname + '?page=' + (page + 1);
|
||||||
|
let prevLink = u.pathname + '?page=' + (page - 1);
|
||||||
|
|
||||||
|
if (page > 1) {
|
||||||
|
head += '<link rel="prev" href="' + prevLink + '"></link>';
|
||||||
|
}
|
||||||
|
head += '<link rel="next" href="' + nextLink + '"></link>';
|
||||||
|
|
||||||
|
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||||
|
res.end('<!DOCTYPEhtml><html lang="en"><head>' + head + '</head><body"></body></html">');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFollow = (req, res) => {
|
||||||
|
let body = '';
|
||||||
|
body += '<a href="#a">a</a>';
|
||||||
|
body += '<a href="#external" target="_blank">external</a>';
|
||||||
|
body += '<img width="320" height="240" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" usemap="#map"><map name="map"><area href="#area" shape="rect" coords="15,19,126,104"></map>'
|
||||||
|
|
||||||
|
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||||
|
res.end('<!DOCTYPEhtml><html lang="en"><body">' + body + '</body></html">');
|
||||||
|
}
|
||||||
|
|
||||||
|
const handle404 = (req, res) => {
|
||||||
|
res.writeHead(404, {'Content-Type': 'text/plain'});
|
||||||
|
res.end('not found')
|
||||||
|
};
|
||||||
|
|
||||||
http.createServer(function (req, res) {
|
http.createServer(function (req, res) {
|
||||||
res.writeHead(200, {'Content-Type': 'text/html'});
|
if (req.method !== 'GET') {
|
||||||
res.end(content);
|
handle404(req, res);
|
||||||
}).listen(11111, '127.0.0.1');
|
}
|
||||||
|
|
||||||
|
let u = url.parse(req.url);
|
||||||
|
if (u.pathname === '/scroll') {
|
||||||
|
handleScroll(req, res);
|
||||||
|
} else if (u.pathname === '/a-pagenation') {
|
||||||
|
handleAPagenation(req, res);
|
||||||
|
} else if (u.pathname === '/link-pagenation') {
|
||||||
|
handleLinkPagenation(req, res);
|
||||||
|
} else if (u.pathname === '/follow') {
|
||||||
|
handleFollow(req, res);
|
||||||
|
} else {
|
||||||
|
handle404(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`"${req.method} ${req.url}"`, res.statusCode)
|
||||||
|
}).listen(serverUrl.PORT, serverUrl.HOST);
|
||||||
|
|
5
e2e/web-server/url.js
Normal file
5
e2e/web-server/url.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
PORT: 11111,
|
||||||
|
HOST: '127.0.0.1',
|
||||||
|
CLIENT_URL: 'http://127.0.0.1:11111',
|
||||||
|
}
|
Reference in a new issue