125 lines
4.1 KiB
TypeScript
125 lines
4.1 KiB
TypeScript
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<string>;
|
|
abbreviation: FormControl<string>;
|
|
description: FormControl<string>;
|
|
}> {
|
|
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> = {}): 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');
|
|
});
|
|
}); |