4

I'm trying to get JavaScript decorators to work using Jest and Babel:

./package.json

[...]
"devDependencies": {
    [...]
    "@babel/core": "7.2.2",
    "@babel/plugin-proposal-class-properties": "^7.3.0",
    "@babel/plugin-proposal-decorators": "^7.3.0",
    "@babel/preset-env": "^7.3.1",
    [...]
    "jest": "^24.1.0"
},
[...]
"scripts": {
    [...]
    "jest --no-cache --verbose --config ./test/unit/jest.json"
}

./test/unit/.babelrc

{
    "presets": [
        [
            "@babel/preset-env", {
                "targets": {
                    "node": "current"
                },
                "modules": "commonjs",
                "loose": true,
                "debug": true
            }
        ]
    ],
    "plugins": [
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        ["@babel/plugin-proposal-class-properties", { "loose": true}]
    ]
}

./test/unit/jest.json

{
    "modulePaths": [
        "<rootDir>/../../src",
        "<rootDir>/../../node_modules"
    ],
    "moduleFileExtensions": [
        "js",
        "json"
    ],
    "testRegex": "\\.spec\\.js$",
    "setupFiles": [
        "<rootDir>/jest.js"
    ],
    "testEnvironment": "node"
}

./test/unit/jest.js

import 'aurelia-polyfills';
import {Options} from 'aurelia-loader-nodejs';
import {globalize} from 'aurelia-pal-nodejs';
import * as path from 'path';
Options.relativeToDir = path.join(__dirname, '../../src');
globalize();

When I run yarn test I get:

yarn run v1.12.3
$ jest --no-cache --verbose --config ./test/unit/jest.json
@babel/preset-env: `DEBUG` option

Using targets:
{
  "node": "11.9"
}

Using modules transform: commonjs

Using plugins:
  syntax-async-generators { "node":"11.9" }
  syntax-object-rest-spread { "node":"11.9" }
  syntax-json-strings { "node":"11.9" }
  syntax-optional-catch-binding { "node":"11.9" }

Using polyfills: No polyfills were added, since the `useBuiltIns` option was not set.
  console.error internal/process/next_tick.js:81
    { SyntaxError: [...]/src/resources/elements/product/price.js: Support for the experimental syntax 'decorators-legacy' isn't currently enabled (10:1):

       8 | import { DataService } from 'services';
       9 | 
    > 10 | @inject(Element, Store, DataService, EventAggregator, I18N)
         | ^
      11 | @useViewStrategy(new RemoteViewStrategy())
      12 | export class ProductPrice {
      13 | 
        at Parser.raise ([...]/node_modules/@babel/parser/lib/index.js:3831:17)
        at Parser.expectOnePlugin ([...]/node_modules/@babel/parser/lib/index.js:5158:18)
        at Parser.parseDecorator ([...]/node_modules/@babel/parser/lib/index.js:7428:10)
        at Parser.parseDecorators ([...]/node_modules/@babel/parser/lib/index.js:7410:30)
        at Parser.parseStatement ([...]/node_modules/@babel/parser/lib/index.js:7245:12)
        at Parser.parseBlockOrModuleBlockBody ([...]/node_modules/@babel/parser/lib/index.js:7812:25)
        at Parser.parseBlockBody ([...]/node_modules/@babel/parser/lib/index.js:7799:10)
        at Parser.parseTopLevel ([...]/node_modules/@babel/parser/lib/index.js:7181:10)
        at Parser.parse ([...]/node_modules/@babel/parser/lib/index.js:8660:17)
        at parse ([...]/node_modules/@babel/parser/lib/index.js:10643:38)
      pos: 362,
      loc: Position { line: 10, column: 0 },
      missingPlugin: [ 'decorators-legacy', 'decorators' ],
      code: 'BABEL_PARSE_ERROR' }

  console.log test/unit/resources/elements/price.spec.js:25
    SyntaxError: [...]/src/resources/elements/product/price.js: Support for the experimental syntax 'decorators-legacy' isn't currently enabled (10:1):

       8 | import { DataService } from 'services';
       9 | 
    > 10 | @inject(Element, Store, DataService, EventAggregator, I18N)
         | ^
      11 | @useViewStrategy(new RemoteViewStrategy())
      12 | export class ProductPrice {
      13 | 

 FAIL  test/unit/resources/elements/price.spec.js (5.467s)
  ProductPrice
    ✕ should render current (5008ms)

  ● ProductPrice › should render current

    Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

      18 |     });
      19 | 
    > 20 |     it('should render current', done => {
         |     ^
      21 |         component.create(bootstrap).then(() => {
      22 |             const currentElement = document.querySelector('.current');
      23 |             expect(currentElement.innerHTML).toBe('');

      at Spec (../../node_modules/jest-jasmine2/build/jasmine/Spec.js:92:20)
      at Suite.it (resources/elements/price.spec.js:20:5)

  ● ProductPrice › should render current

    Cannot call ComponentTester.dispose() before ComponentTester.create()

      27 | 
      28 |     afterEach(() => {
    > 29 |         component.dispose();
         |                   ^
      30 |     });
      31 |   });

      at ComponentTester.Object.<anonymous>.ComponentTester.dispose (../../node_modules/aurelia-testing/dist/commonjs/component-tester.js:66:19)
      at Object.dispose (resources/elements/price.spec.js:29:19)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        6.389s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

What I'm doing wrong?

witrin
  • 3,701
  • 1
  • 24
  • 49
  • This is weird. The closest I could find is this https://stackoverflow.com/questions/52262084/syntax-error-support-for-the-experimental-syntax-decorators-legacy-isnt-cur . Which did exactly what you did, so I guess you may want to call the decorator yourself to work around first? – bigopon Feb 08 '19 at 08:58
  • @bigopon This was weird! I've posted a (quick) solution and the matching issue on GitHub. – witrin Feb 09 '19 at 01:19
  • Yeah, they said `.babelrc` was a mistake – bigopon Feb 09 '19 at 02:06

1 Answers1

1

A good hint comes with the error message:

[...] missingPlugin: [ 'decorators-legacy', 'decorators' ], code: 'BABEL_PARSE_ERROR' }

The Babel integration of Jest tooks the .babelrc in the first place, for every other file reached from the test it searched only in the project root. In this case the Babel configuration was in ./test/unit.

So putting .babelrc into the project root folder is one possible fix (but not the best). More approaches can be found here.

witrin
  • 3,701
  • 1
  • 24
  • 49