javascript - Jest: Kan ikke lese egenskapen til undefined når man importerer fra egen pakke


Jeg har opprettet en pakke kalt @package/test. Når den importeres til en ny, tom React TypeScript-app fungerer den perfekt. Problemene begynner i Jest-testsett.

Versjonen av commonJS-pakken får Jest til å kaste:

Test suite failed to run. TypeError:Cannot read property 'getSelectors' of undefined
import { Test } from `@package/test
const selectors = Test.getSelectors(...); //error here indicating that Test is undefined

Når jeg kompilerte en ES modules-pakkeversjon, får det Jest til å feile

export * from './common';
^^^^^^
SyntaxError: Unexpected token export

som er den første linjen i min src/index.ts inne i pakken min.

Jeg har testet mange løsninger, for eksempel:

  • Definerer transformIgnorePatterns for Jest
  • Søker etter sirkulære avhengigheter ved å bruke eslint-plugins og Madge
  • Testet på Node.js-versjoner: 10.20.0, 12.21.0, 15.12.0
  • Testet på TypeScript-versjoner: 3.7.5, 4.1.2

Noen detaljer om pakken:

/* package.json */
{
  "name": "@package/test",
  "version": "2.4.0",
  "main": "./dist/index.js",
  "scripts": {
    "build": "tsc -b ./tsconfig.package.json"
  },
  "typings": "./dist/index.d.ts",
  "files": [
    "dist"
  ],
  "dependencies": {...},
  "peerDependencies": {...},
  "sideEffects": "false"
}
/* tsconfig.package.json */
{
  "extends": "../../tsconfig.packages.json",
  "compilerOptions": { "outDir": "./dist", "rootDir": "./src", "composite": true },
  "references": [],
  "include": ["src"],
  "exclude": ["src/**/*.spec.*", "dist", "node_modules"]
}
/* tsconfig.packages.json */
{
  "extends": "../tsconfig.base.json",
  "compilerOptions": {
    "module": "es2020",
    "lib": ["es5", "es2015", "es2020", "dom"]
  }
}
/* tsconfig.base.json */
{
  "compileOnSave": false,
  "compilerOptions": {
    "declaration": true,
    "sourceMap": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "downlevelIteration": true,
    "skipLibCheck": true,
    "jsx": "react",
    "strict": true,
    "target": "es5"
  }
}

Hvordan Test eksporteres:

import * as actions from './actions';
import reducer, { Action, RootState} from './reducer';
import getSelectors from './getSelectors';

export const Test = {
  actions,
  reducer,
  getSelectors,
};

export { Action, RootState};
export * from './types';
export * from './helpers';

Hvordan getSelectors eksporteres:

export default function getSelectors<S>(selectNavigation: Selector<S, RootState>) {
  const getInitialized = createSelector(selectNavigation, (s) => s.initialized);
    ...
  return { getInitialized, ... };
}

Detaljer om React-testapplikasjon

/* package.json */
{
  "name": "jest-verify",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@package/test": "2.4.0",
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "@types/jest": "^26.0.15",
    "@types/node": "^12.0.0",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "typescript": "^4.1.2",
    "web-vitals": "^1.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
}
/* tsconfig.json */
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

REDIGER: Jeg klarte å få det til å fungere i min test React-app med transformIgnorePatterns, men dessverre fungerer det ikke i min Angular 1.6 (webpack, babel) app. La også til noen babel-plugins for å transformere pakken til commonJS, men ingen effekt.

Svar #1

Problemet var mye mer komplekst enn det så ut.

Ekstra utgave:

Jest respekterte ikke Babel-konfigurasjonen i json-filen. Jeg måtte transformere den til js.

Løsning nr. 1:

  • Installer @babel/preset-env som en dev-avhengighet.
  • Registrer det som en forhåndsinnstilling i Babels konfigurasjon:
env: {
    test: {
      presets: ['@babel/preset-env'],
    },
}
  • Registrer nødvendig transformIgnorePatterns i Jest-konfigurasjon
  • Legg dette til i transform-seksjonen i Jest-konfigurasjonen: "^.+\\.js$": "babel-jest"

Løsninger nr. 2:

  • Installer babel-jest og @babel/plugin-transform-modules-commonjs som utviklingsavhengigheter.
  • Registrer pluginen i Babels konfigurasjon:
env: {
    test: {
      plugins: ['@babel/plugin-transform-modules-commonjs'],
    },
}
  • Registrer nødvendig transformIgnorePatterns i Jest-konfigurasjon
  • Legg dette til i transform-seksjonen i Jest-konfigurasjonen: "^.+\\.js$": "babel-jest"

Relaterte artikler