import '@angular/compiler'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { syncCategoryForm, CategoryFormMode, } from '../../frontend/src/app/features/admin/categories/category-form-modal.component'; import { AdminCategory } from '../../frontend/src/app/core/services/admin.service'; function buildForm(): FormGroup<{ name: FormControl; abbreviation: FormControl; description: FormControl; }> { const fb = new FormBuilder(); return fb.nonNullable.group({ name: fb.nonNullable.control('', []), abbreviation: fb.nonNullable.control('', []), description: fb.nonNullable.control(''), }); } function makeRow(overrides: Partial = {}): AdminCategory { return { id: 'row-1', name: 'Cryptography', abbreviation: 'CRY', description: 'Cryptographic challenges', iconPath: '', isSystem: true, systemKey: 'CRY', createdAt: '', updatedAt: '', ...overrides, }; } describe('syncCategoryForm - edit prefill', () => { it('populates name, abbreviation, description for a system row and locks abbreviation', () => { const form = buildForm(); const result = syncCategoryForm(form, 'edit', makeRow()); expect(form.controls.name.value).toBe('Cryptography'); expect(form.controls.abbreviation.value).toBe('CRY'); expect(form.controls.description.value).toBe('Cryptographic challenges'); expect(result.abbreviationReadonly).toBe(true); expect(result.iconPreview).toBeNull(); }); it('does not lock abbreviation for a user (non-system) row', () => { const form = buildForm(); const result = syncCategoryForm( form, 'edit', makeRow({ name: 'Misc', abbreviation: 'MSC', description: 'Other', isSystem: false, systemKey: null, }), ); expect(form.controls.name.value).toBe('Misc'); expect(form.controls.abbreviation.value).toBe('MSC'); expect(form.controls.description.value).toBe('Other'); expect(result.abbreviationReadonly).toBe(false); }); it('re-populates when invoked a second time with a different category', () => { const form = buildForm(); syncCategoryForm( form, 'edit', makeRow({ name: 'Alpha', abbreviation: 'AAA', description: 'first', isSystem: false, systemKey: null }), ); expect(form.controls.name.value).toBe('Alpha'); expect(form.controls.abbreviation.value).toBe('AAA'); const result = syncCategoryForm( form, 'edit', makeRow({ name: 'Bravo', abbreviation: 'BBB', description: 'second', isSystem: false, systemKey: null }), ); expect(form.controls.name.value).toBe('Bravo'); expect(form.controls.abbreviation.value).toBe('BBB'); expect(form.controls.description.value).toBe('second'); expect(result.abbreviationReadonly).toBe(false); }); it('clears the form when invoked with mode="create" and a null category', () => { const form = buildForm(); syncCategoryForm(form, 'edit', makeRow()); expect(form.controls.name.value).toBe('Cryptography'); const result = syncCategoryForm(form, 'create', null); expect(form.controls.name.value).toBe(''); expect(form.controls.abbreviation.value).toBe(''); expect(form.controls.description.value).toBe(''); expect(result.abbreviationReadonly).toBe(false); expect(result.iconPreview).toBeNull(); }); it('marks controls as pristine and untouched after prefill', () => { const form = buildForm(); syncCategoryForm(form, 'edit', makeRow()); expect(form.controls.name.pristine).toBe(true); expect(form.controls.name.touched).toBe(false); expect(form.controls.abbreviation.pristine).toBe(true); expect(form.controls.abbreviation.touched).toBe(false); expect(form.controls.description.pristine).toBe(true); expect(form.controls.description.touched).toBe(false); }); it('returns iconPreview from category.iconPath when set', () => { const form = buildForm(); const result = syncCategoryForm( form, 'edit', makeRow({ iconPath: '/uploads/icons/cry.png' }), ); expect(result.iconPreview).toBe('/uploads/icons/cry.png'); }); });