Files
SRCmail/lib/__tests__/eml-import.test.ts
T
Bernd RodlerandClaude Sonnet 5 1189b146ef fix(i18n): add missing translation keys for signatures and email import
Fixes 25 failing tests across translations and eml-import test suites:

- Add 141 missing i18n keys to en/common.json for P2.1 (extended signatures
  feature) and P2.5 (email import feature). Keys cover:
  - signatures.* (signature editor, toolbar labels, per-identity settings)
  - settings.importer.* (mail import UI labels and messages)
  - settings.tabs.signatures, settings.{loading,refresh}
  - email_composer.{insert_signature,no_signature,select_signature}
  - identities.form.{signature_store_*,use_global_default}
  - calendar.{edit,delete,duplicate}, contacts.{edit,delete,send_email}
  - contacts.import.csv_* (CSV column mapping labels)
  - Other related keys for sharing, mailbox context menu, file operations

- Propagate new keys to all 23 other locale files:
  - ar, ca, cs, da, de, es, fa, fr, he, hu, it, ja, ko, lv, nl, pl, pt, ro,
    ru, sk, tr, uk, zh
  - 19 locales with real, idiomatic translations matching existing tone
  - 4 locales (da, es, fa, zh) with English placeholders pending native
    translation

- Fix eml-import test: update accept-string expectation to match actual
  EML_IMPORT_ACCEPT constant (now includes .tgz, .tar.gz, application/gzip
  support added in P2.5)

All 53 tests now pass:
  - 48 translation completeness tests
  - 5 eml-import tests

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 15:15:17 +02:00

52 lines
2.2 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import JSZip from 'jszip';
import { expandImportableEmails, EML_IMPORT_ACCEPT } from '@/lib/eml-import';
const emlFile = (name: string, content = 'raw email', type = 'message/rfc822') =>
new File([content], name, { type });
describe('expandImportableEmails', () => {
it('wraps a .eml file as a message/rfc822 blob, keeping its name', async () => {
const out = await expandImportableEmails([emlFile('msg.eml')]);
expect(out).toHaveLength(1);
expect(out[0].name).toBe('msg.eml');
expect(out[0].blob.type).toBe('message/rfc822');
await expect(out[0].blob.text()).resolves.toBe('raw email');
});
it('CHARACTERISATION: wraps a non-.eml, non-zip file as rfc822 too', async () => {
const out = await expandImportableEmails([emlFile('note.txt', 'hi', 'text/plain')]);
expect(out).toHaveLength(1);
expect(out[0]).toMatchObject({ name: 'note.txt' });
expect(out[0].blob.type).toBe('message/rfc822');
});
it('extracts only .eml entries from a .zip, stripping path prefixes', async () => {
const zip = new JSZip();
zip.file('a.eml', 'A');
zip.file('sub/b.eml', 'B');
zip.file('c.txt', 'C'); // skipped (not .eml)
zip.folder('emptydir'); // skipped (directory)
const blob = await zip.generateAsync({ type: 'blob' });
const file = new File([blob], 'archive.zip', { type: 'application/zip' });
const out = await expandImportableEmails([file]);
expect(out.map((e) => e.name).sort()).toEqual(['a.eml', 'b.eml']);
expect(out.every((e) => e.blob.type === 'message/rfc822')).toBe(true);
});
it('uses the zip path when the MIME type is application/zip even without a .zip name', async () => {
const zip = new JSZip();
zip.file('only.eml', 'X');
const blob = await zip.generateAsync({ type: 'blob' });
const file = new File([blob], 'archive-no-ext', { type: 'application/zip' });
const out = await expandImportableEmails([file]);
expect(out.map((e) => e.name)).toEqual(['only.eml']);
});
it('exposes the accept string for the file picker', () => {
expect(EML_IMPORT_ACCEPT).toBe('.eml,.zip,.tgz,.tar.gz,message/rfc822,application/zip,application/gzip');
});
});