Skip to content

Commit

Permalink
Added support to use nightwatch.conf.ts and a few other improvements …
Browse files Browse the repository at this point in the history
…for running typescript tests (#3316)
  • Loading branch information
Vaibhav Singh committed Oct 14, 2022
1 parent 257da2d commit 92ad22d
Show file tree
Hide file tree
Showing 12 changed files with 430 additions and 61 deletions.
23 changes: 4 additions & 19 deletions bin/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,16 @@
*/
const Nightwatch = require('../lib/index.js');
const {Logger, shouldReplaceStack, alwaysDisplayError} = require('../lib/utils');
const path = require('path');

try {
const projectTsFile = path.join(process.cwd(), 'nightwatch', 'tsconfig.json');
let projectTsExists = false;
try {
require(projectTsFile);
projectTsExists = true;

require('ts-node').register({
esm: false,
project: projectTsFile
});
} catch (err) {
// eslint-disable-line
}

Nightwatch.cli(function(argv) {
Nightwatch.cli(function (argv) {
argv._source = argv['_'].slice(0);

const runner = Nightwatch.CliRunner(argv);

return runner
.setupAsync()
.catch(err => {
.catch((err) => {
if (err.code === 'ERR_REQUIRE_ESM') {
err.showTrace = false;
}
Expand All @@ -36,10 +21,10 @@ try {
})
.then(() => runner.runTests())
.catch((err) => {
if (!err.displayed || alwaysDisplayError(err) && !err.displayed) {
if (!err.displayed || (alwaysDisplayError(err) && !err.displayed)) {
Logger.error(err);
}

runner.processListener.setExitCode(10).exit();
});
});
Expand Down
41 changes: 33 additions & 8 deletions lib/runner/cli/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class CliRunner {
return './nightwatch.conf.cjs';
}

static get CONFIG_FILE_TS() {
return './nightwatch.conf.ts';
}

static createDefaultConfig(destFileName) {
// eslint-disable-next-line no-console
console.log(Logger.colors.cyan('No config file found in the current working directory, creating nightwatch.conf.js in the current folder...'));
Expand Down Expand Up @@ -181,6 +185,7 @@ class CliRunner {

this.createTestRunner();
this.setupConcurrency();
this.loadTypescriptTranspiler();

analyticsCollector.updateSettings(this.test_settings);
analyticsCollector.updateLogger(Logger);
Expand All @@ -198,6 +203,17 @@ class CliRunner {
return this;
}

loadTypescriptTranspiler() {
const isTypescriptProject = Utils.fileExistsSync(path.join(process.cwd(), 'tsconfig.json'));
if (isTypescriptProject) {
Logger.info('Now you can run TS tests directly using Nightwatch.');
}
const projectTsFilePath = Utils.findTSConfigFile(this.test_settings.tsconfig_path);
if (projectTsFilePath !== '' && !this.test_settings.disable_typescript) {
Utils.loadTSNode(projectTsFilePath);
}
}

isConfigDefault(configFile, localJsValue = CliRunner.CONFIG_FILE_JS) {
return ArgvSetup.isDefault('config', configFile) || path.resolve(configFile) === localJsValue;
}
Expand All @@ -213,29 +229,38 @@ class CliRunner {
packageInfo = packageInfo || {};
const usingESM = packageInfo.type === 'module';

return path.resolve(usingESM ? CliRunner.CONFIG_FILE_CJS : CliRunner.CONFIG_FILE_JS);
const usingTS = Utils.fileExistsSync(CliRunner.CONFIG_FILE_TS);

if (usingESM) {
return path.resolve(CliRunner.CONFIG_FILE_CJS);
}
if (usingTS) {
return path.resolve(CliRunner.CONFIG_FILE_TS);
}

return path.resolve(CliRunner.CONFIG_FILE_JS);
}

loadConfig() {
if (!this.argv.config) {
return null;
}

const localJsValue = this.getLocalConfigFileName();
const localJsOrTsValue = this.getLocalConfigFileName();

// use default nightwatch.json file if we haven't received another value
if (this.isConfigDefault(this.argv.config, localJsValue)) {
if (this.isConfigDefault(this.argv.config, localJsOrTsValue)) {
let newConfigCreated = false;
const defaultValue = ArgvSetup.getDefault('config');
const hasJsConfig = Utils.fileExistsSync(localJsValue);
const hasJsOrTsConfig = Utils.fileExistsSync(localJsOrTsValue);
const hasJsonConfig = Utils.fileExistsSync(defaultValue);

if (!hasJsConfig && !hasJsonConfig) {
newConfigCreated = CliRunner.createDefaultConfig(localJsValue);
if (!hasJsOrTsConfig && !hasJsonConfig) {
newConfigCreated = CliRunner.createDefaultConfig(localJsOrTsValue);
}

if (hasJsConfig || newConfigCreated) {
this.argv.config = localJsValue;
if (hasJsOrTsConfig || newConfigCreated) {
this.argv.config = localJsOrTsValue;
} else if (hasJsonConfig) {
this.argv.config = path.join(path.resolve('./'), this.argv.config);
}
Expand Down
3 changes: 3 additions & 0 deletions lib/settings/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ module.exports = {
// property globals on the main client instance.
globals_path: null,

// Location of the existing TypeScript config file. If not provided Nightwatch will search for "nightwatch/tsconfig.json" or "tsconfig.nightwatch.json".
tsconfig_path: '',

// An object which will be made available on the main test api, throughout the test execution
globals: {

Expand Down
43 changes: 41 additions & 2 deletions lib/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ class Utils {
if (glob.hasMagic(source)) {
return resolve();
}

fs[followSymlinks ? 'stat' : 'lstat'](source, function(err, stats) {
if (err) {
return reject(err.code === 'ENOENT' && originalErr || err);
Expand Down Expand Up @@ -361,7 +361,7 @@ class Utils {
}
resolve(list);
};

glob.hasMagic(source) ? glob(source, callback) : fs.readdir(source, callback);
});
}
Expand Down Expand Up @@ -540,6 +540,45 @@ class Utils {
static shouldReplaceStack(err) {
return !alwaysDisplayError(err);
}

static findTSConfigFile(existingTSConfig) {
const projectTsFileLocation1 = path.join(process.cwd(), 'nightwatch', 'tsconfig.json');
const projectTsFileLocation2 = path.join(process.cwd(), 'tsconfig.nightwatch.json');

if (Utils.fileExistsSync(existingTSConfig)) {
return existingTSConfig;
}

if (Utils.fileExistsSync(projectTsFileLocation1)) {
return projectTsFileLocation1;
}
if (Utils.fileExistsSync(projectTsFileLocation2)) {
return projectTsFileLocation2;
}

return '';
}

static loadTSNode(projectTsFile) {
try {
require('ts-node').register({
esm: false,
project: projectTsFile
});
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') {
const error = new Error(`ts-node needs to be installed as a project dependency. You can install ts-node from NPM using:\n\n ${Logger.colors.light_green('npm i ts-node --save-dev')}`);
error.showTrace = false;
error.displayed = false;

throw error;
}

err.showTrace = false;

throw err;
}
}
}

lodashMerge(Utils, {
Expand Down
83 changes: 83 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
},
"devDependencies": {
"@cucumber/cucumber": "^8.2.1",
"@types/nightwatch": "^2.3.4",
"@types/node": "^16.7.1",
"chromedriver": "^106.0.1",
"coveralls": "^3.1.1",
Expand Down
Loading

0 comments on commit 92ad22d

Please sign in to comment.