Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build targeting Jest with relevant transforms #2698

Merged
merged 24 commits into from
Feb 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .babelrc-test-env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
"extends": "./.babelrc.js",
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-transform-async-to-generator",
"@babel/plugin-syntax-dynamic-import",
"dynamic-import-node"
],
};
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ dist
node_modules
es
lib
test-env
types
eui.d.ts
**/*.snap.js
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ tmp/
dist/
lib/
es/
test-env/
.idea
.vscode/
.DS_Store
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- Converted `EuiColorPicker` color conversion functions to `chroma-js` methods ([#2805](https://github.com/elastic/eui/pull/2805))
- Added `direction` parameter to `euiPaletteColorBlind()` for specifiying lighter or darker (or both) alternates ([#2822](https://github.com/elastic/eui/pull/2822))
- Converted `EuiSideNav` to TypeScript ([#2818](https://github.com/elastic/eui/issues/2818))
- Added babel-transformed and partially mocked commonjs build (`test-env/`) to target Kibana's Jest environment ([#2698](https://github.com/elastic/eui/pull/2698))

**Bug fixes**

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-object-rest-spread": "^7.8.3",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-async-to-generator": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/preset-env": "^7.8.3",
"@babel/preset-react": "^7.8.3",
"@babel/preset-typescript": "^7.8.3",
Expand Down
1 change: 1 addition & 0 deletions scripts/compile-clean.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ const rimraf = require('rimraf');
rimraf.sync('dist');
rimraf.sync('lib');
rimraf.sync('es');
rimraf.sync('test-env');
27 changes: 24 additions & 3 deletions scripts/compile-eui.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const chalk = require('chalk');
const shell = require('shelljs');
const path = require('path');
const glob = require('glob');
const fs = require('fs');
const dtsGenerator = require('dts-generator').default;

function compileLib() {
Expand All @@ -13,11 +14,12 @@ function compileLib() {
'lib/test'
);

console.log('Compiling src/ to es/ and lib/');
console.log('Compiling src/ to es/, lib/, and test-env/');

// Run all code (com|trans)pilation through babel (ESNext JS & TypeScript)

execSync(
'babel --quiet --out-dir=es --extensions .js,.ts,.tsx --ignore "**/webpack.config.js,**/*.test.js,**/*.d.ts" src',
'babel --quiet --out-dir=es --extensions .js,.ts,.tsx --ignore "**/webpack.config.js,**/*.test.js,**/*.test.ts,**/*.test.tsx,**/*.d.ts,**/*.testenv.js,**/*.testenv.tsx,**/*.testenv.ts" src',
{
env: {
...process.env,
Expand All @@ -26,15 +28,34 @@ function compileLib() {
},
}
);

execSync(
'babel --quiet --out-dir=lib --extensions .js,.ts,.tsx --ignore "**/webpack.config.js,**/*.test.js,**/*.test.ts,**/*.test.tsx,**/*.d.ts,**/*.testenv.js,**/*.testenv.tsx,**/*.testenv.ts" src',
{
env: {
...process.env,
NO_COREJS_POLYFILL: true,
},
}
);

execSync(
'babel --quiet --out-dir=lib --extensions .js,.ts,.tsx --ignore "**/webpack.config.js,**/*.test.js,**/*.d.ts" src',
'babel --quiet --out-dir=test-env --extensions .js,.ts,.tsx --config-file="./.babelrc-test-env.js" --ignore "**/webpack.config.js,**/*.test.js,**/*.test.ts,**/*.test.tsx,**/*.d.ts" src',
{
env: {
...process.env,
NO_COREJS_POLYFILL: true,
},
}
);
glob('./test-env/**/*.testenv.js', undefined, (error, files) => {
files.forEach(file => {
const dir = path.dirname(file);
const fileName = path.basename(file, '.js');
const targetName = fileName.replace('.testenv', '');
fs.renameSync(file, path.join(dir, `${targetName}.js`));
});
});

console.log(chalk.green('✔ Finished compiling src/'));

Expand Down
2 changes: 2 additions & 0 deletions scripts/dtsgenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const generator = dtsGenerator({
'src-framer/**/*',
'**/*.test.ts',
'**/*.test.tsx',
'**/*.testenv.ts',
'**/*.testenv.tsx',
'src/themes/charts/*' // A separate d.ts file is generated for the charts theme file
],
resolveModuleId(params) {
Expand Down
7 changes: 5 additions & 2 deletions src/components/date_picker/date_picker_range.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';

import { EuiText } from '../text';
import { IconPropType, EuiIcon } from '../icon';
import { EuiIcon } from '../icon';

export const EuiDatePickerRange = ({
children,
Expand Down Expand Up @@ -88,7 +88,10 @@ EuiDatePickerRange.propTypes = {
/**
* Pass either an icon type or set to `false` to remove icon entirely
*/
iconType: PropTypes.oneOfType([PropTypes.bool, IconPropType]),
iconType: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
]),
fullWidth: PropTypes.bool,
/**
* Won't apply any additional props to start and end date components
Expand Down
8 changes: 8 additions & 0 deletions src/components/icon/icon.testenv.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';
export const EuiIcon = ({ type, ...rest }: any) => (
<div data-euiicon-type={type} {...rest} />
);

export const TYPES = [];
export const COLORS = [];
export const SIZES = [];
6 changes: 0 additions & 6 deletions src/components/icon/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import React, {
ReactElement,
SVGAttributes,
} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import { CommonProps, keysOf } from '../common';
Expand Down Expand Up @@ -396,11 +395,6 @@ export type EuiIconType = keyof typeof typeToPathMap;

export type IconType = EuiIconType | string | ReactElement;

export const IconPropType = PropTypes.oneOfType([
PropTypes.string,
PropTypes.node,
]);

const colorToClassMap = {
default: null,
primary: 'euiIcon--primary',
Expand Down
1 change: 0 additions & 1 deletion src/components/icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export {
IconColor,
IconSize,
IconType,
IconPropType,
TYPES as ICON_TYPES,
SIZES as ICON_SIZES,
COLORS as ICON_COLORS,
Expand Down
20 changes: 20 additions & 0 deletions wiki/consuming.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,23 @@ ReactDOM.render(
### "Module build failed" or "Module parse failed: Unexpected token" error

If you get an error when importing a React component, you might need to configure Webpack's `resolve.mainFields` to `['webpack', 'browser', 'main']` to import the components from `lib` intead of `src`. See the [Webpack docs](https://webpack.js.org/configuration/resolve/#resolve-mainfields) for more info.

## Using the `test-env` build

EUI provides a separate babel-transformed and partially mocked commonjs build for testing environments in consuming projects. The output is identical to that of `lib/`, but has transformed async functions and dynamic import statements, and also applies some useful mocks. This build mainly targets Kibana's Jest environment, but may be helpful for testing environments in other projects.

### Mapping to the `test-env` directory

In Kibana's Jest configuration, the `moduleNameMapper` option is used to resolve standard EUI import statements with `test-env` aliases.

```js
moduleNameMapper: {
'@elastic/eui$': '<rootDir>/node_modules/@elastic/eui/test-env'
}
```

This eliminates the need to polyfill or transform the EUI build for an environment that otherwise has no need for such processing.

### Mocked component files

Besides babel transforms, the test environment build consumes mocked component files of the type `src/**/[name].testenv.*`. During the build, files of the type `src/**/[name].*` will be replaced by those with the `testenv` namespace. The purpose of this mocking is to further mitigate the impacts of time- and import-dependent rendering, and simplify environment output such as test snapshots. Information on creating mock component files can be found with [testing documentation](testing).
14 changes: 14 additions & 0 deletions wiki/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,17 @@ describe('YourComponent', () => {
});

```

## Writing mock component files

A component file can be mocked for snapshot simplification or to mitigate nondeterministic rendering in test environments. See [`src/components/icon`](../src/components/icon) for a example.

_Although mock component files are currently only used as part of consuming project test environments, the concept will soon be applied to EUI's own testing environment._

### Using the mock namespace

Component mocking relies on using the `[name].testenv.*` namespace for identification. The mocked module will replace the standard import in the `test-env` build. Both `index` files and individual component files can mocked.

### Mapping all module exports

The rendered output of a mocked component is at the author's discretion, however, all public exports from a module must be preserved in the mock file. Note that this does not apply to exported TypeScript types and interfaces, which will always be derived from the original component file.
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,16 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"

"@babel/plugin-transform-runtime@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz#c0153bc0a5375ebc1f1591cb7eea223adea9f169"
integrity sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==
dependencies:
"@babel/helper-module-imports" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
resolve "^1.8.1"
semver "^5.5.1"

"@babel/plugin-transform-shorthand-properties@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8"
Expand Down