~glacambre/firenvim

4907b8d3554aae7f7f2c298a73f7f512f0ead2ed — glacambre 1 year, 11 months ago f351643
Improve testsuite

This commit:
- Coalesces window population + cursor movement in a single RPC
  operation removing latency
- Refactors and reduces testing delays
- Removes dead tests
4 files changed, 38 insertions(+), 113 deletions(-)

M src/NeovimFrame.ts
M tests/_common.ts
M tests/chrome.ts
M tests/firefox.ts
M src/NeovimFrame.ts => src/NeovimFrame.ts +10 -12
@@ 68,19 68,17 @@ window.addEventListener("load", async () => {

        const filename = toFileName(url, selector);
        const content = await contentPromise;
        const beforeCursor = content.slice(0, cursor);
        const newlines = beforeCursor.match(/\n.*/g);
        let line = 1;
        let col = beforeCursor.length;
        if (newlines) {
            line = newlines.length + 1;
            col = newlines[newlines.length - 1].length - 1;
        }
        nvim.call_function("writefile", [content.split("\n"), filename])
            .then(() => nvim.command(`noswapfile edit ${filename}`))
            .then(() => {
                const beforeCursor = content.slice(0, cursor);
                const newlines = beforeCursor.match(/\n.*/g);
                let line = 1;
                let col = beforeCursor.length;
                if (newlines) {
                    line = newlines.length + 1;
                    col = newlines[newlines.length - 1].length - 1;
                }
                return nvim.win_set_cursor(0, [line, col]);
            });
            .then(() => nvim.command(`noswapfile edit ${filename} `
                                     + `| call nvim_win_set_cursor(0, [${line}, ${col}])`));

        // Keep track of last active instance (necessary for firenvim#focus_input() & others)
        const chan = nvim.get_current_channel();

M tests/_common.ts => tests/_common.ts +26 -95
@@ 7,7 7,9 @@ const By = webdriver.By;

import { readVimrc, writeVimrc } from "./_vimrc";

jest.setTimeout(40000)
jest.setTimeout(15000);
const keyDelay = 50;
const FIRENVIM_INIT_DELAY = 450;

export const pagesDir = path.resolve(path.join("tests", "pages"));
export const extensionDir = path.resolve("target");


@@ 37,13 39,12 @@ export function getNewestFileMatching(directory: string, pattern: string | RegEx
                .then((stats: any[]) => (stats.sort((stat1, stat2) => stat2.mtime - stat1.mtime)[0] || {}).path)
}

const keyDelay = 50;

function sendKeys(driver: any, keys: any[]) {
        return keys.reduce((prom, key) => prom
                .then((action: any) => action.sendKeys(key))
                .then((action: any) => action.pause(keyDelay))
                , Promise.resolve(driver.actions())).then((action: any) => action.perform());
                , Promise.resolve(driver.actions()))
            .then((action: any) => action.perform());
}

function loadLocalPage(driver: any, page: string) {


@@ 60,7 61,7 @@ export async function testModifiers(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing <C-v><C-a><C-v><A-v><C-v><D-a><S-Left>…");
        await driver.actions()
                .keyDown("a")


@@ 103,7 104,6 @@ export async function testModifiers(driver: any) {
                .keyUp(webdriver.Key.SHIFT)
                .pause(keyDelay)
                .perform();
        await driver.sleep(500);
        console.log("Writing keycodes.");
        await sendKeys(driver, [webdriver.Key.ESCAPE]
                       .concat(":wq!".split(""))


@@ 123,7 123,7 @@ export async function testGStartedByFirenvim(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing a<C-r>=g:started_by_firenvim<CR><Esc>:wq<CR>…");
        await sendKeys(driver, ["a"])
        await driver.actions()


@@ 137,7 137,6 @@ export async function testGStartedByFirenvim(driver: any) {
                       .concat([webdriver.Key.ESCAPE])
                       .concat(":wq!".split(""))
                       .concat(webdriver.Key.ENTER));
        await driver.sleep(500);
        console.log("Waiting for span to be removed from page…");
        await driver.wait(Until.stalenessOf(span));
        console.log("Waiting for value update…");


@@ 153,7 152,7 @@ export async function testCodemirror(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(3)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing stuff…");
        await sendKeys(driver, "iTest".split("")
                .concat(webdriver.Key.ESCAPE)


@@ 175,7 174,7 @@ export async function testAce(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(4)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing stuff…");
        await sendKeys(driver, "ATest".split("")
                .concat(webdriver.Key.ESCAPE)


@@ 197,7 196,7 @@ export async function testMonaco(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(9)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing stuff…");
        await sendKeys(driver, "iTest".split("")
                .concat(webdriver.Key.ESCAPE)


@@ 219,7 218,7 @@ export async function testDynamicTextareas(driver: any) {
        await driver.actions().click(btn).perform();
        console.log("Waiting for span to be created…");
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(4)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing things…");
        await sendKeys(driver, "aTest".split("")
                .concat(webdriver.Key.ESCAPE)


@@ 242,7 241,7 @@ export async function testNestedDynamicTextareas(driver: any) {
        await driver.actions().click(btn).perform();
        console.log("Waiting for span to be created…");
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(4)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing things…");
        await sendKeys(driver, "aTest".split("")
                .concat(webdriver.Key.ESCAPE)


@@ 274,7 273,7 @@ export async function killPreloadedInstance(driver: any) {
                .keyUp("e")
                .keyUp(webdriver.Key.CONTROL)
                .perform();
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        await driver.executeScript(`
                const elem = document.getElementById("${id}");
                elem.parentElement.removeChild(elem);


@@ 305,73 304,6 @@ export async function testVimrcFailure(driver: any) {
        await driver.wait(Until.stalenessOf(span));
}

export async function testManualNvimify(driver: any) {
        await loadLocalPage(driver, "simple.html");
        console.log("Backing up vimrc…");
        const backup = await readVimrc();
        console.log("Overwriting it…");
        await writeVimrc(`
let g:firenvim_config = {
    \\ 'localSettings': {
        \\ '.*': {
            \\ 'selector': '',
            \\ 'priority': 0,
        \\ }
    \\ }
\\ }
${backup}
                `);
        await killPreloadedInstance(driver);
        await loadLocalPage(driver, "simple.html");
        const input = await driver.wait(Until.elementLocated(By.id("content-input")));
        await driver.executeScript("arguments[0].scrollIntoView(true);", input);
        console.log("Clicking on input…");
        await driver.actions().click(input).perform();
        console.log("Making sure a frame didn't pop up.");
        await driver.sleep(500);
        await driver.findElement(By.css("body > span:nth-child(2)"))
                .catch((): void => undefined)
                .then((e: any) => {
                        if (e !== undefined) {
                                throw new Error("Frame automatically created while disabled by config.");
                        }
                });
        await driver.actions()
                .keyDown(webdriver.Key.CONTROL)
                .keyDown("e")
                .pause(keyDelay)
                .keyUp("e")
                .keyUp(webdriver.Key.CONTROL)
                .perform();
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        console.log("Typing things…");
        await sendKeys(driver, "aTest".split("")
                .concat(webdriver.Key.ESCAPE)
                .concat(":wq!".split(""))
                .concat(webdriver.Key.ENTER)
        );
        console.log("Waiting for span to be removed…");
        await driver.wait(Until.stalenessOf(span));
        console.log("Waiting for value update…");
        await driver.wait(async () => (await input.getAttribute("value")) === "Test");
        // Unfocus element
        await driver.executeScript("arguments[0].blur();", input);
        await driver.sleep(500);
        await driver.actions().click(input).perform();
        console.log("Making sure a frame didn't pop up.");
        await driver.sleep(500);
        await driver.findElement(By.css("body > span:nth-child(2)"))
                .catch((): void => undefined)
                .then((e: any) => {
                        if (e !== undefined) {
                                throw new Error("Frame automatically created while disabled by config.");
                        }
                });
        await writeVimrc(backup);
        await killPreloadedInstance(driver);
}

export async function testGuifont(driver: any) {
        await loadLocalPage(driver, "simple.html");
        console.log("Backing up vimrc…");


@@ 391,7 323,7 @@ ${backup}
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        let span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing 30aa<Esc>^gjib<Esc>:wq!<Enter>…");
        await sendKeys(driver, "30aa".split("")
                .concat(webdriver.Key.ESCAPE)


@@ 404,7 336,7 @@ ${backup}
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing ^gjib<Esc>:wq!<Enter>…");
        await sendKeys(driver, "^gjib".split("")
                .concat(webdriver.Key.ESCAPE)


@@ 423,7 355,7 @@ export async function testPageFocus(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        let span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing :call firenvim#focus_page()<CR>…");
        await sendKeys(driver, ":call firenvim#focus_page()".split("")
                .concat(webdriver.Key.ENTER));


@@ 440,7 372,7 @@ export async function testInputFocus(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        let span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing :call firenvim#focus_input()<CR>…");
        await sendKeys(driver, ":call firenvim#focus_input()".split("")
                .concat(webdriver.Key.ENTER));


@@ 458,7 390,7 @@ export async function testPressKeys(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        let span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing iHello<Esc>:w<CR>:call firenvim#press_keys('<CR>')<CR>:q!<CR>…");
        await sendKeys(driver, "iHello".split("")
                .concat(webdriver.Key.ESCAPE)


@@ 481,7 413,7 @@ export async function testInputFocusedAfterLeave(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        let span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing :q!<CR>…");
        await sendKeys(driver, ":q!".split("")
                .concat(webdriver.Key.ENTER));


@@ 508,7 440,7 @@ ${backup}
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        let span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        await writeVimrc(backup);
        console.log("Typing :q!<CR>…");
        await sendKeys(driver, ":q!".split("")


@@ 516,10 448,9 @@ ${backup}
        console.log("Focusing body…");
        const body = await driver.wait(Until.elementLocated(By.id("body")));
        await driver.actions().click(body).perform();
        await driver.sleep(500);
        console.log("Focusing input again…");
        await driver.actions().click(input).perform();
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Making sure span didn't pop up.");
        await driver.findElement(By.css("body > span:nth-child(2)"))
                .catch((): void => undefined)


@@ 547,7 478,7 @@ ${backup}
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        let span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing ii<Esc>:wq!<CR>…");
        await sendKeys(driver, "ii".split("")
            .concat(webdriver.Key.ESCAPE)


@@ 560,7 491,7 @@ ${backup}
        await driver.wait(async () => (await input.getAttribute("value")) === "i");
        console.log("Focusing input again…");
        await driver.actions().click(input).perform();
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Making sure span didn't pop up.");
        await driver.findElement(By.css("body > span:nth-child(2)"))
                .catch((): void => undefined)


@@ 586,7 517,7 @@ ${backup}
        await driver.executeScript("arguments[0].scrollIntoView(true);", input);
        console.log("Clicking on input…");
        await driver.actions().click(input).perform();
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Making sure span didn't pop up.");
        await driver.findElement(By.css("body > span:nth-child(2)"))
                .catch((): void => undefined)


@@ 605,7 536,7 @@ ${backup}
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        let span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        console.log("Typing :q!<CR>…");
        await sendKeys(driver, ":q!".split("").concat(webdriver.Key.ENTER));
        console.log("Waiting for span to be removed from page…");


@@ 623,7 554,7 @@ export async function testLargeBuffers(driver: any) {
        await driver.actions().click(input).perform();
        console.log("Waiting for span to be created…");
        const span = await driver.wait(Until.elementLocated(By.css("body > span:nth-child(2)")));
        await driver.sleep(500);
        await driver.sleep(FIRENVIM_INIT_DELAY);
        await sendKeys(driver, ":wq!".split("").concat(webdriver.Key.ENTER))
        console.log("Waiting for span to be removed from page…");
        await driver.wait(Until.stalenessOf(span));

M tests/chrome.ts => tests/chrome.ts +1 -2
@@ 68,6 68,7 @@ describe("Chrome", () => {
                        .forBrowser("chrome")
                        .setChromeOptions(options)
                        .build();
                return Promise.resolve();
        });

        afterAll(() => killDriver(driver));


@@ 89,6 90,4 @@ describe("Chrome", () => {
        nonHeadlessTest()("Takeover: empty works", () => testTakeoverEmpty(driver));
        nonHeadlessTest()("Takeover: nonempty works", () => testTakeoverNonEmpty(driver));
        nonHeadlessTest()("Takeover: once works", () => testTakeoverOnce(driver));
        // Disabled because Chrome doesn't pass keyboard shortcuts to webextensions…
        // test("Manually calling firenvim works", () => testManualNvimify(driver));
})

M tests/firefox.ts => tests/firefox.ts +1 -4
@@ 20,7 20,6 @@ import {
 testInputFocus,
 testInputFocusedAfterLeave,
 testLargeBuffers,
 testManualNvimify,
 testModifiers,
 testMonaco,
 testNestedDynamicTextareas,


@@ 67,7 66,7 @@ describe("Firefox", () => {
                        .forBrowser("firefox")
                        .setFirefoxOptions(options)
                        .build();
                driver.getCapabilities().then((cap: any) => {
                return driver.getCapabilities().then((cap: any) => {
                        console.log(`${cap.getBrowserName()} ${cap.getBrowserVersion()} ${xpiPath}`);
                });
        });


@@ 91,6 90,4 @@ describe("Firefox", () => {
        test("Takeover: empty works", () => testTakeoverEmpty(driver));
        test("Takeover: nonempty works", () => testTakeoverNonEmpty(driver));
        test("Takeover: once works", () => testTakeoverOnce(driver));
        // Disabled because Firefox doesn't pass keyboard shortcuts to webextensions…
        // test("Manually calling firenvim works", () => testManualNvimify(driver));
})