mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-02-15 07:28:59 +00:00
312 lines
9.4 KiB
TypeScript
312 lines
9.4 KiB
TypeScript
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import { assert } from 'chai';
|
|
import { Proto } from '@signalapp/mock-server';
|
|
import * as durations from '../../util/durations/index.std.js';
|
|
import type { App, Bootstrap } from './fixtures.node.js';
|
|
import {
|
|
initStorage,
|
|
debug,
|
|
STICKER_PACKS,
|
|
EMPTY,
|
|
storeStickerPacks,
|
|
getStickerPackRecordPredicate,
|
|
getStickerPackLink,
|
|
} from './fixtures.node.js';
|
|
import {
|
|
getMessageInTimelineByTimestamp,
|
|
sendTextMessage,
|
|
} from '../helpers.node.js';
|
|
import { strictAssert } from '../../util/assert.std.js';
|
|
|
|
const { StickerPackOperation } = Proto.SyncMessage;
|
|
|
|
describe('stickers', function (this: Mocha.Suite) {
|
|
this.timeout(durations.MINUTE);
|
|
|
|
let bootstrap: Bootstrap;
|
|
let app: App;
|
|
|
|
beforeEach(async () => {
|
|
({ bootstrap, app } = await initStorage());
|
|
const { server } = bootstrap;
|
|
await storeStickerPacks(server, STICKER_PACKS);
|
|
});
|
|
|
|
afterEach(async function (this: Mocha.Context) {
|
|
if (!bootstrap) {
|
|
return;
|
|
}
|
|
|
|
await bootstrap.maybeSaveLogs(this.currentTest, app);
|
|
await app.close();
|
|
await bootstrap.teardown();
|
|
});
|
|
|
|
it('should install/uninstall stickers', async () => {
|
|
const { phone, desktop, contacts } = bootstrap;
|
|
const [firstContact] = contacts;
|
|
|
|
const window = await app.getWindow();
|
|
|
|
const leftPane = window.locator('#LeftPane');
|
|
const conversationView = window.locator(
|
|
'.Inbox__conversation > .ConversationView'
|
|
);
|
|
|
|
debug('sending two sticker pack links');
|
|
await firstContact.sendText(
|
|
desktop,
|
|
`First sticker pack ${getStickerPackLink(STICKER_PACKS[0])}`
|
|
);
|
|
await firstContact.sendText(
|
|
desktop,
|
|
`Second sticker pack ${getStickerPackLink(STICKER_PACKS[1])}`
|
|
);
|
|
|
|
await leftPane
|
|
.locator(`[data-testid="${firstContact.device.aci}"]`)
|
|
.click();
|
|
|
|
{
|
|
debug('installing first sticker pack via UI');
|
|
const state = await phone.expectStorageState('initial state');
|
|
|
|
await conversationView
|
|
.locator(`a:has-text("${STICKER_PACKS[0].id.toString('hex')}")`)
|
|
.click();
|
|
await window
|
|
.getByTestId('StickerPreviewModal')
|
|
.getByRole('button', { name: 'Install' })
|
|
.click();
|
|
|
|
debug('waiting for sync message');
|
|
const { syncMessage } = await phone.waitForSyncMessage(entry =>
|
|
Boolean(entry.syncMessage.stickerPackOperation?.length)
|
|
);
|
|
const [syncOp] = syncMessage.stickerPackOperation ?? [];
|
|
assert.isTrue(STICKER_PACKS[0].id.equals(syncOp?.packId ?? EMPTY));
|
|
assert.isTrue(STICKER_PACKS[0].key.equals(syncOp?.packKey ?? EMPTY));
|
|
assert.strictEqual(syncOp?.type, StickerPackOperation.Type.INSTALL);
|
|
|
|
debug('waiting for storage service update');
|
|
const stateAfter = await phone.waitForStorageState({ after: state });
|
|
const stickerPack = stateAfter.findRecord(
|
|
getStickerPackRecordPredicate(STICKER_PACKS[0])
|
|
);
|
|
assert.ok(
|
|
stickerPack,
|
|
'New storage state should have sticker pack record'
|
|
);
|
|
assert.isTrue(
|
|
STICKER_PACKS[0].key.equals(
|
|
stickerPack?.record.stickerPack?.packKey ?? EMPTY
|
|
),
|
|
'Wrong sticker pack key'
|
|
);
|
|
assert.strictEqual(
|
|
stickerPack?.record.stickerPack?.position,
|
|
11,
|
|
'Wrong sticker pack position'
|
|
);
|
|
}
|
|
|
|
{
|
|
debug('uninstalling first sticker pack via UI');
|
|
const state = await phone.expectStorageState('initial state');
|
|
|
|
await conversationView
|
|
.locator(`a:has-text("${STICKER_PACKS[0].id.toString('hex')}")`)
|
|
.click();
|
|
await window
|
|
.getByTestId('StickerPreviewModal')
|
|
.getByRole('button', { name: 'Uninstall' })
|
|
.click();
|
|
|
|
// Confirm
|
|
await window
|
|
.locator('.module-Button--destructive >> "Uninstall"')
|
|
.click();
|
|
|
|
debug('waiting for sync message');
|
|
const { syncMessage } = await phone.waitForSyncMessage(entry =>
|
|
Boolean(entry.syncMessage.stickerPackOperation?.length)
|
|
);
|
|
const [syncOp] = syncMessage.stickerPackOperation ?? [];
|
|
assert.isTrue(STICKER_PACKS[0].id.equals(syncOp?.packId ?? EMPTY));
|
|
assert.strictEqual(syncOp?.type, StickerPackOperation.Type.REMOVE);
|
|
|
|
debug('waiting for storage service update');
|
|
const stateAfter = await phone.waitForStorageState({ after: state });
|
|
const stickerPack = stateAfter.findRecord(
|
|
getStickerPackRecordPredicate(STICKER_PACKS[0])
|
|
);
|
|
assert.ok(
|
|
stickerPack,
|
|
'New storage state should have sticker pack record'
|
|
);
|
|
assert.deepStrictEqual(
|
|
stickerPack?.record.stickerPack?.packKey,
|
|
EMPTY,
|
|
'Sticker pack key should be removed'
|
|
);
|
|
const deletedAt =
|
|
stickerPack?.record.stickerPack?.deletedAtTimestamp?.toNumber() ?? 0;
|
|
assert.isAbove(
|
|
deletedAt,
|
|
Date.now() - durations.HOUR,
|
|
'Sticker pack should have deleted at timestamp'
|
|
);
|
|
}
|
|
|
|
debug('opening sticker manager');
|
|
|
|
const FunButton = window.getByRole('button', {
|
|
name: 'Add an Emoji, Sticker, or GIF',
|
|
});
|
|
const FunDialog = window.getByRole('dialog', {
|
|
name: 'Add an Emoji, Sticker, or GIF',
|
|
});
|
|
const FunPickerStickersTab = FunDialog.getByRole('tab', {
|
|
name: 'Stickers',
|
|
});
|
|
const FunPickerAddSticker = FunDialog.getByRole('button', {
|
|
name: 'Add a sticker pack',
|
|
});
|
|
|
|
await FunButton.click();
|
|
await FunPickerStickersTab.click();
|
|
await FunPickerAddSticker.click();
|
|
|
|
const stickerManager = conversationView.locator(
|
|
'[data-testid=StickerManager]'
|
|
);
|
|
|
|
debug('switching to Installed tab');
|
|
await stickerManager.locator('.Tabs__tab >> "Installed"').click();
|
|
|
|
{
|
|
debug('installing first sticker pack via storage service');
|
|
const state = await phone.expectStorageState('initial state');
|
|
|
|
await phone.setStorageState(
|
|
state.updateRecord(
|
|
getStickerPackRecordPredicate(STICKER_PACKS[0]),
|
|
record => ({
|
|
...record,
|
|
stickerPack: {
|
|
...record?.stickerPack,
|
|
packKey: STICKER_PACKS[0].key,
|
|
position: 7,
|
|
deletedAtTimestamp: undefined,
|
|
},
|
|
})
|
|
)
|
|
);
|
|
await phone.sendFetchStorage({
|
|
timestamp: bootstrap.getTimestamp(),
|
|
});
|
|
|
|
debug('waiting for sticker pack to become visible');
|
|
await stickerManager
|
|
.locator(`[data-testid="${STICKER_PACKS[0].id.toString('hex')}"]`)
|
|
.waitFor();
|
|
}
|
|
|
|
{
|
|
debug('installing second sticker pack via sync message');
|
|
const state = await phone.expectStorageState('initial state');
|
|
|
|
await phone.sendStickerPackSync({
|
|
type: 'install',
|
|
packId: STICKER_PACKS[1].id,
|
|
packKey: STICKER_PACKS[1].key,
|
|
timestamp: bootstrap.getTimestamp(),
|
|
});
|
|
|
|
debug('waiting for sticker pack to become visible');
|
|
await stickerManager
|
|
.locator(`[data-testid="${STICKER_PACKS[1].id.toString('hex')}"]`)
|
|
.waitFor();
|
|
|
|
debug('waiting for storage service update');
|
|
const stateAfter = await phone.waitForStorageState({ after: state });
|
|
const stickerPack = stateAfter.findRecord(
|
|
getStickerPackRecordPredicate(STICKER_PACKS[1])
|
|
);
|
|
assert.ok(
|
|
stickerPack,
|
|
'New storage state should have sticker pack record'
|
|
);
|
|
assert.isTrue(
|
|
STICKER_PACKS[1].key.equals(
|
|
stickerPack?.record.stickerPack?.packKey ?? EMPTY
|
|
),
|
|
'Wrong sticker pack key'
|
|
);
|
|
assert.strictEqual(
|
|
stickerPack?.record.stickerPack?.position,
|
|
12,
|
|
'Wrong sticker pack position'
|
|
);
|
|
}
|
|
|
|
debug('Verifying the final manifest version');
|
|
const finalState = await phone.expectStorageState('consistency check');
|
|
|
|
assert.strictEqual(finalState.version, 5);
|
|
|
|
debug(
|
|
'verifying that stickers from packs can be received and paths are deduplicated'
|
|
);
|
|
const firstTimestamp = bootstrap.getTimestamp();
|
|
const secondTimestamp = bootstrap.getTimestamp();
|
|
await sendTextMessage({
|
|
from: firstContact,
|
|
to: desktop,
|
|
desktop,
|
|
text: undefined,
|
|
sticker: {
|
|
packId: STICKER_PACKS[0].id,
|
|
packKey: STICKER_PACKS[0].key,
|
|
stickerId: 0,
|
|
},
|
|
timestamp: firstTimestamp,
|
|
});
|
|
|
|
await sendTextMessage({
|
|
from: firstContact,
|
|
to: desktop,
|
|
desktop,
|
|
text: undefined,
|
|
sticker: {
|
|
packId: STICKER_PACKS[0].id,
|
|
packKey: STICKER_PACKS[0].key,
|
|
stickerId: 0,
|
|
},
|
|
timestamp: secondTimestamp,
|
|
});
|
|
|
|
await window.getByRole('button', { name: 'Go back' }).click();
|
|
await getMessageInTimelineByTimestamp(window, firstTimestamp)
|
|
.locator('.module-image--loaded')
|
|
.waitFor();
|
|
|
|
await getMessageInTimelineByTimestamp(window, secondTimestamp)
|
|
.locator('.module-image--loaded')
|
|
.waitFor();
|
|
|
|
const firstStickerData = (await app.getMessagesBySentAt(firstTimestamp))[0]
|
|
.sticker?.data;
|
|
const secondStickerData = (
|
|
await app.getMessagesBySentAt(secondTimestamp)
|
|
)[0].sticker?.data;
|
|
|
|
strictAssert(firstStickerData?.path, 'path exists');
|
|
strictAssert(firstStickerData?.localKey, 'localKey exists');
|
|
assert.strictEqual(firstStickerData.path, secondStickerData?.path);
|
|
assert.strictEqual(firstStickerData.localKey, secondStickerData?.localKey);
|
|
});
|
|
});
|