managarten/packages/qr-export/src/encoder.test.ts
Till-JS e5109da732 feat(wallpaper-generator): add device wallpaper generation package
Add new @manacore/wallpaper-generator package for creating device
wallpapers from QR codes and images.

Features:
- 30 device presets (phones, tablets, desktops)
- 3 layout types (center, corner, pattern)
- 5 gradient presets + solid color backgrounds
- Browser (Canvas) and Node.js (Sharp) renderers
- Svelte WallpaperModal UI component

Integrations:
- @manacore/qr-export: toWallpaper() function
- @manacore/spiral-db: toWallpaper() function
- QRExportModal: "Als Wallpaper" button

Also includes the full @manacore/qr-export package which was
previously untracked.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-17 12:57:43 +01:00

153 lines
4.1 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { encode, decode, estimateSize, willFitInQR, MANA_QR_PREFIX } from './encoder';
import { createManaQRExport, contact, event, todo } from './builder';
import type { ManaQRExport } from './types';
describe('encoder', () => {
const sampleExport: ManaQRExport = {
v: 1,
ts: 1708185600,
u: {
n: 'Till',
z: 'Europe/Berlin',
l: 'de',
w: 'Berlin',
},
c: [
{ n: 'Mama', p: '+491701234567', r: 1 },
{ n: 'Papa', p: '+491707654321', r: 1 },
],
e: [
{ t: 'Zahnarzt', s: 1708272000, d: 60, l: 'Praxis Dr. Weber' },
{ t: 'Team Meeting', s: 1708358400, d: 30 },
],
t: [
{ t: 'Steuererklärung abgeben', p: 1, d: 14 },
{ t: 'Backup machen', p: 3 },
],
};
describe('encode', () => {
it('should encode data with correct prefix', () => {
const result = encode(sampleExport);
expect(result.data.startsWith(MANA_QR_PREFIX)).toBe(true);
expect(result.size).toBeGreaterThan(0);
});
it('should report fitsInQR correctly for small data', () => {
const result = encode(sampleExport);
expect(result.fitsInQR).toBe(true);
expect(result.size).toBeLessThan(2500);
});
it('should compress data significantly', () => {
const jsonSize = JSON.stringify(sampleExport).length;
const result = encode(sampleExport);
// Encoded should be smaller than raw JSON
expect(result.size).toBeLessThan(jsonSize);
});
});
describe('decode', () => {
it('should decode encoded data correctly', () => {
const encoded = encode(sampleExport);
const decoded = decode(encoded.data);
expect(decoded.success).toBe(true);
if (decoded.success) {
expect(decoded.data.u.n).toBe('Till');
expect(decoded.data.c).toHaveLength(2);
expect(decoded.data.e).toHaveLength(2);
expect(decoded.data.t).toHaveLength(2);
}
});
it('should fail for invalid prefix', () => {
const result = decode('INVALID:xyz');
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error).toBe('INVALID_PREFIX');
}
});
it('should fail for invalid base64', () => {
const result = decode(MANA_QR_PREFIX + '!!!invalid!!!');
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error).toBe('INVALID_BASE64');
}
});
});
describe('roundtrip', () => {
it('should preserve all data through encode/decode', () => {
const encoded = encode(sampleExport);
const decoded = decode(encoded.data);
expect(decoded.success).toBe(true);
if (decoded.success) {
expect(decoded.data).toEqual(sampleExport);
}
});
});
describe('estimateSize', () => {
it('should estimate size within reasonable range', () => {
const estimated = estimateSize(sampleExport);
const actual = encode(sampleExport).size;
// Estimate should be within 50% of actual
expect(estimated).toBeGreaterThan(actual * 0.5);
expect(estimated).toBeLessThan(actual * 1.5);
});
});
describe('willFitInQR', () => {
it('should return true for small data', () => {
expect(willFitInQR(sampleExport)).toBe(true);
});
});
});
describe('builder', () => {
it('should build export with fluent API', () => {
const result = createManaQRExport()
.user({ n: 'Test', z: 'UTC', l: 'en' })
.addContact(contact('Alice', '+1234567890', 1))
.addEvent(event('Meeting', new Date('2024-02-20T10:00:00Z'), 60))
.addTodo(todo('Task 1', 1, 7))
.build();
expect(result.v).toBe(1);
expect(result.u.n).toBe('Test');
expect(result.c).toHaveLength(1);
expect(result.e).toHaveLength(1);
expect(result.t).toHaveLength(1);
});
it('should encode to valid QR string', () => {
const result = createManaQRExport()
.userName('Test')
.timezone('UTC')
.addContact({ n: 'Bob', r: 3 })
.encode();
expect(result.data.startsWith(MANA_QR_PREFIX)).toBe(true);
expect(result.fitsInQR).toBe(true);
});
it('should estimate size correctly', () => {
const builder = createManaQRExport().userName('Test').addContact({ n: 'Alice', r: 1 });
const estimated = builder.estimateSize();
const _actual = builder.encode().size;
expect(estimated).toBeGreaterThan(0);
expect(builder.willFit()).toBe(true);
});
});