testing-library / user-event

🐕 Simulate user events
https://testing-library.com/user-event
MIT License
2.18k stars 246 forks source link

Upon updating to user event 14.4.3 typescript errors appear and npm run webpack fails #1077

Closed ghortat closed 1 year ago

ghortat commented 1 year ago

Reproduction example

No sandbox

Prerequisites

  1. tsconfig.json
{
  "compilerOptions": {
    "jsx": "react",
    "target": "es6",
    "module": "esnext",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "suppressImplicitAnyIndexErrors": true,
    "outDir": "build/resources/main/static/app",
    "lib": ["dom", "es2015", "es2016", "es2017", "es2020.string"],
    "types": ["jest", "webpack-env", "@testing-library/jest-dom"],
    "allowJs": true,
    "checkJs": false,
    "baseUrl": "./",
    "paths": {
      "app/*": ["src/main/webapp/app/*"]
    },
    "importHelpers": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["src/main/webapp/app", "src/test/javascript/spec", "src/test/javascript/spec/jest-setup.ts"],
  "exclude": ["node_modules"]
}
  1. tsconfig.test.json
{
  "extends": "./tsconfig",
  "compilerOptions": {
    "module": "commonjs",
    "allowSyntheticDefaultImports": true,
    "types": ["jest", "webpack-env"]
  }
}
  1. jest.conf.js
const tsconfig = require('../../../tsconfig.json');

module.exports = {
  transform: {
    '^.+\\.tsx?$': 'ts-jest'
  },
  rootDir: '../../../',
  testURL: 'http://localhost/',
  testEnvironment: "jsdom",
  cacheDirectory: '<rootDir>/build/jest-cache',
  coverageDirectory: '<rootDir>/build/test-results/',
  coverageReporters: ['text', 'lcov', 'cobertura'],
  testMatch: ['<rootDir>/src/test/javascript/spec/**/@(*.)@(spec.ts?(x))'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  coveragePathIgnorePatterns: [
    '<rootDir>/src/test/javascript'
  ],
  moduleNameMapper: mapTypescriptAliasToJestAlias({
    '\\.(css|scss)$': 'identity-obj-proxy'
  }),
  reporters: [
    'default',
    [ 'jest-junit', { outputDirectory: './build/test-results/', outputName: 'TESTS-results-jest.xml' } ]
  ],
  testResultsProcessor: 'jest-sonar-reporter',
  testPathIgnorePatterns: [
    '<rootDir>/node_modules/'
  ],
  setupFiles: [
    '<rootDir>/src/test/javascript/spec/enzyme-setup.ts',
    '<rootDir>/src/test/javascript/spec/storage-mock.ts'
  ],
  setupFilesAfterEnv: ['<rootDir>/src/test/javascript/spec/jest-setup.ts'],
  snapshotSerializers: ['enzyme-to-json/serializer'],
  globals: {
    'ts-jest': {
      tsconfig: './tsconfig.test.json',
      diagnostics: false
    }
  }
};

function mapTypescriptAliasToJestAlias(alias = {}) {
    const jestAliases = { ...alias };
    if (!tsconfig.compilerOptions.paths) {
      return jestAliases;
    }
    Object.entries(tsconfig.compilerOptions.paths)
      .filter(([key, value]) => {
        // use Typescript alias in Jest only if this has value
        if (value.length) {
          return true;
        }
        return false;
      })
      .map(([key, value]) => {
        // if Typescript alias ends with /* then in Jest:
        // - alias key must end with /(.*)
        // - alias value must end with /$1
        const regexToReplace = /(.*)\/\*$/;
        const aliasKey = key.replace(regexToReplace, '$1/(.*)');
        const aliasValue = value[0].replace(regexToReplace, '$1/$$1');
        return [aliasKey, `<rootDir>/${aliasValue}`];
      })
      .reduce((aliases, [key, value]) => {
        aliases[key] = value;
        return aliases;
      }, jestAliases);
    return jestAliases;
  }
  1. webpack.prod.js
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const sass = require('sass');

const utils = require('./utils.js');
const commonConfig = require('./webpack.common.js');

const ENV = 'production';

module.exports = webpackMerge(commonConfig({ env: ENV }), {
  // devtool: 'source-map', // Enable source maps. Please note that this will slow down the build
  mode: ENV,
  entry: {
    main: './src/main/webapp/app/index'
  },
  output: {
    path: utils.root('build/resources/main/static/'),
    filename: 'app/[name].[hash].bundle.js',
    chunkFilename: 'app/[name].[hash].chunk.js'
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.s?css$/,
        loader: 'stripcomment-loader'
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../'
            }
          },
          'css-loader',
          'postcss-loader',
          {
            loader: 'sass-loader',
            options: { implementation: sass }
          }
        ]
      }
    ]
  },
  optimization: {
    runtimeChunk: false,
    minimizer: [
      new TerserPlugin({
        cache: true,
        parallel: true,
        // sourceMap: true, // Enable source maps. Please note that this will slow down the build
        terserOptions: {
          ecma: 6,
          toplevel: true,
          module: true,
          beautify: false,
          comments: false,
          compress: {
            warnings: false,
            ecma: 6,
            module: true,
            toplevel: true
          },
          output: {
              comments: false,
              beautify: false,
              indent_level: 2,
              ecma: 6
          },
          mangle: {
            keep_fnames: true,
            module: true,
            toplevel: true
          }
        }
      }),
      new OptimizeCSSAssetsPlugin({})
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      filename: 'content/[name].[hash].css',
      chunkFilename: 'content/[name].[hash].css'
    }),
    new MomentLocalesPlugin({
      localesToKeep: [
        // jhipster-needle-i18n-language-moment-webpack - JHipster will add/remove languages in this array
      ]
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false
    }),
    new WorkboxPlugin.GenerateSW({
      clientsClaim: true,
      skipWaiting: true,
      exclude: [/swagger-ui/]
    })
  ]
});

For webserver prod to start:

npm run webpack -- --config webpack/webpack.prod.js --profile

Expected behavior

Type errors should not exist and webpack server should run properly without ts errors same as with userEvent 13.5.

Actual behavior

ERROR in C:/NFVRI/dashboard-ng/node_modules/@testing-library/user-event/dist/types/setup/setup.d.ts(15,5): TS2502: 'dispatchUIEvent' is referenced directly or indirectly in its own type annotation. ERROR in C:/NFVRI/dashboard-ng/node_modules/@testing-library/user-event/dist/types/utils/dataTransfer/Clipboard.d.ts(1,114): TS2304: Cannot find name 'ClipboardItem'. Version: typescript 3.8.3, eslint 6.8.0

User-event version

14.4.3

Environment

Testing Library framework: @testing-library/react@12.1.5 "@testing-library/jest-dom": "5.16.5", "@testing-library/dom": "7.31.2"

JS framework: react@16.13.1

Test environment: jest@27.5.1 ts-jest@27.1.5

DOM implementation: jsdom

webpack@4.43

Additional context

I am not so confident with ES modules and advanced configuration needed in order to support each and every one of the new features, however at that point i do not understand what breaking changes cause these errors. Perhaps this is caused due to Typescript discrepancy and the new testing dependencies cannot co-operate with TS 3.8.3 version.

ph-fritsche commented 1 year ago

typescript@3.8.3 is outdated since May 2020 and typescript@^4 is stable since August 2020. We won't work on compatibility with old Typescript versions.

ghortat commented 1 year ago

Ok i will update and let you know if this solved the problem.