Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/schematics/angular/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ ts_project(
include = ["**/*.ts"],
exclude = [
"**/*_spec.ts",
"refactor/jasmine-vitest/test-helpers.ts",
# Also exclude templated files.
"*/files/**/*.ts",
"*/other-files/**/*.ts",
Expand Down Expand Up @@ -114,6 +115,7 @@ ts_project(
include = [
"**/*_spec.ts",
"utility/test/**/*.ts",
"refactor/jasmine-vitest/test-helpers.ts",
],
exclude = [
# NB: we need to exclude the nested node_modules that is laid out by yarn workspaces
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,28 @@ export function transformJasmineToVitest(
// Transform the node itself based on its type
if (ts.isCallExpression(transformedNode)) {
const transformations = [
// **Stage 1: High-Level & Context-Sensitive Transformations**
// These transformers often wrap or fundamentally change the nature of the call,
// so they need to run before more specific matchers.
transformWithContext,
transformExpectAsync,
transformSyntacticSugarMatchers,
transformFocusedAndSkippedTests,
transformPending,
transformDoneCallback,

// **Stage 2: Core Matcher & Spy Transformations**
// This is the bulk of the `expect(...)` and `spyOn(...)` conversions.
transformSyntacticSugarMatchers,
transformComplexMatchers,
transformSpies,
transformCreateSpyObj,
transformSpyReset,
transformSpyCallInspection,
transformPending,
transformDoneCallback,
transformtoHaveBeenCalledBefore,
transformToHaveClass,

// **Stage 3: Global Functions & Cleanup**
// These handle global Jasmine functions and catch-alls for unsupported APIs.
transformTimerMocks,
transformGlobalFunctions,
transformUnsupportedJasmineCalls,
Expand All @@ -97,6 +106,7 @@ export function transformJasmineToVitest(
}
} else if (ts.isPropertyAccessExpression(transformedNode)) {
const transformations = [
// These transformers handle `jasmine.any()` and other `jasmine.*` properties.
transformAsymmetricMatchers,
transformSpyCallInspection,
transformUnknownJasmineProperties,
Expand All @@ -105,6 +115,8 @@ export function transformJasmineToVitest(
transformedNode = transformer(transformedNode, refactorCtx);
}
} else if (ts.isExpressionStatement(transformedNode)) {
// Statement-level transformers are mutually exclusive. The first one that
// matches will be applied, and then the visitor will stop for this node.
const statementTransformers = [
transformCalledOnceWith,
transformArrayWithExactContents,
Expand All @@ -130,7 +142,7 @@ export function transformJasmineToVitest(
}
};

return (node) => ts.visitNode(node, visitor) as ts.SourceFile;
return (node) => ts.visitEachChild(node, visitor, context);
};

const result = ts.transform(sourceFile, [transformer]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { logging } from '@angular-devkit/core';
import { format } from 'prettier';
import { transformJasmineToVitest } from './test-file-transformer';
import { RefactorReporter } from './utils/refactor-reporter';

async function expectTransformation(input: string, expected: string): Promise<void> {
const logger = new logging.NullLogger();
const reporter = new RefactorReporter(logger);
const transformed = transformJasmineToVitest('spec.ts', input, reporter);
const formattedTransformed = await format(transformed, { parser: 'typescript' });
const formattedExpected = await format(expected, { parser: 'typescript' });

expect(formattedTransformed).toBe(formattedExpected);
}
import { expectTransformation } from './test-helpers';

describe('Jasmine to Vitest Transformer', () => {
describe('Nested Transformations', () => {
Expand Down Expand Up @@ -164,7 +151,6 @@ describe('Jasmine to Vitest Transformer', () => {
*/
.mockReturnValue(true);
`,
skipped: true,
},
{
description: 'should preserve a trailing comment on a matcher line',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/

import { logging } from '@angular-devkit/core';
import { format } from 'prettier';
import { transformJasmineToVitest } from './test-file-transformer';
import { RefactorReporter } from './utils/refactor-reporter';

/**
* A test helper to run the Jasmine to Vitest transformer on a given code
* snippet and compare it to an expected output.
*
* This function automatically handles the setup of a `RefactorReporter` and
* formats both the transformed and expected code using Prettier. This ensures
* that test comparisons are consistent and not affected by minor formatting
* differences.
*
* @param input The Jasmine code snippet to be transformed.
* @param expected The expected Vitest code snippet after transformation.
*/
export async function expectTransformation(input: string, expected: string): Promise<void> {
const logger = new logging.NullLogger();
const reporter = new RefactorReporter(logger);
const transformed = transformJasmineToVitest('spec.ts', input, reporter);
const formattedTransformed = await format(transformed, { parser: 'typescript' });
const formattedExpected = await format(expected, { parser: 'typescript' });

expect(formattedTransformed).toBe(formattedExpected);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { logging } from '@angular-devkit/core';
import { format } from 'prettier';
import { transformJasmineToVitest } from '../test-file-transformer';
import { RefactorReporter } from '../utils/refactor-reporter';

async function expectTransformation(input: string, expected: string): Promise<void> {
const logger = new logging.NullLogger();
const reporter = new RefactorReporter(logger);
const transformed = transformJasmineToVitest('spec.ts', input, reporter);
const formattedTransformed = await format(transformed, { parser: 'typescript' });
const formattedExpected = await format(expected, { parser: 'typescript' });

expect(formattedTransformed).toBe(formattedExpected);
}
import { expectTransformation } from '../test-helpers';

describe('Jasmine to Vitest Transformer', () => {
describe('transformDoneCallback', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { logging } from '@angular-devkit/core';
import { format } from 'prettier';
import { transformJasmineToVitest } from '../test-file-transformer';
import { RefactorReporter } from '../utils/refactor-reporter';

async function expectTransformation(input: string, expected: string): Promise<void> {
const logger = new logging.NullLogger();
const reporter = new RefactorReporter(logger);
const transformed = transformJasmineToVitest('spec.ts', input, reporter);
const formattedTransformed = await format(transformed, { parser: 'typescript' });
const formattedExpected = await format(expected, { parser: 'typescript' });

expect(formattedTransformed).toBe(formattedExpected);
}
import { expectTransformation } from '../test-helpers';

describe('Jasmine to Vitest Transformer', () => {
describe('transformAsymmetricMatchers', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,15 @@ export function transformFail(node: ts.Node, { sourceFile, reporter }: RefactorC
reporter.reportTransformation(sourceFile, node, 'Transformed `fail()` to `throw new Error()`.');
const reason = node.expression.arguments[0];

return ts.factory.createThrowStatement(
const replacement = ts.factory.createThrowStatement(
ts.factory.createNewExpression(
ts.factory.createIdentifier('Error'),
undefined,
reason ? [reason] : [],
),
);

return ts.setOriginalNode(ts.setTextRange(replacement, node), node);
}

return node;
Expand Down Expand Up @@ -119,7 +121,7 @@ export function transformDefaultTimeoutInterval(
),
]);

return ts.factory.createExpressionStatement(setConfigCall);
return ts.factory.updateExpressionStatement(node, setConfigCall);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { logging } from '@angular-devkit/core';
import { format } from 'prettier';
import { transformJasmineToVitest } from '../test-file-transformer';
import { RefactorReporter } from '../utils/refactor-reporter';

async function expectTransformation(input: string, expected: string): Promise<void> {
const logger = new logging.NullLogger();
const reporter = new RefactorReporter(logger);
const transformed = transformJasmineToVitest('spec.ts', input, reporter);
const formattedTransformed = await format(transformed, { parser: 'typescript' });
const formattedExpected = await format(expected, { parser: 'typescript' });

expect(formattedTransformed).toBe(formattedExpected);
}
import { expectTransformation } from '../test-helpers';

describe('Jasmine to Vitest Transformer', () => {
describe('transformTimerMocks', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,12 @@ export function transformSpies(node: ts.Node, refactorCtx: RefactorContext): ts.
node,
`Transformed spy strategy \`.and.${strategyName}()\` to \`.${newMethodName}()\`.`,
);
const newExpression = createPropertyAccess(spyCall, newMethodName);

const newExpression = ts.factory.updatePropertyAccessExpression(
pae,
spyCall,
ts.factory.createIdentifier(newMethodName),
);

return ts.factory.updateCallExpression(
node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { logging } from '@angular-devkit/core';
import { format } from 'prettier';
import { transformJasmineToVitest } from '../test-file-transformer';
import { RefactorReporter } from '../utils/refactor-reporter';

async function expectTransformation(input: string, expected: string): Promise<void> {
const logger = new logging.NullLogger();
const reporter = new RefactorReporter(logger);
const transformed = transformJasmineToVitest('spec.ts', input, reporter);
const formattedTransformed = await format(transformed, { parser: 'typescript' });
const formattedExpected = await format(expected, { parser: 'typescript' });

expect(formattedTransformed).toBe(formattedExpected);
}
import { expectTransformation } from '../test-helpers';

describe('Jasmine to Vitest Transformer', () => {
describe('transformSpies', () => {
Expand Down