sumup-oss / circuit-ui

SumUp's design system for the web
https://circuit.sumup.com
Apache License 2.0
917 stars 130 forks source link

Jests tests cannot execute imports inside circuit-ui components #662

Closed AndriyOnyshchenko closed 4 years ago

AndriyOnyshchenko commented 4 years ago

First problem I faced is that imports from index file not working in tests (like this import { Toggle } from '@sumup/circuit-ui' ). In this case import statement returns undefined. I fixed it by changing path to import Toggle from '@sumup/circuit-ui/dist/es/components/Toggle/Toggle';

Right now jest cannot import modules inside circuit component /node_modules/@sumup/circuit-ui/dist/es/components/Toggle/Toggle.js:15 import React from 'react'; SyntaxError: Cannot use import statement outside a module

jest.config.js

module.exports = {
    testEnvironment: 'jest-environment-jsdom',
    moduleNameMapper: {
        '\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
            '<rootDir>/__mocks__/fileMock.js',
        '\\.(css|scss)$': '<rootDir>/test/__mocks__/styleMock.js',
        Components: '<rootDir>/client/static/react/components/',
        '^gfx/(.*)$': '<rootDir>/client/static/gfx/$1',
        '^shared/(.*)$': '<rootDir>/client/static/src/shared/$1',
        '^sales/(.*)$': '<rootDir>/client/static/src/sales/$1',
        '^src/(.*)$': '<rootDir>/client/static/src/$1',
        '^react/(.*)$': '<rootDir>/client/static/react/$1'
    },
    snapshotSerializers: ['enzyme-to-json/serializer'],
    setupFilesAfterEnv: ['<rootDir>/setup.enzyme.js'],
    testPathIgnorePatterns: ['.spec.js'],
    moduleDirectories: ['node_modules', 'src', 'react'],
    transform: {
        '^.+\\.(ts|tsx)?$': 'ts-jest',
        '^.+\\.(js|jsx)$': 'babel-jest',
        '^.+\\.svg$': 'jest-svg-transformer'
    }
};

babel.config.json

{
    "sourceType": "unambiguous",
    "plugins": [
        "@babel/plugin-proposal-function-bind",
        "@babel/plugin-proposal-export-default-from",
        "@babel/plugin-proposal-logical-assignment-operators",
        ["@babel/plugin-proposal-optional-chaining", { "loose": false }],
        ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }],
        ["@babel/plugin-proposal-nullish-coalescing-operator", { "loose": false }],
        "@babel/plugin-proposal-do-expressions",
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        "@babel/plugin-proposal-function-sent",
        "@babel/plugin-proposal-export-namespace-from",
        "@babel/plugin-proposal-numeric-separator",
        "@babel/plugin-proposal-throw-expressions",
        "@babel/plugin-syntax-dynamic-import",
        "@babel/plugin-syntax-import-meta",
        ["@babel/plugin-proposal-class-properties", { "loose": true }],
        "@babel/plugin-proposal-json-strings",
        "@babel/plugin-transform-modules-commonjs",
        "@babel/plugin-transform-runtime"
    ],
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react",
        "@babel/preset-typescript"
    ]
}

package.json dependencies

    "dependencies": {
        "@babel/core": "7.10.1",
        "@babel/plugin-proposal-class-properties": "7.10.1",
        "@babel/plugin-proposal-decorators": "7.10.1",
        "@babel/plugin-proposal-do-expressions": "7.10.1",
        "@babel/plugin-proposal-export-default-from": "7.10.1",
        "@babel/plugin-proposal-export-namespace-from": "7.10.1",
        "@babel/plugin-proposal-function-bind": "7.10.1",
        "@babel/plugin-proposal-function-sent": "7.10.1",
        "@babel/plugin-proposal-json-strings": "7.10.1",
        "@babel/plugin-proposal-logical-assignment-operators": "7.10.1",
        "@babel/plugin-proposal-nullish-coalescing-operator": "7.10.1",
        "@babel/plugin-proposal-numeric-separator": "7.10.1",
        "@babel/plugin-proposal-optional-chaining": "7.10.1",
        "@babel/plugin-proposal-pipeline-operator": "7.10.1",
        "@babel/plugin-proposal-throw-expressions": "7.10.1",
        "@babel/plugin-syntax-class-properties": "7.10.1",
        "@babel/plugin-syntax-dynamic-import": "7.8.3",
        "@babel/plugin-syntax-export-default-from": "7.10.1",
        "@babel/plugin-syntax-import-meta": "7.10.1",
        "@babel/plugin-transform-modules-commonjs": "7.10.1",
        "@babel/plugin-transform-runtime": "7.10.1",
        "@babel/polyfill": "7.10.1",
        "@babel/preset-env": "7.10.1",
        "@babel/preset-react": "7.10.1",
        "@babel/preset-typescript": "^7.10.4",
        "@babel/register": "7.10.1",
        "@debitoor/accounting": "2.4.4",
        "@debitoor/billing-pricing": "0.1.4",
        "@debitoor/email-template": "1.2.3",
        "@debitoor/log": "6.1.1",
        "@debitoor/number-series": "1.2.5",
        "@debitoor/printify": "1.1.15",
        "@debitoor/service-log": "4.1.4",
        "@debitoor/service-url": "5.18.0",
        "@debitoor/taxrates": "1.37.0",
        "@emotion/core": "^10.0.28",
        "@emotion/styled": "^10.0.27",
        "@sumup/circuit-ui": "^2.0.0",
        "@sumup/collector": "^1.0.0-alpha.1",
        "@sumup/design-tokens": "^1.0.3",
        "@sumup/icons": "^1.0.1",
        "@sumup/intl": "^1.1.2",
        "@svgr/webpack": "4.3.3",
        "@types/enzyme": "^3.10.5",
        "@types/jest": "^26.0.9",
        "app-root-path": "3.0.0",
        "async": "2.0.1",
        "autoprefixer": "9.7.4",
        "babel-cli": "^6.26.0",
        "babel-core": "7.0.0-bridge.0",
        "babel-loader": "8.1.0",
        "before-build-webpack": "0.2.9",
        "browser-filesaver": "1.1.1",
        "classnames": "2.2.5",
        "clean-webpack-plugin": "3.0.0",
        "cnf": "3.3.3",
        "compression": "1.7.1",
        "copy-webpack-plugin": "5.1.1",
        "cors": "2.8.4",
        "css-loader": "3.4.2",
        "debitoor-alias-pattern": "git+ssh://git@github.com/debitoor/debitoor-alias-pattern.git#v1.0.1",
        "debounce": "1.0.0",
        "dompurify": "2.0.12",
        "dot-prop-immutable": "1.1.2",
        "ejs": "2.5.6",
        "email-address": "git+ssh://git@github.com/debitoor/email-address.git#v1.2.0",
        "emotion-theming": "^10.0.27",
        "enzyme": "^3.11.0",
        "enzyme-adapter-react-16": "^1.15.3",
        "enzyme-to-json": "^3.5.0",
        "event-stream": "3.3.4",
        "express": "4.16.1",
        "express-timeout-handler": "2.1.2",
        "file-loader": "5.0.2",
        "friendly-errors-webpack-plugin": "1.7.0",
        "glob-to-regexp": "0.4.0",
        "gulp": "4.0.2",
        "gulp-svg-sprite": "1.5.0",
        "html-webpack-plugin": "4.0.0-beta.11",
        "http-proxy": "1.18.1",
        "imports-loader": "0.7.1",
        "jest": "^26.4.0",
        "linear-depreciation": "git+ssh://git@github.com/debitoor/linear-depreciation.git#v1.2.2",
        "mini-css-extract-plugin": "0.9.0",
        "mobile-detect": "1.4.4",
        "mobx": "4.9.2",
        "mobx-react": "5.4.3",
        "mobx-react-form": "1.36.0",
        "moment": "2.20.1",
        "node-sass": "4.13.1",
        "nodeerrors": "2.1.2",
        "npm-run-all": "4.1.5",
        "optimize-css-assets-webpack-plugin": "5.0.3",
        "path-to-regexp": "6.1.0",
        "payment-terms": "1.0.2",
        "postcss-loader": "3.0.0",
        "prop-types": "15.6.1",
        "qs": "6.4.0",
        "raw-loader": "0.5.1",
        "react": "16.9.0",
        "react-color": "2.14.1",
        "react-dom": "16.9.0",
        "react-dropzone": "10.0.0",
        "react-markdown": "3.3.3",
        "react-onclickoutside": "6.9.0",
        "react-select": "1.2.1",
        "react-textarea-autosize": "7.1.0",
        "react-virtualized": "9.19.1",
        "request": "2.75.0",
        "request-retry-stream": "2.1.0",
        "resolve-url-loader": "3.1.1",
        "sass-loader": "6.0.6",
        "spark-md5": "3.0.1",
        "style-loader": "0.19.1",
        "svg-url-loader": "3.0.3",
        "svgo": "1.3.2",
        "svgo-loader": "2.2.1",
        "terser-webpack-plugin": "2.3.3",
        "trackjs": "3.6.0",
        "traverse": "0.6.6",
        "ts-jest": "^26.2.0",
        "typescript": "^3.9.7",
        "underscore": "1.4.4",
        "url-loader": "3.0.0",
        "validatorjs": "3.17.1",
        "webpack": "4.39.3",
        "webpack-cli": "3.3.10",
        "webpack-fix-style-only-entries": "0.4.0",
        "webpack-merge": "4.2.2",
        "whatwg-fetch": "2.0.1",
        "xtend": "4.0.1"
    },
    "devDependencies": {
        "@debitoor/eslint-config-debitoor": "3.0.2",
        "@debitoor/mocha-strict-dependencies": "1.1.0",
        "@debitoor/parse-dependencies": "1.0.1",
        "@debitoor/start-development-service": "1.3.0",
        "@debitoor/tenantmongo": "4.0.0",
        "@testing-library/cypress": "6.0.0",
        "babel-eslint": "10.1.0",
        "babel-jest": "26.0.1",
        "chai": "3.5.0",
        "chai-as-promised": "6.0.0",
        "chai-pretty-expect": "1.0.1",
        "chai-subset": "1.6.0",
        "cypress": "4.8.0",
        "eslint-config-prettier": "6.0.0",
        "eslint-plugin-cypress": "2.10.3",
        "eslint-plugin-prettier": "3.1.0",
        "eslint-plugin-react": "6.3.0",
        "husky": "4.2.3",
        "jasmine-core": "2.5.2",
        "jest-svg-transformer": "1.0.0",
        "karma": "3.1.1",
        "karma-chrome-launcher": "2.2.0",
        "karma-jasmine": "1.0.2",
        "karma-phantomjs-launcher": "1.0.4",
        "lint-staged": "10.1.2",
        "mocha": "7.2.0",
        "mocha-csslint": "2.0.0",
        "mocha-eslint": "6.0.0",
        "mocha-junit-reporter": "1.23.3",
        "mocha-multi-reporters": "1.1.7",
        "mockery": "1.7.0",
        "optimist": "0.6.1",
        "prettier": "1.19.1",
        "sinon": "1.17.6",
        "sinon-chai": "2.8.0",
        "start-server-and-test": "1.10.11",
        "test-data-bot": "0.8.0",
        "webpack-dev-server": "3.11.0"
    },
connor-baer commented 4 years ago

Thanks for filing an issue @AndriyOnyshchenko. Please use an issue template next time your file an issue — it ensures that all relevant information is included so that we can help you faster and the consistent format helps others to browse the issues.

It seems like Jest isn't able to parse the Circuit UI code, likely because we changed how it is transpiled in v2 (see the migration guide). Try including Circuit UI in Jest's transpilation by excluding it from the transformIgnorePatterns:

// jest.config.js
"transformIgnorePatterns": ["/node_modules/(?!@sumup).+\\.js$"]

From https://github.com/facebook/jest/issues/6229#issuecomment-403539460


I fixed it by changing path to import Toggle from '@sumup/circuit-ui/dist/es/components/Toggle/Toggle';

You could try import Toggle from '@sumup/circuit-ui/dist/cjs/components/Toggle/Toggle'; (note the cjs) instead. However, using the absolute path to the component file has two major downsides: it prevents your bundler from choosing the best format (CJS vs ES) and this will break if the file structure in the /dist folder changes (which is likely to happen eventually).

AndriyOnyshchenko commented 4 years ago

@connor-baer I have added current line "transformIgnorePatterns": ["/node_modules/(?!@sumup).+\\.js$"] but it not helped. About absolute path you are right, at some parts of application it fails. Thanks, didn't notice that.

So basically with imports from index jest gets undefined.

Screenshot 2020-08-17 at 17 42 18
connor-baer commented 4 years ago

@AndriyOnyshchenko Hm, that's too bad. I would need to look at the code/project to be able to debug it further. Do you have a reproducible test case? Can you share the project?

github-actions[bot] commented 4 years ago

:tada: This issue has been resolved in version 2.1.0-canary.3 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

connor-baer commented 4 years ago

Update for future reference: @AndriyOnyshchenko provided access to the project which enabled me to debug the issue further. It turned out the problem wasn't solved with the bugfix above.

Rather, it was the configuration for absolute import paths that was too greedy. It matched all imports starting with Components which included the ComponentsContext component from Circuit UI. Changing the config to only match imports from the Components/ folder fixed the issue:

jest.config.js

- Components: '<rootDir>/client/static/react/components/',`
+ '^Components/(.*)$': '<rootDir>/client/static/react/components/$1',
github-actions[bot] commented 4 years ago

:tada: This issue has been resolved in version 2.1.0-beta.1 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

github-actions[bot] commented 4 years ago

:tada: This issue has been resolved in version 2.1.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: