// Script to find regressions // // It should use as few liberator methods as possible, but fall back to standard mozilla/DOM methods // The reason it, we don't want to find regressions in the regressions script, and it should survive // massive changes in the internal liberator API, but just test for functionality of // user-visible commands/mappings // // NOTE: It is preferable to run this script in a clean profile or at least do NOT use // :mkvimperatorrc afterwards, as it can remove commands/mappings, etc. // // Usage: :[count]regr[essions] // When [count] is given, just run this test. TODO: move to :regressions [spec]? // all tests var skipTests = [":bmarks", "gg"]; ///////////////////////////////////////////////////////////////////////////////////////// // Put definitions here which might change due to internal liberator refactoring ///////////////////////////////////////////////////////////////////////////////////////// var doc; // document where we output status messages var multilineOutput = document.getElementById("liberator-multiline-output"); var singlelineOutput = document.getElementById("liberator-message"); ///////////////////////////////////////////////////////////////////////////////////////// // TESTS // // They are run in order, so you can specify commands which expect side effects of a // previous command ///////////////////////////////////////////////////////////////////////////////////////// // A series of Ex commands or mappings, each with a // function checking whether the command succeeded // If the string starts with a ":" it is executed as an Ex command, otherwise as a mapping // You can also mix commands and mappings let tests = [ { cmds: [":!dir"], verify: function () getMultilineOutput().length > 10 }, { cmds: [":abbr VIMP vimperator labs", ":abbr"], verify: function () getOutput().indexOf("vimperator labs") >= 0 }, { cmds: [":unabbr VIMP", ":abbr"], verify: function () getOutput().indexOf("vimperator labs") == -1 }, { cmds: [":bmarks"], verify: function () getMultilineOutput().length > 100 }, { cmds: [":echo \"test\""], verify: function () getSinglelineOutput() == "test" }, { cmds: [":qmark V http://test.vimperator.org", ":qmarks"], verify: function () getMultilineOutput().indexOf("test.vimperator.org") >= 0 }, { cmds: [":javascript liberator.echo('test', commandline.FORCE_MULTILINE)"], verify: function () getMultilineOutput() == "test" }, // { cmds: [":echomsg \"testmsg\""], // verify: function () getOutput() == "testmsg" }, // { cmds: [":echoerr \"testerr\""], // verify: function () getOutput() == "testerr" }, { cmds: ["gg", ""], // NOTE: does not work when there is no page to scroll, we should load a large page before doing these tests verify: function () this._initialPos.y != getBufferPosition().y, init: function () this._initialPos = getBufferPosition() } // testing tab behavior ]; // these functions highly depend on the liberator API, so use Ex command tests whenever possible let functions = [ function () { return bookmarks.get("").length > 0 }, // will fail for people without bookmarks :( Might want to add one before function () { return history.get("").length > 0 } ]; ///////////////////////////////////////////////////////////////////////////////////////// // functions below should be as generic as possible, and not require being rewritten // even after doing major Vimperator refactoring ///////////////////////////////////////////////////////////////////////////////////////// function resetEnvironment() { multilineOutput.contentDocument.body.innerHTML = ""; singlelineOutput.value = ""; commandline.close(); modes.reset(); } function getOutput() multilineOutput.contentDocument.body.textContent || singlelineOutput.value; function getMultilineOutput() multilineOutput.contentDocument.body.textContent; function getSinglelineOutput() singlelineOutput.value; function getTabIndex() getBrowser().mTabContainer.selectedIndex; function getTabCount() getBrowser().mTabs.length; function getBufferPosition() { let win = window.content; return { x: win.scrollMaxX ? win.pageXOffset / win.scrollMaxX : 0, y: win.scrollMaxY ? win.pageYOffset / win.scrollMaxY : 0 } }; function getLocation() window.content.document.location.href; function echoLine(str, group) { if (!doc) return; doc.body.appendChild(util.xmlToDom(
{str}
, doc)); } function echoMulti(str, group) { if (!doc) return; doc.body.appendChild(util.xmlToDom(
{template.maybeXML(str)}
, doc)); } commands.addUserCommand(["regr[essions]"], "Run regression tests", function (args) { // TODO: might need to increase the 'messages' option temporarily // TODO: count (better even range) support to just run test 34 of 102 // TODO: bang support to either: a) run commands like deleting bookmarks which // should only be done in a clean profile or b) run functions and not // just Ex command tests; Yet to be decided let updateOutputHeight = null; function init() { liberator.registerObserver("echoLine", echoLine); liberator.registerObserver("echoMultiline", echoMulti); liberator.open("chrome://liberator/content/buffer.xhtml", liberator.NEW_TAB); events.waitForPageLoad(); doc = content.document; doc.body.setAttributeNS(NS.uri, "highlight", "CmdLine"); updateOutputHeight = commandline.updateOutputHeight; commandline.updateOutputHeight = function (open) { let elem = document.getElementById("liberator-multiline-output"); if (open) elem.collapsed = false; elem.height = 0; }; } function cleanup() { liberator.unregisterObserver("echoLine", echoLine); liberator.unregisterObserver("echoMultiline", echoMulti); commandline.updateOutputHeight = updateOutputHeight; } function run () { let now = Date.now(); let totalTests = tests.length + functions.length; let successfulTests = 0; let skippedTests = 0; let currentTest = 0; init(); // TODO: might want to unify 'tests' and 'functions' handling // 1.) run commands and mappings tests outer: for (let [, test] in Iterator(tests)) { currentTest++; if (args.count >= 1 && currentTest != args.count) continue; let testDescription = util.clip(test.cmds.join(" -> "), 80); for (let [,cmd] in Iterator(test.cmds)) { if (skipTests.indexOf(cmd) != -1) { skippedTests++; liberator.echomsg("Skipping test " + currentTest + " of " + totalTests + ": " + testDescription, 0); continue outer; } }; commandline.echo("Running test " + currentTest + " of " + totalTests + ": " + testDescription, "Filter", commandline.APPEND_TO_MESSAGES); resetEnvironment(); if ("init" in test) test.init(); test.cmds.forEach(function (cmd) { if (cmd[0] == ":") liberator.execute(cmd); else events.feedkeys(cmd); }); if (!test.verify()) liberator.echoerr("Test " + currentTest + " failed: " + testDescription); else successfulTests++; } // 2.) Run function tests for (let [, func] in Iterator(functions)) { currentTest++; if (args.count >= 1 && currentTest != args.count) continue; commandline.echo("Running test " + currentTest + " of " + totalTests + ": " + util.clip(func.toString().replace(/[\s\n]+/gm, " "), 80), "Filter", commandline.APPEND_TO_MESSAGES); resetEnvironment(); if (!func()) liberator.echoerr("Test " + currentTest + " failed!"); else successfulTests++; } cleanup(); let runTests = (args.count >= 1 ? 1 : totalTests) - skippedTests; XML.ignoreWhitespace = false; liberator.echomsg( {successfulTests} of {runTests} tests successfully completed ({skippedTests} tests skipped) in {((Date.now() - now) / 1000.0)} msec .*); liberator.execute(":messages"); } if (!args.bang) { liberator.echo( Running tests should always be done in a new profile.
It should not do any harm to your profile, but your current settings like options, abbreviations or mappings might not be in the same state as before running the tests. Just make sure, you don't :mkvimperatorrc, after running the tests.

Use :regressions! to skip this prompt.
.*); commandline.input("Type 'yes' to run the tests: ", function (res) { if (res == "yes") run(); } ); return; } run(); }, { bang: true, argCount: "0", count: true }); // vimperator: set et sts=4 sw=4 :