From d1878e261ec382aec1deb406cb7aba45a2b4397b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= Date: Thu, 11 Nov 2021 20:27:57 +0100 Subject: [PATCH] Scripts: Add TypeScript for builds and tests (#36260) * Scripts: Add TypeScript for builds and tests * Scripts: Add documentation for improved TS support --- package-lock.json | 115 ++++++++++++++++++-- package.json | 2 +- packages/create-block/package.json | 2 +- packages/jest-preset-default/CHANGELOG.md | 4 + packages/jest-preset-default/README.md | 2 +- packages/jest-preset-default/jest-preset.js | 8 +- packages/scripts/CHANGELOG.md | 4 + packages/scripts/README.md | 22 ++-- packages/scripts/config/jest-e2e.config.js | 4 +- packages/scripts/config/jest-unit.config.js | 2 +- packages/scripts/config/webpack.config.js | 28 +++-- packages/scripts/package.json | 1 + 12 files changed, 148 insertions(+), 46 deletions(-) diff --git a/package-lock.json b/package-lock.json index faad17a80aa633..2224ca3b0e3789 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18918,7 +18918,7 @@ "check-node-version": "^4.1.0", "commander": "^4.1.0", "execa": "^4.0.2", - "fast-glob": "^2.2.7", + "fast-glob": "^3.2.7", "inquirer": "^7.1.0", "lodash": "^4.17.21", "make-dir": "^3.0.0", @@ -19683,6 +19683,7 @@ "eslint": "^7.17.0", "eslint-plugin-markdown": "^2.2.0", "expect-puppeteer": "^4.4.0", + "fast-glob": "^3.2.7", "filenamify": "^4.2.0", "jest": "^26.6.3", "jest-circus": "^26.6.3", @@ -35873,17 +35874,97 @@ "dev": true }, "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } } }, "fast-json-parse": { @@ -37658,6 +37739,20 @@ "path-type": "^3.0.0" } }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, "glob": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", diff --git a/package.json b/package.json index 949137dbc8ee9c..564ebdf2ab4546 100644 --- a/package.json +++ b/package.json @@ -171,7 +171,7 @@ "eslint-plugin-eslint-comments": "3.1.2", "eslint-plugin-import": "2.25.2", "execa": "4.0.2", - "fast-glob": "2.2.7", + "fast-glob": "3.2.7", "glob": "7.1.2", "husky": "7.0.0", "inquirer": "7.1.0", diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 4115fbf5d5a9e8..fb549db04e6887 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -36,7 +36,7 @@ "check-node-version": "^4.1.0", "commander": "^4.1.0", "execa": "^4.0.2", - "fast-glob": "^2.2.7", + "fast-glob": "^3.2.7", "inquirer": "^7.1.0", "lodash": "^4.17.21", "make-dir": "^3.0.0", diff --git a/packages/jest-preset-default/CHANGELOG.md b/packages/jest-preset-default/CHANGELOG.md index 5d68d2b9d3f1b9..29df66d9ef3df6 100644 --- a/packages/jest-preset-default/CHANGELOG.md +++ b/packages/jest-preset-default/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fix + +- Improve support for test files with `.jsx` and `.tsx` extensions ([#36260](https://github.com/WordPress/gutenberg/pull/36260)). + ## 7.1.2 (2021-10-22) ### Bug Fix diff --git a/packages/jest-preset-default/README.md b/packages/jest-preset-default/README.md index 245734b9136578..fc1e7a024fdb82 100644 --- a/packages/jest-preset-default/README.md +++ b/packages/jest-preset-default/README.md @@ -31,7 +31,7 @@ npm install @wordpress/jest-preset-default --save-dev - `setupFiles` - runs code before each test which sets up global variables required in the testing environment. - `setupFilesAfterEnv` - runs code which adds improved support for `Console` object and `React` components to the testing framework before each test. - `snapshotSerializers` - makes it possible to use snapshot tests on `Enzyme` wrappers. -- `testMatch`- includes `/test/` subfolder in addition to the glob patterns Jest uses to detect test files. It detects only test files containing `.js` (or `.ts`) suffix. It doesn't match files with `.spec.js` suffix. +- `testMatch`- includes `/test/` subfolder in addition to the glob patterns Jest uses to detect test files. It detects only test files containing `.js`, `.jsx`, `.ts` and `.tsx` suffix. It doesn't match files with `.spec.js` suffix. - `timers` - use of [fake timers](https://jestjs.io/docs/en/timer-mocks.html) for functions such as `setTimeout` is enabled. - `transform` - keeps the default [babel-jest](https://github.com/facebook/jest/tree/HEAD/packages/babel-jest) transformer. - `verbose` - each individual test won't be reported during the run. diff --git a/packages/jest-preset-default/jest-preset.js b/packages/jest-preset-default/jest-preset.js index 5dc0277f2d88e2..cdf8a1bcc170fa 100644 --- a/packages/jest-preset-default/jest-preset.js +++ b/packages/jest-preset-default/jest-preset.js @@ -17,13 +17,13 @@ module.exports = { ], snapshotSerializers: [ require.resolve( 'enzyme-to-json/serializer.js' ) ], testMatch: [ - '**/__tests__/**/*.[jt]s', - '**/test/*.[jt]s', - '**/?(*.)test.[jt]s', + '**/__tests__/**/*.[jt]s?(x)', + '**/test/*.[jt]s?(x)', + '**/?(*.)test.[jt]s?(x)', ], testPathIgnorePatterns: [ '/node_modules/', '/vendor/' ], timers: 'fake', transform: { - '^.+\\.[jt]sx?$': require.resolve( 'babel-jest' ), + '\\.[jt]sx?$': require.resolve( 'babel-jest' ), }, }; diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 8a871e3133b375..ff6055e019a00a 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -16,6 +16,10 @@ - The webpack config was updated to no longer include the polyfill by default when creating the `assets.php` file. If your usage requires the `wp-polyfill`, you must explicitly set it as a dependency ([#34536](https://github.com/WordPress/gutenberg/pull/35436)]. +### New Features + +- Add basic support for TypeScript in `build`, `start`, `test-e2e` and `test-unit-js` commands ([#36260](https://github.com/WordPress/gutenberg/pull/36260)). + ### Enhancements - Allow customization of the `ARTIFACTS_PATH` in the `jest-environment-puppeteer` failed test reporter via the `WP_ARTIFACTS_PATH` environment variable ([#35371](https://github.com/WordPress/gutenberg/pull/35371)). diff --git a/packages/scripts/README.md b/packages/scripts/README.md index 39fe366e8c97fd..67fa682186d1ee 100644 --- a/packages/scripts/README.md +++ b/packages/scripts/README.md @@ -58,7 +58,7 @@ We commit to keeping the breaking changes minimal so you can upgrade `@wordpress ### `build` -Transforms your code according the configuration provided so it’s ready for production and optimized for the best performance. The entry point for your project’s code should be located in `src/index.js`. The output generated will be written to `build/index.js`. This script exits after producing a single build. For incremental builds, better suited for development, see the [start](#start) script. +Transforms your code according the configuration provided so it’s ready for production and optimized for the best performance. The entry point for your project’s code should be located in `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`). The output generated will be written to `build/index.js`. This script exits after producing a single build. For incremental builds, better suited for development, see the [start](#start) script. _Example:_ @@ -154,7 +154,7 @@ By default, files located in `build`, `node_modules`, and `vendor` folders are i ### `lint-js` -Helps enforce coding style guidelines for your JavaScript files. +Helps enforce coding style guidelines for your JavaScript and TypeScript files. _Example:_ @@ -169,8 +169,8 @@ _Example:_ This is how you execute the script with presented setup: -- `npm run lint:js` - lints JavaScript files in the entire project’s directories. -- `npm run lint:js:src` - lints JavaScript files in the project’s `src` subfolder’s directories. +- `npm run lint:js` - lints JavaScript and TypeScript files in the entire project’s directories. +- `npm run lint:js:src` - lints JavaScript and TypeScript files in the project’s `src` subfolder’s directories. When you run commands similar to the `npm run lint:js:src` example above, you can provide a file, a directory, or `glob` syntax or any combination of them. See [more examples](https://eslint.org/docs/user-guide/command-line-interface). @@ -305,7 +305,7 @@ The command checks which packages whose name starts with `@wordpress/` are used ### `start` -Transforms your code according the configuration provided so it’s ready for development. The script will automatically rebuild if you make changes to the code, and you will see the build errors in the console. The entry point for your project’s code should be located in `src/index.js`. The output generated will be written to `build/index.js`. For single builds, better suited for production, see the [build](#build) script. +Transforms your code according the configuration provided so it’s ready for development. The script will automatically rebuild if you make changes to the code, and you will see the build errors in the console. The entry point for your project’s code should be located in `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`). The output generated will be written to `build/index.js`. For single builds, better suited for production, see the [build](#build) script. _Example:_ @@ -364,8 +364,8 @@ This is how you execute those scripts using the presented setup: Jest will look for test files with any of the following popular naming conventions: -- Files with `.js` (or `.ts`) suffix at any level of depth in `spec` folders. -- Files with `.spec.js` (or `.spec.ts`) suffix. +- Files with `.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) suffix at any level of depth in `spec` folders. +- Files with `.spec.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) suffix. This script automatically detects the best config to start Puppeteer but sometimes you may need to specify custom options: @@ -417,9 +417,9 @@ This is how you execute those scripts using the presented setup: Jest will look for test files with any of the following popular naming conventions: -- Files with `.js` (or `.ts`) suffix located at any level of depth in `__tests__` folders. -- Files with `.js` (or `.ts`) suffix directly located in `test` folders. -- Files with `.test.js` (or `.test.ts`) suffix. +- Files with `.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) suffix located at any level of depth in `__tests__` folders. +- Files with `.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) suffix directly located in `test` folders. +- Files with `.test.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) suffix. #### Advanced information @@ -498,7 +498,7 @@ The `build` and `start` commands use [webpack](https://webpack.js.org/) behind t - [Entry](https://webpack.js.org/configuration/entry-context/#entry): `src/index.js` - [Output](https://webpack.js.org/configuration/output): `build/index.js` - [Loaders](https://webpack.js.org/loaders/): - - [`babel-loader`](https://webpack.js.org/loaders/babel-loader/) allows transpiling JavaScript files using Babel and webpack. + - [`babel-loader`](https://webpack.js.org/loaders/babel-loader/) allows transpiling JavaScript and TypeScript files using Babel and webpack. - [`@svgr/webpack`](https://www.npmjs.com/package/@svgr/webpack) and [`url-loader`](https://webpack.js.org/loaders/url-loader/) makes it possible to handle SVG files in JavaScript code. - [`css-loader`](https://webpack.js.org/loaders/css-loader/) chained with [`postcss-loader`](https://webpack.js.org/loaders/postcss-loader/) and [sass-loader](https://webpack.js.org/loaders/sass-loader/) let webpack process CSS, SASS or SCSS files referenced in JavaScript files. - [Plugins](https://webpack.js.org/configuration/plugins) (among others): diff --git a/packages/scripts/config/jest-e2e.config.js b/packages/scripts/config/jest-e2e.config.js index 93f2f712b40199..8d87faa553b29a 100644 --- a/packages/scripts/config/jest-e2e.config.js +++ b/packages/scripts/config/jest-e2e.config.js @@ -21,7 +21,7 @@ const jestE2EConfig = { ], setupFilesAfterEnv: [ 'expect-puppeteer' ], testEnvironment: path.join( __dirname, 'jest-environment-puppeteer' ), - testMatch: [ '**/specs/**/*.[jt]s', '**/?(*.)spec.[jt]s' ], + testMatch: [ '**/specs/**/*.[jt]s?(x)', '**/?(*.)spec.[jt]s?(x)' ], testPathIgnorePatterns: [ '/node_modules/' ], testRunner: 'jest-circus/runner', testTimeout: 30000, @@ -29,7 +29,7 @@ const jestE2EConfig = { if ( ! hasBabelConfig() ) { jestE2EConfig.transform = { - '^.+\\.[jt]sx?$': path.join( __dirname, 'babel-transform' ), + '\\.[jt]sx?$': path.join( __dirname, 'babel-transform' ), }; } diff --git a/packages/scripts/config/jest-unit.config.js b/packages/scripts/config/jest-unit.config.js index a6228f60b02d5d..22be3e4a39e021 100644 --- a/packages/scripts/config/jest-unit.config.js +++ b/packages/scripts/config/jest-unit.config.js @@ -19,7 +19,7 @@ const jestUnitConfig = { if ( ! hasBabelConfig() ) { jestUnitConfig.transform = { - '^.+\\.[jt]sx?$': path.join( __dirname, 'babel-transform' ), + '\\.[jt]sx?$': path.join( __dirname, 'babel-transform' ), }; } diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index d4f7730ba7cb2f..d745b874f936a6 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -7,7 +7,7 @@ const MiniCSSExtractPlugin = require( 'mini-css-extract-plugin' ); const TerserPlugin = require( 'terser-webpack-plugin' ); const { CleanWebpackPlugin } = require( 'clean-webpack-plugin' ); const browserslist = require( 'browserslist' ); -const fs = require( 'fs' ); +const { sync: glob } = require( 'fast-glob' ); const path = require( 'path' ); /** @@ -36,17 +36,14 @@ let entry = {}; if ( process.env.WP_ENTRY ) { entry = JSON.parse( process.env.WP_ENTRY ); } else { - // By default the script checks if `src/index.js` exists and sets it as an entry point. - // In the future we should add similar handling for `src/script.js` and `src/view.js`. - [ 'index' ].forEach( ( entryName ) => { - const filepath = path.resolve( - process.cwd(), - 'src', - `${ entryName }.js` - ); - if ( fs.existsSync( filepath ) ) { - entry[ entryName ] = filepath; - } + // The script checks whether standard file names can be detected in the `src` folder, + // and converts all found files to entry points. + const entryFiles = glob( 'src/index.[jt]s?(x)', { + absolute: true, + } ); + entryFiles.forEach( ( filepath ) => { + const [ entryName ] = path.basename( filepath ).split( '.' ); + entry[ entryName ] = filepath; } ); } @@ -115,6 +112,7 @@ const config = { alias: { 'lodash-es': 'lodash', }, + extensions: [ '.ts', '.tsx', '...' ], }, optimization: { // Only concatenate modules in production, when not analyzing bundles. @@ -155,7 +153,7 @@ const config = { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(j|t)sx?$/, exclude: /node_modules/, use: [ { @@ -200,7 +198,7 @@ const config = { }, { test: /\.svg$/, - issuer: /\.jsx?$/, + issuer: /\.(j|t)sx?$/, use: [ '@svgr/webpack', 'url-loader' ], type: 'javascript/auto', }, @@ -259,7 +257,7 @@ if ( ! isProduction ) { // See: https://webpack.js.org/configuration/devtool/#devtool. config.devtool = process.env.WP_DEVTOOL || 'source-map'; config.module.rules.unshift( { - test: /\.js$/, + test: /\.(j|t)sx?$/, exclude: [ /node_modules/ ], use: require.resolve( 'source-map-loader' ), enforce: 'pre', diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 057fb6a2f759aa..c63fcd130615a8 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -56,6 +56,7 @@ "eslint": "^7.17.0", "eslint-plugin-markdown": "^2.2.0", "expect-puppeteer": "^4.4.0", + "fast-glob": "^3.2.7", "filenamify": "^4.2.0", "jest": "^26.6.3", "jest-circus": "^26.6.3",