From 85621f11e1cbcceb93d9cf1d464afe780d7bdca0 Mon Sep 17 00:00:00 2001 From: Leon Senft Date: Tue, 16 Dec 2025 15:31:09 -0800 Subject: [PATCH] test(forms): add test coverage for binding `errors` to custon controls This input was missing dedicated test coverage. (cherry picked from commit e7745dc9dd2e8f81ff2b711e136c52a7b272bc50) --- .../signals/test/web/field_directive.spec.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/packages/forms/signals/test/web/field_directive.spec.ts b/packages/forms/signals/test/web/field_directive.spec.ts index 14dc8eef6c3..1d38f5abe9f 100644 --- a/packages/forms/signals/test/web/field_directive.spec.ts +++ b/packages/forms/signals/test/web/field_directive.spec.ts @@ -44,6 +44,7 @@ import { provideSignalFormsConfig, readonly, required, + requiredError, validateAsync, type DisabledReason, type FieldTree, @@ -352,6 +353,67 @@ describe('field directive', () => { }); }); + describe('errors', () => { + it('should bind to custom control', () => { + @Component({ + selector: 'custom-control', + template: '', + }) + class CustomControl implements FormValueControl { + readonly value = model.required(); + readonly errors = input.required[]>(); + } + + @Component({ + template: ` `, + imports: [CustomControl, Field], + }) + class TestCmp { + readonly data = signal(''); + readonly f = form(this.data, (p) => { + required(p); + }); + readonly customControl = viewChild.required(CustomControl); + } + + const comp = act(() => TestBed.createComponent(TestCmp)).componentInstance; + expect(comp.customControl().errors()).toEqual([requiredError({fieldTree: comp.f})]); + + act(() => comp.f().value.set('valid')); + expect(comp.customControl().errors()).toEqual([]); + }); + + it('should be reset when field changes on custom control', () => { + @Component({selector: 'custom-control', template: ``}) + class CustomControl implements FormValueControl { + readonly value = model.required(); + readonly errors = input.required[]>(); + } + + @Component({ + imports: [Field, CustomControl], + template: ``, + }) + class TestCmp { + readonly f = form(signal({x: '', y: ''}), (p) => { + required(p.x); + }); + readonly field = signal(this.f.x); + readonly customControl = viewChild.required(CustomControl); + } + + const fixture = act(() => TestBed.createComponent(TestCmp)); + const component = fixture.componentInstance; + + expect(component.customControl().errors()).toEqual([ + requiredError({fieldTree: component.f.x}), + ]); + + act(() => component.field.set(component.f.y)); + expect(component.customControl().errors()).toEqual([]); + }); + }); + describe('hidden', () => { it('should bind to a custom control', () => { @Component({selector: 'custom-control', template: ``})