Skip to content

Commit 36c138e

Browse files
author
CircleCI
committed
test sync callbacks, add docu and type test
1 parent 4045eb7 commit 36c138e

File tree

4 files changed

+192
-72
lines changed

4 files changed

+192
-72
lines changed

docs/JestObjectAPI.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,13 +575,25 @@ const otherCopyOfMyModule = require('myModule');
575575
```js
576576
let myModule;
577577
await jest.isolateModulesAsync(async () => {
578-
constmyModule = require('myModule');
578+
myModule = await import('myModule');
579579
// do async stuff here
580580
});
581581

582582
const otherCopyOfMyModule = require('myModule');
583583
```
584584

585+
`jest.isolateModulesAsync()` can also run synchronous callbacks:
586+
587+
```js
588+
let myModule;
589+
await jest.isolateModulesAsync(() => {
590+
myModule = require('myModule');
591+
// do sync stuff here
592+
});
593+
594+
const otherCopyOfMyModule = require('myModule');
595+
```
596+
585597
## Mock Functions
586598

587599
### `jest.fn(implementation?)`

packages/jest-runtime/src/__tests__/runtime_require_module_or_mock.test.js

Lines changed: 176 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -343,110 +343,220 @@ describe('isolateModules', () => {
343343
});
344344

345345
describe('isolateModulesAsync', () => {
346-
it('keeps its registry isolated from global one', async () => {
347-
const runtime = await createRuntime(__filename, {
348-
moduleNameMapper,
349-
});
350-
let exports;
351-
exports = runtime.requireModuleOrMock(
352-
runtime.__mockRootPath,
353-
'ModuleWithState',
354-
);
355-
exports.increment();
356-
expect(exports.getState()).toBe(2);
346+
describe('with sync callback', () => {
347+
it('keeps its registry isolated from global one', async () => {
348+
const runtime = await createRuntime(__filename, {
349+
moduleNameMapper,
350+
});
351+
let exports;
352+
exports = runtime.requireModuleOrMock(
353+
runtime.__mockRootPath,
354+
'ModuleWithState',
355+
);
356+
exports.increment();
357+
expect(exports.getState()).toBe(2);
358+
359+
await runtime.isolateModulesAsync(() => {
360+
exports = runtime.requireModuleOrMock(
361+
runtime.__mockRootPath,
362+
'ModuleWithState',
363+
);
364+
expect(exports.getState()).toBe(1);
365+
});
357366

358-
await runtime.isolateModulesAsync(async () => {
359367
exports = runtime.requireModuleOrMock(
360368
runtime.__mockRootPath,
361369
'ModuleWithState',
362370
);
363-
expect(exports.getState()).toBe(1);
371+
expect(exports.getState()).toBe(2);
364372
});
365373

366-
exports = runtime.requireModuleOrMock(
367-
runtime.__mockRootPath,
368-
'ModuleWithState',
369-
);
370-
expect(exports.getState()).toBe(2);
371-
});
374+
it('resets all modules after the block', async () => {
375+
const runtime = await createRuntime(__filename, {
376+
moduleNameMapper,
377+
});
378+
let exports;
379+
await runtime.isolateModulesAsync(() => {
380+
exports = runtime.requireModuleOrMock(
381+
runtime.__mockRootPath,
382+
'ModuleWithState',
383+
);
384+
expect(exports.getState()).toBe(1);
385+
exports.increment();
386+
expect(exports.getState()).toBe(2);
387+
});
372388

373-
it('resets all modules after the block', async () => {
374-
const runtime = await createRuntime(__filename, {
375-
moduleNameMapper,
376-
});
377-
let exports;
378-
await runtime.isolateModulesAsync(async () => {
379389
exports = runtime.requireModuleOrMock(
380390
runtime.__mockRootPath,
381391
'ModuleWithState',
382392
);
383393
expect(exports.getState()).toBe(1);
384-
exports.increment();
385-
expect(exports.getState()).toBe(2);
386394
});
387395

388-
exports = runtime.requireModuleOrMock(
389-
runtime.__mockRootPath,
390-
'ModuleWithState',
391-
);
392-
expect(exports.getState()).toBe(1);
393-
});
396+
it('resets module after failing', async () => {
397+
const runtime = await createRuntime(__filename, {
398+
moduleNameMapper,
399+
});
400+
await expect(
401+
runtime.isolateModulesAsync(() => {
402+
throw new Error('Error from isolated module');
403+
}),
404+
).rejects.toThrow('Error from isolated module');
405+
406+
await runtime.isolateModulesAsync(() => {
407+
expect(true).toBe(true);
408+
});
409+
});
394410

395-
it('resets module after failing', async () => {
396-
const runtime = await createRuntime(__filename, {
397-
moduleNameMapper,
411+
it('cannot nest isolateModulesAsync blocks', async () => {
412+
const runtime = await createRuntime(__filename, {
413+
moduleNameMapper,
414+
});
415+
await expect(async () => {
416+
await runtime.isolateModulesAsync(async () => {
417+
await runtime.isolateModulesAsync(() => {});
418+
});
419+
}).rejects.toThrow(
420+
'isolateModulesAsync cannot be nested inside another isolateModulesAsync or isolateModules.',
421+
);
398422
});
399-
await expect(
400-
runtime.isolateModulesAsync(async () => {
401-
throw new Error('Error from isolated module');
402-
}),
403-
).rejects.toThrow('Error from isolated module');
404423

405-
await runtime.isolateModulesAsync(async () => {
406-
expect(true).toBe(true);
424+
it('can call resetModules within a isolateModules block', async () => {
425+
const runtime = await createRuntime(__filename, {
426+
moduleNameMapper,
427+
});
428+
let exports;
429+
await runtime.isolateModulesAsync(() => {
430+
exports = runtime.requireModuleOrMock(
431+
runtime.__mockRootPath,
432+
'ModuleWithState',
433+
);
434+
expect(exports.getState()).toBe(1);
435+
436+
exports.increment();
437+
runtime.resetModules();
438+
439+
exports = runtime.requireModuleOrMock(
440+
runtime.__mockRootPath,
441+
'ModuleWithState',
442+
);
443+
expect(exports.getState()).toBe(1);
444+
});
445+
446+
exports = runtime.requireModuleOrMock(
447+
runtime.__mockRootPath,
448+
'ModuleWithState',
449+
);
450+
expect(exports.getState()).toBe(1);
407451
});
408452
});
409453

410-
it('cannot nest isolateModulesAsync blocks', async () => {
411-
const runtime = await createRuntime(__filename, {
412-
moduleNameMapper,
413-
});
414-
await expect(async () => {
454+
describe('with async callback', () => {
455+
it('keeps its registry isolated from global one', async () => {
456+
const runtime = await createRuntime(__filename, {
457+
moduleNameMapper,
458+
});
459+
let exports;
460+
exports = runtime.requireModuleOrMock(
461+
runtime.__mockRootPath,
462+
'ModuleWithState',
463+
);
464+
exports.increment();
465+
expect(exports.getState()).toBe(2);
466+
415467
await runtime.isolateModulesAsync(async () => {
416-
await runtime.isolateModulesAsync(() => Promise.resolve());
468+
exports = runtime.requireModuleOrMock(
469+
runtime.__mockRootPath,
470+
'ModuleWithState',
471+
);
472+
expect(exports.getState()).toBe(1);
417473
});
418-
}).rejects.toThrow(
419-
'isolateModulesAsync cannot be nested inside another isolateModulesAsync or isolateModules.',
420-
);
421-
});
422474

423-
it('can call resetModules within a isolateModules block', async () => {
424-
const runtime = await createRuntime(__filename, {
425-
moduleNameMapper,
475+
exports = runtime.requireModuleOrMock(
476+
runtime.__mockRootPath,
477+
'ModuleWithState',
478+
);
479+
expect(exports.getState()).toBe(2);
426480
});
427-
let exports;
428-
await runtime.isolateModulesAsync(async () => {
481+
482+
it('resets all modules after the block', async () => {
483+
const runtime = await createRuntime(__filename, {
484+
moduleNameMapper,
485+
});
486+
let exports;
487+
await runtime.isolateModulesAsync(async () => {
488+
exports = runtime.requireModuleOrMock(
489+
runtime.__mockRootPath,
490+
'ModuleWithState',
491+
);
492+
expect(exports.getState()).toBe(1);
493+
exports.increment();
494+
expect(exports.getState()).toBe(2);
495+
});
496+
429497
exports = runtime.requireModuleOrMock(
430498
runtime.__mockRootPath,
431499
'ModuleWithState',
432500
);
433501
expect(exports.getState()).toBe(1);
502+
});
434503

435-
exports.increment();
436-
runtime.resetModules();
504+
it('resets module after failing', async () => {
505+
const runtime = await createRuntime(__filename, {
506+
moduleNameMapper,
507+
});
508+
await expect(
509+
runtime.isolateModulesAsync(async () => {
510+
throw new Error('Error from isolated module');
511+
}),
512+
).rejects.toThrow('Error from isolated module');
513+
514+
await runtime.isolateModulesAsync(async () => {
515+
expect(true).toBe(true);
516+
});
517+
});
518+
519+
it('cannot nest isolateModulesAsync blocks', async () => {
520+
const runtime = await createRuntime(__filename, {
521+
moduleNameMapper,
522+
});
523+
await expect(async () => {
524+
await runtime.isolateModulesAsync(async () => {
525+
await runtime.isolateModulesAsync(() => Promise.resolve());
526+
});
527+
}).rejects.toThrow(
528+
'isolateModulesAsync cannot be nested inside another isolateModulesAsync or isolateModules.',
529+
);
530+
});
531+
532+
it('can call resetModules within a isolateModules block', async () => {
533+
const runtime = await createRuntime(__filename, {
534+
moduleNameMapper,
535+
});
536+
let exports;
537+
await runtime.isolateModulesAsync(async () => {
538+
exports = runtime.requireModuleOrMock(
539+
runtime.__mockRootPath,
540+
'ModuleWithState',
541+
);
542+
expect(exports.getState()).toBe(1);
543+
544+
exports.increment();
545+
runtime.resetModules();
546+
547+
exports = runtime.requireModuleOrMock(
548+
runtime.__mockRootPath,
549+
'ModuleWithState',
550+
);
551+
expect(exports.getState()).toBe(1);
552+
});
437553

438554
exports = runtime.requireModuleOrMock(
439555
runtime.__mockRootPath,
440556
'ModuleWithState',
441557
);
442558
expect(exports.getState()).toBe(1);
443559
});
444-
445-
exports = runtime.requireModuleOrMock(
446-
runtime.__mockRootPath,
447-
'ModuleWithState',
448-
);
449-
expect(exports.getState()).toBe(1);
450560
});
451561

452562
describe('can use isolateModulesAsync from a beforeEach block', () => {

packages/jest-runtime/src/index.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,7 @@ export default class Runtime {
11411141
}
11421142
}
11431143

1144-
async isolateModulesAsync(fn: () => Promise<void>): Promise<void> {
1144+
async isolateModulesAsync(fn: () => Promise<void> | void): Promise<void> {
11451145
if (this._isolatedModuleRegistry || this._isolatedMockRegistry) {
11461146
throw new Error(
11471147
'isolateModulesAsync cannot be nested inside another isolateModulesAsync or isolateModules.',
@@ -2180,9 +2180,6 @@ export default class Runtime {
21802180
this.isolateModules(fn);
21812181
return jestObject;
21822182
};
2183-
const isolateModulesAsync = async (fn: () => Promise<void>) => {
2184-
await this.isolateModulesAsync(fn);
2185-
};
21862183
const fn = this._moduleMocker.fn.bind(this._moduleMocker);
21872184
const spyOn = this._moduleMocker.spyOn.bind(this._moduleMocker);
21882185
const mocked =
@@ -2248,7 +2245,7 @@ export default class Runtime {
22482245
getTimerCount: () => _getFakeTimers().getTimerCount(),
22492246
isMockFunction: this._moduleMocker.isMockFunction,
22502247
isolateModules,
2251-
isolateModulesAsync,
2248+
isolateModulesAsync: this.isolateModulesAsync,
22522249
mock,
22532250
mocked,
22542251
now: () => _getFakeTimers().now(),

packages/jest-types/__typetests__/jest.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ expectType<typeof jest>(jest.isolateModules(() => {}));
9999
expectError(jest.isolateModules());
100100

101101
expectType<Promise<void>>(jest.isolateModulesAsync(async () => {}));
102+
expectType<Promise<void>>(jest.isolateModulesAsync(() => {}));
102103
expectError(jest.isolateModulesAsync());
103104

104105
expectType<typeof jest>(jest.mock('moduleName'));

0 commit comments

Comments
 (0)