Skip to content

Commit 8c89107

Browse files
thekhegayalan-agius4
authored andcommitted
fix(@schematics/angular): do not drop callThrough() on existing spies in refactor-jasmine-vitest
bare `spyOn` is migrated as stub now, so `spy.and.callThrough()` on spy created earlier is what turns real method back on, yet it was still dropped as redundant and left just `spy;` with no TODO vitest has no exact equivalent (`mockReset()` brings original implemntation back but also clears recorded calls), so call is now kept with TODO, chained `spyOn(...).and.callThrough()` is still removed like before (cherry picked from commit 01abe08)
1 parent 2aa56cc commit 8c89107

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

‎packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-spy.ts‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,19 @@ function isChainedWithAnd(node: ts.Node): boolean {
9595
return false;
9696
}
9797

98+
function isSpyCreation(node: ts.Expression): boolean {
99+
const expression = unwrapExpression(node);
100+
if (!ts.isCallExpression(expression)) {
101+
return false;
102+
}
103+
104+
if (ts.isIdentifier(expression.expression)) {
105+
return expression.expression.text === 'spyOn' || expression.expression.text === 'spyOnProperty';
106+
}
107+
108+
return isJasmineCallExpression(expression, 'createSpy');
109+
}
110+
98111
function transformPrimarySpy(node: ts.CallExpression, refactorCtx: RefactorContext): ts.Node {
99112
const { sourceFile, reporter, pendingVitestValueImports } = refactorCtx;
100113
if (
@@ -224,6 +237,16 @@ function transformSpyStrategy(node: ts.CallExpression, refactorCtx: RefactorCont
224237
newMethodName = 'mockImplementation';
225238
break;
226239
case 'callThrough':
240+
if (!isSpyCreation(spyCall)) {
241+
// On an existing spy, `.and.callThrough()` restores the original implementation,
242+
// so it is not redundant and cannot be dropped.
243+
const category = 'callThrough-on-existing-spy';
244+
reporter.recordTodo(category, sourceFile, node);
245+
addTodoComment(node, category);
246+
247+
return node;
248+
}
249+
227250
reporter.reportTransformation(
228251
sourceFile,
229252
node,

‎packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-spy_spec.ts‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,23 @@ describe('Jasmine to Vitest Transformer - transformSpies', () => {
4848
input: `spyOn(service, 'myMethod').and.callThrough();`,
4949
expected: `vi.spyOn(service, 'myMethod');`,
5050
},
51+
{
52+
description: 'should remove .and.callThrough() on a wrapped spyOn call',
53+
input: `(spyOn(service, 'myMethod')!).and.callThrough();`,
54+
expected: `(vi.spyOn(service, 'myMethod')!);`,
55+
},
56+
{
57+
description: 'should add a TODO for .and.callThrough() on an existing spy',
58+
input: `mySpy.and.callThrough();`,
59+
expected: `// TODO: vitest-migration: Vitest does not have a direct equivalent for .and.callThrough() on an existing spy. Please migrate this manually, for example with spy.mockReset(), which restores the original implementation but also clears the recorded calls. See: https://vitest.dev/api/mock.html#mockreset
60+
mySpy.and.callThrough();`,
61+
},
62+
{
63+
description: 'should add a TODO for .and.callThrough() on a spy returned by a call',
64+
input: `getSpy().and.callThrough();`,
65+
expected: `// TODO: vitest-migration: Vitest does not have a direct equivalent for .and.callThrough() on an existing spy. Please migrate this manually, for example with spy.mockReset(), which restores the original implementation but also clears the recorded calls. See: https://vitest.dev/api/mock.html#mockreset
66+
getSpy().and.callThrough();`,
67+
},
5168
{
5269
description: 'should transform jasmine.createSpy("name") to vi.fn().mockName("name")',
5370
input: `const mySpy = jasmine.createSpy('mySpy');`,

‎packages/schematics/angular/refactor/jasmine-vitest/utils/todo-notes.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@ export const TODO_NOTES = {
158158
`Unsupported spy strategy ".and.${context.name}()" found. Please migrate this manually.`,
159159
url: 'https://vitest.dev/api/mocked.html#mock',
160160
},
161+
'callThrough-on-existing-spy': {
162+
message:
163+
'Vitest does not have a direct equivalent for .and.callThrough() on an existing spy.' +
164+
' Please migrate this manually, for example with spy.mockReset(), which restores' +
165+
' the original implementation but also clears the recorded calls.',
166+
url: 'https://vitest.dev/api/mock.html#mockreset',
167+
},
161168
'mostRecent-without-args': {
162169
message:
163170
'Direct usage of mostRecent() is not supported.' +

0 commit comments

Comments
 (0)