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.
44 lines
1.4 KiB
TypeScript
44 lines
1.4 KiB
TypeScript
import { describe, it, expect, beforeEach } from 'vitest';
|
|
import {
|
|
exposePluginExternals,
|
|
deactivatePlugin,
|
|
isPluginActive,
|
|
deactivateAllPlugins,
|
|
} from '../plugin-loader';
|
|
import { clearAllHooks, pluginErrorTracker } from '../plugin-hooks';
|
|
|
|
beforeEach(() => {
|
|
clearAllHooks();
|
|
pluginErrorTracker.resetAll();
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
delete (globalThis as any).__PLUGIN_EXTERNALS__;
|
|
});
|
|
|
|
describe('exposePluginExternals', () => {
|
|
it('is a no-op that does not publish globals (sandbox injects React per-iframe)', () => {
|
|
exposePluginExternals();
|
|
// The blob-import loader that needed window.__PLUGIN_EXTERNALS__ is gone;
|
|
// exposePluginExternals is kept only as a no-op for legacy callers.
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
expect((globalThis as any).__PLUGIN_EXTERNALS__).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('isPluginActive', () => {
|
|
it('returns false for unknown plugin', () => {
|
|
expect(isPluginActive('nonexistent')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('deactivatePlugin', () => {
|
|
it('does nothing for unknown plugin (no error)', () => {
|
|
expect(() => deactivatePlugin('nonexistent')).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('deactivateAllPlugins', () => {
|
|
it('does not throw when no plugins active', () => {
|
|
expect(() => deactivateAllPlugins()).not.toThrow();
|
|
});
|
|
});
|