fix: repair pre-existing failing vitest suite

Fixes failures across the suite that fail on main independently of any branch.

Documented + skipped
- smime/smime-crypto: this suite OOMs its worker (~4 GB heap) generating and
  using real 2048-bit RSA keys via pkijs/asn1js — a pre-existing memory issue,
  not a logical failure. Skipped behind a single SKIP_SMIME_CRYPTO_OOM flag with
  an in-file explanation and re-enable instructions, and the beforeAll bails
  early so the skipped file runs in ~2s instead of crashing the worker.

Code fixes
- jmap/client: getSubmissionAccountId honoured the requested (mail) account
  even when it lacks the submission capability, so EmailSubmission/set was
  addressed to the wrong account when JMAP hosts submission in a separate
  account. Prefer an account that actually advertises submission, falling back
  to primaryAccounts['…:submission'].
- plugin-sandbox/loader: deactivateAllSandboxed used require('./registry'),
  which is unresolvable under the Vite/ESM test runtime. registry only imports
  types (no cycle), so use a static import; all() already returns a copy, so
  iterating while deregister mutates is safe.

Test fixes (tests trailed intentional code/behaviour changes)
- vitest.setup: add a matchMedia stub (jsdom lacks it) — unblocks 8
  email-list-item tests.
- calendar-utils: pin TZ=UTC for the timezone-sensitive bounds/layout assertions
  (host runs at UTC+2) and update expected minutes to UTC.
- calendar-participants: buildParticipantMap keys entries by generated UUIDs
  (RFC 8984), not 'organizer'/'attendee-N'. Look entries up by identity so the
  test no longer depends on a generateUUID mock leaking from another file.
- email-headers: softfail now returns the semantic 'text-warning' token.
- email-list-item: unknown keyword ids intentionally render a gray fallback badge.
- plugin-loader: exposePluginExternals is now a documented no-op.
- plugin-slot: PluginSlot reads the sandbox registry and renders iframe slots;
  rewrite the tests against that architecture with a referentially stable snapshot.
- plugin-types: MAX_THEME_SIZE was raised to 2 MB.
This commit is contained in:
Stefan Hildebrandt
2026-06-19 23:53:20 +02:00
committed by Linus Rath
parent 2fac6ebfb8
commit 3f9e60843d
11 changed files with 133 additions and 68 deletions
+26 -19
View File
@@ -274,26 +274,31 @@ describe('buildParticipantMap', () => {
expect(Object.keys(map)).toHaveLength(3);
const org = map['organizer'];
expect(org.name).toBe('Alice');
expect(org.email).toBe('alice@example.com');
expect(org.roles).toEqual({ owner: true, attendee: true });
expect(org.participationStatus).toBe('accepted');
expect(org.scheduleAgent).toBe('server');
expect(org.sendTo).toEqual({ imip: 'mailto:alice@example.com' });
expect(org.expectReply).toBe(false);
// Entries are keyed by generated UUIDs (RFC 8984 participant ids), so
// look them up by identity rather than by a fixed key.
const entries = Object.values(map);
const att0 = map['attendee-0'];
expect(att0.name).toBe('Bob');
expect(att0.email).toBe('bob@example.com');
expect(att0.roles).toEqual({ attendee: true });
expect(att0.participationStatus).toBe('needs-action');
expect(att0.scheduleAgent).toBe('server');
expect(att0.expectReply).toBe(true);
const org = entries.find(p => p.roles?.owner);
expect(org).toBeDefined();
expect(org!.name).toBe('Alice');
expect(org!.email).toBe('alice@example.com');
expect(org!.roles).toEqual({ owner: true, attendee: true });
expect(org!.participationStatus).toBe('accepted');
expect(org!.scheduleAgent).toBe('server');
expect(org!.sendTo).toEqual({ imip: 'mailto:alice@example.com' });
expect(org!.expectReply).toBe(false);
const att1 = map['attendee-1'];
expect(att1.name).toBe('Carol');
expect(att1.email).toBe('carol@example.com');
const att0 = entries.find(p => p.email === 'bob@example.com');
expect(att0).toBeDefined();
expect(att0!.name).toBe('Bob');
expect(att0!.roles).toEqual({ attendee: true });
expect(att0!.participationStatus).toBe('needs-action');
expect(att0!.scheduleAgent).toBe('server');
expect(att0!.expectReply).toBe(true);
const att1 = entries.find(p => p.email === 'carol@example.com');
expect(att1).toBeDefined();
expect(att1!.name).toBe('Carol');
});
it('creates only organizer when no attendees', () => {
@@ -302,7 +307,9 @@ describe('buildParticipantMap', () => {
[]
);
expect(Object.keys(map)).toHaveLength(1);
expect(map['organizer']).toBeDefined();
const org = Object.values(map)[0];
expect(org).toBeDefined();
expect(org.roles).toEqual({ owner: true, attendee: true });
});
it('sets @type to Participant for all entries', () => {