Skip to content

fix(@schematics/angular): do not drop callThrough() on existing spies in refactor-jasmine-vitest - #34555

Merged
alan-agius4 merged 2 commits into
angular:mainfrom
thekhegay:jasmine-vitest-callthrough
Oct 28, 2026
Merged

alan-agius4 merged 2 commits into
angular:mainfrom
thekhegay:jasmine-vitest-callthrough

Conversation

@thekhegay

@thekhegay thekhegay commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

PR Checklist

PR Type

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

refactor-jasmine-vitest drops .and.callThrough() on spy that already exists and leaves just spy;
Before #33266 that mostly worked since vi.spyOn calls through anyway, now bare spyOn becomes vi.spyOn(...).mockReturnValue(undefined) and spy stays stub after migration, without any TODO

beforeEach(() => {
  api = new Api();
  spy = spyOn(api, 'get');
});

it('calls the real method after callThrough()', () => {
  spy.and.callThrough();
  expect(api.get(1)).toBe('1');
  expect(spy).toHaveBeenCalledWith(1);
});

Passes on Jasmine, after migration ng test fails with AssertionError: expected undefined to be '1' and nothing points to dropped line
Spy that got .and.returnValue('x') first keeps returning 'x' same way

What is the new behavior?

When .and.callThrough() is called on existing spy (spy, getSpy()), it is kept as is with TODO, so converted spec fails right on that line until it is migrated
Vitest has no exact equivalent there, mockReset() brings original implementation back but also clears recorded calls, so TODO sugests it and says that
Chain right on spy creation (spyOn(...).and.callThrough(), same for spyOnProperty and jasmine.createSpy) is removed like before, also when call is wrapped in parens or type assertion

New spec cases for existing spy fail on main (get mySpy; and getSpy();), wrapped spyOn case passes on main and guards new check

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

I went with TODO since rewrite is not 1:1. If you prefer, it can emit spy.mockReset() directly with "verify" TODO, like arrayWithExactContents-check does
That makes example above pass right after migration, but test that counts calls made before callThrough() fails with expected "get" to be called 2 times, but got 1 times

… 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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces handling for .and.callThrough() on existing spies during the Jasmine-to-Vitest migration, adding a TODO comment instead of dropping it. It also includes corresponding unit tests and TODO notes. The review feedback highlights that the current check !ts.isCallExpression is insufficient because custom helper calls (e.g., getSomeSpy().and.callThrough()) would be incorrectly treated as spy creations and silently dropped. It is recommended to explicitly check for spyOn or spyOnProperty calls and add a test case to cover this scenario.

Comment thread packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-spy.ts Outdated
@clydin clydin added the target: patch This PR is targeted for the next patch release label Oct 28, 2026
@alan-agius4 alan-agius4 added the action: merge The PR is ready for merge by the caretaker label Oct 28, 2026
@alan-agius4
alan-agius4 merged commit 01abe08 into angular:main Oct 28, 2026
41 checks passed
@alan-agius4

Copy link
Copy Markdown
Collaborator

This PR was merged into the repository. The changes were merged into the following branches:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: merge The PR is ready for merge by the caretaker area: @schematics/angular target: patch This PR is targeted for the next patch release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants