Skip to content

fix(@schematics/angular): cast createSpyObj to MockedObject for jasmine.SpyObj variables in refactor-jasmine-vitest - #34602

Open
thekhegay wants to merge 2 commits into
angular:mainfrom
thekhegay:jasmine-vitest-createspyobj-type
Open

thekhegay wants to merge 2 commits into
angular:mainfrom
thekhegay:jasmine-vitest-createspyobj-type

Conversation

@thekhegay

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

Pattern from Angular testing guide

let heroServiceSpy: jasmine.SpyObj<HeroService>;

beforeEach(() => {
  heroServiceSpy = jasmine.createSpyObj('HeroService', ['getHeroes']);
});

is migrated to MockedObject<HeroService> variable and object literal with only getHeroes. Jasmine createSpyObj returns any so it compiled before, after migration tsc fails with

error TS2322: Type '{ getHeroes: Mock<Procedure>; }' is not assignable to type 'MockedObject<HeroService>'.

File is reported as transformed and there is no TODO

What is the new behavior?

When createSpyObj initializes or is assigned to variable annotated with jasmine.SpyObj<T>, literal is cast as MockedObject<T> and type import is added. Declaration is looked up in nearest enclosing block, so svc declared in two describe blocks gets its own type in each. Migrated spec from above passes tsc --strict (TS 6.0, vitest 5.0)

New spec cases cover assignment, initializer and two describe blocks with same name, they fail on main

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Cast types members that were not spied as present, same as jasmine.SpyObj<T> with untyped createSpyObj did before migration. Other option is TODO without cast, I went with cast since it keeps migrated tests compiling

…ne.SpyObj variables in refactor-jasmine-vitest

`let svc: jasmine.SpyObj<T>; svc = jasmine.createSpyObj(...)` from Angular testing guide became `MockedObject<T>` variable assigned an object literal with only spied methods, which fails with TS2322 after migration and nothing in report points to it
when createSpyObj initializes or is assigned to variable annotated with `jasmine.SpyObj<T>`, literal is now cast `as MockedObject<T>`, declaration is looked up in nearest enclosing block so same name in another describe gets its own type

@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 enhances the Jasmine-to-Vitest refactoring schematic by casting jasmine.createSpyObj calls to MockedObject<T> when they are assigned to or initialize a variable annotated with jasmine.SpyObj<T>. This ensures proper type safety and compatibility with Vitest. The review feedback suggests utilizing the existing getUnwrappedParent utility function instead of manually unwrapping parenthesized expressions to handle other transparent wrappers like non-null assertions or type assertions more robustly.

…r jasmine.SpyObj variables in refactor-jasmine-vitest
@alan-agius4 alan-agius4 added action: review The PR is still awaiting reviews from at least one requested reviewer target: patch This PR is targeted for the next patch release labels Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: review The PR is still awaiting reviews from at least one requested reviewer 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.

2 participants