mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-23 23:10:17 +05:30
197 lines
7.0 KiB
JavaScript
197 lines
7.0 KiB
JavaScript
/**
|
|
* Tests for the export-preset persistence module (Task 21).
|
|
* The module is pure list logic over the settings store's `exportPresets`
|
|
* array; the store is injected, mirroring the SettingsStore test pattern.
|
|
*/
|
|
|
|
const ExportPresets = require('../../src/main/ExportPresets');
|
|
|
|
function createStore(initial = {}) {
|
|
const data = { ...initial };
|
|
return {
|
|
get: (key, defaultValue) => (data[key] === undefined ? defaultValue : data[key]),
|
|
set: (key, value) => {
|
|
data[key] = value;
|
|
},
|
|
data,
|
|
};
|
|
}
|
|
|
|
describe('ExportPresets', () => {
|
|
describe('loadPresets', () => {
|
|
test('returns an empty array when nothing is stored', () => {
|
|
expect(ExportPresets.loadPresets(createStore())).toEqual([]);
|
|
});
|
|
|
|
test('returns the stored presets', () => {
|
|
const store = createStore({
|
|
exportPresets: [{ id: 'p1', name: 'Book PDF', format: 'pdf', options: { toc: true } }],
|
|
});
|
|
const presets = ExportPresets.loadPresets(store);
|
|
expect(presets).toHaveLength(1);
|
|
expect(presets[0].name).toBe('Book PDF');
|
|
});
|
|
|
|
test('returns an empty array when the stored value is corrupt (not an array)', () => {
|
|
expect(ExportPresets.loadPresets(createStore({ exportPresets: 'garbage' }))).toEqual([]);
|
|
expect(ExportPresets.loadPresets(createStore({ exportPresets: { p1: 1 } }))).toEqual([]);
|
|
});
|
|
|
|
test('drops malformed entries (missing id or name) from the stored array', () => {
|
|
const store = createStore({
|
|
exportPresets: [
|
|
{ id: 'p1', name: 'Good', format: 'pdf', options: {} },
|
|
{ name: 'No id', options: {} },
|
|
{ id: 'p3', options: {} },
|
|
null,
|
|
],
|
|
});
|
|
const presets = ExportPresets.loadPresets(store);
|
|
expect(presets).toHaveLength(1);
|
|
expect(presets[0].id).toBe('p1');
|
|
});
|
|
});
|
|
|
|
describe('savePreset', () => {
|
|
test('adds a new preset with a generated id and persists it', () => {
|
|
const store = createStore();
|
|
const presets = ExportPresets.savePreset(store, {
|
|
name: 'Book PDF',
|
|
format: 'pdf',
|
|
options: { toc: true, tocDepth: 3 },
|
|
});
|
|
|
|
expect(presets).toHaveLength(1);
|
|
expect(presets[0].id).toMatch(/^preset-/);
|
|
expect(presets[0].name).toBe('Book PDF');
|
|
expect(presets[0].format).toBe('pdf');
|
|
expect(presets[0].options).toEqual({ toc: true, tocDepth: 3 });
|
|
expect(store.data.exportPresets).toEqual(presets);
|
|
});
|
|
|
|
test('upserts by id — saving with an existing id replaces the entry', () => {
|
|
const store = createStore({
|
|
exportPresets: [{ id: 'p1', name: 'Old name', format: 'pdf', options: { toc: false } }],
|
|
});
|
|
const presets = ExportPresets.savePreset(store, {
|
|
id: 'p1',
|
|
name: 'New name',
|
|
format: 'docx',
|
|
options: { toc: true },
|
|
});
|
|
|
|
expect(presets).toHaveLength(1);
|
|
expect(presets[0]).toEqual({
|
|
id: 'p1',
|
|
name: 'New name',
|
|
format: 'docx',
|
|
options: { toc: true },
|
|
});
|
|
expect(store.data.exportPresets).toEqual(presets);
|
|
});
|
|
|
|
test('appends when the id is new, preserving existing presets', () => {
|
|
const store = createStore({
|
|
exportPresets: [{ id: 'p1', name: 'First', format: 'pdf', options: {} }],
|
|
});
|
|
const presets = ExportPresets.savePreset(store, {
|
|
name: 'Second',
|
|
format: 'html',
|
|
options: {},
|
|
});
|
|
|
|
expect(presets).toHaveLength(2);
|
|
expect(presets.map((p) => p.name)).toEqual(['First', 'Second']);
|
|
});
|
|
|
|
test('throws when the preset is not an object', () => {
|
|
const store = createStore();
|
|
expect(() => ExportPresets.savePreset(store, null)).toThrow('Preset must be an object');
|
|
expect(() => ExportPresets.savePreset(store, 'nope')).toThrow('Preset must be an object');
|
|
});
|
|
|
|
test('throws when the name is missing or empty after trimming', () => {
|
|
const store = createStore();
|
|
expect(() => ExportPresets.savePreset(store, { name: ' ', options: {} })).toThrow(
|
|
'Preset name is required'
|
|
);
|
|
expect(() => ExportPresets.savePreset(store, { options: {} })).toThrow(
|
|
'Preset name is required'
|
|
);
|
|
});
|
|
|
|
test('trims the name and caps it at 100 characters', () => {
|
|
const store = createStore();
|
|
const presets = ExportPresets.savePreset(store, { name: ' Spaced ', options: {} });
|
|
expect(presets[0].name).toBe('Spaced');
|
|
|
|
const long = ExportPresets.savePreset(store, { name: 'x'.repeat(150), options: {} });
|
|
expect(long[1].name).toHaveLength(100);
|
|
});
|
|
|
|
test('defaults a missing options object to {} and a missing format to null', () => {
|
|
const store = createStore();
|
|
const presets = ExportPresets.savePreset(store, { name: 'Bare' });
|
|
expect(presets[0].options).toEqual({});
|
|
expect(presets[0].format).toBeNull();
|
|
});
|
|
|
|
test('refuses to add beyond the preset cap', () => {
|
|
const full = Array.from({ length: ExportPresets.MAX_PRESETS }, (_, i) => ({
|
|
id: `p${i}`,
|
|
name: `Preset ${i}`,
|
|
format: 'pdf',
|
|
options: {},
|
|
}));
|
|
const store = createStore({ exportPresets: full });
|
|
expect(() => ExportPresets.savePreset(store, { name: 'One too many' })).toThrow(
|
|
/more than \d+ export presets/
|
|
);
|
|
});
|
|
|
|
test('still allows updating an existing preset when the list is full', () => {
|
|
const full = Array.from({ length: ExportPresets.MAX_PRESETS }, (_, i) => ({
|
|
id: `p${i}`,
|
|
name: `Preset ${i}`,
|
|
format: 'pdf',
|
|
options: {},
|
|
}));
|
|
const store = createStore({ exportPresets: full });
|
|
const presets = ExportPresets.savePreset(store, { id: 'p7', name: 'Updated' });
|
|
expect(presets).toHaveLength(ExportPresets.MAX_PRESETS);
|
|
expect(presets.find((p) => p.id === 'p7').name).toBe('Updated');
|
|
});
|
|
|
|
test('generates distinct ids for successive new presets', () => {
|
|
const store = createStore();
|
|
const a = ExportPresets.savePreset(store, { name: 'A' });
|
|
const b = ExportPresets.savePreset(store, { name: 'B' });
|
|
expect(a[0].id).not.toBe(b[1].id);
|
|
});
|
|
});
|
|
|
|
describe('deletePreset', () => {
|
|
test('removes the preset with the given id and returns the updated list', () => {
|
|
const store = createStore({
|
|
exportPresets: [
|
|
{ id: 'p1', name: 'Keep', format: 'pdf', options: {} },
|
|
{ id: 'p2', name: 'Drop', format: 'html', options: {} },
|
|
],
|
|
});
|
|
const presets = ExportPresets.deletePreset(store, 'p2');
|
|
expect(presets).toHaveLength(1);
|
|
expect(presets[0].id).toBe('p1');
|
|
expect(store.data.exportPresets).toEqual(presets);
|
|
});
|
|
|
|
test('is idempotent when the id does not exist', () => {
|
|
const store = createStore({
|
|
exportPresets: [{ id: 'p1', name: 'Keep', format: 'pdf', options: {} }],
|
|
});
|
|
const presets = ExportPresets.deletePreset(store, 'missing');
|
|
expect(presets).toHaveLength(1);
|
|
expect(store.data.exportPresets).toHaveLength(1);
|
|
});
|
|
});
|
|
});
|