From a9cf9525053f91b957ad1aebb896fc3bd0c3fe51 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 19 Jun 2017 17:58:45 +0530 Subject: [PATCH] UI Tests for Frappe (#3500) * init nightwatch.js * add nightwatch to travis typo nightwatch fix kill node launch_url run tests on local selenium manually run sc sc in bg with sleep minor minor run test on chromedriver simplify travis minor add chrome package implicit chromedriver nightwatch.global.js path fix console statement enable screenshot send screenshot to telegram path minor remove chromium add binary screenshot url cleanup increase timout minor minor minor * login test add page_objects in config Fix login test * bench run-ui-tests * update package.json * update travis * bench reinstall before running ui tests --- .travis.yml | 19 +++++--- frappe/commands/utils.py | 28 +++++++++++ frappe/nightwatch.global.js | 12 +++++ frappe/nightwatch.js | 96 +++++++++++++++++++++++++++++++++++++ frappe/tests/ui/login.js | 19 ++++++++ package.json | 2 + 6 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 frappe/nightwatch.global.js create mode 100644 frappe/nightwatch.js create mode 100644 frappe/tests/ui/login.js diff --git a/.travis.yml b/.travis.yml index bfebd00947..36379390b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,11 +4,17 @@ dist: trusty python: - "2.7" +addons: + apt: + sources: + - google-chrome + packages: + - google-chrome-stable + services: - mysql before_install: - - export CHROME_BIN=chromium-browser - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start @@ -23,18 +29,19 @@ install: - cd ~/ && bench init frappe-bench --frappe-path $TRAVIS_BUILD_DIR - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/ -script: - - set -e - - bench --verbose run-tests - before_script: - mysql -u root -ptravis -e 'create database test_frappe' - echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis - echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis - cd ~/frappe-bench - - npm install babel-core less chokidar babel-preset-es2015 babel-preset-es2016 babel-preset-es2017 babel-preset-babili - bench use test_site - bench reinstall --yes - bench start & - sleep 10 + +script: + - set -e + - bench --verbose run-tests + - bench reinstall --yes + - bench run-ui-tests --ci diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index 9d7d13a1a1..cfe6d83cbe 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -326,6 +326,33 @@ def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None sys.exit(ret) +@click.command('run-ui-tests') +@click.option('--app', help="App to run tests on, leave blank for all apps") +@click.option('--ci', is_flag=True, default=False, help="Run in CI environment") +@pass_context +def run_ui_tests(context, app=None, ci=False): + "Run UI tests" + import subprocess + + site = get_site(context) + frappe.init(site=site) + + if app is None: + app = ",".join(frappe.get_installed_apps()) + + cmd = [ + './node_modules/.bin/nightwatch', + '--config', './apps/frappe/frappe/nightwatch.js', + '--app', app, + '--site', site + ] + + if ci: + cmd.extend(['--env', 'ci_server']) + + bench_path = frappe.utils.get_bench_path() + subprocess.call(cmd, cwd=bench_path) + @click.command('serve') @click.option('--port', default=8000) @click.option('--profile', is_flag=True, default=False) @@ -459,6 +486,7 @@ commands = [ request, reset_perms, run_tests, + run_ui_tests, serve, set_config, watch, diff --git a/frappe/nightwatch.global.js b/frappe/nightwatch.global.js new file mode 100644 index 0000000000..f7530e422f --- /dev/null +++ b/frappe/nightwatch.global.js @@ -0,0 +1,12 @@ +var chromedriver = require('chromedriver'); +module.exports = { + before: function (done) { + chromedriver.start(); + done(); + }, + + after: function (done) { + chromedriver.stop(); + done(); + } +}; \ No newline at end of file diff --git a/frappe/nightwatch.js b/frappe/nightwatch.js new file mode 100644 index 0000000000..a54c764b88 --- /dev/null +++ b/frappe/nightwatch.js @@ -0,0 +1,96 @@ +const fs = require('fs'); + +const ci_mode = get_cli_arg('env') === 'ci_server'; +const site_name = get_cli_arg('site'); +let app_name = get_cli_arg('app'); + +if(!app_name) { + console.log('Please specify app to run tests'); + return; +} + +if(!ci_mode && !site_name) { + console.log('Please specify site to run tests'); + return; +} + +// site url +let site_url; +if(site_name) { + site_url = 'http://' + site_name + ':' + get_port(); +} + +// multiple apps +if(app_name.includes(',')) { + app_name = app_name.split(','); +} else { + app_name = [app_name]; +} + +let test_folders = []; +let page_objects = []; +for(const app of app_name) { + const test_folder = `apps/${app}/${app}/tests/ui`; + const page_object = test_folder + '/page_objects'; + + if(!fs.existsSync(test_folder)) { + console.log(`No test folder found for "${app}"`); + continue; + } + test_folders.push(test_folder); + + if(fs.existsSync(page_object)) { + page_objects.push(); + } +} + +const config = { + "src_folders": test_folders, + "globals_path" : 'apps/frappe/frappe/nightwatch.global.js', + "page_objects_path": page_objects, + "selenium": { + "start_process": false + }, + "test_settings": { + "default": { + "launch_url": site_url, + "selenium_port": 9515, + "selenium_host": "127.0.0.1", + "default_path_prefix": "", + "silent": true, + // "screenshots": { + // "enabled": true, + // "path": SCREENSHOT_PATH + // }, + "globals": { + "waitForConditionTimeout": 15000 + }, + "desiredCapabilities": { + "browserName": "chrome", + "chromeOptions": { + "args": ["--no-sandbox", "--start-maximized"] + }, + "javascriptEnabled": true, + "acceptSslCerts": true + } + }, + "ci_server": { + "launch_url": 'http://localhost:8000' + } + } +} +module.exports = config; + +function get_cli_arg(key) { + var args = process.argv; + var i = args.indexOf('--' + key); + if(i === -1) { + return null; + } + return args[i + 1]; +} + +function get_port() { + var bench_config = JSON.parse(fs.readFileSync('sites/common_site_config.json')); + return bench_config.webserver_port; +} \ No newline at end of file diff --git a/frappe/tests/ui/login.js b/frappe/tests/ui/login.js new file mode 100644 index 0000000000..4d9c8ef21b --- /dev/null +++ b/frappe/tests/ui/login.js @@ -0,0 +1,19 @@ +module.exports = { + beforeEach: browser => { + browser + .url(browser.launch_url + '/login') + .waitForElementVisible('body', 5000) + }, + 'Login': browser => { + browser + .assert.title('Login') + .assert.visible('#login_email', 'Check if login box is visible') + .setValue("#login_email", "Administrator") + .setValue("#login_password", "admin") + .click(".btn-login") + .waitForElementVisible("#body_div", 15000); + }, + after: browser => { + browser.end(); + }, +}; \ No newline at end of file diff --git a/package.json b/package.json index c115c6bf9b..b26b4f2a53 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,11 @@ "babel-preset-es2016": "^6.24.1", "babel-preset-es2017": "^6.24.1", "chokidar": "^1.7.0", + "chromedriver": "^2.30.1", "cookie": "^0.3.1", "express": "^4.15.3", "less": "^2.7.2", + "nightwatch": "^0.9.16", "redis": "^2.7.1", "socket.io": "^2.0.1", "superagent": "^3.5.2"