Search code examples
typescriptcucumbercucumberjs

TypeScript Module Resolution doesn't quite work with Cucumber-js


I'm doing a small Proof of Concept for Cucumber-js – using TypeScript. So far everything is fine...but I can't find a way to properly configure the module resolution when using tsconfig-paths.

This is my project structure:

.
├── cucumber.js
├── features
│   └── bank-account.feature
├── package.json
├── package-lock.json
├── step-definitions
│   └── bank-account.steps.ts
├── support
│   └── model
│       └── bank-account.model.ts
├── tsconfig.json
└── tslint.json

I'm using cucumber-tsflow, so the "step definitions" looks like:

// import { BankAccount } from "@model/bank-account.model"; // ...trouble!
import { BankAccount } from "../support/model/bank-account.model";

import { expect } from "chai";
import { binding, given, then, when } from "cucumber-tsflow";

@binding()
export class BankAccountSteps {
  ...

  @when("{int} is deposited")
  public when(amount: number) {
    this.account.deposit(amount);
  }

  ...
}

...but I can't make use of @model/bank-account.model, even though I have it properly configured in tsconfig.json and cucumber.js:

# file: tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    ...
    "paths": {
      "*": ["./*"],
      "@model/*": ["./support/model/*"]
    },
    ...
    "types": [
      "@types/chai",
      "@types/cucumber",
      "node"
    ]
  },
  "exclude": ["node_modules/"],
  "include": ["./step-definitions/**/*", "./support/**/*"]
}
# file: cucumber.js
const common = [
  "features/**/*.feature",
  "--require-module ts-node/register",
  // "--require-module tsconfig-paths/register",
  "--require step-definitions/**/*.ts",
  "--require support/**/*.ts"
].join(" ");

module.exports = {
  default: common,
};

As soon as I "activate" tsconfig-paths – read: uncomment "--require-module tsconfig-paths/register" inside cucumber.js, I get this error message:

$ npm run test

> cucumber-js --profile default

TypeError: cucumber_1.Before is not a function
    at _.once (/home/x80486/Workshop/Development/cucumber-basics/node_modules/cucumber-tsflow/src/binding-decorator.ts:78:3)
    at /home/x80486/Workshop/Development/cucumber-basics/node_modules/underscore/underscore.js:957:21
    at /home/x80486/Workshop/Development/cucumber-basics/node_modules/cucumber-tsflow/src/binding-decorator.ts:38:5
    at __decorate (/home/x80486/Workshop/Development/cucumber-basics/step-definitions/bank-account.steps.ts:5:95)
    at Object.<anonymous> (/home/x80486/Workshop/Development/cucumber-basics/step-definitions/bank-account.steps.ts:8:30)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Module.m._compile (/home/x80486/Workshop/Development/cucumber-basics/node_modules/ts-node/src/index.ts:473:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/home/x80486/Workshop/Development/cucumber-basics/node_modules/ts-node/src/index.ts:476:12)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:690:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at supportCodePaths.forEach.codePath (/home/x80486/Workshop/Development/cucumber-basics/node_modules/cucumber/lib/cli/index.js:142:42)
    at Array.forEach (<anonymous>)

Anyone versed in TypeScript and/or Cucumber can shed some light on what's going on here?


UPDATE

If I delete cucumber.js and just pass all the options in the npm script ("test": "cucumber-js features/**/*.feature --require-module ts-node/register --require-module tsconfig-paths/register --require step-definitions/**/*.ts --require support/**/*.ts") it works :mind-blowing:

Also, changing baseUrl to something other than "./", for instance, "./support", without deleting cucumber.js does the trick.


Solution

  • Not really an answer with a resolution to this problem, but this is currently working with @cucumber/cucumber version 7.x — and probably the change was backported to previous stable versions.

    Here is a working (template-like project) to test this.