diff --git a/QA.md b/QA.md
index e2a6fac..4d1a270 100644
--- a/QA.md
+++ b/QA.md
@@ -8,19 +8,6 @@ Test operations with default key maps.
The behaviors of the console are tested in [Console section](#consoles).
-- [ ] :: open empty console
-- [ ] o, t, w: open a console with `open`, `tabopen`, `winopen`
-- [ ] O, T, W: open a console with `open`, `tabopen`, `winopen` and current URL
-- [ ] b: open a console with `buffer`
-- [ ] a: open a console with `addbookmark` and the current page's title
-
-#### Tabs
-
-- [ ] r: reload current tab
-- [ ] R: reload current tab without cache
-- [ ] gh: open start page on current tab
-- [ ] gH: open start page to new tab
-
#### Misc
- [ ] y: yank current URL and show a message
@@ -50,41 +37,6 @@ The behaviors of the console are tested in [Console section](#consoles).
#### Exec a command
- [ ] ``: do nothing
-
-
-- [ ] `open an apple`: search with keywords "an apple" by default search engine (google)
-- [ ] `open github.com`: open github.com
-- [ ] `open https://github.com`: open github.com
-- [ ] `open yahoo an apple`: search with keywords "an apple" by yahoo.com
-- [ ] `open yahoo`: search with empty keywords; yahoo redirects to top page
-- [ ] `open`: open default search engine
-
-
-- [ ] `tabopen`: do above tests replaced `open` with `tabopen`, and verify the page is opened in new tab
-- [ ] `winopen`: do above tests replaced `open` with `winopen`, and verify the page is opened in new window
-
-
-- [ ] `buffer`: do nothing
-- [ ] `buffer `, `buffer `: select tab which has an title matched with
-- [ ] `buffer 1`: select leftmost tab
-- [ ] `buffer 0`, `buffer `: shows an error
-- [ ] select tabs rotationally when more than two tabs are matched
-- [ ] `buffer %`: select current tab (nothing to do)
-- [ ] `buffer #`: select last selected tab
-
-
-- [ ] `addbookmark` creates a bookmark
-
-
-- [ ] `q`, `quit`: close current tab
-- [ ] `qa`, `quitall`: close all tabs
-- [ ] `bdelete`: delete a not-pinned tab matches with keywords
-- [ ] `bdelete`: show errors no-tabs or more than 1 tabs matched
-- [ ] `bdelete`: can not delete pinned tab
-- [ ] `bdelete!`: delete a tab matches with keywords
-- [ ] `bdelete!`: delete a pinned tab matches with keywords
-- [ ] `bdeletes`: delete tabs with matched with keywords excluding pinned
-- [ ] `bdeletes!`: delete tabs with matched with keywords including pinned
### Completions
diff --git a/e2e/command_addbookmark.test.js b/e2e/command_addbookmark.test.js
new file mode 100644
index 0000000..e8995bc
--- /dev/null
+++ b/e2e/command_addbookmark.test.js
@@ -0,0 +1,67 @@
+const express = require('express');
+const lanthan = require('lanthan');
+const path = require('path');
+const assert = require('assert');
+const eventually = require('./eventually');
+
+const Key = lanthan.Key;
+
+const newApp = () => {
+ let app = express();
+ app.get('/happy', (req, res) => {
+ res.send(`
+
+
+ how to be happy
+
+`);
+ });
+ return app;
+};
+
+describe('addbookmark command test', () => {
+ const port = 12321;
+ let http;
+ let firefox;
+ let session;
+ let browser;
+
+ before(async() => {
+ http = newApp().listen(port);
+
+ firefox = await lanthan.firefox({
+ spy: path.join(__dirname, '..'),
+ builderf: (builder) => {
+ builder.addFile('build/settings.js');
+ },
+ });
+ session = firefox.session;
+ browser = firefox.browser;
+ });
+
+ after(async() => {
+ http.close();
+ if (firefox) {
+ await firefox.close();
+ }
+ });
+
+ beforeEach(async() => {
+ await session.navigateTo(`http://127.0.0.1:${port}/happy`);
+ });
+
+ it('should add a bookmark from the current page', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('addbookmark how to be happy', Key.Enter);
+
+ await eventually(async() => {
+ var bookmarks = await browser.bookmarks.search({ title: 'how to be happy' });
+ assert.equal(bookmarks.length, 1);
+ assert.equal(bookmarks[0].url, `http://127.0.0.1:${port}/happy`);
+ });
+ });
+});
diff --git a/e2e/command_bdelete.test.js b/e2e/command_bdelete.test.js
new file mode 100644
index 0000000..1f416db
--- /dev/null
+++ b/e2e/command_bdelete.test.js
@@ -0,0 +1,203 @@
+const express = require('express');
+const lanthan = require('lanthan');
+const path = require('path');
+const assert = require('assert');
+const eventually = require('./eventually');
+
+const Key = lanthan.Key;
+
+const newApp = () => {
+ let app = express();
+ app.get('/*', (req, res) => {
+ res.send(`
+
+
+ my_${req.path.slice(1)}
+
+ ${req.path}
+`);
+ });
+ return app;
+};
+
+describe('bdelete/bdeletes command test', () => {
+ const port = 12321;
+ let http;
+ let firefox;
+ let session;
+ let browser;
+
+ before(async() => {
+ http = newApp().listen(port);
+
+ firefox = await lanthan.firefox({
+ spy: path.join(__dirname, '..'),
+ builderf: (builder) => {
+ builder.addFile('build/settings.js');
+ },
+ });
+ session = firefox.session;
+ browser = firefox.browser;
+ });
+
+ after(async() => {
+ http.close();
+ if (firefox) {
+ await firefox.close();
+ }
+ });
+
+ beforeEach(async() => {
+ let tabs = await browser.tabs.query({});
+ for (let tab of tabs.slice(1)) {
+ await browser.tabs.remove(tab.id);
+ }
+ await browser.tabs.update(tabs[0].id, { url: `http://127.0.0.1:${port}/site1`, pinned: true });
+ await browser.tabs.create({ url: `http://127.0.0.1:${port}/site2`, pinned: true })
+ await browser.tabs.create({ url: `http://127.0.0.1:${port}/site3`, pinned: true })
+ await browser.tabs.create({ url: `http://127.0.0.1:${port}/site4` })
+ await browser.tabs.create({ url: `http://127.0.0.1:${port}/site5` })
+
+ await eventually(async() => {
+ let handles = await session.getWindowHandles();
+ assert.equal(handles.length, 5);
+ await session.switchToWindow(handles[2]);
+ await session.findElementByCSS('iframe');
+ });
+
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ });
+
+ it('should delete an unpinned tab by bdelete command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('bdelete site5', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.deepEqual(tabs.map(t => t.url), [
+ `http://127.0.0.1:${port}/site1`,
+ `http://127.0.0.1:${port}/site2`,
+ `http://127.0.0.1:${port}/site3`,
+ `http://127.0.0.1:${port}/site4`,
+ ])
+ });
+ });
+
+ it('should not delete an pinned tab by bdelete command by bdelete command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('bdelete site1', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 5);
+ });
+ });
+
+ it('should show an error when no tabs are matched by bdelete command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('bdelete xyz', Key.Enter);
+
+ await eventually(async() => {
+ let p = await session.findElementByCSS('.vimvixen-console-error');
+ let text = await p.getText();
+ assert.equal(text, 'No matching buffer for xyz');
+ });
+ });
+
+ it('should show an error when more than one tabs are matched by bdelete command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('bdelete site', Key.Enter);
+
+ await eventually(async() => {
+ let p = await session.findElementByCSS('.vimvixen-console-error');
+ let text = await p.getText();
+ assert.equal(text, 'More than one match for site');
+ });
+ });
+
+ it('should delete an unpinned tab by bdelete! command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('bdelete! site5', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.deepEqual(tabs.map(t => t.url), [
+ `http://127.0.0.1:${port}/site1`,
+ `http://127.0.0.1:${port}/site2`,
+ `http://127.0.0.1:${port}/site3`,
+ `http://127.0.0.1:${port}/site4`,
+ ])
+ });
+ });
+
+ it('should delete an pinned tab by bdelete! command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('bdelete! site1', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.deepEqual(tabs.map(t => t.url), [
+ `http://127.0.0.1:${port}/site2`,
+ `http://127.0.0.1:${port}/site3`,
+ `http://127.0.0.1:${port}/site4`,
+ `http://127.0.0.1:${port}/site5`,
+ ])
+ });
+ });
+
+ it('should delete unpinned tabs by bdeletes command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('bdeletes site', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.deepEqual(tabs.map(t => t.url), [
+ `http://127.0.0.1:${port}/site1`,
+ `http://127.0.0.1:${port}/site2`,
+ `http://127.0.0.1:${port}/site3`,
+ ])
+ });
+ });
+
+ it('should delete both pinned and unpinned tabs by bdeletes! command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('bdeletes! site', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 1);
+ });
+ });
+});
diff --git a/e2e/command_buffer.test.js b/e2e/command_buffer.test.js
new file mode 100644
index 0000000..bf94428
--- /dev/null
+++ b/e2e/command_buffer.test.js
@@ -0,0 +1,202 @@
+const express = require('express');
+const lanthan = require('lanthan');
+const path = require('path');
+const assert = require('assert');
+const eventually = require('./eventually');
+
+const Key = lanthan.Key;
+
+const newApp = () => {
+ let app = express();
+ app.get('/*', (req, res) => {
+ res.send(`
+
+
+ my_${req.path.slice(1)}
+
+ ${req.path}
+`);
+ });
+ return app;
+};
+
+describe('buffer command test', () => {
+ const port = 12321;
+ let http;
+ let firefox;
+ let session;
+ let browser;
+
+ before(async() => {
+ http = newApp().listen(port);
+
+ firefox = await lanthan.firefox({
+ spy: path.join(__dirname, '..'),
+ builderf: (builder) => {
+ builder.addFile('build/settings.js');
+ },
+ });
+ session = firefox.session;
+ browser = firefox.browser;
+ });
+
+ after(async() => {
+ http.close();
+ if (firefox) {
+ await firefox.close();
+ }
+ });
+
+ beforeEach(async() => {
+ let tabs = await browser.tabs.query({});
+ for (let tab of tabs.slice(1)) {
+ await browser.tabs.remove(tab.id);
+ }
+ await browser.tabs.update(tabs[0].id, { url: `http://127.0.0.1:${port}/site1` });
+ for (let i = 2; i <= 5; ++i) {
+ await browser.tabs.create({ url: `http://127.0.0.1:${port}/site${i}`})
+ }
+
+ await eventually(async() => {
+ let handles = await session.getWindowHandles();
+ assert.equal(handles.length, 5);
+ await session.switchToWindow(handles[2]);
+ await session.findElementByCSS('iframe');
+ });
+
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ });
+
+ it('should do nothing by buffer command with no parameters', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true });
+ assert.equal(tabs[0].index, 2);
+ });
+ });
+
+ it('should select a tab by buffer command with a number', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true });
+ assert.equal(tabs[0].index, 2);
+ });
+ });
+
+ it('should should an out of range error by buffer commands', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer 0', Key.Enter);
+
+ await eventually(async() => {
+ let p = await session.findElementByCSS('.vimvixen-console-error');
+ let text = await p.getText();
+ assert.equal(text, 'tab 0 does not exist');
+ });
+
+ await session.switchToParentFrame();
+ body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer 9', Key.Enter);
+
+ await eventually(async() => {
+ let p = await session.findElementByCSS('.vimvixen-console-error');
+ let text = await p.getText();
+ assert.equal(text, 'tab 9 does not exist');
+ });
+ });
+
+ it('should select a tab by buffer command with a title', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer my_site1', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true });
+ assert.equal(tabs[0].index, 0);
+ });
+ });
+
+ it('should select a tab by buffer command with an URL', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer /site1', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true });
+ assert.equal(tabs[0].index, 0);
+ });
+ });
+
+ it('should select tabs rotately', async() => {
+ let handles = await session.getWindowHandles();
+ await session.switchToWindow(handles[4]);
+
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer site', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true });
+ assert.equal(tabs[0].index, 0);
+ });
+ });
+
+ it('should do nothing by ":buffer %"', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer %', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true });
+ assert.equal(tabs[0].index, 2);
+ });
+ });
+
+ it('should selects last selected tab by ":buffer #"', async() => {
+ let handles = await session.getWindowHandles();
+ await session.switchToWindow(handles[1]);
+
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('buffer #', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true });
+ assert.equal(tabs[0].index, 2);
+ });
+ });
+});
diff --git a/e2e/command_open.test.js b/e2e/command_open.test.js
new file mode 100644
index 0000000..0d41f96
--- /dev/null
+++ b/e2e/command_open.test.js
@@ -0,0 +1,149 @@
+const express = require('express');
+const lanthan = require('lanthan');
+const path = require('path');
+const assert = require('assert');
+const eventually = require('./eventually');
+const settings = require('./settings');
+
+const Key = lanthan.Key;
+
+const newApp = () => {
+
+ let app = express();
+ for (let name of ['google', 'yahoo', 'bing', 'duckduckgo', 'twitter', 'wikipedia']) {
+ app.get('/' + name, (req, res) => {
+ res.send(`
+
+ ${name.charAt(0).toUpperCase() + name.slice(1)}
+`);
+ });
+ }
+ app.get('/', (req, res) => {
+ res.send(`
+
+ home
+`);
+ });
+ return app;
+};
+
+describe("open command test", () => {
+ const port = 12321;
+ let http;
+ let firefox;
+ let session;
+ let browser;
+ let body;
+
+ before(async() => {
+ firefox = await lanthan.firefox({
+ spy: path.join(__dirname, '..'),
+ builderf: (builder) => {
+ builder.addFile('build/settings.js');
+ },
+ });
+ session = firefox.session;
+ browser = firefox.browser;
+ http = newApp().listen(port);
+
+ await browser.storage.local.set({
+ settings,
+ });
+ });
+
+ after(async() => {
+ http.close();
+ if (firefox) {
+ await firefox.close();
+ }
+ });
+
+ beforeEach(async() => {
+ await session.navigateTo(`http://127.0.0.1:${port}`);
+ body = await session.findElementByCSS('body');
+ })
+
+ it('should open default search for keywords by open command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('open an apple', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true });
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/google?q=an%20apple`)
+ });
+ });
+
+ it('should open certain search page for keywords by open command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('open yahoo an apple', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true })
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/yahoo?q=an%20apple`)
+ });
+ });
+
+ it('should open default engine with empty keywords by open command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('open', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true })
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/google?q=`)
+ });
+ });
+
+ it('should open certain search page for empty keywords by open command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('open yahoo', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true })
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/yahoo?q=`)
+ });
+ });
+
+ it('should open a site with domain by open command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('open i-beam.org', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true })
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, 'https://i-beam.org/')
+ });
+ });
+
+ it('should open a site with URL by open command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('open https://i-beam.org', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({ active: true })
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, 'https://i-beam.org/')
+ });
+ });
+});
diff --git a/e2e/command_quit.test.js b/e2e/command_quit.test.js
new file mode 100644
index 0000000..ee4c2d8
--- /dev/null
+++ b/e2e/command_quit.test.js
@@ -0,0 +1,125 @@
+const express = require('express');
+const lanthan = require('lanthan');
+const path = require('path');
+const assert = require('assert');
+const eventually = require('./eventually');
+
+const Key = lanthan.Key;
+
+const newApp = () => {
+ let app = express();
+ app.get('/*', (req, res) => {
+ res.send(`
+
+
+ my_${req.path.slice(1)}
+
+ ${req.path}
+`);
+ });
+ return app;
+};
+
+describe('quit/quitall command test', () => {
+ const port = 12321;
+ let http;
+ let firefox;
+ let session;
+ let browser;
+
+ before(async() => {
+ http = newApp().listen(port);
+
+ firefox = await lanthan.firefox({
+ spy: path.join(__dirname, '..'),
+ builderf: (builder) => {
+ builder.addFile('build/settings.js');
+ },
+ });
+ session = firefox.session;
+ browser = firefox.browser;
+ });
+
+ after(async() => {
+ http.close();
+ if (firefox) {
+ await firefox.close();
+ }
+ });
+
+ beforeEach(async() => {
+ let tabs = await browser.tabs.query({});
+ for (let tab of tabs.slice(1)) {
+ await browser.tabs.remove(tab.id);
+ }
+ await browser.tabs.update(tabs[0].id, { url: `http://127.0.0.1:${port}/site1` });
+ for (let i = 2; i <= 5; ++i) {
+ await browser.tabs.create({ url: `http://127.0.0.1:${port}/site${i}`})
+ }
+
+ await eventually(async() => {
+ let handles = await session.getWindowHandles();
+ assert.equal(handles.length, 5);
+ await session.switchToWindow(handles[2]);
+ await session.findElementByCSS('iframe');
+ });
+
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ });
+
+ it('should current tab by q command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('q', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 4)
+ });
+ });
+
+ it('should current tab by quit command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('quit', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 4)
+ });
+ });
+
+ it('should current tab by qa command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('qa', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 1)
+ });
+ });
+
+ it('should current tab by quitall command', async() => {
+ let body = await session.findElementByCSS('body');
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ await input.sendKeys('quitall', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 1)
+ });
+ });
+});
diff --git a/e2e/command_tabopen.test.js b/e2e/command_tabopen.test.js
new file mode 100644
index 0000000..9c5cf3a
--- /dev/null
+++ b/e2e/command_tabopen.test.js
@@ -0,0 +1,160 @@
+const express = require('express');
+const lanthan = require('lanthan');
+const path = require('path');
+const assert = require('assert');
+const eventually = require('./eventually');
+const settings = require('./settings');
+
+const Key = lanthan.Key;
+
+const newApp = () => {
+
+ let app = express();
+ for (let name of ['google', 'yahoo', 'bing', 'duckduckgo', 'twitter', 'wikipedia']) {
+ app.get('/' + name, (req, res) => {
+ res.send(`
+
+ ${name.charAt(0).toUpperCase() + name.slice(1)}
+`);
+ });
+ }
+ app.get('/', (req, res) => {
+ res.send(`
+
+ home
+`);
+ });
+ return app;
+};
+
+describe("tabopen command test", () => {
+ const port = 12321;
+ let http;
+ let firefox;
+ let session;
+ let browser;
+ let body;
+
+ before(async() => {
+ http = newApp().listen(port);
+
+ firefox = await lanthan.firefox({
+ spy: path.join(__dirname, '..'),
+ builderf: (builder) => {
+ builder.addFile('build/settings.js');
+ },
+ });
+ session = firefox.session;
+ browser = firefox.browser;
+ await browser.storage.local.set({
+ settings,
+ });
+ });
+
+ after(async() => {
+ http.close();
+ if (firefox) {
+ await firefox.close();
+ }
+ });
+
+ beforeEach(async() => {
+ let tabs = await browser.tabs.query({});
+ for (let tab of tabs.slice(1)) {
+ await browser.tabs.remove(tab.id);
+ }
+
+ await session.navigateTo(`http://127.0.0.1:${port}`);
+ body = await session.findElementByCSS('body');
+ })
+
+ it('should open default search for keywords by tabopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('tabopen an apple', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 2);
+ let url = new URL(tabs[1].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/google?q=an%20apple`)
+ });
+ });
+
+ it('should open certain search page for keywords by tabopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('tabopen yahoo an apple', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 2);
+ let url = new URL(tabs[1].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/yahoo?q=an%20apple`)
+ });
+ });
+
+ it('should open default engine with empty keywords by tabopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('tabopen', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 2);
+ let url = new URL(tabs[1].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/google?q=`)
+ });
+ });
+
+ it('should open certain search page for empty keywords by tabopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('tabopen yahoo', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 2);
+ let url = new URL(tabs[1].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/yahoo?q=`)
+ });
+ });
+
+ it('should open a site with domain by tabopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('tabopen i-beam.org', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 2);
+ let url = new URL(tabs[1].url);
+ assert.equal(url.href, 'https://i-beam.org/')
+ });
+ });
+
+ it('should open a site with URL by tabopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('tabopen https://i-beam.org', Key.Enter);
+
+ await eventually(async() => {
+ let tabs = await browser.tabs.query({});
+ assert.equal(tabs.length, 2);
+ let url = new URL(tabs[1].url);
+ assert.equal(url.href, 'https://i-beam.org/')
+ });
+ });
+});
diff --git a/e2e/command_winopen.test.js b/e2e/command_winopen.test.js
new file mode 100644
index 0000000..536d759
--- /dev/null
+++ b/e2e/command_winopen.test.js
@@ -0,0 +1,172 @@
+const express = require('express');
+const lanthan = require('lanthan');
+const path = require('path');
+const assert = require('assert');
+const eventually = require('./eventually');
+const settings = require('./settings');
+
+const Key = lanthan.Key;
+
+const newApp = () => {
+
+ let app = express();
+ for (let name of ['google', 'yahoo', 'bing', 'duckduckgo', 'twitter', 'wikipedia']) {
+ app.get('/' + name, (req, res) => {
+ res.send(`
+
+ ${name.charAt(0).toUpperCase() + name.slice(1)}
+`);
+ });
+ }
+ app.get('/', (req, res) => {
+ res.send(`
+
+ home
+`);
+ });
+ return app;
+};
+
+describe("winopen command test", () => {
+ const port = 12321;
+ let http;
+ let firefox;
+ let session;
+ let browser;
+ let body;
+
+ before(async() => {
+ http = newApp().listen(port);
+
+ firefox = await lanthan.firefox({
+ spy: path.join(__dirname, '..'),
+ builderf: (builder) => {
+ builder.addFile('build/settings.js');
+ },
+ });
+ session = firefox.session;
+ browser = firefox.browser;
+ await browser.storage.local.set({
+ settings,
+ });
+ });
+
+ after(async() => {
+ http.close();
+ if (firefox) {
+ await firefox.close();
+ }
+ });
+
+ beforeEach(async() => {
+ let wins = await browser.windows.getAll();
+ for (let win of wins.slice(1)) {
+ await browser.windows.remove(win.id);
+ }
+
+ await session.navigateTo(`http://127.0.0.1:${port}`);
+ body = await session.findElementByCSS('body');
+ })
+
+ it('should open default search for keywords by winopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('winopen an apple', Key.Enter);
+
+ await eventually(async() => {
+ let wins = await browser.windows.getAll();
+ assert.equal(wins.length, 2);
+
+ let tabs = await browser.tabs.query({ windowId: wins[1].id });
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/google?q=an%20apple`)
+ });
+ });
+
+ it('should open certain search page for keywords by winopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('winopen yahoo an apple', Key.Enter);
+
+ await eventually(async() => {
+ let wins = await browser.windows.getAll();
+ assert.equal(wins.length, 2);
+
+ let tabs = await browser.tabs.query({ windowId: wins[1].id });
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/yahoo?q=an%20apple`)
+ });
+ });
+
+ it('should open default engine with empty keywords by winopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('winopen', Key.Enter);
+
+ await eventually(async() => {
+ let wins = await browser.windows.getAll();
+ assert.equal(wins.length, 2);
+
+ let tabs = await browser.tabs.query({ windowId: wins[1].id });
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/google?q=`)
+ });
+ });
+
+ it('should open certain search page for empty keywords by winopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('winopen yahoo', Key.Enter);
+
+ await eventually(async() => {
+ let wins = await browser.windows.getAll();
+ assert.equal(wins.length, 2);
+
+ let tabs = await browser.tabs.query({ windowId: wins[1].id });
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, `http://127.0.0.1:${port}/yahoo?q=`)
+ });
+ });
+
+ it('should open a site with domain by winopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('winopen i-beam.org', Key.Enter);
+
+ await eventually(async() => {
+ let wins = await browser.windows.getAll();
+ assert.equal(wins.length, 2);
+
+ let tabs = await browser.tabs.query({ windowId: wins[1].id });
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, 'https://i-beam.org/')
+ });
+ });
+
+ it('should open a site with URL by winopen command ', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+ let input = await session.findElementByCSS('input');
+ input.sendKeys('winopen https://i-beam.org', Key.Enter);
+
+ await eventually(async() => {
+ let wins = await browser.windows.getAll();
+ assert.equal(wins.length, 2);
+
+ let tabs = await browser.tabs.query({ windowId: wins[1].id });
+ let url = new URL(tabs[0].url);
+ assert.equal(url.href, 'https://i-beam.org/')
+ });
+ });
+});
diff --git a/e2e/console.test.js b/e2e/console.test.js
new file mode 100644
index 0000000..6f6341f
--- /dev/null
+++ b/e2e/console.test.js
@@ -0,0 +1,125 @@
+const express = require('express');
+const lanthan = require('lanthan');
+const path = require('path');
+const assert = require('assert');
+const eventually = require('./eventually');
+
+const Key = lanthan.Key;
+
+const newApp = () => {
+ let app = express();
+ app.get('/', (req, res) => {
+ res.send(`
+
+
+ Hello, world!
+
+`);
+ });
+ return app;
+};
+
+
+describe("console test", () => {
+ const port = 12321;
+ let http;
+ let firefox;
+ let session;
+ let browser;
+ let tab;
+ let body;
+
+ before(async() => {
+ firefox = await lanthan.firefox();
+ await firefox.session.installAddonFromPath(path.join(__dirname, '..'));
+ session = firefox.session;
+ browser = firefox.browser;
+ http = newApp().listen(port);
+ });
+
+ after(async() => {
+ http.close();
+ if (firefox) {
+ await firefox.close();
+ }
+ });
+
+ beforeEach(async() => {
+ await session.navigateTo(`http://127.0.0.1:${port}`);
+ body = await session.findElementByCSS('body');
+ });
+
+ it('open console with :', async() => {
+ await body.sendKeys(':');
+
+ await session.switchToFrame(0);
+
+ let input = await session.findElementByCSS('input');
+ assert.equal(await input.isDisplayed(), true);
+ });
+
+ it('open console with open command by o', async() => {
+ await body.sendKeys('o');
+
+ await session.switchToFrame(0);
+ let value = await session.executeScript(() => document.querySelector('input').value);
+ assert.equal(value, 'open ');
+ });
+
+ it('open console with open command and current URL by O', async() => {
+ await body.sendKeys(Key.Shift, 'o');
+
+ await session.switchToFrame(0);
+ let value = await session.executeScript(() => document.querySelector('input').value);
+ assert.equal(value, `open http://127.0.0.1:${port}/`);
+ });
+
+ it('open console with tabopen command by t', async() => {
+ await body.sendKeys('t');
+
+ await session.switchToFrame(0);
+ let value = await session.executeScript(() => document.querySelector('input').value);
+ assert.equal(value, 'tabopen ');
+ });
+
+ it('open console with tabopen command and current URL by T', async() => {
+ await body.sendKeys(Key.Shift, 't');
+
+ await session.switchToFrame(0);
+ let value = await session.executeScript(() => document.querySelector('input').value);
+ assert.equal(value, `tabopen http://127.0.0.1:${port}/`);
+ });
+
+ it('open console with winopen command by w', async() => {
+ await body.sendKeys('w');
+
+ await session.switchToFrame(0);
+ let value = await session.executeScript(() => document.querySelector('input').value);
+ assert.equal(value, 'winopen ');
+ });
+
+ it('open console with winopen command and current URL by W', async() => {
+ await body.sendKeys(Key.Shift, 'W');
+
+ await session.switchToFrame(0);
+ let value = await session.executeScript(() => document.querySelector('input').value);
+ assert.equal(value, `winopen http://127.0.0.1:${port}/`);
+ });
+
+ it('open console with buffer command by b', async() => {
+ await body.sendKeys('b');
+
+ await session.switchToFrame(0);
+ let value = await session.executeScript(() => document.querySelector('input').value);
+ assert.equal(value, `buffer `);
+ });
+
+ it('open console with addbookmark command with title by a', async() => {
+ await body.sendKeys('a');
+
+ await session.switchToFrame(0);
+ let value = await session.executeScript(() => document.querySelector('input').value);
+ assert.equal(value, `addbookmark Hello, world!`);
+ });
+});
+
diff --git a/e2e/mark.test.js b/e2e/mark.test.js
index 8f350b7..8716c1e 100644
--- a/e2e/mark.test.js
+++ b/e2e/mark.test.js
@@ -29,7 +29,7 @@ describe("mark test", () => {
http = newApp().listen(port);
firefox = await lanthan.firefox();
- await firefox.session.installAddon(path.join(__dirname, '..'));
+ await firefox.session.installAddonFromPath(path.join(__dirname, '..'));
session = firefox.session;
browser = firefox.browser;
});
diff --git a/e2e/navigate.test.js b/e2e/navigate.test.js
index 089fa56..5d9365b 100644
--- a/e2e/navigate.test.js
+++ b/e2e/navigate.test.js
@@ -24,6 +24,15 @@ const newApp = () => {