├── nightwatch.json ├── .gitignore ├── .editorconfig ├── .npmignore ├── .eslintrc ├── saucelabs.json ├── test ├── helpers │ └── custom_cmd.js └── env │ └── default │ └── google-demo.js ├── .travis.yml ├── Gruntfile.coffee ├── tasks └── nightwatch.js ├── package.json └── README.md /nightwatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_folders": ["tests"], 3 | "output_folder": "tests_output" 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .c9 2 | *.log 3 | *.jar 4 | *.xml 5 | *.tgz 6 | nightwatch-*.json 7 | chromedriver 8 | /node_modules 9 | /reports 10 | /tests_output 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.sh 3 | *.log 4 | *.jar 5 | *.xml 6 | *.json 7 | Gruntfile.* 8 | chromedriver 9 | /node_modules 10 | /reports 11 | /helpers 12 | /test 13 | /tests_output 14 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "rules": { 7 | "quotes": [2, "single", "avoid-escape"], 8 | "semi": [2, "always"], 9 | "no-unused-vars": 2, 10 | "no-extra-semi": 2, 11 | "no-undef": 2 12 | }, 13 | "ecmaFeatures": { 14 | "modules": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /saucelabs.json: -------------------------------------------------------------------------------- 1 | { 2 | "test_settings": { 3 | "saucelabs": { 4 | "silent": true, 5 | "selenium_host": "localhost", 6 | "selenium_port": 4445, 7 | "custom_commands_path": "test/helpers", 8 | "desiredCapabilities": { 9 | "username": "${SAUCE_USERNAME}", 10 | "accessKey": "${SAUCE_ACCESS_KEY}" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/helpers/custom_cmd.js: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | 3 | module.exports.command = function(value) { 4 | var self = this; 5 | 6 | function myCommand() { 7 | return document.title; 8 | } 9 | 10 | this.execute(myCommand, [], function(result) { 11 | self.assert.ok(result.value.indexOf(value) > -1, 'page title contains "' + value + '"'); 12 | }); 13 | 14 | return this; 15 | }; 16 | -------------------------------------------------------------------------------- /test/env/default/google-demo.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'Demo test Google': function(browser) { 3 | browser 4 | .url('http://www.google.com') 5 | .waitForElementVisible('body', 1000) 6 | .setValue('input[type=text]', 'nodejs') 7 | .waitForElementVisible('button[name=btnG]', 1000) 8 | .click('button[name=btnG]').pause(1000) 9 | .assert.containsText('#ires', 'nodejs.org') 10 | .custom_cmd('nodejs') 11 | .end(); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | global: 3 | - secure: RdOm3bneof0oP3BA6Tq/a4+MrjdjOi9ZQ9pB6ciClTOmVZKfIOmRr/yQ2JIHU0jXMoWbZVEwxVbtfW+kdvwWicEktXJStTGDaop2bDZ3snInTT3GjFSFtF1oTSv+rfhJCBj/6p/uXkeu/qUIFfCZASPm4LX6bg6gs2Y7taGlsBU= 4 | - secure: gapbisL61+eGzlple+7ZIo3LixOIJ6xALj/Fkepy23HcUlR3xRhOUo+wFIfpOOOxVm91prIpCLoUdJAW4Ow87GvhUH/SpYbxlC3B9hTkLc01EtVElAiCLJwASOAnnfGISeasUPTg/jRB4wiKts86NAd/v4abTSPUYtdaPXJ8wtw= 5 | addons: 6 | sauce_connect: true 7 | language: node_js 8 | node_js: 9 | - 0.12 10 | - 4 11 | - 5 12 | - iojs 13 | before_script: 14 | - npm install -g grunt-cli 15 | script: 16 | - grunt nightwatch:saucelabs --settings=saucelabs.json 17 | notifications: 18 | email: false 19 | -------------------------------------------------------------------------------- /Gruntfile.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (grunt) -> 2 | settings = 3 | nightwatch: 4 | options: 5 | standalone: grunt.cli.options.standalone is on 6 | src_folders: 'test/env' 7 | custom_commands_path: 'test/helpers' 8 | saucelabs: 9 | config_path: grunt.cli.options.settings if grunt.cli.options.settings 10 | 11 | if grunt.cli.options.chrome 12 | settings.nightwatch.options.selenium = 13 | cli_args: 14 | 'webdriver.chrome.driver': require('chromedriver').path 15 | 16 | settings.nightwatch['default'] = 17 | desiredCapabilities: 18 | browserName: 'chrome' 19 | 20 | grunt.initConfig settings 21 | grunt.loadTasks 'tasks' 22 | -------------------------------------------------------------------------------- /tasks/nightwatch.js: -------------------------------------------------------------------------------- 1 | var nwrun = require('nwrun'); 2 | 3 | module.exports = function(grunt) { 4 | grunt.registerTask('nightwatch', 'Run your Nightwatch.js tests', function() { 5 | var _ = grunt.util._; 6 | 7 | var done = this.async(); 8 | var options = grunt.config.get('nightwatch'); 9 | 10 | var config = options.options || {}, 11 | tests = _.omit(options, 'options'); 12 | 13 | var args = Array.prototype.slice.call(arguments); 14 | 15 | if (args.length) { 16 | config.target = config.target || []; 17 | Array.prototype.push.apply(config.target, args); 18 | } 19 | 20 | config.argv = config.argv || grunt.cli.options; 21 | config.verbose = config.verbose || grunt.cli.options.verbose; 22 | config.test_settings = _.merge(config.test_settings || {}, tests); 23 | 24 | nwrun(config, done); 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.5.4", 3 | "name": "grunt-nightwatch", 4 | "description": "Run your Nightwatch.js tests with Grunt", 5 | "scripts": { 6 | "dev:lint": "eslint tasks test" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/gextech/grunt-nightwatch.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/gextech/grunt-nightwatch/issues" 14 | }, 15 | "keywords": [ 16 | "ci", 17 | "browser", 18 | "testing", 19 | "selenium", 20 | "automated", 21 | "functional", 22 | "nightwatch" 23 | ], 24 | "author": { 25 | "name": "Alvaro Cabrera", 26 | "email": "pateketrueke@gmail.com" 27 | }, 28 | "publishConfig": { 29 | "registry": "http://registry.npmjs.org" 30 | }, 31 | "license": "MIT", 32 | "dependencies": { 33 | "nwrun": ">=0.3.1" 34 | }, 35 | "devDependencies": { 36 | "chromedriver": "^2.21.2", 37 | "eslint": "^2.6.0", 38 | "grunt": "^1.0.1", 39 | "nightwatch": "^0.8.18" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Grunt meets Nightwatch.js 2 | 3 | [![Build Status](https://travis-ci.org/gextech/grunt-nightwatch.png?branch=master)](https://travis-ci.org/gextech/grunt-nightwatch) [![NPM version](https://badge.fury.io/js/grunt-nightwatch.png)](http://badge.fury.io/js/grunt-nightwatch) 4 | 5 | Automatize your tests: 6 | 7 | ```javascript 8 | module.exports = function(grunt) { 9 | grunt.initConfig({ 10 | nightwatch: { 11 | options: { /* see below */ } 12 | } 13 | }); 14 | 15 | grunt.loadNpmTasks('grunt-nightwatch'); 16 | }; 17 | ``` 18 | 19 | Write some tests: 20 | 21 | **tests/default/google-test.js** 22 | 23 | ```javascript 24 | module.exports = { 25 | 'Demo test Google': function(browser) { 26 | browser 27 | .url('http://www.google.com') 28 | .waitForElementVisible('body', 1000) 29 | .setValue('input[type=text]', 'nodejs') 30 | .waitForElementVisible('button[name=btnG]', 1000) 31 | .click('button[name=btnG]').pause(1000) 32 | .assert.containsText('#ires', 'joyent/node') 33 | .end(); 34 | } 35 | }; 36 | ``` 37 | 38 | Execute: 39 | 40 | ```bash 41 | $ grunt nightwatch # target: default 42 | $ grunt nightwatch:A # target: A 43 | $ grunt nightwatch:A:B # targets: A, B 44 | ``` 45 | 46 | ## Options 47 | 48 | Currently, `grunt-nightwatch` supports the same options as [nwrun](https://github.com/gextech/nwrun) can handle. 49 | 50 | Note that the **nighwatch.json** file settings is fully supported, but your task options will override them if needed. 51 | 52 | ### Gruntfile.js 53 | ```javascript 54 | module.exports = function(grunt) { 55 | grunt.initConfig({ 56 | nightwatch: { 57 | options: { 58 | // task options 59 | standalone: true, 60 | 61 | // download settings 62 | jar_version: '2.44.0', 63 | jar_path: '/opt/selenium/server.jar', 64 | jar_url: 'http://domain.com/files/selenium-server-standalone-1.2.3.jar', 65 | 66 | // nightwatch settings 67 | globals: { foo: 'bar' }, 68 | globals_path: 'custom_tests/globals', 69 | custom_commands_path: 'custom_tests/helpers', 70 | custom_assertions_path: 'custom_tests/asserts', 71 | src_folders: ['custom_tests/nightwatch'], 72 | output_folder: 'report', 73 | test_settings: {}, 74 | selenium: {} 75 | }, 76 | custom: { 77 | // custom target + overrides 78 | config_path: '/path/to/file.json', 79 | src_folders: ['other_tests/nightwatch'] 80 | } 81 | } 82 | }); 83 | }; 84 | ``` 85 | 86 | ## CLI options 87 | 88 | Since `0.5.0`, `grunt-nightwatch` will pass `grunt.cli.options` as the `argv` option to `nwrun`. 89 | 90 | This means you can use `grunt nightwatch:A:B --group foo --tag bar` directly on the CLI. 91 | 92 | ### Known issues 93 | 94 | When running in parallel Nightwatch will copy the `process.argv` and it may produce bugs if you expect a single boolean argument like `grunt nightwatch:A:B --standalone`. 95 | 96 | It will spawn `grunt nightwatch --standalone --env A` and the argv will be erroneously parsed as `--standalone=--env`. 97 | 98 | ## Targets 99 | 100 | All options are the same as the main settings. 101 | 102 | ```javascript 103 | nightwatch: { 104 | demo: { /* see above */ } 105 | } 106 | ``` 107 | 108 | Now you can execute `grunt nightwatch:demo` to run your tests. 109 | 110 | Note that your tests must be grouped together as follows: `tests//test.js` 111 | 112 | ### Running tests with different browsers 113 | 114 | ```javascript 115 | nightwatch: { 116 | options: { 117 | // task options 118 | standalone: true, 119 | // download settings 120 | jar_version: '2.53.0', 121 | jar_path: '../nightwatch/selenium-server-standalone-2.53.0.jar', 122 | // jar_url: 'http://domain.com/files/selenium-server-standalone-1.2.3.jar', 123 | src_folders: ['custom_tests/nightwatch'], 124 | test_settings: { 125 | phantom: { 126 | "desiredCapabilities": { 127 | "browserName": "phantomjs", 128 | "phantomjs.binary.path": "binaries/nightwatch/phantomjs.exe" 129 | } 130 | }, 131 | firefox: { 132 | "desiredCapabilities": { 133 | "browserName": "firefox" 134 | } 135 | }, 136 | chrome: { 137 | "desiredCapabilities": { 138 | "browserName": "chrome" 139 | }, 140 | "cli_args" : { 141 | "webdriver.chrome.driver" : "binaries/nightwatch/chromedriver.exe" 142 | } 143 | } 144 | } 145 | } 146 | } 147 | ``` 148 | 149 | This configuration allows you to run your tests against different browsers by calling ```grunt nightwatch:chrome``` or ```grunt nightwatch:phantom``` etc. 150 | --------------------------------------------------------------------------------