Description
@Component() without an explicit changeDetection behaves differently depending on how it's compiled:
So the exact same component can pass its tests and then behave differently in prod, or vice versa.
Reproduction
@Component({
selector: 'my-comp',
template: '',
})
class MyComponent {}
Compile this with ngc/a normal ng build → OnPush.
Run it through TestBed.createComponent(MyComponent) in a spec → Eager.
We hit this for real: after upgrading to v22, we removed an explicit changeDetection: ChangeDetectionStrategy.OnPush from a component (reasoning: it's the default now, why write it). One TestBed spec started failing (signal read during notification phase) — only under Jest, not in the actual app.
Root cause
packages/core/src/metadata/directives.ts still hardcodes the JIT decorator's own default:
(c: Component = {}) => ({changeDetection: ChangeDetectionStrategy.Eager, ...c}),
This line wasn't touched by #67687, which only updated the AOT compiler and the JIT "declare component" linking path (convertDeclareComponentFacadeToMetadata in jit_compiler_facade.ts), not the plain decorator that TestBed/Jest actually exercise.
There's even a TODO for this exact spot, removed the same day #67687 merged, without the value being updated:
- // TODO(jeanmeche): remove the ts-ignore when OnPush is the default
- // @ts-ignore
(c: Component = {}) => ({changeDetection: ChangeDetectionStrategy.Eager, ...c}),
(commit cf3b7fe489)
Still reproduces on main and on the latest published 22.1.2.
Fix
PR: #70261 — one-line default flip + a regression test. Couldn't run the full internal test suite locally, so CI may turn up other spec files relying on the old JIT default.
Environment
Angular: 22.1.2 (also reproduces on main)
Description
@Component()without an explicitchangeDetectionbehaves differently depending on how it's compiled:OnPush(the documented default since v22, feat(core): Set default Component changeDetection strategy to OnPush #67687)EagerSo the exact same component can pass its tests and then behave differently in prod, or vice versa.
Reproduction
Compile this with
ngc/a normalng build→OnPush.Run it through
TestBed.createComponent(MyComponent)in a spec →Eager.We hit this for real: after upgrading to v22, we removed an explicit
changeDetection: ChangeDetectionStrategy.OnPushfrom a component (reasoning: it's the default now, why write it). One TestBed spec started failing (signal read during notification phase) — only under Jest, not in the actual app.Root cause
packages/core/src/metadata/directives.tsstill hardcodes the JIT decorator's own default:This line wasn't touched by #67687, which only updated the AOT compiler and the JIT "declare component" linking path (
convertDeclareComponentFacadeToMetadatainjit_compiler_facade.ts), not the plain decorator that TestBed/Jest actually exercise.There's even a TODO for this exact spot, removed the same day #67687 merged, without the value being updated:
(commit
cf3b7fe489)Still reproduces on
mainand on the latest published22.1.2.Fix
PR: #70261 — one-line default flip + a regression test. Couldn't run the full internal test suite locally, so CI may turn up other spec files relying on the old JIT default.
Environment
Angular: 22.1.2 (also reproduces on
main)