From c442d75a340d91f3eb830d2ac2e4d58f2babe569 Mon Sep 17 00:00:00 2001 From: Ray <11846445+A77AY@users.noreply.github.com> Date: Thu, 24 Sep 2026 19:36:38 +0800 Subject: [PATCH] Fix label control logic and add tests for optional struct presence --- .../struct-form/struct-form.component.spec.ts | 58 +++++++++++++++++++ .../struct-form/struct-form.component.ts | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 projects/ng-thrift/src/lib/components/thrift-editor/components/struct-form/struct-form.component.spec.ts diff --git a/projects/ng-thrift/src/lib/components/thrift-editor/components/struct-form/struct-form.component.spec.ts b/projects/ng-thrift/src/lib/components/thrift-editor/components/struct-form/struct-form.component.spec.ts new file mode 100644 index 000000000..63c580696 --- /dev/null +++ b/projects/ng-thrift/src/lib/components/thrift-editor/components/struct-form/struct-form.component.spec.ts @@ -0,0 +1,58 @@ +import { Component, provideZonelessChangeDetection } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; + +import { ThriftData } from '../../../../models'; +import { ThriftAstMetadata } from '../../../../types'; + +import { StructFormComponent } from './struct-form.component'; + +@Component({ + imports: [ReactiveFormsModule, StructFormComponent], + template: ``, +}) +class StructFormHost { + control = new FormControl>({}); + metadata: ThriftAstMetadata[] = [ + { name: 'test', path: 'test.thrift', ast: { struct: { Parent: [], Empty: [] } } }, + ]; + data = new ThriftData( + this.metadata, + 'test', + 'Empty', + { name: 'empty', type: 'Empty', option: 'optional' }, + new ThriftData(this.metadata, 'test', 'Parent'), + ); +} + +describe('Optional struct presence', () => { + beforeEach(() => { + TestBed.configureTestingModule({ providers: [provideZonelessChangeDetection()] }); + }); + + it('checks an empty struct and preserves its value when toggled', async () => { + const fixture = TestBed.createComponent(StructFormHost); + await fixture.whenStable(); + const checkbox: HTMLInputElement = fixture.nativeElement.querySelector('input'); + + expect(checkbox.checked).toBe(true); + expect(fixture.componentInstance.control.value).toEqual({}); + + checkbox.click(); + await fixture.whenStable(); + expect(fixture.componentInstance.control.value).toBeNull(); + + checkbox.click(); + await fixture.whenStable(); + expect(fixture.componentInstance.control.value).toEqual({}); + }); + + it.each([null, undefined])('leaves an absent struct unchecked (%s)', async (value) => { + const fixture = TestBed.createComponent(StructFormHost); + fixture.componentInstance.control.setValue(value); + await fixture.whenStable(); + + const checkbox: HTMLInputElement = fixture.nativeElement.querySelector('input'); + expect(checkbox.checked).toBe(false); + }); +}); diff --git a/projects/ng-thrift/src/lib/components/thrift-editor/components/struct-form/struct-form.component.ts b/projects/ng-thrift/src/lib/components/thrift-editor/components/struct-form/struct-form.component.ts index fe727ddaf..b3feb925f 100644 --- a/projects/ng-thrift/src/lib/components/thrift-editor/components/struct-form/struct-form.component.ts +++ b/projects/ng-thrift/src/lib/components/thrift-editor/components/struct-form/struct-form.component.ts @@ -116,7 +116,7 @@ export class StructFormComponent> handleIncomingValue(value: T) { this.control.patchValue(value as never, { emitEvent: false }); - this.setLabelControl(!!(value && Object.keys(value).length)); + this.setLabelControl(!isNil(value)); } override validate(_control: AbstractControl): ValidationErrors | null {