testing-library/angular-testing-library

signalInputs

Closed this issue ยท 13 comments

Add test cases for signal inputs.
Do we need to do something to cover these, or does this just work? ๐Ÿ‘€

it seems that something needs to be adapted because when I run some tests on components with signal inputs, I get the following type of error:
NG0303: Can't set value of the 'tags' input on the 'TagListComponent' component. Make sure that the 'tags' property is annotated with @Input() or a mapped @Input('tags') exists.
The "tags" input is declared as follow:
readonly tags = input.required<SearchTag[]>();

could it be related to this issue? angular/angular#54013

@FabienDehopre thanks for the information.
It does seem like the referenced issue is related, internally ATL also uses fixture.setInput().

I'm facing the same issue. Seems like it's fixed in thymikee/jest-preset-angular#2246

@tutkli the referenced PR allows us to set signal inputs via other components, but not directly using fixture.componentRef.setInput().

How do we handle model changes? We can have two-way binding now but need a way to test any changes.

Example:

@Component({
	selector: 'app-search',
	standalone: true,
	template: `<input [(ngModel)]="keywords()" />`,
})
export class SearchComponent {
	public keywords = model('');
}

Anyone who consumes this component can split the i/o like

<app-search [keywords]="keywords" (keywordsChange)="handleKeywordsChange($event)" />

I'd like to write a test like so but it doesnt appear to be handled currently:

test('it outputs form values per vale change.', async () => {
	const keywordsChange = jest.fn();
	const { getByLabelText } = await renderComponent({
		componentOutputs: {
			keywordsChange,
		}
	});

	await userEvent.type(getByLabelText('Search'), 'a');
	expect(keywordsChange).toHaveBeenCalledWith('a');

	await userEvent.type(getByLabelText('Search'), 'b');
	expect(keywordsChange).toHaveBeenLastCalledWith('ab');

	await userEvent.type(getByLabelText('Search'), 'c');
	expect(keywordsChange).toHaveBeenLastCalledWith('abc');

	await userEvent.type(getByLabelText('Search'), '{backspace}');
	expect(keywordsChange).toHaveBeenLastCalledWith('ab');

	await userEvent.type(getByLabelText('Search'), '{backspace}');
	expect(keywordsChange).toHaveBeenLastCalledWith('a');

	await userEvent.type(getByLabelText('Search'), '{backspace}');
	expect(keywordsChange).toHaveBeenLastCalledWith('');
});

We haven't looked into supporting model for now.
since it's "just" a writable signal, have you tried creating a signal instead of a jest mock?

Update: after also updating Jest this does work

For an example see https://github.com/testing-library/angular-testing-library/blob/main/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts

This is not working for me ๐Ÿ˜ž. I updated jest-preset, Testing Library and jest, but I get still the error

Similar to this

NG0303: Can't set value of the 'tags' input on the 'TagListComponent' component. Make sure that the 'tags' property is annotated with @Input() or a mapped @Input('tags') exists.

Do you got a reproduction @mnkyjs ?

Update: after also updating Jest this does work

For an example see https://github.com/testing-library/angular-testing-library/blob/main/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts

This is not working for me ๐Ÿ˜ž. I updated jest-preset, Testing Library and jest, but I get still the error

Similar to this

NG0303: Can't set value of the 'tags' input on the 'TagListComponent' component. Make sure that the 'tags' property is annotated with @Input() or a mapped @Input('tags') exists.

I've seen this too. Some input names do not work. For me it was 'visible'. Changing the input name fixed it.

@johnwalshuk see #443 to test output/models

Do you got a reproduction @mnkyjs ?

It was my bad ๐Ÿคฆ , after I removed my node_modules folder and rerun npm install everything worked again ๐Ÿ‘