Skip to content

Commit 50f7d99

Browse files
giltayarsearls
authored andcommitted
esm support done
1 parent 602ed0e commit 50f7d99

21 files changed

+280
-47
lines changed

index.d.ts

+22
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,28 @@ export function callback(...args: any[]): void;
261261
* @returns {*}
262262
*/
263263
export function replace(path: string, f?: any): any;
264+
/**
265+
* Swap out real dependenencies with fake one. Intercept calls to `require`
266+
* that dependency module and ensure your subject is handed a fake instead.
267+
*
268+
* @export
269+
* @param {string} path
270+
* @param {*} [f]
271+
* @returns {*}
272+
*/
273+
export function replaceCjs(path: string, f?: any): any;
274+
/**
275+
* Swap out real dependenencies with fake one. Intercept calls to `import`
276+
* that dependency module and ensure your subject is handed a fake instead.
277+
*
278+
* @export
279+
* @param {string} path
280+
* @param {*} [namedExportStubs]
281+
* @param {*} [defaultExportStub]
282+
* @returns {Promise<{default?: any, [namedExport: string]: any}>}
283+
*/
284+
export function replaceEsm(path: string, namedExportStubs?: any, defaultExportStub?: any):
285+
Promise<{default?: any, [namedExport: string]: any}>;
264286

265287
/**
266288
* Swap out real dependenencies with fake one. Reference to the property will

notypescript/import-esm-car.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// @ts-ignore
2+
module.exports = () => import('../test/safe-esm/fixtures/car.mjs')

package-lock.json

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

package.json

+10-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"clean": "rimraf dist lib coverage",
2323
"clean:hard": "npm run clean && rimraf node_modules \"examples/*/node_modules\"",
2424
"postclean": "mkdirp dist",
25-
"compile:browser": "cross-conf-env browserify src/index.js --standalone td --outfile $npm_package_config_build_file -p tsify -p headerify",
25+
"compile:browser": "cross-conf-env browserify src/index.js --standalone td --outfile $npm_package_config_build_file -p [ tsify --project tsconfig-browser.json ] -p headerify",
2626
"compile:node": "tsc",
2727
"precompile": "npm run clean",
2828
"compile": "run-s compile:node compile:browser",
@@ -32,10 +32,11 @@
3232
"style": "run-p style:js style:ts",
3333
"style:js": "standard --fix",
3434
"style:ts": "standard --fix --parser @typescript-eslint/parser --plugin @typescript-eslint/eslint-plugin \"**/*.ts\"",
35-
"test": "teenytest --helper test/helper.js \"test/**/*.test.{js,ts}\"",
35+
"test": "NODE_OPTIONS='--loader=quibble' TS_NODE_IGNORE='(?:^|/)node_modules/,notypescript' ./test/safe-esm/teenytest-proxy.js --helper test/helper.js \"test/**/*.test.{js,ts}\"",
3636
"test:all": "run-s test test:example",
3737
"test:unit": "teenytest --helper test/helper.js \"test/unit/**/*.test.{js,ts}\"",
3838
"test:safe": "teenytest --helper test/helper.js \"test/safe/**/*.test.{js,ts}\"",
39+
"test:esm": "NODE_OPTIONS='--loader=quibble' TS_NODE_IGNORE='(?:^|/)node_modules/,notypescript' ./test/safe-esm/teenytest-proxy.js --helper test/helper.js test/safe-esm/replace.test.js",
3940
"test:ci": "npm run compile && run-p style test:all && echo \"All done!\"",
4041
"test:example": "run-p test:example:babel test:example:jest test:example:jest-broken test:example:plain-html test:example:node test:example:node-ava test:example:webpack",
4142
"test:example:babel": "./script/run-examples babel",
@@ -78,12 +79,13 @@
7879
},
7980
"teenytest": {
8081
"plugins": [
81-
"test/support/tdify-plugin.js"
82+
"test/support/tdify-plugin.js",
83+
"teenytest-promise"
8284
]
8385
},
8486
"dependencies": {
8587
"lodash": "^4.17.15",
86-
"quibble": "^0.5.7",
88+
"quibble": "^0.6.0",
8789
"stringify-object-es5": "^2.5.0",
8890
"theredoc": "^1.0.0"
8991
},
@@ -97,14 +99,16 @@
9799
"dedent": "^0.7.0",
98100
"headerify": "^1.0.1",
99101
"is-number": "^7.0.0",
102+
"is-promise": "^4.0.0",
100103
"mkdirp": "^1.0.3",
101104
"npm-run-all": "^4.1.5",
102105
"nyc": "^15.0.0",
103106
"rimraf": "^3.0.2",
104107
"standard": "^14.3.1",
105-
"teenytest": "^5.3.0",
108+
"teenytest": "^6.0.0",
109+
"teenytest-promise": "^1.0.0",
106110
"testdouble": "^3.12.5",
107-
"ts-node": "^8.6.2",
111+
"ts-node": "^8.10.1",
108112
"tsify": "^4.0.1",
109113
"typescript": "^3.8.2"
110114
},

src/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import imitate from './imitate'
55
import when from './when'
66
import verify from './verify'
77
import matchers from './matchers'
8-
import replace from './replace'
8+
import replace, { replaceEsm } from './replace'
99
import explain from './explain'
1010
import reset from './reset'
1111
import config from './config'
@@ -23,6 +23,7 @@ module.exports = {
2323
verify,
2424
matchers,
2525
replace,
26+
replaceEsm,
2627
explain,
2728
reset,
2829
config,

src/replace/index.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import _ from '../wrap/lodash'
22
import * as quibble from 'quibble'
3-
import replaceModule from './module'
3+
import replaceModule, { replaceEsModule } from './module'
44
import replaceProperty from './property'
55

66
quibble.ignoreCallsFromThisFile()
@@ -12,3 +12,9 @@ export default function (target) {
1212
return replaceProperty(...arguments)
1313
}
1414
}
15+
16+
export function replaceEsm (_modulePath, _namedExportReplacement, _defaultExportReplacement) {
17+
// Sending arguments instead of the above arguments is crucial because `replaceEsModule`
18+
// uses arguments.length to figure out what to do.
19+
return replaceEsModule(...arguments)
20+
}

src/replace/module/index.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,28 @@ import fakeName from './fake-name'
77

88
quibble.ignoreCallsFromThisFile()
99

10-
export default function replaceModule (path, stub) {
10+
export default function replaceCjsModule (path, stub) {
1111
if (typeof jest === 'object') return jestModule(...arguments)
1212
if (arguments.length > 1) { return quibble(path, stub) }
1313
const realThing = requireActual(path)
1414
const fakeThing = imitate(realThing, fakeName(path, realThing))
1515
quibble(path, fakeThing)
1616
return fakeThing
1717
}
18+
19+
export async function replaceEsModule (path, namedExportsStub, defaultExportStub) {
20+
if (typeof jest === 'object') {
21+
throw new Error(`stubbing ES modules (${path}) under Jest is not yet supported`)
22+
}
23+
if (arguments.length > 1) {
24+
return quibble.esm(path, namedExportsStub, defaultExportStub)
25+
}
26+
27+
const { modulePath, module } = await quibble.esmImportWithPath(path)
28+
const { default: fakeDefaultExport = undefined, ...fakeNamedExports } =
29+
imitate(module, fakeName(path, module))
30+
31+
await quibble.esm(modulePath, fakeNamedExports, fakeDefaultExport)
32+
33+
return { default: fakeDefaultExport, ...fakeNamedExports }
34+
}

test/safe-esm/fixtures/car.mjs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import Passenger from './passenger.mjs'
2+
import isPromise from 'is-promise'
3+
import honk from './honk.mjs'
4+
import turn from './turn.mjs'
5+
import brake from './brake.mjs'
6+
import * as lights from './lights.mjs'
7+
import shift, { neutral } from './shift.mjs'
8+
9+
export default {
10+
seatPassenger: function () {
11+
return new Passenger().sit()
12+
},
13+
honk,
14+
turn,
15+
brake,
16+
lights,
17+
shift,
18+
neutral,
19+
isASpeed: function (thing) {
20+
return isPromise(thing)
21+
}
22+
}

test/safe-esm/fixtures/es6class.mjs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class ES6Class {
2+
foo () { return 'og foo' }
3+
4+
bar () { return 'og bar' }
5+
}
6+
7+
export default ES6Class

test/safe-esm/fixtures/honk.mjs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function () {
2+
throw 'honk' // eslint-disable-line
3+
}

test/safe-esm/fixtures/lights.mjs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const count = 4
2+
export function headlight () {
3+
throw 'headlight' // eslint-disable-line
4+
}
5+
export function turnSignal () {
6+
throw 'turnSignal' // eslint-disable-line
7+
}
8+
9+
export class Brights {
10+
beBright () {
11+
throw 'too bright!' // eslint-disable-line
12+
}
13+
}

test/safe-esm/fixtures/passenger.mjs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default class Passenger {
2+
sit () {
3+
throw 'i am sitting' // eslint-disable-line
4+
}
5+
}

test/safe-esm/fixtures/shift.mjs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function shift () {
2+
return 'Faster'
3+
}
4+
5+
export function neutral () {
6+
return 'Coast'
7+
}

test/safe-esm/fixtures/turn.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default function turn () {}

0 commit comments

Comments
 (0)