From 9f7150e96b7b228429f9f893657f4647e5a8cb51 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Tue, 16 Apr 2019 21:56:17 +0900 Subject: [PATCH] Add e2e tests for completions --- QA.md | 7 -- e2e/completion.test.js | 136 +++++++++++++++++++++++++++++++++++++ e2e/completion_set.test.js | 75 ++++++++++++++++++++ e2e/lib/Console.js | 10 ++- 4 files changed, 220 insertions(+), 8 deletions(-) create mode 100644 e2e/completion.test.js create mode 100644 e2e/completion_set.test.js diff --git a/QA.md b/QA.md index 5272597..16b4442 100644 --- a/QA.md +++ b/QA.md @@ -35,13 +35,6 @@ The behaviors of the console are tested in [Console section](#consoles). - [ ] ``: do nothing -### Completions - -#### History and search engines - -- [ ] `set `: show prperties starts with keywords -- [ ] Complete commands matched with input keywords in the prefix. - #### Misc - [ ] Select next item by Tab and previous item by Shift+Tab diff --git a/e2e/completion.test.js b/e2e/completion.test.js new file mode 100644 index 0000000..5d910c6 --- /dev/null +++ b/e2e/completion.test.js @@ -0,0 +1,136 @@ +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 Console = require('./lib/Console'); + +const Key = lanthan.Key; + +const newApp = () => { + let app = express(); + app.get('/', (req, res) => { + res.send(` + + ok +`); + }); + return app; +}; + +describe("general completion 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 all commands on empty line', async() => { + await body.sendKeys(':'); + + await session.switchToFrame(0); + let c = new Console(session); + + await eventually(async() => { + let items = await c.getCompletions(); + assert.equal(items.length, 10); + assert.deepEqual(items[0], { type: 'title', text: 'Console Command' }); + assert(items[1].text.startsWith('set')) + assert(items[2].text.startsWith('open')) + assert(items[3].text.startsWith('tabopen')) + }); + }); + + it('should only commands filtered by prefix', async() => { + await body.sendKeys(':'); + + await session.switchToFrame(0); + let c = new Console(session); + await c.sendKeys('b'); + + await eventually(async() => { + let items = await c.getCompletions(); + assert.equal(items.length, 4); + assert.deepEqual(items[0], { type: 'title', text: 'Console Command' }); + assert(items[1].text.startsWith('buffer')) + assert(items[2].text.startsWith('bdelete')) + assert(items[3].text.startsWith('bdeletes')) + }); + }); + + it('selects completion items by / keys', async() => { + await body.sendKeys(':'); + + await session.switchToFrame(0); + let c = new Console(session); + await c.sendKeys('b'); + + await eventually(async() => { + let items = await c.getCompletions(); + assert.equal(items.length, 4); + }); + + await c.sendKeys(Key.Tab); + await eventually(async() => { + let items = await c.getCompletions(); + assert(items[1].highlight) + + let v = await c.currentValue(); + assert.equal(v, 'buffer'); + }); + + await c.sendKeys(Key.Tab, Key.Tab); + await eventually(async() => { + let items = await c.getCompletions(); + assert(items[3].highlight) + + let v = await c.currentValue(); + assert.equal(v, 'bdeletes'); + }); + + await c.sendKeys(Key.Tab); + await eventually(async() => { + let v = await c.currentValue(); + assert.equal(v, 'b'); + }); + + await c.sendKeys(Key.Shift, Key.Tab); + await eventually(async() => { + let items = await c.getCompletions(); + assert(items[3].highlight) + + let v = await c.currentValue(); + assert.equal(v, 'bdeletes'); + }); + }); +}); diff --git a/e2e/completion_set.test.js b/e2e/completion_set.test.js new file mode 100644 index 0000000..cf5ff5b --- /dev/null +++ b/e2e/completion_set.test.js @@ -0,0 +1,75 @@ +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 Console = require('./lib/Console'); + +const Key = lanthan.Key; + +describe("completion on set commands", () => { + const port = 12321; + 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; + + await browser.storage.local.set({ + settings, + }); + }); + + after(async() => { + if (firefox) { + await firefox.close(); + } + }); + + beforeEach(async() => { + await session.navigateTo(`about:blank`); + body = await session.findElementByCSS('body'); + }); + + it('should show all property names by "set" command with empty params', async() => { + await body.sendKeys(':'); + + await session.switchToFrame(0); + let c = new Console(session); + await c.sendKeys('set '); + + await eventually(async() => { + let items = await c.getCompletions(); + assert.equal(items.length, 5); + assert.deepEqual(items[0], { type: 'title', text: 'Properties' }); + assert(items[1].text.startsWith('hintchars')) + assert(items[2].text.startsWith('smoothscroll')) + assert(items[3].text.startsWith('nosmoothscroll')) + assert(items[4].text.startsWith('complete')) + }); + }); + + it('should show filtered property names by "set" command', async() => { + await body.sendKeys(':'); + + await session.switchToFrame(0); + let c = new Console(session); + await c.sendKeys('set no'); + + await eventually(async() => { + let items = await c.getCompletions(); + assert.equal(items.length, 2); + assert(items[1].text.includes('nosmoothscroll')) + }); + }); +}); diff --git a/e2e/lib/Console.js b/e2e/lib/Console.js index a3391ee..3a39b64 100644 --- a/e2e/lib/Console.js +++ b/e2e/lib/Console.js @@ -8,6 +8,13 @@ class Console { input.sendKeys(...keys); } + async currentValue() { + return await this.session.executeScript(() => { + let input = document.querySelector('input'); + return input.value; + }); + } + async getCompletions() { return await this.session.executeScript(() => { let items = document.querySelectorAll('.vimvixen-console-completion > li'); @@ -20,7 +27,8 @@ class Console { if (li.classList.contains('vimvixen-console-completion-title')) { objs.push({ type: 'title', text: li.textContent.trim() }); } else if ('vimvixen-console-completion-item') { - objs.push({ type: 'item', text: li.textContent.trim() }); + let highlight = li.classList.contains('vimvixen-completion-selected'); + objs.push({ type: 'item', text: li.textContent.trim(), highlight }); } else { throw new Error(`unexpected class: ${li.className}`); }