Skip to content

Template of fixture is not updated using signals (in test) #56863

@Undestor

Description

@Undestor

Which @angular/* package(s) are the source of the bug?

core

Is this a regression?

Yes

Description

In the following test scenario:

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')
	})
})

Only test no. 1 does work and test no. 2 will fail. Apparently the fixture.detectChanges() before setting the input is needed. Otherwise the template does not get updated (See test no. 2).
Is this the correct behaviour or is this a bug?
If this is the expected behaviour, how can i test a required signal input, like in the following scenario:

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')
	})
})

In this scenario both of the tests will fail. The test no. 1 fails (and throws an the error NG0950: Input is required but no value is available yet) because i need to set the input before using fixture.detectChanges() and the test no. 2 does fail because i have not used fixture.detectChanges before setting the input and therefore the template is not updated.\

I hope i was able to describe my dilemma :)

Please provide a link to a minimal reproduction of the bug

No response

Please provide the exception or error you saw

No response

Please provide the environment you discovered this bug in (run 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

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: coreIssues related to the framework runtimearea: testingIssues related to Angular testing features, such as TestBedbugcore: reactivityWork related to fine-grained reactivity in the core frameworkcross-cutting: signals

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions