Add unit/component tests for proclamation admin forms
Server tests cover load content stripping per role and upsert/delete role enforcement. Client tests verify field rendering, pre-fill on edit, content visibility per role, and submit button dirty-state. Switched selects from bind:value/value to selected attribute pattern to work around Svelte 5 select value reactivity in test env.
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
import { page } from 'vitest/browser';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { render } from 'vitest-browser-svelte';
|
||||
|
||||
vi.mock('$app/forms', () => ({
|
||||
enhance: () => () => {}
|
||||
}));
|
||||
|
||||
vi.mock('$lib/components/tiptap/TipTap.svelte', () => ({
|
||||
default: ($anchor: Element) => {
|
||||
const div = document.createElement('div');
|
||||
div.setAttribute('data-testid', 'tiptap-mock');
|
||||
$anchor.replaceWith(div);
|
||||
}
|
||||
}));
|
||||
|
||||
import ProclamationForm from './ProclamationForm.svelte';
|
||||
|
||||
const relationOptionsData = {
|
||||
solfeggioFrequencyId: [
|
||||
{ label: 'UT - 396', value: 1 },
|
||||
{ label: 'RE - 417', value: 2 }
|
||||
],
|
||||
subscriptionLevelId: [
|
||||
{ label: 'Free', value: 1 },
|
||||
{ label: 'Premium', value: 2 }
|
||||
]
|
||||
};
|
||||
|
||||
const categories = [
|
||||
{ id: 1, name: 'Healing', parentId: null },
|
||||
{ id: 2, name: 'Manifestation', parentId: null },
|
||||
{ id: 3, name: 'Physical Healing', parentId: 1 },
|
||||
{ id: 4, name: 'Emotional Healing', parentId: 1 }
|
||||
];
|
||||
|
||||
describe('ProclamationForm', () => {
|
||||
it('renders all basic fields in create mode', async () => {
|
||||
render(ProclamationForm, {
|
||||
relationOptionsData,
|
||||
categories,
|
||||
isSuper: true
|
||||
});
|
||||
|
||||
await expect
|
||||
.element(page.getByRole('textbox', { name: 'Name' }))
|
||||
.toBeInTheDocument();
|
||||
await expect
|
||||
.element(page.getByRole('combobox', { name: /^Frequency$/ }))
|
||||
.toBeInTheDocument();
|
||||
await expect
|
||||
.element(page.getByRole('combobox', { name: /^Category$/ }))
|
||||
.toBeInTheDocument();
|
||||
await expect
|
||||
.element(page.getByRole('combobox', { name: /^Sub-Category$/ }))
|
||||
.toBeInTheDocument();
|
||||
await expect
|
||||
.element(page.getByRole('combobox', { name: /^Subscription Level$/ }))
|
||||
.toBeInTheDocument();
|
||||
await expect
|
||||
.element(page.getByRole('button', { name: 'Save' }))
|
||||
.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('pre-fills name input when editing an existing record', async () => {
|
||||
render(ProclamationForm, {
|
||||
record: {
|
||||
id: 'proc-1',
|
||||
name: 'Test Proclamation',
|
||||
solfeggioFrequencyId: 2,
|
||||
subscriptionLevelId: 2,
|
||||
categoryId: 3,
|
||||
parentCategoryId: 1
|
||||
},
|
||||
relationOptionsData,
|
||||
categories,
|
||||
isSuper: true,
|
||||
submitLabel: 'Update'
|
||||
});
|
||||
|
||||
await expect
|
||||
.element(page.getByRole('textbox', { name: 'Name' }))
|
||||
.toHaveValue('Test Proclamation');
|
||||
});
|
||||
|
||||
it('pre-fills select values when editing an existing record', async () => {
|
||||
render(ProclamationForm, {
|
||||
record: {
|
||||
id: 'proc-1',
|
||||
name: 'Test Proclamation',
|
||||
solfeggioFrequencyId: 2,
|
||||
subscriptionLevelId: 2,
|
||||
categoryId: 3,
|
||||
parentCategoryId: 1
|
||||
},
|
||||
relationOptionsData,
|
||||
categories,
|
||||
isSuper: true
|
||||
});
|
||||
|
||||
const freqEl = (await page
|
||||
.getByRole('combobox', { name: /^Frequency$/ })
|
||||
.element()) as HTMLSelectElement;
|
||||
const levelEl = (await page
|
||||
.getByRole('combobox', { name: /^Subscription Level$/ })
|
||||
.element()) as HTMLSelectElement;
|
||||
|
||||
expect(freqEl.value).toBe('2');
|
||||
expect(levelEl.value).toBe('2');
|
||||
});
|
||||
|
||||
it('shows content field when isSuper is true', async () => {
|
||||
render(ProclamationForm, {
|
||||
record: { id: 'proc-1', name: 'Test', content: '<p>Secret</p>' },
|
||||
relationOptionsData,
|
||||
categories,
|
||||
isSuper: true
|
||||
});
|
||||
|
||||
await expect.element(page.getByText('Content')).toBeInTheDocument();
|
||||
await expect.element(page.getByTestId('tiptap-mock')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('hides content field when isSuper is false', async () => {
|
||||
render(ProclamationForm, {
|
||||
record: { id: 'proc-1', name: 'Test', content: '<p>Secret</p>' },
|
||||
relationOptionsData,
|
||||
categories,
|
||||
isSuper: false
|
||||
});
|
||||
|
||||
await expect.element(page.getByText('Content')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('disables submit button when editing and not dirty', async () => {
|
||||
render(ProclamationForm, {
|
||||
record: { id: 'proc-1', name: 'Test' },
|
||||
relationOptionsData,
|
||||
categories,
|
||||
isSuper: true,
|
||||
submitLabel: 'Update'
|
||||
});
|
||||
|
||||
await expect
|
||||
.element(page.getByRole('button', { name: 'Update' }))
|
||||
.toBeDisabled();
|
||||
});
|
||||
|
||||
it('enables submit button when editing and user modifies a field', async () => {
|
||||
render(ProclamationForm, {
|
||||
record: { id: 'proc-1', name: 'Test' },
|
||||
relationOptionsData,
|
||||
categories,
|
||||
isSuper: true,
|
||||
submitLabel: 'Update'
|
||||
});
|
||||
|
||||
await page.getByRole('textbox', { name: 'Name' }).fill('New Name');
|
||||
|
||||
await expect
|
||||
.element(page.getByRole('button', { name: 'Update' }))
|
||||
.toBeEnabled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user