Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -441,28 +441,47 @@ export function transformCreateSpy(node: ts.Node, ctx: RefactorContext): ts.Node
}

addVitestValueImport(pendingVitestValueImports, 'vi');
reporter.reportTransformation(
sourceFile,
node,
'Transformed `jasmine.createSpy()` to `vi.fn()`.',
);

const spyName = node.arguments[0];
const viFnCallExpression = createViCallExpression(
ctx,
'fn',
node.arguments.length > 1 ? [node.arguments[1]] : [],
);
const originalFn = node.arguments[1];
const viFnCallExpression = createViCallExpression(ctx, 'fn', originalFn ? [originalFn] : []);

// jasmine.createSpy() -> vi.fn()
// jasmine.createSpy(name, originalFn) -> vi.fn(originalFn).mockName(name)
return !spyName
// jasmine.createSpy(name) -> vi.fn().mockName(name)
// jasmine.createSpy(name, originalFn) -> vi.fn(originalFn).mockName(name)...
let result: ts.Expression = !spyName
? viFnCallExpression
: ts.factory.createCallExpression(
createPropertyAccess(viFnCallExpression, 'mockName'),
undefined,
[node.arguments[0]],
[spyName],
);

// Jasmine only invokes `originalFn` after `.and.callThrough()`, while `vi.fn(originalFn)`
// calls it right away. Without a chained strategy, stub the spy so `originalFn` is kept
// for `mockReset()` but not invoked, as `transformPrimarySpy` does for bare `spyOn`.
if (originalFn && !isChainedWithAnd(node)) {
reporter.reportTransformation(
sourceFile,
node,
'Transformed `jasmine.createSpy()` to `vi.fn()`, ' +
'appending `.mockReturnValue(undefined)` to preserve stub-by-default semantics.',
);

result = ts.factory.createCallExpression(
createPropertyAccess(result, 'mockReturnValue'),
undefined,
[ts.factory.createIdentifier('undefined')],
);
} else {
reporter.reportTransformation(
sourceFile,
node,
'Transformed `jasmine.createSpy()` to `vi.fn()`.',
);
}

return result;
}

export function transformCreateSpyObj(node: ts.Node, ctx: RefactorContext): ts.Node {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,22 @@ getSpy().and.callThrough();`,
expected: `const mySpy = vi.fn().mockName('mySpy');`,
},
{
description: 'should transform jasmine.createSpy("name", fn) to vi.fn(fn).mockName("name")',
description:
'should transform jasmine.createSpy("name", fn) to ' +
'vi.fn(fn).mockName("name").mockReturnValue(undefined)',
input: `const mySpy = jasmine.createSpy('mySpy', () => 'foo');`,
expected: `const mySpy = vi.fn(() => 'foo').mockName('mySpy').mockReturnValue(undefined);`,
},
{
description: 'should not stub jasmine.createSpy("name", fn) chained with .and.callThrough()',
input: `const mySpy = jasmine.createSpy('mySpy', () => 'foo').and.callThrough();`,
expected: `const mySpy = vi.fn(() => 'foo').mockName('mySpy');`,
},
Comment thread
MeAkib marked this conversation as resolved.
Resolved
{
description: 'should not stub jasmine.createSpy("name", fn) chained with another strategy',
input: `const mySpy = jasmine.createSpy('mySpy', () => 'foo').and.returnValue(true);`,
expected: `const mySpy = vi.fn(() => 'foo').mockName('mySpy').mockReturnValue(true);`,
},
{
description:
'should transform spyOnProperty(object, "prop") to vi.spyOn(object, "prop", "get").mockReturnValue(undefined)',
Expand Down
Loading