哪个@angular/*包是bug的来源?
core
这是一个回归吗?
是的
描述
在以下测试场景中:
describe('Test with input', () => {
@Component({
standalone: true,
template: `{{ htmlData }}`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestComponentWithInput {
data = input<string>()
htmlData?: string
constructor() {
effect(() => {
this.htmlData = this.data()
})
}
}
it('#1 should have "foobar" in template', () => {
const fixture = TestBed.configureTestingModule({
imports: [TestComponentWithInput],
}).createComponent(TestComponentWithInput)
fixture.detectChanges() // <---- This is necessary
fixture.componentRef.setInput('data', 'foobar')
fixture.detectChanges()
expect(fixture.debugElement.nativeElement.textContent).toContain('foobar')
})
it('#2 should have "foobar" in template', () => {
const fixture = TestBed.configureTestingModule({
imports: [TestComponentWithInput],
}).createComponent(TestComponentWithInput)
//fixture.detectChanges() // <---- Template is not updated because of missing detectChanges
fixture.componentRef.setInput('data', 'foobar')
fixture.detectChanges()
expect(fixture.debugElement.nativeElement.textContent).toContain('foobar')
})
})
只有测试1起作用,测试2将失败。显然,在设置输入之前需要 fixture.detectChanges()
。否则,模板不会更新(请参见测试2)。
这是正确的行为还是一个bug?
如果这是预期的行为,我应该如何测试所需的信号输入,例如以下场景:
describe('Test with required input', () => {
@Component({
standalone: true,
template: `{{ htmlData }}`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestComponentWithRequiredInput {
data = input.required<string>()
htmlData?: string
constructor() {
effect(() => {
this.htmlData = this.data()
})
}
}
it('#1 should have "foobar" in template', () => {
const fixture = TestBed.configureTestingModule({
imports: [TestComponentWithRequiredInput],
}).createComponent(TestComponentWithRequiredInput)
fixture.detectChanges() // <---- This is necessary but throws error
fixture.componentRef.setInput('data', 'foobar')
fixture.detectChanges()
expect(fixture.debugElement.nativeElement.textContent).toContain('foobar')
})
it('#2 should have "foobar" in template (but i am broken)', () => {
const fixture = TestBed.configureTestingModule({
imports: [TestComponentWithRequiredInput],
}).createComponent(TestComponentWithRequiredInput)
//fixture.detectChanges() // <---- Template is not updated because of missing detectChanges
fixture.componentRef.setInput('data', 'foobar')
fixture.detectChanges()
expect(fixture.debugElement.nativeElement.textContent).toContain('foobar')
})
})
在这个场景中,两个测试都会失败。测试1失败(并抛出错误 NG0950: Input is required but no value is available yet
)因为我需要在使用 fixture.detectChanges()
之前设置输入,而测试2失败是因为我在设置输入之前没有使用 fixture.detectChanges
,因此模板没有更新。
希望我能够描述我的困境 :)
请提供一个最小重现bug的链接
- 无响应*
请提供您看到的异常或错误
- 无响应*
请提供您发现此bug的环境(运行 ng version
)
Angular CLI: 18.0.4
Node: 20.12.2
Package Manager: npm 10.3.0
OS: darwin arm64
Angular: 18.0.3
... animations, cdk, common, compiler, compiler-cli, core, forms
... language-service, material, platform-browser
... platform-browser-dynamic, platform-server, router
... service-worker
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1703.8
@angular-devkit/build-angular 18.0.4
@angular-devkit/core 18.0.4
@angular-devkit/schematics 18.0.4
@angular/cli 18.0.4
@angular/ssr 18.0.4
@schematics/angular 18.0.4
ng-packagr 18.0.0
rxjs 7.8.1
typescript 5.4.4
webpack 5.92.0
zone.js 0.14.2
还有其他信息吗?
- 无响应*
2条答案
按热度按时间4xrmg8kj1#
你的单元测试实际上突出显示了团队正在寻求解决的效果调度问题。(参见 #56501 )
效果应该可能在模板更新之前运行。
目前,组件中的效果在检测到更改后更新模板。
这就是为什么它需要2次调用detectChanges。
这里有一个复现示例:https://stackblitz.com/edit/ng-jasmine-tghqjg?file=src%2Fapp%2Fapp.component.spec.ts
jm81lzqq2#
感谢您的澄清!