99 lines
2.8 KiB
TypeScript
99 lines
2.8 KiB
TypeScript
import {
|
|
describe,
|
|
expect,
|
|
it
|
|
} from 'vitest';
|
|
|
|
import {
|
|
buildAttachmentDisplayPinKey,
|
|
canRevokeAttachmentDisplayBlob,
|
|
collectMessageIdsForInactiveRoomBlobRelease,
|
|
shouldRevokeDisplayBlobForAttachment
|
|
} from './attachment-blob-eviction.rules';
|
|
|
|
describe('attachment-blob-eviction rules', () => {
|
|
it('builds a stable pin key from message and attachment ids', () => {
|
|
expect(buildAttachmentDisplayPinKey('msg-1', 'att-1')).toBe('msg-1:att-1');
|
|
});
|
|
|
|
it('allows revoking blob urls when a disk path can rehydrate the attachment', () => {
|
|
expect(canRevokeAttachmentDisplayBlob({
|
|
objectUrl: 'blob:http://localhost/abc',
|
|
savedPath: '/appdata/photo.png',
|
|
receivedBytes: 0,
|
|
available: true
|
|
})).toBe(true);
|
|
});
|
|
|
|
it('refuses to revoke blobs that are the only local copy', () => {
|
|
expect(canRevokeAttachmentDisplayBlob({
|
|
objectUrl: 'blob:http://localhost/abc',
|
|
receivedBytes: 0,
|
|
available: true
|
|
})).toBe(false);
|
|
});
|
|
|
|
it('refuses to revoke blobs while a download is still in progress', () => {
|
|
expect(canRevokeAttachmentDisplayBlob({
|
|
objectUrl: 'blob:http://localhost/abc',
|
|
savedPath: '/appdata/photo.png',
|
|
receivedBytes: 1024,
|
|
available: false
|
|
})).toBe(false);
|
|
});
|
|
|
|
it('skips revocation for pinned attachments', () => {
|
|
const attachment = {
|
|
id: 'att-1',
|
|
objectUrl: 'blob:http://localhost/abc',
|
|
savedPath: '/appdata/photo.png',
|
|
receivedBytes: 0,
|
|
available: true
|
|
};
|
|
|
|
expect(shouldRevokeDisplayBlobForAttachment(
|
|
'msg-1',
|
|
attachment,
|
|
new Set([buildAttachmentDisplayPinKey('msg-1', 'att-1')])
|
|
)).toBe(false);
|
|
|
|
expect(shouldRevokeDisplayBlobForAttachment('msg-1', attachment, new Set())).toBe(true);
|
|
});
|
|
|
|
describe('collectMessageIdsForInactiveRoomBlobRelease', () => {
|
|
const messageRoomIds = new Map([
|
|
['msg-a', 'room-1'],
|
|
['msg-b', 'room-2'],
|
|
['msg-c', 'room-2']
|
|
]);
|
|
|
|
it('selects messages that belong to rooms other than the active one', () => {
|
|
expect(collectMessageIdsForInactiveRoomBlobRelease(
|
|
[
|
|
'msg-a',
|
|
'msg-b',
|
|
'msg-c'
|
|
],
|
|
(messageId) => messageRoomIds.get(messageId) ?? null,
|
|
'room-1'
|
|
)).toEqual(['msg-b', 'msg-c']);
|
|
});
|
|
|
|
it('skips messages with an unknown room so they are not evicted by mistake', () => {
|
|
expect(collectMessageIdsForInactiveRoomBlobRelease(
|
|
['msg-a', 'msg-unknown'],
|
|
(messageId) => messageRoomIds.get(messageId) ?? null,
|
|
'room-2'
|
|
)).toEqual(['msg-a']);
|
|
});
|
|
|
|
it('selects every known-room message when no room is active', () => {
|
|
expect(collectMessageIdsForInactiveRoomBlobRelease(
|
|
['msg-a', 'msg-b'],
|
|
(messageId) => messageRoomIds.get(messageId) ?? null,
|
|
null
|
|
)).toEqual(['msg-a', 'msg-b']);
|
|
});
|
|
});
|
|
});
|