Skip to content

Commit be23b4c

Browse files
refactor(operators): migrate unit tests to Vitest (#5031)
Closes #5021
1 parent 466326f commit be23b4c

File tree

13 files changed

+140
-118
lines changed

13 files changed

+140
-118
lines changed

modules/operators/eslint.config.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,11 @@ export default [
4747
...config.rules,
4848
},
4949
})),
50+
{
51+
ignores: [
52+
'schematics-core',
53+
'**/vite.config.*.timestamp*',
54+
'**/vitest.config.*.timestamp*',
55+
],
56+
},
5057
];

modules/operators/jest.config.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

modules/operators/migrations/20_0_0-rc_0-tap-response/index.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import {
66
import { createWorkspace } from '@ngrx/schematics-core/testing';
77

88
describe('migrate tapResponse', () => {
9-
const collectionPath = path.join(__dirname, '../migration.json');
9+
const collectionPath = path.join(
10+
process.cwd(),
11+
'dist/modules/operators/migrations/migration.json'
12+
);
1013
const schematicRunner = new SchematicTestRunner('schematics', collectionPath);
1114
let appTree: UnitTestTree;
1215

modules/operators/project.json

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,24 @@
2525
{
2626
"command": "pnpm exec tsc -p modules/operators/tsconfig.schematics.json"
2727
},
28+
{
29+
"command": "pnpm exec rimraf node_modules/@ngrx/operators"
30+
},
31+
{
32+
"command": "pnpm exec mkdirp node_modules/@ngrx/operators"
33+
},
34+
{
35+
"command": "ncp dist/modules/operators node_modules/@ngrx/operators"
36+
},
2837
{
2938
"command": "cpy LICENSE dist/modules/operators"
3039
}
3140
]
3241
},
33-
"outputs": ["{workspaceRoot}/dist/modules/operators"]
42+
"outputs": [
43+
"{workspaceRoot}/dist/modules/operators",
44+
"{workspaceRoot}/node_modules/@ngrx/operators"
45+
]
3446
},
3547
"lint": {
3648
"executor": "@nx/eslint:lint",
@@ -43,12 +55,8 @@
4355
"outputs": ["{options.outputFile}"]
4456
},
4557
"test": {
46-
"executor": "@nx/jest:jest",
47-
"options": {
48-
"jestConfig": "modules/operators/jest.config.ts",
49-
"runInBand": true,
50-
"passWithNoTests": false
51-
},
58+
"executor": "@analogjs/vitest-angular:test",
59+
"dependsOn": ["build"],
5260
"outputs": ["{workspaceRoot}/coverage/modules/operators"]
5361
}
5462
}

modules/operators/schematics-core/jest.config.js

Lines changed: 0 additions & 18 deletions
This file was deleted.

modules/operators/schematics-core/jest.config.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

modules/operators/schematics/ng-add/index.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import { createWorkspace } from '@ngrx/schematics-core/testing';
99
describe('Operators ng-add Schematic', () => {
1010
const schematicRunner = new SchematicTestRunner(
1111
'@ngrx/operators',
12-
path.join(__dirname, '../collection.json')
12+
path.join(
13+
process.cwd(),
14+
'dist/modules/operators/schematics/collection.json'
15+
)
1316
);
1417
const defaultOptions: SchemaOptions = {
1518
skipPackageJson: false,

modules/operators/spec/map-response.spec.ts

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { noop, Observable, of, throwError } from 'rxjs';
22
import { mapResponse } from '..';
33
import { concatMap, finalize } from 'rxjs/operators';
4+
import { vi } from 'vitest';
45

56
describe('mapResponse', () => {
67
it('should map the emitted value using the next callback', () => {
@@ -20,41 +21,43 @@ describe('mapResponse', () => {
2021
expect(results).toEqual([2, 3, 4]);
2122
});
2223

23-
it('should map the thrown error using the error callback', (done) => {
24-
throwError(() => 'error')
25-
.pipe(
26-
mapResponse({
27-
next: noop,
28-
error: (error) => `mapped ${error}`,
29-
})
30-
)
31-
.subscribe((result) => {
32-
expect(result).toBe('mapped error');
33-
done();
34-
});
35-
});
24+
it('should map the thrown error using the error callback', () =>
25+
new Promise((done) => {
26+
throwError(() => 'error')
27+
.pipe(
28+
mapResponse({
29+
next: noop,
30+
error: (error) => `mapped ${error}`,
31+
})
32+
)
33+
.subscribe((result) => {
34+
expect(result).toBe('mapped error');
35+
done(void 0);
36+
});
37+
}));
3638

37-
it('should map the error thrown in next callback using error callback', (done) => {
38-
function producesError() {
39-
throw 'error';
40-
}
39+
it('should map the error thrown in next callback using error callback', () =>
40+
new Promise((done) => {
41+
function producesError() {
42+
throw 'error';
43+
}
4144

42-
of(1)
43-
.pipe(
44-
mapResponse({
45-
next: producesError,
46-
error: (error) => `mapped ${error}`,
47-
})
48-
)
49-
.subscribe((result) => {
50-
expect(result).toBe('mapped error');
51-
done();
52-
});
53-
});
45+
of(1)
46+
.pipe(
47+
mapResponse({
48+
next: producesError,
49+
error: (error) => `mapped ${error}`,
50+
})
51+
)
52+
.subscribe((result) => {
53+
expect(result).toBe('mapped error');
54+
done(void 0);
55+
});
56+
}));
5457

5558
it('should not unsubscribe from outer observable on inner observable error', () => {
56-
const innerCompleteCallback = jest.fn<void, []>();
57-
const outerCompleteCallback = jest.fn<void, []>();
59+
const innerCompleteCallback = vi.fn<() => void>();
60+
const outerCompleteCallback = vi.fn<() => void>();
5861

5962
new Observable((subscriber) => subscriber.next(1))
6063
.pipe(

modules/operators/spec/tap-response.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import { EMPTY, noop, Observable, of, throwError } from 'rxjs';
22
import { tapResponse } from '..';
33
import { concatMap, finalize } from 'rxjs/operators';
4+
import { vi } from 'vitest';
45

56
describe('tapResponse', () => {
67
it('should invoke next callback on next', () => {
7-
const nextCallback = jest.fn<void, [number]>();
8+
const nextCallback = vi.fn<(value: [number]) => void>();
89

910
of(1, 2, 3).pipe(tapResponse(nextCallback, noop)).subscribe();
1011

1112
expect(nextCallback.mock.calls).toEqual([[1], [2], [3]]);
1213
});
1314

1415
it('should invoke error callback on error', () => {
15-
const errorCallback = jest.fn<void, [{ message: string }]>();
16+
const errorCallback = vi.fn<() => [{ message: string }]>();
1617
const error = { message: 'error' };
1718

1819
throwError(() => error)
@@ -23,7 +24,7 @@ describe('tapResponse', () => {
2324
});
2425

2526
it('should invoke error callback on the exception thrown in next', () => {
26-
const errorCallback = jest.fn<void, [{ message: string }]>();
27+
const errorCallback = vi.fn<() => [{ message: string }]>();
2728
const error = { message: 'error' };
2829

2930
function producesError() {
@@ -36,7 +37,7 @@ describe('tapResponse', () => {
3637
});
3738

3839
it('should invoke complete callback on complete', () => {
39-
const completeCallback = jest.fn<void, []>();
40+
const completeCallback = vi.fn<() => void>();
4041

4142
EMPTY.pipe(tapResponse(noop, noop, completeCallback)).subscribe();
4243

@@ -97,8 +98,8 @@ describe('tapResponse', () => {
9798
});
9899

99100
it('should not unsubscribe from outer observable on inner observable error', () => {
100-
const innerCompleteCallback = jest.fn<void, []>();
101-
const outerCompleteCallback = jest.fn<void, []>();
101+
const innerCompleteCallback = vi.fn<() => void>();
102+
const outerCompleteCallback = vi.fn<() => void>();
102103

103104
new Observable((subscriber) => subscriber.next(1))
104105
.pipe(

modules/operators/test-setup.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
1-
import 'zone.js/plugins/zone-legacy';
2-
import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
1+
import {
2+
TextEncoder as NodeTextEncoder,
3+
TextDecoder as NodeTextDecoder,
4+
} from 'util';
35

4-
setupZoneTestEnv();
5-
Object.assign(global, { TextDecoder, TextEncoder });
6+
// Only assign if not already defined, using type assertion to satisfy TypeScript
7+
if (typeof globalThis.TextEncoder === 'undefined') {
8+
globalThis.TextEncoder = NodeTextEncoder as unknown as {
9+
new (): TextEncoder;
10+
prototype: TextEncoder;
11+
};
12+
}
13+
14+
if (typeof globalThis.TextDecoder === 'undefined') {
15+
globalThis.TextDecoder = NodeTextDecoder as unknown as {
16+
new (): TextDecoder;
17+
prototype: TextDecoder;
18+
};
19+
}
20+
21+
import '@angular/compiler';
22+
import '@analogjs/vitest-angular/setup-zone';
23+
24+
import {
25+
BrowserTestingModule,
26+
platformBrowserTesting,
27+
} from '@angular/platform-browser/testing';
28+
import { getTestBed } from '@angular/core/testing';
29+
30+
getTestBed().initTestEnvironment(
31+
BrowserTestingModule,
32+
platformBrowserTesting()
33+
);

0 commit comments

Comments
 (0)