Skip to content

Commit 16f9c46

Browse files
ctavanSimenB
andauthoredAug 3, 2022
fix: add Jest/jsdom compatibility (#642)
Jest runs browser tests in a jsdom environment which now also supports web crypto polyfills. Since ESM support in Jest is currently still limited, it requires a commonJS build for browser environments, see the discussion in #616 for all the details. Co-authored-by: Christoph Tavan <dev@tavan.de> Co-authored-by: Simen Bekkhus <sbekkhus91@gmail.com>
1 parent 04686f5 commit 16f9c46

13 files changed

+7388
-55
lines changed
 

‎babel.config.json

+7-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
"presets": [],
33
"plugins": [],
44
"env": {
5-
"commonjs": {
5+
"commonjsNode": {
66
"presets": [["@babel/preset-env", { "targets": { "node": "10" }, "modules": "commonjs" }]]
77
},
8-
"esmBrowser": {
9-
"presets": [["@babel/preset-env", { "modules": false }]]
10-
},
118
"esmNode": {
129
"presets": [["@babel/preset-env", { "targets": { "node": "10" }, "modules": false }]]
10+
},
11+
"commonjsBrowser": {
12+
"presets": [["@babel/preset-env", { "modules": "commonjs" }]]
13+
},
14+
"esmBrowser": {
15+
"presets": [["@babel/preset-env", { "modules": false }]]
1316
}
1417
}
1518
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>UUID esmodule webpack example</title>
5+
</head>
6+
<body>
7+
<script type="text/javascript" src="./dist/allRequire.js"></script>
8+
</body>
9+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
const uuid = require('uuid');
2+
const {
3+
NIL: NIL_UUID,
4+
parse: uuidParse,
5+
stringify: uuidStringify,
6+
v1: uuidv1,
7+
v3: uuidv3,
8+
v4: uuidv4,
9+
v5: uuidv5,
10+
validate: uuidValidate,
11+
version: uuidVersion,
12+
} = uuid;
13+
14+
const { default: testpage } = require('../utils/testpage');
15+
16+
testpage(function (addTest, done) {
17+
addTest('Named exports');
18+
19+
addTest('uuidv1()', uuidv1());
20+
21+
addTest('uuidv4()', uuidv4());
22+
23+
// ... using predefined DNS namespace (for domain names)
24+
addTest('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS));
25+
26+
// ... using predefined URL namespace (for, well, URLs)
27+
addTest('uuidv3() URL', uuidv3('http://example.com/hello', uuidv3.URL));
28+
29+
// ... using a custom namespace
30+
//
31+
// Note: Custom namespaces should be a UUID string specific to your application!
32+
// E.g. the one here was generated using this modules `uuid` CLI.
33+
const MY_NAMESPACE = '55238d15-c926-4598-b49d-cf4e913ba13c';
34+
addTest('uuidv3() MY_NAMESPACE', uuidv3('Hello, World!', MY_NAMESPACE));
35+
36+
// ... using predefined DNS namespace (for domain names)
37+
addTest('uuidv5() DNS', uuidv5('hello.example.com', uuidv5.DNS));
38+
39+
// ... using predefined URL namespace (for, well, URLs)
40+
addTest('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL));
41+
42+
// ... using a custom namespace
43+
//
44+
// Note: Custom namespaces should be a UUID string specific to your application!
45+
// E.g. the one here was generated using this modules `uuid` CLI.
46+
// const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
47+
addTest('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE));
48+
49+
// Utility functions
50+
addTest('NIL_UUID', NIL_UUID);
51+
addTest('uuidParse()', uuidParse(MY_NAMESPACE));
52+
addTest('uuidStringify()', uuidStringify(uuidParse(MY_NAMESPACE)));
53+
addTest('uuidValidate()', uuidValidate(MY_NAMESPACE));
54+
addTest('uuidVersion()', uuidVersion(MY_NAMESPACE));
55+
56+
addTest('Default export');
57+
58+
addTest('uuid.v1()', uuid.v1());
59+
addTest('uuid.v4()', uuid.v4());
60+
addTest('uuid.v3() DNS', uuid.v3('hello.example.com', uuid.v3.DNS));
61+
addTest('uuid.v3() URL', uuid.v3('http://example.com/hello', uuid.v3.URL));
62+
addTest('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
63+
addTest('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS));
64+
addTest('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL));
65+
addTest('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE));
66+
67+
addTest('uuid.NIL', uuid.NIL);
68+
addTest('uuid.parse()', uuid.parse(MY_NAMESPACE));
69+
addTest('uuid.stringify()', uuid.stringify(uuid.parse(MY_NAMESPACE)));
70+
addTest('uuid.validate()', uuid.validate(MY_NAMESPACE));
71+
addTest('uuid.version()', uuid.version(MY_NAMESPACE));
72+
73+
done();
74+
});

‎examples/browser-webpack/webpack.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module.exports = {
44
},
55
entry: {
66
all: './example-all.js',
7+
allRequire: './example-all-require.js',
78
v1: './example-v1.js',
89
v4: './example-v4.js',
910

‎examples/node-commonjs/package-lock.json

+24-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/node-esmodules/package-lock.json

+24-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/node-jest/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# uuid example Node.js Jest
2+
3+
```
4+
npm install
5+
npm test
6+
```

‎examples/node-jest/jsdom.test.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/** @jest-environment jsdom */
2+
3+
const uuid = require('uuid');
4+
5+
test('uuidv4()', () => {
6+
const val = uuid.v4();
7+
expect(uuid.version(val)).toBe(4);
8+
});

‎examples/node-jest/node.test.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const uuid = require('uuid');
2+
3+
test('uuidv4()', () => {
4+
const val = uuid.v4();
5+
expect(uuid.version(val)).toBe(4);
6+
});

‎examples/node-jest/package-lock.json

+7,180
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/node-jest/package.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "uuid-example-node-jest",
3+
"version": "0.0.0",
4+
"private": true,
5+
"scripts": {
6+
"test": "jest"
7+
},
8+
"dependencies": {
9+
"uuid": "file:../../.local/uuid"
10+
},
11+
"devDependencies": {
12+
"jest": "^29.0.0-alpha.0",
13+
"jest-environment-jsdom": "^29.0.0-alpha.0"
14+
}
15+
}

‎package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
"require": "./dist/index.js",
2626
"import": "./wrapper.mjs"
2727
},
28+
"browser": {
29+
"import": "./dist/esm-browser/index.js",
30+
"require": "./dist/commonjs-browser/index.js"
31+
},
2832
"default": "./dist/esm-browser/index.js"
2933
},
3034
"./package.json": "./package.json"
@@ -86,12 +90,13 @@
8690
"examples:browser:rollup:build": "cd examples/browser-rollup && npm install && npm run build",
8791
"examples:node:commonjs:test": "cd examples/node-commonjs && npm install && npm test",
8892
"examples:node:esmodules:test": "cd examples/node-esmodules && npm install && npm test",
93+
"examples:node:jest:test": "cd examples/node-jest && npm install && npm test",
8994
"prepare": "cd $( git rev-parse --show-toplevel ) && husky install",
9095
"lint": "npm run eslint:check && npm run prettier:check",
9196
"eslint:check": "eslint src/ test/ examples/ *.js",
9297
"eslint:fix": "eslint --fix src/ test/ examples/ *.js",
9398
"pretest": "[ -n $CI ] || npm run build",
94-
"test": "BABEL_ENV=commonjs node --throw-deprecation node_modules/.bin/jest test/unit/",
99+
"test": "BABEL_ENV=commonjsNode node --throw-deprecation node_modules/.bin/jest test/unit/",
95100
"pretest:browser": "optional-dev-dependency && npm run build && npm-run-all --parallel examples:browser:**",
96101
"test:browser": "wdio run ./wdio.conf.js",
97102
"pretest:node": "npm run build",

‎scripts/build.sh

+28-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,26 @@ DIR="$ROOT/dist"
1111
rm -rf "$DIR"
1212
mkdir -p "$DIR"
1313

14-
# Transpile CommonJS versions of files
15-
babel --env-name commonjs src --source-root src --out-dir "$DIR" --copy-files --quiet
14+
# We ship 4 builds of this library: ESM and CommonJS, each for Node.js and the Browser.
15+
# In ./src, code that uses browser APIs lives in `-browser.js` files, while code for node APIs
16+
# lives in files without suffix.
17+
# For historical reasons, the Node.js CommonJS build lives in the top level ./dist directory while
18+
# the other 3 builds live in their respective ./dist/{commonjs,esm}-{node,browser}/ subdirectories.
19+
#
20+
# The code below produces this layout:
21+
#
22+
# dist (<-- the commonjs-node build)
23+
# ├── commonjs-browser
24+
# ├── esm-node
25+
# ├── esm-node
26+
# └── bin (<-- Node.js CLI)
27+
28+
# Transpile CommonJS versions of files for node
29+
babel --env-name commonjsNode src --source-root src --out-dir "$DIR" --copy-files --quiet
30+
31+
# Transpile CommonJS versions of files for the browser
32+
babel --env-name commonjsBrowser src --source-root src --out-dir "$DIR/commonjs-browser" \
33+
--copy-files --quiet
1634

1735
# Transpile ESM versions of files for the browser
1836
babel --env-name esmBrowser src --source-root src --out-dir "$DIR/esm-browser" --copy-files --quiet
@@ -21,11 +39,19 @@ babel --env-name esmBrowser src --source-root src --out-dir "$DIR/esm-browser" -
2139
babel --env-name esmNode src --source-root src --out-dir "$DIR/esm-node" --copy-files --quiet
2240

2341
# No need to have the CLI files in the esm build
42+
rm -rf "$DIR/commonjs-browser/bin"
43+
rm -rf "$DIR/commonjs-browser/uuid-bin.js"
2444
rm -rf "$DIR/esm-browser/bin"
2545
rm -rf "$DIR/esm-browser/uuid-bin.js"
2646
rm -rf "$DIR/esm-node/bin"
2747
rm -rf "$DIR/esm-node/uuid-bin.js"
2848

49+
for FILE in "$DIR"/commonjs-browser/*-browser.js
50+
do
51+
echo "Replacing node-specific file for commonjs-browser: $FILE"
52+
mv "$FILE" "${FILE/-browser.js/.js}"
53+
done
54+
2955
for FILE in "$DIR"/esm-browser/*-browser.js
3056
do
3157
echo "Replacing node-specific file for esm-browser: $FILE"

5 commit comments

Comments
 (5)

monsieurnebo commented on Aug 3, 2022

@monsieurnebo

@ctavan @SimenB Thanks for that guys 👏

Is a release planned soon to publish this fix?

ctavan commented on Aug 3, 2022

@ctavan
MemberAuthor

I hope I will be able to finish up the release this week.

SimenB commented on Aug 3, 2022

@SimenB
Contributor

FWIW a stable release of jest@29 will also come this week

monsieurnebo commented on Aug 3, 2022

@monsieurnebo

FWIW a stable release of jest@29 will also come this week

Glad to hear. I'm tracking this as well.

ctavan commented on Aug 5, 2022

@ctavan
MemberAuthor

I have released uuid@9.0.0-beta.0 that contains this patch. Please try it out and let me know if it fixes the Jest interoperability (to be tested with jest@29.0.0-alpha.1).

Please sign in to comment.