Skip to content

Commit 36cf3af

Browse files
jnizetclydin
authored andcommitted
feat(@schematics/angular): add browserMode option to jasmine-vitest schematic
This option allows not migrating the `toHaveClass` assertion, which exists in Vitest in browser mode and thus is best left as is. fix #31917
1 parent ff519b8 commit 36cf3af

File tree

5 files changed

+61
-5
lines changed

5 files changed

+61
-5
lines changed

packages/schematics/angular/refactor/jasmine-vitest/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export default function (options: Schema): Rule {
121121
const content = tree.readText(file);
122122
const newContent = transformJasmineToVitest(file, content, reporter, {
123123
addImports: !!options.addImports,
124+
browserMode: !!options.browerMode,
124125
});
125126

126127
if (content !== newContent) {

packages/schematics/angular/refactor/jasmine-vitest/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
"type": "boolean",
3131
"description": "Whether to add imports for the Vitest API. The Angular `unit-test` system automatically uses the Vitest globals option, which means explicit imports for global APIs like `describe`, `it`, `expect`, and `vi` are often not strictly necessary unless Vitest has been configured not to use globals.",
3232
"default": false
33+
},
34+
"browserMode": {
35+
"type": "boolean",
36+
"description": "Whether the tests are intended to run in browser mode. If true, the `toHaveClass` assertions are left as is because Vitest browser mode has such an assertion. Otherwise they're migrated to an equivalent assertion.",
37+
"default": false
3338
}
3439
}
3540
}

packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.integration_spec.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,17 @@ import { format } from 'prettier';
1111
import { transformJasmineToVitest } from './test-file-transformer';
1212
import { RefactorReporter } from './utils/refactor-reporter';
1313

14-
async function expectTransformation(input: string, expected: string): Promise<void> {
14+
async function expectTransformation(
15+
input: string,
16+
expected: string,
17+
options: { addImports: boolean; browserMode: boolean } = {
18+
addImports: false,
19+
browserMode: false,
20+
},
21+
): Promise<void> {
1522
const logger = new logging.NullLogger();
1623
const reporter = new RefactorReporter(logger);
17-
const transformed = transformJasmineToVitest('spec.ts', input, reporter, { addImports: false });
24+
const transformed = transformJasmineToVitest('spec.ts', input, reporter, options);
1825
const formattedTransformed = await format(transformed, { parser: 'typescript' });
1926
const formattedExpected = await format(expected, { parser: 'typescript' });
2027

@@ -389,6 +396,44 @@ describe('Jasmine to Vitest Transformer - Integration Tests', () => {
389396
await expectTransformation(jasmineCode, vitestCode);
390397
});
391398

399+
it('should not transform toHaveClass in browser mode', async () => {
400+
const jasmineCode = `
401+
describe('toHaveClass in browser mode', () => {
402+
let el: HTMLElement;
403+
404+
beforeEach(() => {
405+
el = document.createElement('div');
406+
});
407+
408+
it('should handle DOM matchers like toHaveClass', () => {
409+
el.classList.add('my-class');
410+
expect(el).withContext('element should have my-class').toHaveClass('my-class');
411+
el.classList.remove('my-class');
412+
expect(el).not.toHaveClass('my-class');
413+
});
414+
});
415+
`;
416+
417+
const vitestCode = `
418+
describe('toHaveClass in browser mode', () => {
419+
let el: HTMLElement;
420+
421+
beforeEach(() => {
422+
el = document.createElement('div');
423+
});
424+
425+
it('should handle DOM matchers like toHaveClass', () => {
426+
el.classList.add('my-class');
427+
expect(el, 'element should have my-class').toHaveClass('my-class');
428+
el.classList.remove('my-class');
429+
expect(el).not.toHaveClass('my-class');
430+
});
431+
});
432+
`;
433+
434+
await expectTransformation(jasmineCode, vitestCode, { addImports: false, browserMode: true });
435+
});
436+
392437
it('should add TODOs for unsupported Jasmine features', async () => {
393438
const jasmineCode = `
394439
describe('Unsupported Features', () => {

packages/schematics/angular/refactor/jasmine-vitest/test-file-transformer.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export function transformJasmineToVitest(
165165
filePath: string,
166166
content: string,
167167
reporter: RefactorReporter,
168-
options: { addImports: boolean },
168+
options: { addImports: boolean; browserMode: boolean },
169169
): string {
170170
const contentWithPlaceholders = preserveBlankLines(content);
171171

@@ -202,7 +202,9 @@ export function transformJasmineToVitest(
202202
}
203203

204204
for (const transformer of callExpressionTransformers) {
205-
transformedNode = transformer(transformedNode, refactorCtx);
205+
if (!(options.browserMode && transformer === transformToHaveClass)) {
206+
transformedNode = transformer(transformedNode, refactorCtx);
207+
}
206208
}
207209
} else if (ts.isPropertyAccessExpression(transformedNode)) {
208210
for (const transformer of propertyAccessExpressionTransformers) {

packages/schematics/angular/refactor/jasmine-vitest/test-helpers.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ export async function expectTransformation(
3030
): Promise<void> {
3131
const logger = new logging.NullLogger();
3232
const reporter = new RefactorReporter(logger);
33-
const transformed = transformJasmineToVitest('spec.ts', input, reporter, { addImports });
33+
const transformed = transformJasmineToVitest('spec.ts', input, reporter, {
34+
addImports,
35+
browserMode: false,
36+
});
3437
const formattedTransformed = await format(transformed, { parser: 'typescript' });
3538
const formattedExpected = await format(expected, { parser: 'typescript' });
3639

0 commit comments

Comments
 (0)