File: README.md
Nightwatch.js
[Homepage](https://nightwatchjs.org) • [Developer Guide](https://nightwatchjs.org/guide) • [API Reference](https://nightwatchjs.org/api) • [About](https://nightwatchjs.org/about) • [Blog](https://nightwatchjs.org/blog)
Nightwatch is an integrated testing framework powered by Node.js and using the W3C Webdriver API. It is a complete testing solution developed at BrowserStack and which can be used for:
โ๏ธ end-to-end testing of web applications and websites
โ๏ธ component testing in isolation (React / Vue / Storybook / Angular)
โ๏ธ Node.js unit, visual regression testing, accessibility testing & API testing
โ๏ธ Native mobile app testing on Android & iOS
๐ Nightwatch v3
What's New | Release Notes | Discussions
Nightwatch v3 is an all new generation that has been built around these three pillars:
Developer Experience : The entire experience from getting started, to writing and debugging tests, has been redesigned for speed, stability, and consistent non-flaky results.
Mobile first: Test your web or native, iOS and Android, mobile applications on simulators, real mobile devices or a cloud grid like BrowserStack.
One test automation framework: Run all types of tests from unit, component, and E2E to API, visual, and accessibility with a single framework.
The Nightwatch v3 is not just a new version, itโs the result of months of engineering effort to reimagine test automation for the future. Try it out in 60 seconds and see it in action.
โ๏ธ Get started in 60 seconds
1. Install Nightwatch from NPM
From your existing project's root dir:
npm init nightwatch@latestor, if you want to initialize a new project:
npm init nightwatch@latest ./path/to/new/project2. Answer a few questions about your preferred setup:
- What is your Language - Test Runner setup?
- Where do you want to run your e2e tests?
- Where you'll be testing on?
- Where do you plan to keep your end-to-end tests?
- What is the base_url of your project?
Nightwatch will do the entire setup for you based on your answers.
3. Run a Demo Test:
Nightwatch comes with a few examples, which are automatically copied to your Nightwatch project during the setup and can also be used as boilerplate to write your own tests on top of them.
You can follow the instructions given at the end of the setup to run your first test with Nightwatch.
Nightwatch mobile app testing
Nightwatch enables automation testing of native mobile applications via Appium. It combines the robustness of Appium with the enhanced developer experience provided by Nightwatch. It enables end-to-end functional testing of native mobile apps on Android and iOS devices. Try it now
Go beyond E2E
[Component testing](https://nightwatchjs.org/guide/component-testing/introduction.html)
With Nightwatch you can test components in isolation by mounting them in the browser. Nightwatch 2 added support for component testing for popular web frameworks such as
Nightwatch unit tests
The tests for Nightwatch are written using Mocha.
Clone the project
bashgit clone https://github.com/nightwatchjs/nightwatch.git # change directory cd nightwatch # install the dependencies npm installRun tests
To run the complete test suite:
bashnpm testTo check test coverage, run the command:
bashnpm run mocha-coverageand then open the generated coverage/index.html file in your browser.
See Unit testing guide for more details.
Other types of testing
[Visual Regression Testing](https://nightwatchjs.org/guide/writing-tests/visual-regression-testing.html)
Nightwatch v3 introduces visual regression testing as an in-house plugin. The plugin takes care of
- Capturing screenshots
- Comparison with baseline to highlight visual differences
- Report to review the differences
- Approve the changes
VRT can be done on real desktop & mobile browsers. Also, VRT can be run on components as part of component testing as well.
[API Testing](https://nightwatchjs.org/guide/writing-tests/api-testing.html)
API testing is now available with Nightwatch v3. The following functionality can be achieved with API testing
- Request assertions
- Response assertions
- Viewing API tests in the HTML report
- Mock server
[Accessibility Testing](https://nightwatchjs.org/guide/using-nightwatch/accessibility-testing.html)
Nightwatch v3 packages the aXe-core package developed by Deque Systems as a plugin. It enables 90 different types of accessibility tests for WCAG compliance.
๐ฆ About Nightwatch
Nightwatch was initially built by @pineviewlabs - an independent software consultancy based in Oslo, Norway, with help from contributors. In mid 2021, Nightwatch has become a part of the @BrowserStack family and it is being developed further at the BrowserStack Open-source Program Office. Read more on our blog.
Contributing
We welcome any and all contributions from the community which can help improve Nightwatch. Please check out CONTRIBUTING.md for more extensive contributing guidelines.
Licence
File: CODE_OF_CONDUCT.md
Code of Conduct
Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, gender, gender identity and expression, sex characteristics, disability, ethnicity, level of experience, education, socio-economic status, nationality, personal appearance, body size, race, religion (or lack thereof), or sexual identity and orientation.
Our Standards
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language - please read the inclusive language guidance from the UUA
- Being respectful of differing viewpoints and experiences
- Showing empathy towards other community members
- Gracefully accepting constructive criticism
- Exercising consideration and respect in your speech and actions
- Attempting collaboration before conflict or criticism
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, spamming, intentionally disrupting conversations, making insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing or threatening to publish others' private information, such as a physical or electronic address, without explicit permission
- Advocating for, or encouraging, any of the above behavior
- Other conduct which could reasonably be considered inappropriate in a professional setting
Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [email protected]. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html.
It's inspired among other things by:
For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq
File: codecov.yml
codecov:
require_ci_to_pass: yes
coverage:
precision: 2
round: down
range: "70...100"
parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no
comment: false
File: CONTRIBUTING.md
Contributing to Nightwatch
Contributions to Nightwatch are always welcome but please try to follow these guidelines when sending in something as it will help addressing the issue quicker and more smoothly.
Please do not ask for assistance in the Issues list. Join our Discord server to ask questions and seek help.
Assistance requests posted in the Issues list are usually closed right away.
Code of Conduct
Contributors are expected to adhere to the Code of Conduct.
Submit an issue
Before submitting a new issues, try searching for a similar one here: https://github.com/nightwatchjs/nightwatch/search?type=Issues and add your scenario there and anything else which you think will help with fixing it;
If you are filing a bug report, regression issue or what it appears to be strange behaviour, please follow the steps below:
- Please write an elaborate title which explains the problem as accurate as possible
For instance:- not helpful: "Issue with tags"
- much better: "Tags don't work when combined with --skiptags option"
- Include a sample test which reproduces the problem you're experiencing. The test should be against a public url. The test and other info should be posted inline, attachments will be ignored;
- Include the verbose output, if possible (run nightwatch with
--verboseargument); - Include your configuration (try to leave out the irrelevant bits);
- Also include: Nightwatch version, Node.js version, OS version and Webdriver/Selenium Server version;
- Please try not to report issues you have with individual browser drivers which cannot or should not be solved in Nightwatch.
Requesting a feature
Feature requests are welcome.
- Indicate in the issue title that it is a feature/enhancement request;
- Explain the use case and include a sample test case and/or usage, if possible;
- Try to submit enhancements that you cannot build with custom commands/assertions and something that will benefit the community;
- Same as for issues, add your comments/vote to an existing feature request if you'd like to see it implemented.
Submitting a pull request
Thanks in advance for your contribution.
Follow the usual git workflow for submitting a pull request:
- Fork and clone the project.
- Create a new branch from main (e.g.
features/my-new-featureorissue/123-my-bugfix). - Add your changes.
- Try to run some Nightwatch example tests locally to test the functionality after making your changes:
node ./bin/nightwatch examples/tests/ecosia.js --env chrome. - Run Nightwatch unit tests locally:
npm test;
Or, run individual tests:npx mocha test/src/api/commands/client/testWaitUntil.js. - Commit your changes and create a pull request.
Note: When running Nightwatch example test for the first time, if you encounter "Cannot read source" error, go to
nightwatch.conf.jsfile and set 'page_objects_path' and 'custom_commands_path' configs to[].If you're fixing a bug, also create an issue if one doesn't exist yet.
If it's a new feature/enhancement, explain why do you think it's necessary.
If your change include drastic or low level changes please discuss them to make sure they will be accepted and what the impact will be.
If your change is based on existing functionality, please consider refactoring first. Pull requests that duplicate code will not make it in very quick, if at all.
Do not include changes that are not related to the issue at hand.
Follow the same coding style with regards to spaces, semicolons, variable naming etc.
Always add tests - after all this is a testing framework.
File: LICENSE.md
The MIT License (MIT)
Copyright (c) 2014-2021, Pine View Software AS. https://pineview.io
Copyright (c) 2022, BrowserStack Limited. https://www.browserstack.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
File: package.json
{
"name": "nightwatch",
"description": "Easy to use Node.js based end-to-end testing solution for web applications using the W3C WebDriver API.",
"version": "3.16.0",
"author": "Andrei Rusu",
"homepage": "https://nightwatchjs.org",
"main": "./lib/index.js",
"types": "./types/index.d.ts",
"license": "MIT",
"bugs": {
"url": "https://github.com/nightwatchjs/nightwatch/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/nightwatchjs/nightwatch.git"
},
"dependencies": {
"@nightwatch/chai": "5.0.3",
"@nightwatch/html-reporter-template": "^0.3.0",
"@nightwatch/nightwatch-inspector": "^1.0.1",
"@types/chai": "^4.3.5",
"@types/selenium-webdriver": "^4.1.14",
"ansi-to-html": "0.7.2",
"aria-query": "5.1.3",
"assertion-error": "1.1.0",
"boxen": "5.1.2",
"chai-nightwatch": "^0.5.3",
"chalk": "^4.1.2",
"ci-info": "3.3.0",
"cli-table3": "^0.6.3",
"devtools-protocol": "^0.0.1140464",
"didyoumean": "^1.2.2",
"dotenv": "16.3.1",
"ejs": "^3.1.10",
"envinfo": "7.11.0",
"glob": "7.2.3",
"jsdom": "^24.1.0",
"lodash": "^4.17.21",
"minimatch": "3.1.5",
"minimist": "1.2.6",
"mocha": "10.8.2",
"nightwatch-axe-verbose": "^2.3.0",
"open": "8.4.2",
"ora": "5.4.1",
"piscina": "^4.3.1",
"selenium-webdriver": "4.27.0",
"semver": "7.5.4",
"stacktrace-parser": "0.1.10",
"strip-ansi": "6.0.1",
"untildify": "4.0.0",
"uuid": "8.3.2"
},
"devDependencies": {
"@cucumber/cucumber": "^8.2.1",
"@swc/core": "^1.3.67",
"@types/node": "^18.17.3",
"@typescript-eslint/eslint-plugin": "^6.3.0",
"@typescript-eslint/parser": "^6.3.0",
"copyfiles": "^2.4.1",
"cross-env": "^7.0.3",
"eslint": "^8.46.0",
"husky": "^8.0.0",
"is-ci": "^3.0.1",
"js-yaml": "^3.13.1",
"lint-staged": "^13.2.2",
"mocha-junit-reporter": "^2.0.2",
"mochawesome": "^7.1.3",
"mochawesome-merge": "^4.2.1",
"mochawesome-report-generator": "^6.2.0",
"mockery": "~2.1.0",
"nock": "^13.2.9",
"nyc": "^15.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rimraf": "^3.0.2",
"serve": "^14.2.6",
"ts-node": "^10.9.1",
"tsd": "^0.31.2",
"wait-on": "^7.2.0"
},
"peerDependencies": {
"@cucumber/cucumber": ""
},
"peerDependenciesMeta": {
"chromedriver": {
"optional": true
},
"geckodriver": {
"optional": true
},
"@cucumber/cucumber": {
"optional": true
}
},
"overrides": {
"minimatch@^5.0.0": "^5.1.7"
},
"bin": {
"nightwatch": "./bin/nightwatch"
},
"man": "",
"scripts": {
"eslint": "eslint index.js lib bin api examples test --quiet",
"mocha": "mocha",
"mocha-coverage": "nyc --reporter=html mocha test/src/ --recursive",
"test": "mocha test/src/ --recursive --timeout 20000",
"test:types": "tsd --files types/tests",
"component-tests": "mocha test/component-tests/src",
"test-cucumber": "mocha test/cucumber-integration-tests --parallel",
"coverage": "npx nyc report --reporter=text-lcov > ./coverage/mocha_coverage.lcov",
"prepare": "husky install"
},
"eslintConfig": {
"extends": "eslint:recommended",
"env": {
"browser": false,
"node": true
},
"rules": {
"eqeqeq": "off",
"curly": [
"error",
"all"
],
"quotes": [
"error",
"single"
]
}
},
"engines": {
"node": ">= 18.20.5"
},
"keywords": [
"nightwatch",
"nightwatchjs",
"selenium",
"testing",
"webdriver",
"browserstack",
"end-to-end",
"automated-testing",
"e2e",
"component",
"integration",
"test",
"browser",
"mobile",
"runner",
"appium",
"cucumber",
"mocha",
"automation"
],
"files": [
"bin",
"examples",
"lib",
"api",
"types",
"README.md",
"CODE_OF_CONDUCT.md",
"LICENSE.md",
"index.js"
],
"lint-staged": {
"**/.js": [
"npx eslint --fix"
]
}
}
File: api/README.md
Nightwatch API Commands
Public commands api exported by Nightwatch in order to be extended upon from outside.
Example:
const {Quit: quit} = require('nightwatch/api');
module.exports = CustomQuit extends Quit {
async command(cb = function(r) {return r}) {
console.log('from custom quit command');
await super.command(cb);
}
}This is a work in progress.
Element commands:
Finding elements:
Element interaction:
Element state:
Element location:
Element location:
Document handling:
Session related:
Navigation:
Window related:
Frames:
User actions:
User prompts:
Mobile related:
Utilities & Debugging:
File: examples/globals.json
{
"default" : {
"myGlobal" : 1
},
"test_env" : {
"myGlobal" : 2
}
}
File: examples/tsconfig.json
{
"extends": "../tsconfig",
"include": ["."]
}
File: examples/cucumber-js/README.md
Using Cucumber.js with Nightwatch 2
Nightwatch 2 brings integrated support for using Cucumber.js directly as an alternative test runner. No other plugins are necessary, other than the Cucumber library itself (version 7.3 or higher).
Simply run the following in the same project where Nightwatch is also installed:
$ npm i @cucumber/cucumber --save-devConfiguration
{
test_runner: {
// set cucumber as the runner
type: 'cucumber',
// define cucumber specific options
options: {
//set the feature path
feature_path: 'examples/cucumber-js/*/*.feature',
// start the webdriver session automatically (enabled by default)
auto_start_session: true,
// use parallel execution in Cucumber
parallel: 2 // set number of workers to use (can also be defined in the cli as --parallel 2
}
},
src_folders: ['examples/cucumber-js/features/step_definitions']
}CLI Options
| option | description |
|---|---|
--dry-run |
Do all the aggregation work of looking at your feature files, loading your support code etc but without actually executing the tests. read more |
--name |
Specify a scenario by its name matching a regular expression. read more |
--tags |
Use tags to run specific scenario or features. read more |
--require |
Use --require <GLOB OR DIR OR FILE> to explicitly require support files before executing the features. read more |
--format |
Use --format <TYPE[:PATH]> to specify the format of the output. read more |
--format-options |
Many formatters, including the built-in ones, support some configurability via options. You can provide this data as a JSON literal via the --format-options CLI option. read more |
--fail-fast |
Abort the run on first failure (default: false). read more |
--retries |
Use --retries <NUMBER-OF-ATTEMPT> to have Cucumber attempt it multiple times until either it passes or the maximum number of attempts is reached. read more |
--retry-tag-filter |
Use --retry-tag-filter to retry failed scenarios based on tags. read more |
--require-module |
read more |
--no-strict |
By default, cucumber runner works in strict mode, meaning it will fail if there are pending steps. |
--parallel |
Use --parallel <NUMBER-OF-WORKER-THREADS> to run your scenarios in parallel. read more |
--profile |
As of now only cucumber.js is considered while picking up profiles. read more |
--world-parameters |
Provide this data as a JSON literal via the --world-parameters. read more |
Running
Cucumber spec files/step definition files can be provided in src_folders in Nightwatch config or as a CLI argument.
With src_folders defined:
$ npx nightwatchWithout src_folders defined:
$ npx nightwatch examples/cucumber-js/features/step_definitionsParallel running using 2 workers:
$ nightwatch examples/cucumber-js/features/step_definitions --parallel 2Use other test runner options as usual:
$ npx nightwatch examples/cucumber-js/features/step_definitions --headlessDisable the automatic session start
You might need sometimes to not start the Webdriver session automatically after Nightwatch is instantiated. For this purpose, Nightwatch provides the instance available as this.client, which contains an launchBrowser() method.
Configuration:
test_runner: {
type: 'cucumber',
options: {
feature_path: 'examples/cucumber-js/*/*.feature',
auto_start_session: false
}
}You can then use an extra setup file that you can pass as an extra --require to Nightwatch, which will be forwarded to Cucumber. In the extra setup file, you can add other operations needed to be executed before the session is started.
Example _extra_setup.js:
Remember to set the browser on this so it can be closed automatically by Nightwatch. Otherwise, remember to call .quit() in your own Cucumber After() hooks.
const {Before} = require('@cucumber/cucumber');
Before(async function(testCase) {
if (!this.client) {
console.error('Nightwatch instance was not created.');
return;
}
this.client.updateCapabilities({
testCap: 'testing'
});
this.browser = await this.client.launchBrowser();
});Nightwatch setup file for Cucumber
You might also want to inspect the built-in setup file that Nightwatch uses for initializing the Cucumber runner. It is available in our project root folder at /cucumber-js/_setup_cucumber_runner.js.
Run with extra setup:
$ nightwatch examples/cucumber-js/features/step_definitions --require {/full/path/to/_extra_setup.js}Reporting
When using the integrated Cucumber test runner, you need to use the Cucumber formatters for generating output.
Nightwatch reporters (like JUnit XML reports or the global custom reporter) are not available. The main reason is that reporting is delegated to the Cucumber CLI. You can also write your own Cucumber formatter.
Nightwatch will forward --format and --format-options CLI arguments, if present, to Cucumber.
By default, the progress formatter is used. Here's how the output looks like when running the example tests in Firefox:
โน Connected to GeckoDriver on port 4444 (1740ms).
Using: firefox (92.0.1) on MAC (20.6.0).
.. โ Testing if the page title equals 'Rijksmuseum Amsterdam, home of the Dutch masters' (4ms)
. โ Element <#rijksmuseum-app> was visible after 46 milliseconds.
. โ Testing if element <.search-results> contains text 'Operation Night Watch' (1994ms)
... โ Testing if the page title equals 'Rijksmuseum Amsterdam, home of the Dutch masters' (8ms)
. โ Element <#rijksmuseum-app> was visible after 49 milliseconds.
. โ Testing if element <.search-results> contains text 'The Night Watch, Rembrandt van Rijn, 1642' (1427ms)
.
2 scenarios (2 passed)
10 steps (10 passed)
0m13.024s (executing steps: 0m12.998s)File: examples/tests/README.md
Using Mocha as a test runner in Nightwatch 2
Nightwatch 2 brings support for Mocha v9 as an alternative test runner which contains most of the existing functionality from the Nightwatch default runner.
We are still in the process of updating the examples. Please check back here soon.
File: lib/runner/test-runners/cucumber/README.md
Using Cucumber.js with Nightwatch 2
Nightwatch 2 brings integrated support for using Cucumber.js directly as an alternative test runner. No other plugins are necessary, other than the Cucumber library itself (version 7.3 or higher).
Simply run the following in the same project where Nightwatch is also installed:
$ npm i @cucumber/cucumber --save-devThe examples folder contains a few example spec files and cucumber features, as well as configuration details.
File: test/nightwatch.json
{
"src_folders" : ["./test/src"],
"test_workers" : false,
"selenium" : {
"start_process" : false,
"start_session" : false
},
"test_settings": {
"default" : {
"filter" : "**/*.js",
"compatible_testcase_support" : true,
"globals": {
"asyncHookTimeout" : 15000
}
}
}
}
File: test/tsconfig.json
{
"compilerOptions": {
"target": "esnext",
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. /
"module": "node16",
/ Specify what module code is generated. /
"allowJs": true,
/ Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. /
"outDir": "dist",
/ Specify an output folder for all emitted files. /
"esModuleInterop": true,
/ Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. /
"forceConsistentCasingInFileNames": true,
/ Ensure that casing is correct in imports. /
"strict": true,
/ Enable all strict type-checking options. /
"noImplicitAny": true,
/ Enable error reporting for expressions and declarations with an implied 'any' type. /
"skipLibCheck": true
/ Skip type checking all .d.ts files. */
},
"include": [
"."
],
"files": [
"./types/index.d.ts"
]
}
File: test/extra/minimalJsonReporter.json
{
"modules": {
"demoTagTest": {
"modulePath": "./test/sampletests/tags/sample.js",
"status": "pass"
},
"demoTest": {
"modulePath": "./test/sampletests/simple/test/sample.js",
"status": "fail"
}
}
}
File: test/extra/nightwatch.json
{
"src_folders" : ["../sampletests"],
"output_folder" : "./output",
"custom_commands_path" : "",
"custom_assertions_path" : "",
"globals_path" : "./globals.js",
"test_workers" : {
"enabled" : false
},
"output" : false,
"selenium" : {
"start_process" : false,
"server_path" : "./bin/selenium-server.jar"
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
},
"filter" : ["async/**"]
},
"mixed" : {
"filter" : ["mixed/*"]
} }
}
File: test/extra/package.json
{
"name": "nightwatch"
}
File: test/extra/parallelism-auto.json
{
"src_folders" : ["./test/sampletests/before-after"],
"output_folder" : false,
"test_workers" : {
"enabled" : true,
"workers" : "auto"
},
"output" : false,
"selenium" : {
"start_process" : false
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
}
}
}
}
File: test/extra/parallelism-count.json
{
"src_folders" : ["./test/sampletests/before-after"],
"output_folder" : false,
"output" : false,
"test_workers" : {
"enabled" : true,
"workers" : 6
},
"selenium" : {
"start_process" : false
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
}
}
}
}
File: test/extra/parallelism-customCommandsSync.json
{
"src_folders" : ["./test/apidemos/custom-commands-parallel"],
"test_workers": true,
"custom_commands_path": ["./test/extra/commands/other"],
"persist_globals": true,
"output_folder" : false,
"output" : false,
"silent": false,
"selenium" : {
"start_process" : false,
"port": 10195
},
"test_settings": {
"default" : {
"desiredCapabilities" : {
"browserName" : "firefox"
}
}
}
}
File: test/extra/parallelism-disabled.json
{
"src_folders" : ["./test/sampletests"],
"output_folder" : false,
"test_workers" : {
"enabled" : true,
"workers" : "auto"
},
"output" : false,
"selenium" : {
"start_process" : false
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
},
"test_workers" : false
}
}
}
File: test/extra/parallelism-envs.json
{
"src_folders" : ["./test/sampletests"],
"output_folder" : false,
"output" : false,
"selenium" : {
"start_process" : false
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
}
},
"env1" : {
"filter" : "mixed/*"
},
"env2" : {
"filter" : "simple/**"
}
}
}
File: test/extra/parallelism-execArgv-selected.json
{
"src_folders" : ["./test/sampletests"],
"output_folder" : false,
"test_workers" : {
"enabled": true,
"node_options": ["--harmony"]
},
"output" : false,
"selenium" : {
"start_process" : false
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
}
}
}
}
File: test/extra/parallelism-execArgv.json
{
"src_folders" : ["./test/sampletests"],
"output_folder" : false,
"test_workers" : {
"enabled": true,
"node_options": "inherit"
},
"output" : false,
"selenium" : {
"start_process" : false
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
}
}
}
}
File: test/extra/parallelism-selenium-server.json
{
"src_folders" : ["./test/sampletests/before-after"],
"output_folder" : false,
"test_workers" : {
"enabled" : true,
"workers" : 2
},
"output" : false,
"selenium" : {
"start_process" : true
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
}
}
}
}
File: test/extra/parallelism.json
{
"src_folders" : ["./test/sampletests/before-after"],
"output_folder" : false,
"test_workers" : true,
"output" : false,
"selenium" : {
"start_process" : false
},
"test_settings": {
"default" : {
"silent" : true,
"desiredCapabilities" : {
"browserName" : "firefox"
}
}
}
}
File: test/extra/withgeckodriver-concurrent.json
{
"src_folders" : ["../sampletests"],
"output_folder" : "./output",
"custom_commands_path" : "",
"custom_assertions_path" : "",
"globals_path" : "./globals.js",
"test_workers" : {
"enabled" : true
},
"output" : false,
"test_settings": {
"default" : {
"desiredCapabilities" : {
"browserName" : "firefox"
},
"webdriver": {
"start_process": true,
"server_path": "./geckodriver"
}
}
}
}
File: test/extra/withmocha.json
{
"src_folders" : ["./test/mochatests"],
"output_folder" : "./output",
"custom_commands_path" : "",
"custom_assertions_path" : "",
"output" : false,
"selenium" : {
"start_process" : false,
"server_path" : "./bin/selenium-server.jar"
},
"test_runner" : "mocha",
"test_settings": {
"default" : {
"selenium_port" : 10195,
"silent" : true,
"persist_globals" : true,
"globals" : {},
"desiredCapabilities" : {
"browserName" : "firefox"
}
}
}
}
File: test/extra/withsafari-concurrent.json
{
"src_folders" : ["../sampletests"],
"output_folder" : "./output",
"custom_commands_path" : "",
"custom_assertions_path" : "",
"globals_path" : "./globals.js",
"test_workers" : {
"enabled" : true
},
"output" : false,
"test_settings": {
"default" : {
"desiredCapabilities" : {
"browserName" : "safari"
},
"webdriver": {
"start_process": true
}
},
"chrome" : {
"desiredCapabilities" : {
"browserName" : "chrome"
},
"webdriver": {
"start_process": true
}
},
"firefox" : {
"desiredCapabilities" : {
"browserName" : "firefox"
},
"webdriver": {
"start_process": true
}
}
}
}
File: test/lib/mocks.json
{
"mocks": [
{
"url": "/wd/hub/session",
"postdata": {
"desiredCapabilities": {
"browserName": "firefox"
}
},
"response": {
"status": 0,
"sessionId": "1352110219202",
"value": {
"browserName": "firefox",
"browserVersion": "TEST",
"platformVersion": "TEST"
},
"state": null
},
"responseHeaders": {
},
"statusCode": 201,
"method": "POST"
},
{
"url": "/session",
"postdata": {
"capabilities": {
"browserName": "firefox"
},
"desiredCapabilities": {
"browserName": "firefox"
}
},
"response": {
"value": {
"sessionId": "13521-10219-202",
"capabilities": {
"acceptInsecureCerts": false,
"browserName": "firefox",
"browserVersion": "65.0.1",
"platformName": "linux",
"platformVersion": "4.9.125-linuxkit",
"setWindowRect": true,
"strictFileInteractability": false,
"timeouts": {
"implicit": 0,
"pageLoad": 300000,
"script": 30000
},
"unhandledPromptBehavior": "dismiss and notify"
}
}
},
"responseHeaders": {
},
"statusCode": 201,
"method": "POST"
},
{
"url": "/wd/hub/session",
"postdata": "",
"response": {
"status": 0,
"sessionId": "1352110219202",
"value": {
"browserName": "firefox",
"version": "TEST",
"platform": "TEST"
},
"state": null
},
"responseHeaders": {
},
"statusCode": 201,
"method": "POST"
},
{
"url": "/wd/hub/session/1352110219202",
"method": "DELETE",
"response": {
"status": 0,
"state": "success"
}
},
{
"url": "/wd/hub/session/1352110219202/url",
"postdata": {
"url": "http://localhost"
}
},
{
"url": "/wd/hub/test",
"response": {
"status": 0
}
},
{
"url": "/wd/hub/test_error",
"response": {
"status": 7,
"value": {
"screen": "screenshot_data"
}
},
"statusCode": 500
},
{
"url": "/wd/hub/session/1352110219202/element",
"postdata": {
"using": "css selector",
"value": "#weblogin"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": {
"ELEMENT": "0"
},
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/element",
"postdata": {
"using": "css selector",
"value": "#webdriver"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": {
"element-6066-11e4-a52e-4f735466cecf": "5cc459b8-36a8-3042-8b4a-258883ea642b"
}
}
},
{
"url": "/session/13521-10219-202/element",
"postdata": {
"using": "css selector",
"value": "#webdriver"
},
"response": {
"value": {
"element-6066-11e4-a52e-4f735466cecf": "5cc459b8-36a8-3042-8b4a-258883ea642b"
}
}
},
{
"url": "/wd/hub/session/1352110219202/element",
"postdata": {
"using": "css selector",
"value": "#signupSection"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": {
"ELEMENT": "0"
},
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/element",
"postdata": {
"using": "xpath",
"value": "//weblogin"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": {
"ELEMENT": "0"
},
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/element/0/element",
"postdata": {
"using": "css selector",
"value": "#helpBtn"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": {
"ELEMENT": "1"
},
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/elements",
"postdata": {
"using": "css selector",
"value": ".weblogin"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [],
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/elements",
"postdata": {
"using": "css selector",
"value": "#badElement"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [],
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/elements",
"postdata": {
"using": "css selector",
"value": "#weblogin"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [
{
"ELEMENT": "0"
}
],
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/elements",
"postdata": {
"using": "css selector",
"value": "#webdriver"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [
{
"element-6066-11e4-a52e-4f735466cecf": "5cc459b8-36a8-3042-8b4a-258883ea642b"
}
]
}
},
{
"url": "/wd/hub/session/1352110219202/elements",
"postdata": {
"using": "css selector",
"value": "#weblogin-multiple"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [
{
"ELEMENT": "0"
},
{
"ELEMENT": "1"
}
],
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/elements",
"postdata": {
"using": "xpath",
"value": "//weblogin"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [
{
"ELEMENT": "0"
}
],
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/elements",
"postdata": {
"using": "css selector",
"value": "#signupSection"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [
{
"ELEMENT": "0"
},
{
"ELEMENT": "1"
}
],
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/element/0/elements",
"postdata": {
"using": "css selector",
"value": "#helpBtn"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [
{
"ELEMENT": "1"
}
],
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/element/0/elements",
"postdata": {
"using": "css selector",
"value": ".btn"
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"value": [
{
"ELEMENT": "1"
},
{
"ELEMENT": "2"
},
{
"ELEMENT": "3"
}
],
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/buttondown",
"postdata": {
"button": 0
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/window",
"response": {
"sessionId": "1352110219202",
"status": 0
},
"method": "DELETE"
},
{
"url": "/wd/hub/session/1352110219202/window",
"method": "POST",
"response": {
"sessionId": "1352110219202",
"status": 0
}
},
{
"url": "/wd/hub/session/1352110219202/buttondown",
"postdata": {
"button": 1
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
},
{
"url": "/wd/hub/session/1352110219202/buttonup",
"postdata": {
"button": 2
},
"response": {
"sessionId": "1352110219202",
"status": 0,
"class": "org.openqa.selenium.remote.Response",
"hCode": 604376696
}
} ]
}
File: test/lib/mocks/mocks-jsonwire.yaml
mocks:
Default JSON Wire session request with Selenium
url: '/wd/hub/session'
postdata:
capabilities:
firstMatch: [{}]
alwaysMatch:
browserName: firefox
'moz:firefoxOptions':
prefs:
'remote.active-protocols': 3
response:
status: 0
sessionId: &sessionId '1352110219202'
value:
browserName: firefox
browserVersion: TEST_firefox
state:
responseHeaders: {}
statusCode: 201
method: POST
matchEmpty: falseurl: '/wd/hub/session'
postdata:
capabilities:
firstMatch: [{}]
alwaysMatch:
browserName: firefox
response:
status: 0
sessionId: &sessionId '1352110219202'
value:
browserName: firefox
browserVersion: TEST_firefox
state:
responseHeaders: {}
statusCode: 201
method: POST
matchEmpty: trueurl: '/wd/hub/session/1352110219202'
method: DELETE
response:
status: 0
state: successurl: '/wd/hub/session/1352110219202/url'
postdata:
url: http://localhost
response:
status: 0url: '/wd/hub/session/1352110219202/url'
postdata:
url: http://localhost/test_url
response:
status: 0url: '/wd/hub/session/1352110219202/url'
postdata:
url: http://localhost/homepage
response:
status: 0url: '/wd/hub/session/1352110219202/url'
method: GET
response:
status: 0
value: http://localhosturl: '/wd/hub/test'
response:
status: 0url: '/wd/hub/test_error'
response:
status: 7
value:
screen: screenshot_data
statusCode: 500url: '/wd/hub/session/1352110219202/element'
postdata:
using: 'css selector'
value: '#weblogin'
response:
sessionId: '1352110219202'
status: 0
value:
ELEMENT: '0'
class: org.openqa.selenium.remote.Response
hCode: 604376696url: '/wd/hub/session/1352110219202/element'
postdata:
using: 'css selector'
value: '#signupSection'
response:
sessionId: *sessionId
status: 0
value:
ELEMENT: '0'url: '/wd/hub/session/1352110219202/element'
postdata:
using: xpath
value: '//weblogin'
response:
sessionId: *sessionId
status: 0
value:
ELEMENT: '0'url: '/wd/hub/session/1352110219202/element/0/element'
postdata:
using: 'css selector'
value: '#helpBtn'
response:
sessionId: *sessionId
status: 0
value:
ELEMENT: '1'url: '/wd/hub/session/1352110219202/elements'
postdata:
using: 'css selector'
value: '.weblogin'
response:
sessionId: *sessionId
status: 0
value: []url: '/wd/hub/session/1352110219202/elements'
postdata:
using: 'css selector'
value: '#badElement'
response:
sessionId: *sessionId
status: 0
value: []url: '/wd/hub/session/1352110219202/elements'
postdata:
using: 'css selector'
value: '#weblogin'
response:
sessionId: *sessionId
status: 0
value:- ELEMENT: '0'
url: '/wd/hub/session/1352110219202/elements'
postdata:
using: 'css selector'
value: '#weblogin-multiple'
response:
sessionId: *sessionId
status: 0
value:- ELEMENT: '0'
- ELEMENT: '1'
url: '/wd/hub/session/1352110219202/elements'
postdata:
using: xpath
value: '//weblogin'
response:
sessionId: *sessionId
status: 0
value:- ELEMENT: '0'
url: '/wd/hub/session/1352110219202/elements'
postdata:
using: 'css selector'
value: '#signupSection'
response:
sessionId: *sessionId
status: 0
value:- ELEMENT: '0'
url: '/wd/hub/session/1352110219202/element/0/elements'
postdata:
using: 'css selector'
value: '#helpBtn'
response:
sessionId: *sessionId
status: 0
value:- ELEMENT: '1'
url: '/wd/hub/session/1352110219202/element/0/elements'
postdata:
using: 'css selector'
value: '.btn'
response:
sessionId: *sessionId
status: 0
value:- ELEMENT: '1'
- ELEMENT: '2'
- ELEMENT: '3'
url: '/wd/hub/session/1352110219202/buttondown'
postdata:
button: 0
response:
sessionId: *sessionId
status: 0url: '/wd/hub/session/1352110219202/window'
response:
sessionId: *sessionId
status: 0
method: DELETEurl: '/wd/hub/session/1352110219202/window'
method: POST
response:
sessionId: *sessionId
status: 0url: '/wd/hub/session/1352110219202/buttondown'
postdata:
button: 1
response:
sessionId: *sessionId
status: 0url: '/wd/hub/session/1352110219202/buttonup'
postdata:
button: 2
response:
sessionId: *sessionId
status: 0url: '/wd/hub/session/1352110219202/se/log'
postdata:
type: 'browser'
method: POST
response:
sessionId: *sessionId
status: 0
value:- level: 'info'
timestamp: 534547832
message: 'Test log' - level: 'info'
timestamp: 534547442
message: 'Test log2'
- level: 'info'
File: test/lib/mocks/mocks-w3c.yaml
mocks:
Webdriver session request without Selenium
-------------------------------------------------------
url: '/session'
postdata:
capabilities:
firstMatch: [{}]
alwaysMatch:
browserName: firefox
'moz:firefoxOptions':
prefs:
'remote.active-protocols': 3
response:
value:
sessionId: &webdriverSessionId '13521-10219-202'
capabilities:
acceptInsecureCerts: false
browserName: firefox
browserVersion: 65.0.1
platformName: linux
platformVersion: 4.9.125-linuxkit
setWindowRect: true
strictFileInteractability: false
timeouts:
implicit: 0
pageLoad: 300000
script: 30000
unhandledPromptBehavior: 'dismiss and notify'
responseHeaders: {}
statusCode: 201
method: POSTurl: '/session'
postdata:
capabilities:
firstMatch: [{}]
alwaysMatch:
browserName: firefox
response:
value:
sessionId: '13521-10219-202'
capabilities:
acceptInsecureCerts: false
browserName: firefox
browserVersion: 65.0.1
platformName: linux
platformVersion: 4.9.125-linuxkit
setWindowRect: true
strictFileInteractability: false
timeouts:
implicit: 0
pageLoad: 300000
script: 30000
unhandledPromptBehavior: 'dismiss and notify'
responseHeaders: {}
statusCode: 201
method: POSTurl: '/session'
postdata:
capabilities:
firstMatch: [{}]
alwaysMatch:
browserName: firefox
response:
value:
sessionId: '13521-10219-202'
capabilities:
browserName: firefox
browserVersion: 65.0.1
platformName: linux
platformVersion: 4.9.125-linuxkit
responseHeaders: {}
statusCode: 201
method: POSTurl: '/session'
postdata:
desiredCapabilities:
browserName: safari
platformName: iOS
safari:useSimulator: true
safari.options: {}
capabilities:
alwaysMatch:
browserName: safari
platformName: iOS
safari:useSimulator: true
response:
value:
sessionId: '13521-10219-202'
capabilities:
browserName: safari
platformName: iOS
safari:useSimulator: true
safari:platformVersion: 15.6.1
responseHeaders: {}
statusCode: 201
method: POSTurl: '/wd/hub/session'
postdata:
capabilities:
firstMatch: [{}]
alwaysMatch:
appium:automationName: "XCUITest"
appium:appPackage: "org.wikimedia.wikipedia"
platformName: "iOS"
appium:deviceName: "iPhone 13"
appium:platformVersion: "15.5"
response:
value:
sessionId: '13521-10219-202'
capabilities:
appium:automationName: "XCUITest"
appium:appPackage: "org.wikimedia.wikipedia"
platformName: "iOS"
appium:deviceName: "iPhone 13"
appium:platformVersion: "15.5"
responseHeaders: {}
statusCode: 201
method: POSTurl: '/wd/hub/session/1352110219202/element'
postdata:
using: 'css selector'
value: '#webdriver'
response:
sessionId: '1352110219202'
status: 0
value:
element-6066-11e4-a52e-4f735466cecf: 5cc459b8-36a8-3042-8b4a-258883ea642burl: '/session/13521-10219-202/element'
postdata:
using: 'css selector'
value: '#webdriver'
response:
value:
element-6066-11e4-a52e-4f735466cecf: 5cc459b8-36a8-3042-8b4a-258883ea642burl: '/wd/hub/session/1352110219202/elements'
postdata:
using: 'css selector'
value: '#webdriver'
response:
sessionId: '1352110219202'
status: 0
value:- element-6066-11e4-a52e-4f735466cecf: 5cc459b8-36a8-3042-8b4a-258883ea642b
url: '/session/13521-10219-202/elements'
postdata:
using: 'css selector'
value: '#webdriver'
response:
value:- element-6066-11e4-a52e-4f735466cecf: 5cc459b8-36a8-3042-8b4a-258883ea642b
- element-6066-11e4-a52e-4f735466cecf: 3783b042-7001-0740-a2c0-afdaac732e9f
url: '/session/13521-10219-202/elements'
postdata:
using: 'css selector'
value: '#weblogin'
response:
value:- element-6066-11e4-a52e-4f735466cecf: 5cc459b8-36a8-3042-8b4a-258883ea642b
- element-6066-11e4-a52e-4f735466cecf: 3783b042-7001-0740-a2c0-afdaac732e9f
url: '/session/13521-10219-202/elements'
postdata:
using: 'xpath'
value: '//weblogin'
response:
value:- element-6066-11e4-a52e-4f735466cecf: 5cc459b8-36a8-3042-8b4a-258883ea642b
- element-6066-11e4-a52e-4f735466cecf: 3783b042-7001-0740-a2c0-afdaac732e9f
url: '/session/13521-10219-202/elements'
postdata:
using: 'css selector'
value: 'html'
response:
value:- element-6066-11e4-a52e-4f735466cecf: '00'
url: '/session/13521-10219-202/element/00/elements'
postdata:
using: 'css selector'
value: '#signupSection'
response:
value:- element-6066-11e4-a52e-4f735466cecf: '0'
url: '/session/13521-10219-202/elements'
postdata:
using: 'css selector'
value: '#signupSection'
response:
value:- element-6066-11e4-a52e-4f735466cecf: '0'
url: '/session/13521-10219-202/element/0/elements'
postdata:
using: 'css selector'
value: '#helpBtn'
response:
value:- element-6066-11e4-a52e-4f735466cecf: '1'
url: '/session/13521-10219-202/element/0/elements'
postdata:
using: 'css selector'
value: '.btn'
response:
value:- element-6066-11e4-a52e-4f735466cecf: '1'
- element-6066-11e4-a52e-4f735466cecf: '2'
- element-6066-11e4-a52e-4f735466cecf: '3'
File: test/typescript-tests/tsconfig.nightwatch.json
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"strict": true,
"rootDir": ".",
"outDir": "dist",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"sourceMap": false,
"resolveJsonModule": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"skipLibCheck": true
}
}
File: types/tests/tsconfig.json
{
"extends": "../../tsconfig",
"include": ["."]
}
File: .github/FUNDING.yml
open_collective: nightwatch
File: .github/label-commenter-config.yml
Configuration for Label Commenter - https://github.com/peaceiris/actions-label-commenter
labels:
name: needs-triaging
labeled:
issue:
body: |
@{{ issue.user.login }}, thank you for creating this issue. We will troubleshoot it as soon as we can.
---
Info for maintainers
Triage this issue by using labels.
If information is missing, add a helpful comment and add theI-issue-templatelabel.
Thank you!name: I-issue-template
labeled:
issue:
body: |
Hi, @{{ issue.user.login }}.
Please follow the issue template, we need more information to reproduce the issue.
Either a complete code snippet (if more than one file is needed, provide a GitHub repo and instructions to run the code), the specific versions used, or a more detailed description to help us understand the issue.
Reply to this issue when all information is provided, thank you.
File: .github/PULL_REQUEST_TEMPLATE.md
Thanks in advance for your contribution. Please follow the below steps in submitting a pull request, as it will help us with reviewing it quicker.
- Before marking your PR for review, please test and verify your changes by making appropriate modifications to any of the Nightwatch example tests (present in
examples/testsdirectory of the project) and running them.ecosia.jsandduckDuckGo.jsare good examples to work with. - Create a new branch from master (e.g.
features/my-new-featureorissue/123-my-bugfix); - If you're fixing a bug also create an issue if one doesn't exist yet;
- If it's a new feature explain why do you think it's necessary. Please check with the maintainers beforehand to make sure it is something that we will accept. Usually we only accept new features if we feel that they will benefit the entire community;
- Please avoid sending PRs which contain drastic or low level changes. If you are certain that the changes are needed, please discuss them beforehand and indicate what the impact will be;
- If your change is based on existing functionality please consider refactoring first. Pull requests that duplicate code will most likely be ignored;
- Do not include changes that are not related to the issue at hand;
- Follow the same coding style with regards to spaces, semicolons, variable naming etc.;
- Always add unit tests - PRs without tests are most of the times ignored.
File: .github/stale.yml
Number of days of inactivity before an issue becomes stale
daysUntilStale: 90
Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
Issues with these labels will never be considered stale
exemptLabels:
- META
- pinned
- enhancement
Label to use when marking an issue as stale
staleLabel: stale
Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had any recent activity.
If possible, please retry using the latest Nightwatch version and update the issue with any relevant details.
If no further activity occurs, it will be closed. Thank you for your contribution.
Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
File: .github/ISSUE_TEMPLATE/bug_report.yml
name: "Bug Report"
body:
- type: "markdown"
attributes:
value: |
Thanks in advance for your contribution. Before submitting a new issue, try searching for a similar one here: https://github.com/nightwatchjs/nightwatch/search?type=Issues. - type: "textarea"
id: "description"
attributes:
label: "Description of the bug/issue"
placeholder: |
When I ____, I expected ____ to happen but ____ happened instead.
validations:
required: true - type: "textarea"
id: "steps"
attributes:
label: "Steps to reproduce"
Explain how to cause the issue in the provided reproduction.
value: |
1. Go to '...'
2. Click on '...'
3. Scroll down to '...'
4. See error - type: textarea
id: "sample-test"
attributes:
label: "Sample test"
Include a sample test that reproduces the problem you're experiencing. If possible, the test should be against a public URL.
Please add the test and other info inline, not as attachments or screenshots.
placeholder: |
// Please add the sample test here
module.exports = {
sampleTest: function() {
browser
.navigateTo('')
.click('')
.end();
}
}
render: node - type: textarea
id: "run-with-command"
attributes:
label: "Command to run"
placeholder: |
nightwatch test/sampleTest.js --your-other-arguments-here
render: bash - type: textarea
id: "verbose-output"
attributes:
label: "Verbose Output"
"Extended nightwatch command logging during the session.
Please use nightwatch --verbose and paste the output here"
placeholder: |
[Sample Test] Test Suite
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Starting ChromeDriver on port 9515...
Request POST /session
{
desiredCapabilities: {
browserName: 'chrome',
'goog:chromeOptions': { w3c: true, args: [] },
name: 'Sample Test'
},
capabilities: {
alwaysMatch: {
browserName: 'chrome',
'goog:chromeOptions': { w3c: true, args: [] }
}
}
render: fundamental - type: textarea
id: "configuration"
attributes:
label: "Nightwatch Configuration"
placeholder: |
module.exports = {
src_folders: [],
page_objects_path: [],
custom_commands_path: [],
custom_assertions_path: '',
plugins: [],
globals_path: '',
webdriver: {},
test_settings: {}
}
render: node - type: "markdown"
attributes:
value: |
## Your Environment
Include the relevant details related to your environment. - type: "input"
id: "nightwatch-version"
attributes:
label: "Nightwatch.js Version"
placeholder: "2.3.0"
validations:
required: true - type: "input"
id: "node-version"
attributes:
label: "Node Version"
placeholder: "14.0.0" - type: "input"
id: "browser"
attributes:
label: "Browser"
placeholder: "Firefox 102.0.1; Chrome 104.0.0" - type: "input"
id: "operating-system"
attributes:
label: "Operating System"
placeholder: "MacOs Monterey 12.5" - type: "textarea"
id: "additional-information"
attributes:
label: "Additional Information"
Use this section to provide any additional information you might have
like screenshots, notes, or links to ideas.
File: .github/ISSUE_TEMPLATE/config.yml
blank_issues_enabled: true
contact_links:
- name: Ask a question
url: https://github.com/nightwatchjs/nightwatch/discussions
about: Ask questions and discuss topics with other community members - name: Documentation Request
url: https://github.com/nightwatchjs/nightwatch-docs/issues/new
about: Request for documentation to be added/altered - name: Chat with other community members. Ask support questions, discuss news and feature requests.
url: https://discord.gg/x5RuXc6Z
about: The official Nightwatchjs Discord community
File: .github/ISSUE_TEMPLATE/feature-request.yml
name: "Feature Request"
labels: ["enhancement"]
body:
- type: "markdown"
attributes:
value: |
Thanks in advance for your contribution. Before requesting a new feature, try searching for a similar issue here: https://github.com/nightwatchjs/nightwatch/search?type=Issues. - type: "textarea"
id: "description"
attributes:
label: "Description"
validations:
required: true - type: "textarea"
id: "proposed-solution"
attributes:
label: "Suggested solution"
Please provide code snippets, gists, or links to the ideal
design or API. - type: "textarea"
id: "alternatives"
attributes:
label: "Alternatives / Workarounds"
What alternative solutions have you considered before making this
request? - type: "textarea"
id: "additional-information"
attributes:
label: "Additional Information"
What resources (links, screenshots, etc.) do you have to assist this
effort?
File: .github/workflows/build-node.yaml
This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: tests
on:
push:
branches: [ main]
pull_request:
branches: [ main]
jobs:
linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x, 24.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run eslint
- run: npm test windows:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
node-version: [18.x, 20.x, 22.x, 24.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run eslint
- run: npm testFile: .github/workflows/component-tests.yaml
name: component-tests
on:
push:
branches: [ main]
pull_request:
branches: [ main]
jobs:
linux:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm ci- run: npm i @nightwatch/react @nightwatch/vue @testing-library/dom vite-plugin-nightwatch vue react react-dom
- run: npm run component-tests
File: .github/workflows/coverage.yml
This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Coverage Job
on:
push:
branches: [ ]
pull_request:
branches: [ ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run eslint
- run: npm run mocha-coverage
- run: npm run coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_ACCESS_TOKEN }}
files: ./coverage/mocha_coverage.lcov
flags: unittests
name: codecov-umbrella
fail_ci_if_error: true
path_to_write_report: codecov_report.txt
verbose: falseFile: .github/workflows/label-commenter.yml
Configuration for Label Commenter - https://github.com/peaceiris/actions-label-commenter
name: Label Commenter
on:
issues:
types: [ labeled ]
permissions:
contents: read
issues: write
jobs:
comment:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Label Commenter
uses: peaceiris/actions-label-commenter@v1
File: .github/workflows/missing-types-comment.yml
name: Add comment for missing types
on:
workflow_run:
workflows: ["Check missing types"]
types:
- completed
jobs:
add_comment:
runs-on: ubuntu-latest
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
steps:
- name: 'Download artifact'
uses: actions/github-script@v6
with:
script: |
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{github.event.workflow_run.id }},
});
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "pr"
})[0];
var download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
var fs = require('fs');
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
- name: 'Read artifact'
id: modified-files
run: |
unzip pr.zip
cat files_changed
echo "modified=$(cat files_changed)" >> "$GITHUB_OUTPUT"
- name: Comment on PR
if: steps.modified-files.outputs.modified == ''
id: comment-on-pr
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const issue_number = Number(fs.readFileSync('./NR'));
const comment = `
## Status
* โ No modified files found in the **types** directory.
Please make sure to include types for any changes you have made. Thank you!.`;
const pullRequest = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: issue_number
});
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number
});
const existingComment = comments.data.find(comment => comment.user.login === 'github-actions[bot]' && comment.body.includes('No modified files found in the **types** director'));
if (existingComment) {
console.log('Comment already exists');
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,
body: comment
});
}
- name: Edit comment on PR
if: steps.modified-files.outputs.modified != ''
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const issue_number = Number(fs.readFileSync('./NR'));
const comment = `
## Status
* :white_check_mark: Type files updated!`;
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number
});
const existingComment = comments.data.find(comment => comment.user.login === 'github-actions[bot]' && comment.body.includes('No modified files found in the **types** director'));
if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: comment
});
}File: .github/workflows/missing-types.yml
name: Check missing types
on: pull_request
jobs:
detect-modified-files:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get modified files
id: modified-files
run: |
echo $(git diff --name-only origin/$GITHUB_BASE_REF $GITHUB_SHA types/ | tr '\n' ',')
mkdir -p ./pr
echo $(git diff --name-only origin/$GITHUB_BASE_REF $GITHUB_SHA types/ | tr '\n' ',') > ./pr/files_changed
echo ${{ github.event.number }} > ./pr/NR
- uses: actions/upload-artifact@v4
with:
name: pr
path: pr/File: .github/workflows/nightly.yml
name: Nightly
on:
workflow_dispatch:
inputs:
version:
required: false
type: string
default: ''
ref:
required: false
type: string
default: ''
jobs:
nightly:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ inputs.ref }}
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18.x'
- name: Install dependencies
run: npm install
- name: Build Nightwatch
run: npm run build
- name: Create publishable package ๐ฆ
run: npm pack
- name: Release Nightly
uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "nightly-${{ inputs.version }}"
title: "Nightly ${{ inputs.version }}"
prerelease: true
files: '*.tgz'
File: .github/workflows/publish.yml
name: Publish to NPM
on:
push:
tags:
- vv* # to enable this action, change this tag back to v*
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm install
- name: Publish package on NPM ๐ฆ
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
File: .github/workflows/type-declaration-tests.yml
name: Type Declaration Tests
on:
push:
branches: [main, feat/types-test]
pull_request:
branches: [main]
jobs:
linux:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
typescript-version: [3.9, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install TypeScript
run: npm install typescript@${{ matrix.typescript-version }}
- name: Install Dependencies
run: npm ci
- run: npm run test:types