nightwatch icon indicating copy to clipboard operation
nightwatch copied to clipboard

Can't override types with Nightwatch versions that added ts-node support

Open literallyMello opened this issue 3 years ago • 2 comments

Description of the bug/issue

When I use nightwatch.d.ts to extend Nightwatch types I expect to be able to use those types during test runtime

In versions of Nightwatch prior to adding direct .ts file execution (ts-node) I could create a nightwatch.d.ts file in my tests directory to make available custom commands on NightwatchBrowser. For example,

// nightwatch.d.ts
declare module "nightwatch" {
  export interface NightwatchCustomCommands {
    helloWorld(): Awaitable<NightwatchAPI>;
  }
}
// myTestFile.ts
'hello world test': async (browser: NightwatchBrowser) => {
  browser.helloWorld(); // would not give me any errors about the property not existing on Nightwatch browser
}

But in newer versions of Nightwatch when I try to execute the tests it attempts to load the nightwatch.d.ts file which causes this error


┌ ────────────────── ✖  local: nightwatch.d.ts  ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                                                                                                                          │
│     ✖ TypeError                                                                                                                                                                          │
│       Unable to require file: tests/nightwatch.d.ts                                                                                                                                      │
│    This is usually the result of a faulty configuration or import. Make sure there is a `.js`, `.json` or other executable extension with loader attached before `ts-node` available.    │
│        Stack Trace :                                                                                                                                                                     │
│        at getOutput (redacted/node_modules/ts-node/src/index.ts:1085:17)                                                                 │
│        at Object.compile (redacted/node_modules/ts-node/src/index.ts:1433:41)                                                            │
│        at Module.m._compile (redacted/node_modules/ts-node/src/index.ts:1617:30)                                                         │
│        at Module._extensions..js (node:internal/modules/cjs/loader:1180:10)                                                                                                              │
│        at Object.require.extensions.<computed> [as .ts] (redacted/node_modules/ts-node/src/index.ts:1621:12)                             │
│        at Module.load (node:internal/modules/cjs/loader:1004:32)                                                                                                                         │
│        at Function.Module._load (node:internal/modules/cjs/loader:839:12)                                                                                                                │
│        at Module.require (node:internal/modules/cjs/loader:1028:19)                                                                                                                      │
│        at require (node:internal/modules/cjs/helpers:102:18)                                                                                                                             │
│        at Function.module.exports [as requireModule] (/redactednode_modules/nightwatch/lib/utils/requireModule.js:4:16)                  │

Followed by


┌ ────────────────── ✖  local: helloWorldTest.ts  ──────────────────────────────────────────────────────────────────────────┐
│                                                                                                                             │
│     TSError                                                                                                                 │
│       ⨯ Unable to compile TypeScript:                                                                                       │
│    tests/helloWorldTest.ts(10,38): error TS2339: Property 'helloWorld' does not exist on type 'NightwatchBrowser'.    │
│                                                                                                                             │
│                                                                                                                             │
│                                                                                                                             │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

Steps to reproduce

  1. Create a nightwatch.d.ts file to add types not part of @types/nightwatch and put it inside your tests folder
// nightwatch.d.ts
declare module "nightwatch" {
  export interface NightwatchCustomCommands {
    helloWorld(): Awaitable<NightwatchAPI>;
  }
}
  1. In your test IDE those commands should be available in the intellisense, but if you try to execute the test using nightwatch --test yourTestHere.ts it will complain that Property 'helloWorld' does not exist on type 'NightwatchBrowser'.
// myTestFile.ts
'hello world test': async (browser: NightwatchBrowser) => {
  browser.helloWorld(); // IDE will not give me any errors about the property not existing on Nightwatch browser
}

If you try to run all your tests you'll notice Nightwatch tries to execute the nightwatch.d.ts file as a test as well.

If I go back to the older style of using tsc to transpile everything to .js in a separate test directory everything works fine still. It would be nice to leverage the direct execution capability while retaining the ability to extend/override the built in types to allow use of custom commands not part of the @types/nightwatch definitions

Sample test

No response

Command to run

No response

Verbose Output

No response

Nightwatch Configuration

No response

Nightwatch.js Version

2.6.4

Node Version

16.17.1

Browser

No response

Operating System

Mac

Additional Information

No response

literallyMello avatar Jan 03 '23 18:01 literallyMello

Hi, thanks for raising this issue.

For extending the types in Nightwatch, you can have a project structure like the following:

my-project/
  |-- nightwatch/
  |   |-- tsconfig.json
  |-- test/
  |   |--  myTest.ts
  |-- types/
  |   |-- nightwatch.d.ts
  |-- tsconfig.json
  |-- package.json

Now, suppose your test file is as follows:

// test/myTest.ts
import { NightwatchBrowser, NightwatchTests } from "nightwatch";

const Test: NightwatchTests = {
  'hello world test': async (browser: NightwatchBrowser) => {
    browser.helloWorld();
  }
}

export default Test;

You can create a types/nightwatch.d.ts file as below:

// types/nightwatch.d.ts
import 'nightwatch';

declare module "nightwatch" {
  interface NightwatchCustomCommands {
    helloWorld(): Awaitable<NightwatchAPI, unknown>;
  }
}

After creating the above file, the types for your custom command should start to appear in your tests. But if they don't, go to tsconfig.json file present in the root of your project, and add "files" and "include" properties to it:

// tsconfig.json
{
  "compilerOptions": {
    // all configs here
  },
  "files": ["./types/nightwatch.d.ts"],  // path to the recently created nightwatch.d.ts file.
  "include": ["test", "nightwatch"]  // directories in which your nightwatch tests are present, where the above type declaration file should be applied.
}

Also, make sure your nightwatch/tsconfig.json extends the root tsconfig.json so that the above added properties are auto-applied in there:

// nightwatch/tsconfig.json
{
  "extends": "../tsconfig",
  "compilerOptions": {
    // all configs here
  },
  "include": ["."]
}

Your project should run fine after following the above instructions.

Few additional notes:

  • If ts-node is still trying to run your nightwatch.d.ts file, you can use the exclude property in your nightwatch/tsconfig.json file, like below:
    {
      "extends": "../tsconfig",
      "compilerOptions": {
        // all configs here
      },
      "include": ["."],
      "exclude": ["**/*.d.ts"]
    }
    

garg3133 avatar Jan 05 '23 18:01 garg3133

This worked. I had to add the /nightwatch/globals/* and /nightwatch/commands to the exclude path, those contain .js files, to prevent a VS Code warning inside the tsconfig.json json about [files in there] will be overwritten.

reallymello avatar Jan 06 '23 12:01 reallymello