From 647432fd71ccab16a745093842e4c44c516ffba9 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Tue, 20 Dec 2016 12:42:46 +0000 Subject: [PATCH] Add support for running JS tests in LOOT from CLI - Use Karma to run the tests. - Support specifying LOOT UI index page as CLI argument, and treat localhost URLs like http://loot URLs, so that Karma can get LOOT to launch the test page. - Fix the JS query tests when run in LOOT, as window.cefQuery can't be stubbed in CEF. --- karma.conf.js | 35 +++++++++++++++++++++++++++++ package.json | 7 +++++- src/gui/loot_app.cpp | 10 ++++----- src/gui/loot_app.h | 5 ++++- src/gui/loot_handler.cpp | 6 ++++- src/gui/main.cpp | 10 ++++++++- src/tests/gui/html/js/test_query.js | 31 ++++++------------------- 7 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 karma.conf.js diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 00000000..06e302f7 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,35 @@ +const helpers = require('./scripts/helpers'); +const path = require('path'); + +process.env.CHROME_BIN = path.join(helpers.getAppReleasePaths('.')[0].path, 'LOOT'); +console.log(`Running tests using browser executable at ${process.env.CHROME_BIN}`); + +module.exports = (config) => { + config.set({ + basePath: '', + frameworks: ['mocha', 'chai'], + files: [ + 'bower_components/Jed/jed.js', + 'bower_components/jed-gettext-parser/jedGettextParser.js', + 'bower_components/lodash/dist/lodash.core.min.js', + 'src/tests/gui/html/js/mock_*.js', + 'src/gui/html/js/filters.js', + 'src/gui/html/js/plugin.js', + 'src/gui/html/js/game.js', + 'src/gui/html/js/query.js', + 'src/gui/html/js/state.js', + 'src/gui/html/js/translator.js', + 'src/gui/html/js/updateExists.js', + 'src/tests/gui/html/js/*.js', + ], + exclude: [], + preprocessors: {}, + reporters: ['progress'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: false, + browsers: ['Chrome'], + singleRun: true, + }); +}; diff --git a/package.json b/package.json index 504db28c..396a13c7 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,18 @@ "chai": "^3.5.0", "eslint": "^3.5.0", "eslint-config-airbnb-base": "^7.1.0", - "eslint-plugin-import": "^1.15.0", "eslint-plugin-html": "^1.5.0", + "eslint-plugin-import": "^1.15.0", "grunt": "^1.0.1", "grunt-cli": "^1.2.0", "grunt-contrib-connect": "^1.0.0", "grunt-contrib-watch": "^1.0.0", "grunt-saucelabs": "^9.0.0", + "karma": "^1.3.0", + "karma-chai": "^0.1.0", + "karma-chrome-launcher": "^2.0.0", + "karma-cli": "^1.0.1", + "karma-mocha": "^1.3.0", "mkdirp": "^0.5.1", "mocha": "^3.0.1" }, diff --git a/src/gui/loot_app.cpp b/src/gui/loot_app.cpp index 3335f6e4..7f6638d0 100644 --- a/src/gui/loot_app.cpp +++ b/src/gui/loot_app.cpp @@ -35,9 +35,12 @@ #include "gui/loot_scheme_handler_factory.h" namespace loot { -void LootApp::Initialise(const std::string& defaultGame, const std::string& lootDataPath) { +void LootApp::Initialise(const std::string& defaultGame, + const std::string& lootDataPath, + const std::string& url) { LootPaths::initialise(lootDataPath); lootState_.init(defaultGame); + url_ = url; } void LootApp::OnBeforeCommandLineProcessing(const CefString& process_type, @@ -93,11 +96,8 @@ void LootApp::OnContextInitialized() { boost::filesystem::path::imbue(std::locale()); } - // Set URL to load. Ignore any command line values. - const std::string url = "http://loot/ui/index.html"; - // Create the first browser window. - CefBrowserHost::CreateBrowser(window_info, handler.get(), url, browser_settings, NULL); + CefBrowserHost::CreateBrowser(window_info, handler.get(), url_, browser_settings, NULL); } void LootApp::OnWebKitInitialized() { diff --git a/src/gui/loot_app.h b/src/gui/loot_app.h index d287f9fb..056068a6 100644 --- a/src/gui/loot_app.h +++ b/src/gui/loot_app.h @@ -36,7 +36,9 @@ class LootApp : public CefApp, public CefBrowserProcessHandler, public CefRenderProcessHandler { public: - void Initialise(const std::string& defaultGame, const std::string& lootDataPath); + void Initialise(const std::string& defaultGame, + const std::string& lootDataPath, + const std::string& url); // Override CefApp methods. virtual void OnBeforeCommandLineProcessing(const CefString& process_type, @@ -60,6 +62,7 @@ private: LootState lootState_; CefRefPtr message_router_; + std::string url_; IMPLEMENT_REFCOUNTING(LootApp); }; diff --git a/src/gui/loot_handler.cpp b/src/gui/loot_handler.cpp index 862549b5..636abb39 100644 --- a/src/gui/loot_handler.cpp +++ b/src/gui/loot_handler.cpp @@ -224,9 +224,13 @@ bool LootHandler::OnBeforeBrowse(CefRefPtr< CefBrowser > browser, bool is_redirect) { BOOST_LOG_TRIVIAL(trace) << "Attempting to open link: " << request->GetURL().ToString(); - if (boost::starts_with(request->GetURL().ToString(), "http://loot/")) { + const std::string url = request->GetURL().ToString(); + if (boost::starts_with(url, "http://loot/")) { BOOST_LOG_TRIVIAL(trace) << "Link is to LOOT page, allowing CEF's default handling."; return false; + } else if (boost::starts_with(url, "http://localhost:")) { + BOOST_LOG_TRIVIAL(warning) << "Link is to a page on localhost, if this isn't happening while running tests, something has gone wrong"; + return false; } BOOST_LOG_TRIVIAL(info) << "Opening link in Windows' default handler."; diff --git a/src/gui/main.cpp b/src/gui/main.cpp index cfb2e670..5990c6ae 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -94,7 +94,15 @@ void processCommandLineArguments(CefRefPtr app) { lootDataPath = command_line->GetSwitchValue("loot-data-path"); } - app.get()->Initialise(defaultGame, lootDataPath); + std::string url = "http://loot/ui/index.html"; + if (command_line->HasArguments()) { + std::vector arguments; + command_line->GetArguments(arguments); + url = arguments[0]; + BOOST_LOG_TRIVIAL(info) << "Loading homepage using URL " << url; + } + + app.get()->Initialise(defaultGame, lootDataPath, url); } #ifdef _WIN32 diff --git a/src/tests/gui/html/js/test_query.js b/src/tests/gui/html/js/test_query.js index 0a06cfb0..dea7df03 100644 --- a/src/tests/gui/html/js/test_query.js +++ b/src/tests/gui/html/js/test_query.js @@ -1,14 +1,5 @@ 'use strict'; -/* Mock the window.cefQuery method */ -window.cefQuery = (obj) => { - if (obj.request === '{"name":"fail","args":[]}') { - obj.onFailure(-1, obj.request); - } else { - obj.onSuccess(obj.request); - } -}; - describe('query()', () => { it('should throw if no arguments are passed', () => { (() => { loot.query(); }).should.throw(); @@ -19,28 +10,20 @@ describe('query()', () => { }); it('should succeed if a request name is passed', () => - loot.query('test').then((result) => - result.should.equal('{"name":"test","args":[]}') + loot.query('discardUnappliedChanges').then((result) => + result.should.be.empty ) ); it('should succeed if a request name and arguments are passed', () => - loot.query('test', 1, false, ['a']).then((result) => - result.should.equal(JSON.stringify({ - name: 'test', - args: [ - 1, - false, - ['a'], - ], - })) + loot.query('copyContent', 'foo').then((result) => + result.should.be.empty ) ); it('should fail with an Error object when an error occurs', () => - loot.query('fail').catch((error) => { - error.should.be.an('error'); - return error.message.should.equal('{"name":"fail","args":[]}'); - }) + loot.query('copyContent').catch((error) => + error.should.be.an('error') + ) ); });