mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
# Conflicts: # CONTRIBUTING.md # LICENSE # README.md # app/api/calendar-agenda/route.ts # app/api/wopi/files/[fileId]/contents/route.ts # app/api/wopi/launch/route.ts # components/calendar/calendar-app.tsx # components/calendar/calendar-day-view.tsx # components/calendar/calendar-month-view.tsx # components/calendar/calendar-week-view.tsx # components/calendar/event-modal.tsx # components/contacts/contact-detail.tsx # components/email/email-composer.tsx # components/email/email-list.tsx # components/files/file-browser.tsx # components/files/files-app.tsx # components/files/folder-tree-sidebar.tsx # components/filters/filter-rule-modal.tsx # components/mail/mail-app.tsx # hooks/use-mailbox-drop.ts # integration/run-tests.sh # lib/__tests__/calendar-agenda-route.test.ts # lib/__tests__/jmap-draft-lifecycle.test.ts # lib/__tests__/web-push.test.ts # lib/account-state-manager.ts # lib/jmap/client-interface.ts # lib/jmap/client.ts # lib/jmap/types.ts # lib/message-list-order.ts # lib/sieve/generator.ts # lib/sieve/parser.ts # lib/telemetry/payload.ts # lib/thread-utils.ts # lib/unified-mailbox.ts # lib/web-push.ts # lib/wopi/token.ts # locales/ar/common.json # locales/ca/common.json # locales/cs/common.json # locales/da/common.json # locales/de/common.json # locales/en/common.json # locales/es/common.json # locales/fa/common.json # locales/fr/common.json # locales/he/common.json # locales/hu/common.json # locales/it/common.json # locales/ja/common.json # locales/ko/common.json # locales/lv/common.json # locales/mn/common.json # locales/nb/common.json # locales/nl/common.json # locales/pl/common.json # locales/pt/common.json # locales/ro/common.json # locales/ru/common.json # locales/sk/common.json # locales/tr/common.json # locales/uk/common.json # locales/zh-TW/common.json # locales/zh/common.json # scripts/lite/lib.mjs # stores/__tests__/calendar-store-synthetic-ids.test.ts # stores/__tests__/email-store-shared-folder-keywords.test.ts # stores/__tests__/email-store-unified-actions.test.ts # stores/__tests__/file-store.test.ts # stores/email-store.ts # stores/file-store.ts # stores/message-list-tabs-store.ts
81 lines
3.7 KiB
TypeScript
81 lines
3.7 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest';
|
|
import { JMAPClient, sendMethodErrors } from '../jmap/client';
|
|
|
|
// JMAP names a failed method call "error" (RFC 8620 §3.6.2); the client used
|
|
// to test for "<Method>/error", which never matches.
|
|
|
|
function clientResponding(methodResponses: unknown[]): JMAPClient {
|
|
const client = new JMAPClient('https://jmap.example.com', 'user@example.com', 'pass');
|
|
Object.assign(client, { apiUrl: 'https://jmap.example.com/api', accountId: 'a1' });
|
|
vi.spyOn(client as unknown as { request: () => Promise<unknown> }, 'request')
|
|
.mockResolvedValue({ methodResponses });
|
|
return client;
|
|
}
|
|
|
|
describe('sendMethodErrors', () => {
|
|
it('reports an error before the submission as a failed send', () => {
|
|
const { failure, filing } = sendMethodErrors([
|
|
['error', { type: 'forbidden', description: 'nope' }, '0'],
|
|
['error', { type: 'invalidResultReference' }, '1'],
|
|
]);
|
|
expect(failure).toEqual({ type: 'forbidden', description: 'nope' });
|
|
expect(filing).toBeUndefined();
|
|
});
|
|
|
|
it('reports an error after a created submission as a filing problem', () => {
|
|
const { failure, filing } = sendMethodErrors([
|
|
['Email/set', { created: { draft: { id: 'e1' } } }, '0'],
|
|
['EmailSubmission/set', { created: { 1: { id: 's1' } } }, '1'],
|
|
['error', { type: 'serverFail' }, '1'],
|
|
]);
|
|
expect(failure).toBeUndefined();
|
|
expect(filing).toEqual({ type: 'serverFail' });
|
|
});
|
|
|
|
it('reports a refused message create instead of the dangling reference it causes', () => {
|
|
const refused = { type: 'invalidProperties', description: 'Invalid blobId', properties: ['attachments'] };
|
|
const { failure } = sendMethodErrors([
|
|
['Email/set', { created: {}, notCreated: { 'send-1': refused } }, '0'],
|
|
['error', { type: 'invalidResultReference', description: 'Invalid reference to non-existing object "send-1" from "1"' }, '1'],
|
|
['error', { type: 'invalidResultReference' }, 'deliveryStatus'],
|
|
]);
|
|
expect(failure).toEqual(refused);
|
|
});
|
|
|
|
it('treats a submission that created nothing as not sent', () => {
|
|
const { failure } = sendMethodErrors([
|
|
['EmailSubmission/set', { created: {}, notCreated: { 1: { type: 'forbiddenFrom' } } }, '1'],
|
|
['error', { type: 'serverFail' }, '1'],
|
|
]);
|
|
expect(failure).toEqual({ type: 'serverFail' });
|
|
});
|
|
});
|
|
|
|
describe('search method errors', () => {
|
|
const unsupported = ['error', { type: 'unsupportedFilter', description: 'Unsupported filter' }, '0'];
|
|
|
|
it('searchEmails throws instead of returning "no results"', async () => {
|
|
const client = clientResponding([unsupported, ['error', { type: 'invalidResultReference' }, '1']]);
|
|
vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
await expect(client.searchEmails('x')).rejects.toThrow('Search failed: Unsupported filter');
|
|
});
|
|
|
|
it('advancedSearchEmails throws on a failed Email/query', async () => {
|
|
const client = clientResponding([unsupported]);
|
|
vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
await expect(client.advancedSearchEmails({ text: 'x' })).rejects.toThrow('Search failed: Unsupported filter');
|
|
});
|
|
});
|
|
|
|
describe('submission method errors', () => {
|
|
it('cancelEmailSubmission reports a failed call instead of a cancel, and destroys nothing', async () => {
|
|
const client = clientResponding([['error', { type: 'serverFail', description: 'Temporary failure' }, '0']]);
|
|
|
|
await expect(client.cancelEmailSubmission('sub-1', 'a1')).rejects.toThrow('Temporary failure');
|
|
|
|
// The mail may still be queued, and its record is the only way to cancel it.
|
|
const request = (client as unknown as { request: ReturnType<typeof vi.fn> }).request;
|
|
expect(request).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|