From 2d5b70c9644daaf0d186ffefa203ba5e3cb0ae22 Mon Sep 17 00:00:00 2001 From: Kylart Date: Tue, 23 May 2017 16:19:25 +0200 Subject: [PATCH] Implemented nightwatch for front testing --- .gitignore | 4 +- nightwatch.conf.js | 85 +++++++++++++++++++++++++++++++++++++++++ package.json | 21 +++++++++- test/nightwatch/main.js | 51 +++++++++++++++++++++++++ test/server.test.js | 40 ++++--------------- 5 files changed, 165 insertions(+), 36 deletions(-) create mode 100644 nightwatch.conf.js create mode 100644 test/nightwatch/main.js diff --git a/.gitignore b/.gitignore index 449dd8d..f8c1a55 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,6 @@ dist/linux-unpacked dist/latest.yml # tests -.nyc_output \ No newline at end of file +.nyc_output +reports +selenium-debug.log \ No newline at end of file diff --git a/nightwatch.conf.js b/nightwatch.conf.js new file mode 100644 index 0000000..84b24dd --- /dev/null +++ b/nightwatch.conf.js @@ -0,0 +1,85 @@ +/** + * Created by Kylart on 23/05/2017. + */ +// require('env2')('.env') // optionally store your Evironment Variables in .env +require('babel-register')() +const SCREENSHOT_PATH = './screenshots/' +const BINPATH = './node_modules/nightwatch/bin/' + +// we use a nightwatch.conf.js file so we can include comments and helper functions +module.exports = { + 'src_folders': [ + 'test/nightwatch'// Where you are storing your Nightwatch tests + ], + 'output_folder': './reports', // reports (test outcome) output by nightwatch + 'selenium': { // downloaded by selenium-download module (see readme) + 'start_process': true, // tells nightwatch to start/stop the selenium process + 'server_path': './node_modules/nightwatch/bin/selenium.jar', + 'host': '127.0.0.1', + 'port': 4444, // standard selenium port + 'cli_args': { // chromedriver is downloaded by selenium-download (see readme) + 'webdriver.chrome.driver': './node_modules/nightwatch/bin/chromedriver' + } + }, + 'test_settings': { + 'default': { + 'screenshots': { + 'enabled': true, // if you want to keep screenshots + 'path': './screenshots' // save screenshots here + }, + 'globals': { + 'waitForConditionTimeout': 5000, // sometimes internet is slow so wait. + 'asyncHookTimeout': 35000 + }, + 'desiredCapabilities': { // use Chrome as the default browser for tests + 'browserName': 'chrome' + } + }, + 'chrome': { + 'desiredCapabilities': { + 'browserName': 'chrome', + 'javascriptEnabled': true // turn off to test progressive enhancement + } + } + } +} +/** + * selenium-download does exactly what it's name suggests; + * downloads (or updates) the version of Selenium (& chromedriver) + * on your localhost where it will be used by Nightwatch. + /the following code checks for the existence of `selenium.jar` before trying to run our tests. + */ + +require('fs').stat(BINPATH + 'selenium.jar', function (err, stat) { // got it? + if (err || !stat || stat.size < 1) { + require('selenium-download').ensure(BINPATH, function (error) { + if (error) throw new Error(error) // no point continuing so exit! + console.log('✔ Selenium & Chromedriver downloaded to:', BINPATH) + }) + } +}) + +function padLeft (count) { // theregister.co.uk/2016/03/23/npm_left_pad_chaos/ + return count < 10 ? '0' + count : count.toString() +} + +let FILECOUNT = 0 // "global" screenshot file count +/** + * The default is to save screenshots to the root of your project even though + * there is a screenshots path in the config object above! ... so we need a + * function that returns the correct path for storing our screenshots. + * While we're at it, we are adding some meta-data to the filename, specifically + * the Platform/Browser where the test was run and the test (file) name. + */ +function imgpath (browser) { + const a = browser.options.desiredCapabilities + const meta = [a.platform] + meta.push(a.browserName ? a.browserName : 'any') + meta.push(a.version ? a.version : 'any') + meta.push(a.name) // this is the test filename so always exists. + const metadata = meta.join('~').toLowerCase().replace(/ /g, '') + return SCREENSHOT_PATH + metadata + '_' + padLeft(FILECOUNT++) + '_' +} + +module.exports.imgpath = imgpath +module.exports.SCREENSHOT_PATH = SCREENSHOT_PATH diff --git a/package.json b/package.json index ea2e60a..638e4db 100755 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "scripts": { "dev": "cross-env NODE_ENV=development electron .", "test:server": "nyc ava --verbose --serial test/server.test.js", - "test:front": "nuxt build && nyc mocha test/front.test.js", + "test:front": "nightwatch", "test": "standard --fix && nuxt build && mocha test/mocha.js && ava test/nuxt.js", "build": "nuxt build", "start": "electron .", @@ -21,7 +21,8 @@ "buildLinux": "build --linux deb AppImage zip tar.gz", "buildWin": "build --win nsis --ia32 x64 appx zip squirrel", "buildMac": "build --mac dmg zip pkg", - "buildAll": "nuxt build && npm run buildMac && npm run buildWin && npm run buildLinux && build --armv7l" + "buildAll": "nuxt build && npm run buildMac && npm run buildWin && npm run buildLinux && build --armv7l", + "postinstall": "node nightwatch.conf.js" }, "dependencies": { "axios": "^0.16.0", @@ -34,17 +35,22 @@ }, "devDependencies": { "ava": "^0.19.1", + "babel-plugin-add-module-exports": "^0.2.1", + "babel-preset-es2015": "^6.24.1", "chai": "^3.5.0", "colors": "^1.1.2", "cross-env": "^3.1.4", "devtron": "^1.4.0", "electron": "^1.6.6", "electron-builder": "^17.1.1", + "env2": "^2.2.0", "eslint-plugin-vue": "^2.0.1", "jsdom": "^10.1.0", "mocha": "^3.4.1", + "nightwatch": "^0.9.15", "nyc": "^10.3.2", "pre-commit": "^1.2.2", + "selenium-download": "^2.0.10", "spectron": "^3.6.4", "standard": "^10.0.2", "stylus": "^0.54.5", @@ -82,6 +88,17 @@ "babel": { "presets": [ "es2015" + ], + "plugins": [ + "add-module-exports" + ] + }, + "nyc": { + "exclude": [ + "test", + "**/*.test.js", + "**/node_modules/**", + "**/openExternal.js" ] } } diff --git a/test/nightwatch/main.js b/test/nightwatch/main.js new file mode 100644 index 0000000..906cc6f --- /dev/null +++ b/test/nightwatch/main.js @@ -0,0 +1,51 @@ +/** + * Created by Kylart on 23/05/2017. + */ + +import Nuxt from 'nuxt' +import http from 'http' +import initFile from '../../assets/scripts/init/main.js' +import colors from 'colors' // eslint-disable-line +import {resolve} from 'path' + +// We keep the nuxt and server instance +// So we can close them at the end of the test +let nuxt = null +let server = null +const uri = 'http://localhost:4000' + +module.exports = { // adapted from: https://git.io/vodU0 + before: function (browser, done) { + /** + * Nuxt config + */ + const rootDir = resolve(__dirname, '..', '..') + let config = {} + try { config = require(resolve(rootDir, 'nuxt.config.js')) } catch (e) {} + config.rootDir = rootDir // project folder + config.dev = false // production build + + /** + * Server config + */ + nuxt = new Nuxt(config) + const route = initFile.route(nuxt) + server = http.createServer(route) + nuxt.build().then(() => { + server.listen(4000) + console.log(`KawAnime's server is at http://localhost:${server.address().port}`.green) + done() + }) + }, + 'Guinea Pig Assert Title': function (browser) { + browser + .url(uri) + .waitForElementVisible('body') + .assert.title('KawAnime') + .end() + }, + after: function () { + server.close() + nuxt.close() + } +} diff --git a/test/server.test.js b/test/server.test.js index 0188475..8f07459 100644 --- a/test/server.test.js +++ b/test/server.test.js @@ -16,7 +16,7 @@ import {userInfo} from 'os' // So we can close them at the end of the test let nuxt = null let server = null -const uri = 'htp://localhost:4000' +const uri = 'http://localhost:4000' const DIR = join(userInfo().homedir, '.KawAnime') let kawAnimeFilesPath = { @@ -46,6 +46,8 @@ test.before('Init Nuxt.js', async () => { await nuxt.build() server.listen(4000) console.log(`KawAnime's server is at http://localhost:${server.address().port}`.green) + + console.log = (msg) => { void (msg) } }) test.cb(`KawAnime's local file exists`, t => { @@ -170,41 +172,13 @@ test('/news.json route exits and returns 200 elements', async t => { t.is(data.length, 200) }) -// Example of testing only generated html -test('Route / exits and renders title', async t => { - let context = {} - const { html } = await nuxt.renderRoute('/', context) - t.true(html.includes('かわニメ')) -}) +test('/getHistory', async t => { + const { data, status } = await axios.get(`${uri}/getHistory`) -test('Route / exits and renders loader', async t => { - let context = {} - const { html } = await nuxt.renderRoute('/', context) - t.true(html.includes('少々お待ち下さいね〜')) + t.is(status, 200) + t.not(data, undefined) }) -// Might be temporary only -test('Route /downloader exits and renders magnet switch', async t => { - let context = {} - const { html } = await nuxt.renderRoute('/downloader', context) - t.true(html.includes('Get Magnets')) -}) - -test('Route /downloader exits and renders download button', async t => { - let context = {} - const { html } = await nuxt.renderRoute('/downloader', context) - t.true(html.includes('Download!')) -}) - -// Needs fix from nuxt -// test('Route /downloader', async t => { -// const window = await nuxt.renderAndGetWindow() -// let element = window.document.querySelector('div.form-container') -// t.not(element, null) -// t.is(element.className, 'form-container') -// t.is(element.children[0].className, '.row') -// }) - // Close server and ask nuxt to stop listening to file changes test.after('Closing server and server.test.js', () => { server.close()