Почему декораторы не работают в Jest with Babel?

Я пытаюсь заставить работать декораторы JavaScript с помощью Jest и 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();

Когда я бегу yarn test, я получаю:

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.

Что я делаю не так?


person witrin    schedule 07.02.2019    source источник
comment
Это странно. Ближайшее, что я смог найти, это синтаксис stackoverflow.com/questions/52262084/. Что именно сделало то, что вы сделали, так что я предполагаю, что вы можете сначала вызвать декоратора самостоятельно, чтобы обойтись без него?   -  person bigopon    schedule 08.02.2019
comment
@bigopon Это было странно! Я опубликовал (быстрое) решение и проблему соответствия на GitHub.   -  person witrin    schedule 09.02.2019
comment
Да, они сказали, что .babelrc было ошибкой   -  person bigopon    schedule 09.02.2019


Ответы (1)


Хорошая подсказка приходит с сообщением об ошибке:

[...] missingPlugin: ['декораторы-устаревшие', 'декораторы'], код: 'BABEL_PARSE_ERROR'}

Интеграция Jest с Babel в первую очередь использует .babelrc, поскольку для каждого другого файла, полученного в результате теста, он искал только в корне проекта. В этом случае конфигурация Babel была в ./test/unit.

Так что помещение .babelrc в корневую папку проекта - одно из возможных исправлений (но не лучшее). Другие подходы можно найти здесь.

person witrin    schedule 09.02.2019