- before copy paste
This commit is contained in:
@@ -515,6 +515,149 @@ describe('per-object background & text colour', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('full-fidelity JSON export — backgrounds, formats, sheet settings', () => {
|
||||
/** Populate *every* persisted setting, then verify the export string carries
|
||||
* it and a round-trip is byte-for-byte identical. */
|
||||
function loadEverything(s: DocumentStore) {
|
||||
const analyse = s.doc.sheets[0].id;
|
||||
const blatt2 = s.doc.sheets[1].id;
|
||||
const umsatzId = tableId(s, 'Umsatz');
|
||||
const chartId = s.doc.sheets[0].objects.find((o) => o.kind === 'chart')!.id;
|
||||
|
||||
// document
|
||||
s.setDocumentLocale('en-GB');
|
||||
s.setCsvDelimiter(';');
|
||||
|
||||
// sheet ("Arbeitsblatt") settings — on both sheets
|
||||
s.setSheetLocale(analyse, 'de-CH');
|
||||
s.setSheetBackground(analyse, '#eef2ff');
|
||||
s.setSheetForeground(analyse, '#101828');
|
||||
s.setSheetShowGrid(analyse, false);
|
||||
s.setSheetZoom(analyse, 1.25);
|
||||
s.renameSheet(blatt2, 'Notizen');
|
||||
s.setSheetBackground(blatt2, '#fff7ed');
|
||||
|
||||
// table object: colours + geometry + view + per-row/col + cell formats
|
||||
s.setObjectBg(umsatzId, '#0b1220');
|
||||
s.setObjectTextColor(umsatzId, '#f8fafc');
|
||||
s.setObjectLocale(umsatzId, 'fr-FR');
|
||||
s.setTableView(umsatzId, { mode: 'fixed', width: 520, height: 300, frozenRows: 1, frozenCols: 1 });
|
||||
s.setTableRowHeight(umsatzId, 30);
|
||||
s.setRowHeight(umsatzId, 4, 52);
|
||||
s.setColWidth(umsatzId, 0, 130);
|
||||
s.setRangeFormat(umsatzId, { col: 1, row: 1 }, { col: 3, row: 4 }, {
|
||||
align: 'right',
|
||||
valign: 'middle',
|
||||
numFmt: 'pct2',
|
||||
color: '#dc2626',
|
||||
bg: '#fee2e2',
|
||||
bold: true,
|
||||
italic: true,
|
||||
});
|
||||
|
||||
// chart object
|
||||
s.setObjectBg(chartId, '#111827');
|
||||
s.setObjectTextColor(chartId, '#e5e7eb');
|
||||
s.setChartView(chartId, 'line');
|
||||
s.resizeChart(chartId, 600, 360);
|
||||
|
||||
// text object with full formatting
|
||||
const txtId = s.addText(analyse);
|
||||
s.setTextContent(txtId, 'Bericht\nZeile 2');
|
||||
s.setTextFormat(txtId, { fontSize: 20, bold: true, italic: true, align: 'center' });
|
||||
s.setObjectTextColor(txtId, '#334155');
|
||||
s.setObjectBg(txtId, '#f1f5f9');
|
||||
|
||||
// multi-range selection
|
||||
s.setSelection({ tableId: umsatzId, anchor: { col: 0, row: 0 }, focus: { col: 0, row: 0 } });
|
||||
s.addToSelection(umsatzId, 2, 2);
|
||||
s.addToSelection(umsatzId, 4, 5);
|
||||
|
||||
return { analyse, umsatzId, chartId, txtId };
|
||||
}
|
||||
|
||||
it('the exported JSON text literally contains every setting', () => {
|
||||
const s = fresh();
|
||||
loadEverything(s);
|
||||
const json = serializeDocument(s.snapshot());
|
||||
const doc = JSON.parse(json);
|
||||
|
||||
// document
|
||||
expect(doc.locale).toBe('en-GB');
|
||||
expect(doc.csvDelimiter).toBe(';');
|
||||
|
||||
// sheet settings
|
||||
const a = doc.sheets[0];
|
||||
expect(a).toMatchObject({
|
||||
locale: 'de-CH',
|
||||
background: '#eef2ff',
|
||||
foreground: '#101828',
|
||||
showGrid: false,
|
||||
zoom: 1.25,
|
||||
});
|
||||
expect(doc.sheets[1]).toMatchObject({ name: 'Notizen', background: '#fff7ed' });
|
||||
|
||||
// table object
|
||||
const tbl = a.objects.find((o: { kind: string }) => o.kind === 'table');
|
||||
expect(tbl).toMatchObject({
|
||||
bg: '#0b1220',
|
||||
fg: '#f8fafc',
|
||||
locale: 'fr-FR',
|
||||
rowHeight: 30,
|
||||
rowHeights: { '4': 52 },
|
||||
colWidths: { '0': 130 },
|
||||
view: { mode: 'fixed', width: 520, height: 300, frozenRows: 1, frozenCols: 1 },
|
||||
});
|
||||
expect(tbl.formats['1,1']).toEqual({
|
||||
align: 'right',
|
||||
valign: 'middle',
|
||||
numFmt: 'pct2',
|
||||
color: '#dc2626',
|
||||
bg: '#fee2e2',
|
||||
bold: true,
|
||||
italic: true,
|
||||
});
|
||||
|
||||
// chart object
|
||||
const cht = a.objects.find((o: { kind: string }) => o.kind === 'chart');
|
||||
expect(cht).toMatchObject({ bg: '#111827', fg: '#e5e7eb', view: 'line', width: 600, height: 360 });
|
||||
|
||||
// text object
|
||||
const txt = a.objects.find((o: { kind: string }) => o.kind === 'text');
|
||||
expect(txt).toMatchObject({
|
||||
text: 'Bericht\nZeile 2',
|
||||
fontSize: 20,
|
||||
bold: true,
|
||||
italic: true,
|
||||
align: 'center',
|
||||
color: '#334155',
|
||||
bg: '#f1f5f9',
|
||||
});
|
||||
|
||||
// multi-range selection
|
||||
expect(doc.selection.ranges).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('export -> import is lossless for the fully-loaded document', () => {
|
||||
const s = fresh();
|
||||
loadEverything(s);
|
||||
const before = s.snapshot();
|
||||
s.replaceDocument(parseDocument(serializeDocument(before)));
|
||||
expect(s.snapshot()).toEqual(before);
|
||||
});
|
||||
|
||||
it('resetToSeed then re-import the exported file restores the exact state', () => {
|
||||
const s = fresh();
|
||||
loadEverything(s);
|
||||
const exported = serializeDocument(s.snapshot());
|
||||
const before = s.snapshot();
|
||||
s.resetToSeed();
|
||||
expect(s.snapshot()).not.toEqual(before);
|
||||
s.replaceDocument(parseDocument(exported));
|
||||
expect(s.snapshot()).toEqual(before);
|
||||
});
|
||||
});
|
||||
|
||||
describe('v1 -> v2 migration', () => {
|
||||
it('turns each old sheet into a canvas sheet holding one table of the same name', async () => {
|
||||
const { migrateToV2 } = await import('../../io/json');
|
||||
|
||||
Reference in New Issue
Block a user