signal-desktop/ts/test-both/util/retryPlaceholders_test.ts

332 lines
9.7 KiB
TypeScript
Raw Normal View History

2021-05-28 19:11:19 +00:00
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
2021-06-08 21:51:58 +00:00
import sinon from 'sinon';
2021-05-28 19:11:19 +00:00
2023-08-16 20:54:39 +00:00
import { generateAci } from '../../types/ServiceId';
import type { RetryItemType } from '../../util/retryPlaceholders';
2021-05-28 19:11:19 +00:00
import {
2021-06-08 21:51:58 +00:00
getDeltaIntoPast,
2021-05-28 19:11:19 +00:00
RetryPlaceholders,
STORAGE_KEY,
} from '../../util/retryPlaceholders';
/* eslint-disable @typescript-eslint/no-explicit-any */
describe('RetryPlaceholders', () => {
2021-06-08 21:51:58 +00:00
const NOW = 1_000_000;
let clock: any;
beforeEach(async () => {
await window.storage.put(STORAGE_KEY, undefined as any);
2021-06-08 21:51:58 +00:00
clock = sinon.useFakeTimers({
now: NOW,
});
});
afterEach(() => {
clock.restore();
2021-05-28 19:11:19 +00:00
});
function getDefaultItem(): RetryItemType {
return {
conversationId: 'conversation-id',
2021-06-08 21:51:58 +00:00
sentAt: NOW - 10,
receivedAt: NOW - 5,
2021-05-28 19:11:19 +00:00
receivedAtCounter: 4,
2023-08-16 20:54:39 +00:00
senderAci: generateAci(),
2021-05-28 19:11:19 +00:00
};
}
describe('constructor', () => {
it('loads previously-saved data on creation', async () => {
2021-05-28 19:11:19 +00:00
const items: Array<RetryItemType> = [
getDefaultItem(),
{ ...getDefaultItem(), conversationId: 'conversation-id-2' },
];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(2, placeholders.getCount());
});
it('starts with no data if provided data fails to parse', async () => {
await window.storage.put(STORAGE_KEY, [
2021-05-28 19:11:19 +00:00
{ item: 'is wrong shape!' },
{ bad: 'is not good!' },
] as any);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(0, placeholders.getCount());
});
});
describe('#add', () => {
it('adds one item', async () => {
const placeholders = new RetryPlaceholders();
await placeholders.add(getDefaultItem());
assert.strictEqual(1, placeholders.getCount());
});
it('throws if provided data fails to parse', async () => {
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
await assert.isRejected(
2021-05-28 19:11:19 +00:00
placeholders.add({
item: 'is wrong shape!',
} as any),
'Item did not match schema'
);
});
});
describe('#getNextToExpire', () => {
it('returns nothing if no items', () => {
const placeholders = new RetryPlaceholders();
assert.strictEqual(0, placeholders.getCount());
assert.isUndefined(placeholders.getNextToExpire());
});
it('returns only item if just one item', async () => {
2021-05-28 19:11:19 +00:00
const item = getDefaultItem();
const items: Array<RetryItemType> = [item];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(1, placeholders.getCount());
assert.deepEqual(item, placeholders.getNextToExpire());
});
it('returns soonest expiration given a list, and after add', async () => {
const older = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: NOW,
2021-05-28 19:11:19 +00:00
};
const newer = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: NOW + 10,
2021-05-28 19:11:19 +00:00
};
const items: Array<RetryItemType> = [older, newer];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(2, placeholders.getCount());
assert.deepEqual(older, placeholders.getNextToExpire());
const oldest = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: NOW - 5,
2021-05-28 19:11:19 +00:00
};
await placeholders.add(oldest);
assert.strictEqual(3, placeholders.getCount());
assert.deepEqual(oldest, placeholders.getNextToExpire());
});
});
describe('#getExpiredAndRemove', () => {
it('does nothing if no item expired', async () => {
const older = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: NOW + 10,
2021-05-28 19:11:19 +00:00
};
const newer = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: NOW + 15,
2021-05-28 19:11:19 +00:00
};
const items: Array<RetryItemType> = [older, newer];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(2, placeholders.getCount());
assert.deepEqual([], await placeholders.getExpiredAndRemove());
assert.strictEqual(2, placeholders.getCount());
});
it('removes just one if expired', async () => {
const older = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: getDeltaIntoPast() - 1000,
2021-05-28 19:11:19 +00:00
};
const newer = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: NOW + 15,
2021-05-28 19:11:19 +00:00
};
const items: Array<RetryItemType> = [older, newer];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(2, placeholders.getCount());
assert.deepEqual([older], await placeholders.getExpiredAndRemove());
assert.strictEqual(1, placeholders.getCount());
assert.deepEqual(newer, placeholders.getNextToExpire());
});
it('removes all if expired', async () => {
const older = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: getDeltaIntoPast() - 1000,
2021-05-28 19:11:19 +00:00
};
const newer = {
...getDefaultItem(),
2021-06-08 21:51:58 +00:00
receivedAt: getDeltaIntoPast() - 900,
2021-05-28 19:11:19 +00:00
};
const items: Array<RetryItemType> = [older, newer];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(2, placeholders.getCount());
assert.deepEqual(
[older, newer],
await placeholders.getExpiredAndRemove()
);
assert.strictEqual(0, placeholders.getCount());
});
});
2021-06-08 21:51:58 +00:00
describe('#findByConversationAndMarkOpened', () => {
2021-05-28 19:11:19 +00:00
it('does nothing if no items found matching conversation', async () => {
const older = {
...getDefaultItem(),
conversationId: 'conversation-id-1',
};
const newer = {
...getDefaultItem(),
conversationId: 'conversation-id-2',
};
const items: Array<RetryItemType> = [older, newer];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(2, placeholders.getCount());
2021-06-08 21:51:58 +00:00
await placeholders.findByConversationAndMarkOpened('conversation-id-3');
2021-05-28 19:11:19 +00:00
assert.strictEqual(2, placeholders.getCount());
2021-06-08 21:51:58 +00:00
const saveItems = window.storage.get(STORAGE_KEY);
assert.deepEqual([older, newer], saveItems);
2021-05-28 19:11:19 +00:00
});
2021-06-08 21:51:58 +00:00
it('updates all items matching conversation', async () => {
2021-05-28 19:11:19 +00:00
const convo1a = {
...getDefaultItem(),
conversationId: 'conversation-id-1',
2021-06-08 21:51:58 +00:00
receivedAt: NOW - 5,
2021-05-28 19:11:19 +00:00
};
const convo1b = {
...getDefaultItem(),
conversationId: 'conversation-id-1',
2021-06-08 21:51:58 +00:00
receivedAt: NOW - 4,
2021-05-28 19:11:19 +00:00
};
const convo2a = {
...getDefaultItem(),
conversationId: 'conversation-id-2',
2021-06-08 21:51:58 +00:00
receivedAt: NOW + 15,
2021-05-28 19:11:19 +00:00
};
const items: Array<RetryItemType> = [convo1a, convo1b, convo2a];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(3, placeholders.getCount());
2021-06-08 21:51:58 +00:00
await placeholders.findByConversationAndMarkOpened('conversation-id-1');
assert.strictEqual(3, placeholders.getCount());
const firstSaveItems = window.storage.get(STORAGE_KEY);
2021-05-28 19:11:19 +00:00
assert.deepEqual(
2021-06-08 21:51:58 +00:00
[
{
...convo1a,
wasOpened: true,
},
{
...convo1b,
wasOpened: true,
},
convo2a,
],
firstSaveItems
2021-05-28 19:11:19 +00:00
);
const convo2b = {
...getDefaultItem(),
conversationId: 'conversation-id-2',
2021-06-08 21:51:58 +00:00
receivedAt: NOW + 16,
2021-05-28 19:11:19 +00:00
};
await placeholders.add(convo2b);
2021-06-08 21:51:58 +00:00
assert.strictEqual(4, placeholders.getCount());
await placeholders.findByConversationAndMarkOpened('conversation-id-2');
assert.strictEqual(4, placeholders.getCount());
const secondSaveItems = window.storage.get(STORAGE_KEY);
2021-05-28 19:11:19 +00:00
assert.deepEqual(
2021-06-08 21:51:58 +00:00
[
{
...convo1a,
wasOpened: true,
},
{
...convo1b,
wasOpened: true,
},
{
...convo2a,
wasOpened: true,
},
{
...convo2b,
wasOpened: true,
},
],
secondSaveItems
2021-05-28 19:11:19 +00:00
);
});
});
describe('#findByMessageAndRemove', () => {
it('does nothing if no item matching message found', async () => {
2021-06-08 21:51:58 +00:00
const sentAt = NOW - 20;
2021-05-28 19:11:19 +00:00
const older = {
...getDefaultItem(),
conversationId: 'conversation-id-1',
2021-06-08 21:51:58 +00:00
sentAt: NOW - 10,
2021-05-28 19:11:19 +00:00
};
const newer = {
...getDefaultItem(),
conversationId: 'conversation-id-1',
2021-06-08 21:51:58 +00:00
sentAt: NOW - 11,
2021-05-28 19:11:19 +00:00
};
const items: Array<RetryItemType> = [older, newer];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(2, placeholders.getCount());
assert.isUndefined(
await placeholders.findByMessageAndRemove('conversation-id-1', sentAt)
);
assert.strictEqual(2, placeholders.getCount());
});
it('removes the item matching message', async () => {
2021-06-08 21:51:58 +00:00
const sentAt = NOW - 20;
2021-05-28 19:11:19 +00:00
const older = {
...getDefaultItem(),
conversationId: 'conversation-id-1',
2021-06-08 21:51:58 +00:00
sentAt: NOW - 10,
2021-05-28 19:11:19 +00:00
};
const newer = {
...getDefaultItem(),
conversationId: 'conversation-id-1',
sentAt,
};
const items: Array<RetryItemType> = [older, newer];
await window.storage.put(STORAGE_KEY, items);
2021-05-28 19:11:19 +00:00
const placeholders = new RetryPlaceholders();
assert.strictEqual(2, placeholders.getCount());
assert.deepEqual(
newer,
await placeholders.findByMessageAndRemove('conversation-id-1', sentAt)
);
assert.strictEqual(1, placeholders.getCount());
});
});
});