Skip to content

Commit b59da78

Browse files
aryaemami59timdorr
andauthored
Migrate type tests to Vitest (#4731)
Co-authored-by: Tim Dorr <[email protected]>
1 parent d63640f commit b59da78

35 files changed

+3775
-4782
lines changed

.babelrc.cjs

-17
This file was deleted.

.github/workflows/test.yaml

+13-4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ jobs:
4848
- name: Lint
4949
run: yarn lint
5050

51+
- name: Run test suite
52+
run: yarn test
53+
5154
- name: Build
5255
run: yarn build
5356

@@ -90,9 +93,12 @@ jobs:
9093
- name: Install build artifact
9194
run: yarn add ./package.tgz
9295

93-
- run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.json ./vitest.config.mts ./test/tsconfig.json ./test/typescript/tsconfig.json
96+
- name: Erase path aliases
97+
run: sed -i -e /@remap-prod-remove-line/d tsconfig.base.json
9498

9599
- name: Run tests, against dist
100+
env:
101+
TEST_DIST: true
96102
run: yarn test
97103

98104
test-types:
@@ -129,12 +135,15 @@ jobs:
129135
- name: Install build artifact
130136
run: yarn add ./package.tgz
131137

138+
- name: Erase path aliases
139+
run: sed -i -e /@remap-prod-remove-line/d tsconfig.base.json
140+
132141
- name: Test types
142+
env:
143+
TEST_DIST: true
133144
run: |
134145
yarn tsc --version
135-
yarn check-types
136-
yarn test:typecheck
137-
yarn test:types
146+
yarn type-tests
138147
139148
are-the-types-wrong:
140149
name: Check package config with are-the-types-wrong

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,7 @@ website/translated_docs
3030
website/build/
3131
website/node_modules
3232
website/i18n/*
33+
34+
tsconfig.vitest-temp.json
35+
36+
.vscode

package.json

+7-8
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,20 @@
4343
"format": "prettier --write \"{src,test}/**/*.{js,ts}\" \"**/*.md\"",
4444
"format:check": "prettier --list-different \"{src,test}/**/*.{js,ts}\" \"**/*.md\"",
4545
"lint": "eslint --ext js,ts src test",
46-
"check-types": "tsc --noEmit && echo \"Types compiled\"",
47-
"test": "vitest --run",
48-
"test:types": "tsc -p test/typescript && echo \"Typetests passed\"",
46+
"test": "vitest --run --typecheck",
47+
"type-tests": "tsc -p tsconfig.test.json --noEmit",
4948
"test:watch": "vitest --watch",
5049
"test:cov": "vitest --coverage",
51-
"test:typecheck": "tsc -p test && echo \"Types passed\"",
52-
"build": "tsup",
53-
"prepublishOnly": "yarn clean && yarn check-types && yarn format:check && yarn lint && yarn test",
50+
"build": "yarn clean && tsup",
51+
"prepublishOnly": "yarn clean && yarn format:check && yarn lint && yarn test",
5452
"prepack": "yarn build",
5553
"examples:lint": "eslint --ext js,ts examples",
56-
"examples:test": "cross-env CI=true babel-node examples/testAll.js",
5754
"tsc": "tsc"
5855
},
5956
"devDependencies": {
6057
"@babel/core": "^7.24.3",
58+
"@types/babel__core": "^7.20.5",
59+
"@types/babel__helper-module-imports": "^7.18.3",
6160
"@types/node": "^20.11.30",
6261
"@typescript-eslint/eslint-plugin": "^7.3.1",
6362
"@typescript-eslint/parser": "^7.3.1",
@@ -76,7 +75,7 @@
7675
"rxjs": "^7.8.1",
7776
"tsup": "8.0.2",
7877
"typescript": "^5.5.4",
79-
"vitest": "^1.4.0"
78+
"vitest": "^2.0.5"
8079
},
8180
"resolutions": {
8281
"@typescript-eslint/eslint-plugin": "7.3.1",

rollup.config.js

-79
This file was deleted.

scripts/mangleErrors.cjs scripts/mangleErrors.mts

+57-22
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
1-
const fs = require('fs')
2-
const helperModuleImports = require('@babel/helper-module-imports')
1+
import type { Node, PluginObj, PluginPass } from '@babel/core'
2+
import * as helperModuleImports from '@babel/helper-module-imports'
3+
import * as fs from 'node:fs'
4+
5+
type Babel = typeof import('@babel/core')
36

47
/**
5-
* Converts an AST type into a javascript string so that it can be added to the error message lookup.
8+
* Represents the options for the {@linkcode mangleErrorsPlugin}.
9+
*
10+
* @internal
11+
*/
12+
export interface MangleErrorsPluginOptions {
13+
/**
14+
* Whether to minify the error messages or not.
15+
* If `true`, the error messages will be replaced with an index
16+
* that maps object lookup.
17+
*/
18+
minify: boolean
19+
}
20+
21+
/**
22+
* Converts an AST type into a JavaScript string so that it can be added to the error message lookup.
623
*
724
* Adapted from React (https://github.com/facebook/react/blob/master/scripts/shared/evalToString.js) with some
8-
* adjustments
25+
* adjustments.
926
*/
10-
const evalToString = ast => {
27+
const evalToString = (
28+
ast: Node | { type: 'Literal'; value: string }
29+
): string => {
1130
switch (ast.type) {
1231
case 'StringLiteral':
1332
case 'Literal': // ESLint
@@ -31,14 +50,14 @@ const evalToString = ast => {
3150
}
3251

3352
/**
34-
* Takes a `throw new error` statement and transforms it depending on the minify argument. Either option results in a
35-
* smaller bundle size in production for consumers.
53+
* Transforms a `throw new Error` statement based on the `minify` argument, resulting in a smaller bundle size
54+
* for consumers in production.
3655
*
37-
* If minify is enabled, we'll replace the error message with just an index that maps to an arrow object lookup.
56+
* If `minify` is enabled, the error message will be replaced with an index that maps to an object lookup.
3857
*
39-
* If minify is disabled, we'll add in a conditional statement to check the process.env.NODE_ENV which will output a
40-
* an error number index in production or the actual error message in development. This allows consumers using webpack
41-
* or another build tool to have these messages in development but have just the error index in production.
58+
* If `minify` is disabled, a conditional statement will be added to check `process.env.NODE_ENV`, which will output
59+
* an error number index in production or the actual error message in development. This allows consumers using Webpack
60+
* or another build tool to have these messages in development but only the error index in production.
4261
*
4362
* E.g.
4463
* Before:
@@ -49,30 +68,40 @@ const evalToString = ast => {
4968
* throw new Error(0);
5069
* throw new Error(1);
5170
*
52-
* After: (without minify):
53-
* throw new Error(node.process.NODE_ENV === 'production' ? 0 : "This is my error message.");
54-
* throw new Error(node.process.NODE_ENV === 'production' ? 1 : "This is a second error message.");
71+
* After (without minify):
72+
* throw new Error(process.env.NODE_ENV === 'production' ? 0 : "This is my error message.");
73+
* throw new Error(process.env.NODE_ENV === 'production' ? 1 : "This is a second error message.");
5574
*/
56-
module.exports = babel => {
75+
export const mangleErrorsPlugin = (
76+
babel: Babel,
77+
options: MangleErrorsPluginOptions
78+
): PluginObj<PluginPass & MangleErrorsPluginOptions> => {
5779
const t = babel.types
5880
// When the plugin starts up, we'll load in the existing file. This allows us to continually add to it so that the
5981
// indexes do not change between builds.
6082
let errorsFiles = ''
6183
if (fs.existsSync('errors.json')) {
6284
errorsFiles = fs.readFileSync('errors.json').toString()
6385
}
64-
let errors = Object.values(JSON.parse(errorsFiles || '{}'))
86+
const errors = Object.values(JSON.parse(errorsFiles || '{}'))
6587
// This variable allows us to skip writing back to the file if the errors array hasn't changed
6688
let changeInArray = false
6789

6890
return {
91+
name: 'mangle-errors-plugin',
6992
pre: () => {
7093
changeInArray = false
7194
},
7295
visitor: {
73-
ThrowStatement(path, file) {
96+
ThrowStatement(path) {
97+
if (
98+
!('arguments' in path.node.argument) ||
99+
!t.isNewExpression(path.node.argument)
100+
) {
101+
return
102+
}
74103
const args = path.node.argument.arguments
75-
const minify = file.opts.minify
104+
const { minify } = options
76105

77106
if (args && args[0]) {
78107
// Skip running this logic when certain types come up:
@@ -82,11 +111,15 @@ module.exports = babel => {
82111
path.node.argument.arguments[0].type === 'Identifier' ||
83112
path.node.argument.arguments[0].type === 'NumericLiteral' ||
84113
path.node.argument.arguments[0].type === 'ConditionalExpression' ||
85-
path.node.argument.arguments[0].type === 'CallExpression'
114+
path.node.argument.arguments[0].type === 'CallExpression' ||
115+
!t.isExpression(path.node.argument.arguments[0]) ||
116+
!t.isIdentifier(path.node.argument.callee)
86117
) {
87118
return
88119
}
89120

121+
const errorName = path.node.argument.callee.name
122+
90123
const errorMsgLiteral = evalToString(path.node.argument.arguments[0])
91124

92125
if (errorMsgLiteral.includes('Super expression')) {
@@ -106,7 +139,7 @@ module.exports = babel => {
106139
const formatProdErrorMessageIdentifier = helperModuleImports.addNamed(
107140
path,
108141
'formatProdErrorMessage',
109-
'src/utils/formatProdErrorMessage',
142+
'@internal/utils/formatProdErrorMessage',
110143
{ nameHint: 'formatProdErrorMessage' }
111144
)
112145

@@ -119,13 +152,13 @@ module.exports = babel => {
119152
if (minify) {
120153
path.replaceWith(
121154
t.throwStatement(
122-
t.newExpression(t.identifier('Error'), [prodMessage])
155+
t.newExpression(t.identifier(errorName), [prodMessage])
123156
)
124157
)
125158
} else {
126159
path.replaceWith(
127160
t.throwStatement(
128-
t.newExpression(t.identifier('Error'), [
161+
t.newExpression(t.identifier(errorName), [
129162
t.conditionalExpression(
130163
t.binaryExpression(
131164
'===',
@@ -150,3 +183,5 @@ module.exports = babel => {
150183
}
151184
}
152185
}
186+
187+
export default mangleErrorsPlugin

src/createStore.ts

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ import ActionTypes from './utils/actionTypes'
1414
import isPlainObject from './utils/isPlainObject'
1515
import { kindOf } from './utils/kindOf'
1616

17+
/**
18+
* Prevents TypeScript from inferring a generic type parameter.
19+
*
20+
* @template T - The type to prevent inference for.
21+
*
22+
* @internal
23+
*/
1724
type NoInfer<T> = [T][T extends any ? 0 : never]
1825

1926
/**

src/index.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import __DO_NOT_USE__ActionTypes from './utils/actionTypes'
1010

1111
// types
1212
// store
13-
export {
13+
export type {
1414
Dispatch,
1515
Unsubscribe,
1616
Observable,
@@ -21,7 +21,7 @@ export {
2121
StoreEnhancerStoreCreator
2222
} from './types/store'
2323
// reducers
24-
export {
24+
export type {
2525
Reducer,
2626
ReducersMapObject,
2727
StateFromReducersMapObject,
@@ -31,11 +31,11 @@ export {
3131
PreloadedStateShapeFromReducersMapObject
3232
} from './types/reducers'
3333
// action creators
34-
export { ActionCreator, ActionCreatorsMapObject } from './types/actions'
34+
export type { ActionCreator, ActionCreatorsMapObject } from './types/actions'
3535
// middleware
36-
export { MiddlewareAPI, Middleware } from './types/middleware'
36+
export type { MiddlewareAPI, Middleware } from './types/middleware'
3737
// actions
38-
export { Action, UnknownAction, AnyAction } from './types/actions'
38+
export type { Action, UnknownAction, AnyAction } from './types/actions'
3939

4040
export {
4141
createStore,

0 commit comments

Comments
 (0)