104 lines
3.7 KiB
JavaScript
104 lines
3.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { fileURLToPath } from 'node:url';
|
|
import vue from '@vitejs/plugin-vue';
|
|
import { createServer } from 'vite';
|
|
import { createSSRApp, h } from 'vue';
|
|
import { renderToString } from 'vue/server-renderer';
|
|
|
|
const server = await createServer({
|
|
configFile: false,
|
|
cacheDir: 'node_modules/.vite/acceptance-criteria-fixture',
|
|
plugins: [vue()],
|
|
resolve: {
|
|
alias: {
|
|
'@': fileURLToPath(new URL('../../resources/js', import.meta.url)),
|
|
},
|
|
},
|
|
server: { middlewareMode: true, hmr: false, watch: null },
|
|
});
|
|
try {
|
|
const {
|
|
canIndentAcceptanceCriterion: canIndent,
|
|
indentAcceptanceCriterion: indent,
|
|
removeAcceptanceCriterion: remove,
|
|
syncAcceptanceCriteriaDescendantCheckedState: toggle,
|
|
normalizeAcceptanceCriteria: normalize,
|
|
} = await server.ssrLoadModule('/resources/js/lib/acceptance-criteria.ts');
|
|
const items = [
|
|
{ id: 11, text: 'Parent', indent: 0, checked: false },
|
|
{ id: 12, text: 'Child', indent: 1, checked: true },
|
|
{ id: 13, text: 'Grandchild', indent: 2, checked: false },
|
|
{ id: 14, text: 'Next', indent: 0, checked: false },
|
|
];
|
|
const original = structuredClone(items);
|
|
assert.equal(canIndent(items, 0), false);
|
|
assert.equal(canIndent(items, 1), false);
|
|
assert.equal(canIndent(items, 3), true);
|
|
assert.deepEqual(
|
|
indent(items, 1, -1).map((item) => item.indent),
|
|
[0, 0, 1, 0],
|
|
);
|
|
assert.deepEqual(indent(indent(items, 1, -1), 1, 1), items);
|
|
assert.deepEqual(indent(items, 0, -1), items);
|
|
assert.deepEqual(indent(items, -1, 1), items);
|
|
assert.deepEqual(remove(items, 0), [
|
|
{ ...items[1], indent: 0 },
|
|
{ ...items[2], indent: 1 },
|
|
items[3],
|
|
]);
|
|
assert.deepEqual(remove(items, 1), [
|
|
items[0],
|
|
{ ...items[2], indent: 1 },
|
|
items[3],
|
|
]);
|
|
assert.deepEqual(remove(items, 99), items);
|
|
assert.deepEqual(
|
|
toggle(items, 0, true).map((item) => item.checked),
|
|
[true, true, true, false],
|
|
);
|
|
assert.deepEqual(
|
|
toggle(items, 1, false).map((item) => item.checked),
|
|
[false, false, false, false],
|
|
);
|
|
const deep = Array.from({ length: 9 }, (_, indent) => ({
|
|
text: 'Deep',
|
|
checked: false,
|
|
indent,
|
|
}));
|
|
assert.equal(
|
|
canIndent([{ text: 'Before', indent: 0, checked: false }, ...deep], 1),
|
|
false,
|
|
);
|
|
assert.deepEqual(
|
|
normalize(remove(items, 0)).map((item) => item.id),
|
|
[12, 13, 14],
|
|
);
|
|
assert.deepEqual(items, original, 'Editing must not mutate saved criteria');
|
|
const { default: Checklist } = await server.ssrLoadModule(
|
|
'/resources/js/components/tickets/AcceptanceCriteriaChecklist.vue',
|
|
);
|
|
const { createLocalization } = await server.ssrLoadModule(
|
|
'/resources/js/lib/localization.ts',
|
|
);
|
|
const render = (props) =>
|
|
renderToString(
|
|
createSSRApp({ render: () => h(Checklist, props) }).use(
|
|
createLocalization(),
|
|
),
|
|
);
|
|
const editable = await render({ modelValue: items });
|
|
assert.equal((editable.match(/<textarea/g) ?? []).length, 4);
|
|
assert.match(editable, /Indent criterion 4/);
|
|
assert.match(editable, /1 of 4 complete/);
|
|
const readonly = await render({ modelValue: items, readonly: true });
|
|
assert.doesNotMatch(readonly, /<textarea|Add criterion|Edit checklist/);
|
|
assert.equal((readonly.match(/type="checkbox" disabled/g) ?? []).length, 4);
|
|
assert.match(
|
|
await render({ modelValue: [], error: 'Server validation' }),
|
|
/Server validation/,
|
|
);
|
|
console.log('Acceptance criteria behavior checks passed.');
|
|
} finally {
|
|
await server.close();
|
|
}
|