mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 16:13:15 +00:00
A draft's old version is removed by id when the composer saves over it, sends it or discards it. Email ids repeat across accounts and servers - the same user logged in to two servers is account `e` on both - so the removal must go to the login and account the draft lives in. Two paths took the wrong one: - "Edit draft" in an "All folders" search or a tag view took the account from the folder still selected underneath. With a group folder selected, an own draft was opened as the group's, and its first autosave, send or discard destroyed the message with that id in the group account, while the draft stayed in the own Drafts. It now takes the login and account the result is stamped with, reads the draft through that login, and prefers that login's identity when two logins share an address. - The composer discarded through the login of the current From, and replaced or sent through it too. After switching From to another login's identity - which saves nothing by itself - discarding, the next save or the send removed the draft's id on the other server. Each save now records the login it went through (a draft opened from a list starts with the list's). A version saved through another login is removed through that one: after the new version exists when saving, after the message is out when sending, and on discard. The Pro email view, folder tabs and search preview pass their login along with the draft.
67 lines
3.4 KiB
TypeScript
67 lines
3.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { findDraftIdentityIdForLogin, resolveDraftSource } from '../draft-source';
|
|
import type { Identity } from '../jmap/types';
|
|
|
|
// userb is account `e` on the Stalwart 0.16.23 and the 1.0 test server alike,
|
|
// and the team group `c` on both; message ids repeat across all of them.
|
|
const teamInbox = { isShared: true, accountId: 'c' };
|
|
|
|
describe('resolveDraftSource', () => {
|
|
it('takes an own draft found by an "All folders" search as own, with the team folder still selected', () => {
|
|
expect(resolveDraftSource(
|
|
{ sourceClientAccountId: 'userb@v016', sourceAccountId: 'e' },
|
|
{ aggregate: true, mailbox: teamInbox, activeAccountId: 'userb@v016' },
|
|
)).toEqual({ localAccountId: 'userb@v016', accountId: 'e' });
|
|
});
|
|
|
|
it('takes a draft of a tag view from the login and account it is stamped with', () => {
|
|
expect(resolveDraftSource(
|
|
{ sourceClientAccountId: 'userb@v10', sourceAccountId: 'c' },
|
|
{ aggregate: true, mailbox: undefined, activeAccountId: 'userb@v016' },
|
|
)).toEqual({ localAccountId: 'userb@v10', accountId: 'c' });
|
|
});
|
|
|
|
it('never takes the folder underneath for an unstamped row of a list that mixes accounts', () => {
|
|
expect(resolveDraftSource({}, { aggregate: true, mailbox: teamInbox, activeAccountId: 'userb@v016' }))
|
|
.toEqual({ localAccountId: 'userb@v016', accountId: undefined });
|
|
});
|
|
|
|
it('takes a draft of a group folder opened directly as the group\'s', () => {
|
|
expect(resolveDraftSource({}, { aggregate: false, mailbox: teamInbox, activeAccountId: 'userb@v016' }))
|
|
.toEqual({ localAccountId: 'userb@v016', accountId: 'c' });
|
|
});
|
|
|
|
it('takes an own folder\'s draft of the login viewed in the Pro sidebar as that login\'s', () => {
|
|
expect(resolveDraftSource(
|
|
{},
|
|
{ aggregate: false, mailbox: { isShared: false, accountId: 'e' }, viewingAccountId: 'userb@v10', activeAccountId: 'userb@v016' },
|
|
)).toEqual({ localAccountId: 'userb@v10', accountId: undefined });
|
|
});
|
|
|
|
it('takes what the caller says for a send undone from the group identity', () => {
|
|
expect(resolveDraftSource(
|
|
{ sourceClientAccountId: 'userb@v016', sourceAccountId: 'e' },
|
|
{ source: { accountId: 'c', localAccountId: 'userb@v10' }, aggregate: true, activeAccountId: 'userb@v016' },
|
|
)).toEqual({ localAccountId: 'userb@v10', accountId: 'c' });
|
|
});
|
|
});
|
|
|
|
describe('findDraftIdentityIdForLogin', () => {
|
|
const identities = [
|
|
{ id: 'userb@v016::b', email: 'userb@example.org', name: 'userb' },
|
|
{ id: 'userb@v10::c', email: 'userb@example.org', name: 'userb' },
|
|
{ id: 'userb@v10::b', email: 'team@example.org', name: 'Team' },
|
|
] as Identity[];
|
|
|
|
it('picks the identity of the login the draft lives in when two logins share the address', () => {
|
|
expect(findDraftIdentityIdForLogin(identities, { email: 'userb@example.org', name: 'userb' }, 'userb@v10')).toBe('userb@v10::c');
|
|
expect(findDraftIdentityIdForLogin(identities, { email: 'userb@example.org', name: 'userb' }, 'userb@v016')).toBe('userb@v016::b');
|
|
});
|
|
|
|
it('falls back to every login\'s identities', () => {
|
|
expect(findDraftIdentityIdForLogin(identities, { email: 'team@example.org', name: 'Team' }, 'userb@v016')).toBe('userb@v10::b');
|
|
// One account's identities carry no login prefix.
|
|
expect(findDraftIdentityIdForLogin([{ id: 'b', email: 'userb@example.org', name: 'userb' } as Identity], { email: 'userb@example.org' }, 'userb@v016')).toBe('b');
|
|
});
|
|
});
|