Convert js/modules/types/message to Typescript
This commit is contained in:
parent
9975758fde
commit
924c271b13
18 changed files with 748 additions and 398 deletions
|
@ -270,7 +270,7 @@ describe('Contact', () => {
|
|||
const result = await upgradeVersion(message.contact[0], {
|
||||
message,
|
||||
logger,
|
||||
regionCode: '1',
|
||||
getRegionCode: () => '1',
|
||||
writeNewAttachmentData,
|
||||
});
|
||||
assert.deepEqual(result, message.contact[0]);
|
||||
|
@ -311,7 +311,7 @@ describe('Contact', () => {
|
|||
};
|
||||
const result = await upgradeVersion(message.contact[0], {
|
||||
message,
|
||||
regionCode: 'US',
|
||||
getRegionCode: () => 'US',
|
||||
logger,
|
||||
writeNewAttachmentData,
|
||||
});
|
||||
|
@ -355,7 +355,7 @@ describe('Contact', () => {
|
|||
],
|
||||
};
|
||||
const result = await upgradeVersion(message.contact[0], {
|
||||
regionCode: '1',
|
||||
getRegionCode: () => '1',
|
||||
writeNewAttachmentData,
|
||||
message,
|
||||
logger,
|
||||
|
@ -440,7 +440,7 @@ describe('Contact', () => {
|
|||
};
|
||||
|
||||
const result = await upgradeVersion(message.contact[0], {
|
||||
regionCode: '1',
|
||||
getRegionCode: () => '1',
|
||||
writeNewAttachmentData,
|
||||
message,
|
||||
logger,
|
||||
|
@ -487,7 +487,7 @@ describe('Contact', () => {
|
|||
],
|
||||
};
|
||||
const result = await upgradeVersion(message.contact[0], {
|
||||
regionCode: '1',
|
||||
getRegionCode: () => '1',
|
||||
writeNewAttachmentData,
|
||||
message,
|
||||
logger,
|
||||
|
@ -534,7 +534,7 @@ describe('Contact', () => {
|
|||
],
|
||||
};
|
||||
const result = await upgradeVersion(message.contact[0], {
|
||||
regionCode: '1',
|
||||
getRegionCode: () => '1',
|
||||
writeNewAttachmentData,
|
||||
message,
|
||||
logger,
|
||||
|
@ -577,7 +577,7 @@ describe('Contact', () => {
|
|||
},
|
||||
};
|
||||
const result = await upgradeVersion(message.contact[0], {
|
||||
regionCode: '1',
|
||||
getRegionCode: () => '1',
|
||||
writeNewAttachmentData,
|
||||
message,
|
||||
logger,
|
||||
|
@ -606,7 +606,7 @@ describe('Contact', () => {
|
|||
],
|
||||
};
|
||||
const result = await upgradeVersion(message.contact[0], {
|
||||
regionCode: '1',
|
||||
getRegionCode: () => '1',
|
||||
writeNewAttachmentData,
|
||||
message,
|
||||
logger,
|
||||
|
|
869
ts/test-node/types/Message2_test.ts
Normal file
869
ts/test-node/types/Message2_test.ts
Normal file
|
@ -0,0 +1,869 @@
|
|||
// Copyright 2018-2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
|
||||
import * as Message from '../../types/Message2';
|
||||
import { SignalService } from '../../protobuf';
|
||||
import * as Bytes from '../../Bytes';
|
||||
import * as MIME from '../../types/MIME';
|
||||
|
||||
import type { EmbeddedContactType } from '../../types/EmbeddedContact';
|
||||
import type {
|
||||
MessageAttributesType,
|
||||
StickerMessageType,
|
||||
} from '../../model-types.d';
|
||||
import type { AttachmentType } from '../../types/Attachment';
|
||||
import type { LoggerType } from '../../types/Logging';
|
||||
|
||||
describe('Message', () => {
|
||||
const logger: LoggerType = {
|
||||
warn: () => null,
|
||||
error: () => null,
|
||||
fatal: () => null,
|
||||
info: () => null,
|
||||
debug: () => null,
|
||||
trace: () => null,
|
||||
};
|
||||
|
||||
function getDefaultMessage(
|
||||
props?: Partial<MessageAttributesType>
|
||||
): MessageAttributesType {
|
||||
return {
|
||||
id: 'some-id',
|
||||
type: 'incoming',
|
||||
sent_at: 45,
|
||||
received_at: 45,
|
||||
timestamp: 45,
|
||||
conversationId: 'some-conversation-id',
|
||||
...props,
|
||||
};
|
||||
}
|
||||
|
||||
function getDefaultContext(
|
||||
props?: Partial<Message.ContextType>
|
||||
): Message.ContextType {
|
||||
return {
|
||||
getAbsoluteAttachmentPath: (_path: string) =>
|
||||
'fake-absolute-attachment-path',
|
||||
getAbsoluteStickerPath: (_path: string) => 'fake-absolute-sticker-path',
|
||||
getImageDimensions: async (_params: {
|
||||
objectUrl: string;
|
||||
logger: LoggerType;
|
||||
}) => ({
|
||||
width: 10,
|
||||
height: 20,
|
||||
}),
|
||||
getRegionCode: () => 'region-code',
|
||||
logger,
|
||||
makeImageThumbnail: async (_params: {
|
||||
size: number;
|
||||
objectUrl: string;
|
||||
contentType: MIME.MIMEType;
|
||||
logger: LoggerType;
|
||||
}) => new Blob(),
|
||||
makeObjectUrl: (
|
||||
_data: Uint8Array | ArrayBuffer,
|
||||
_contentType: MIME.MIMEType
|
||||
) => 'fake-object-url',
|
||||
makeVideoScreenshot: async (_params: {
|
||||
objectUrl: string;
|
||||
contentType: MIME.MIMEType;
|
||||
logger: LoggerType;
|
||||
}) => new Blob(),
|
||||
revokeObjectUrl: (_objectUrl: string) => undefined,
|
||||
writeNewAttachmentData: async (_data: Uint8Array) =>
|
||||
'fake-attachment-path',
|
||||
writeNewStickerData: async (_sticker: StickerMessageType) =>
|
||||
'fake-sticker-path',
|
||||
...props,
|
||||
};
|
||||
}
|
||||
const writeExistingAttachmentData = () => Promise.resolve();
|
||||
|
||||
describe('createAttachmentDataWriter', () => {
|
||||
it('should ignore messages that didn’t go through attachment migration', async () => {
|
||||
const input = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 2,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 2,
|
||||
});
|
||||
|
||||
const actual = await Message.createAttachmentDataWriter({
|
||||
writeExistingAttachmentData,
|
||||
logger,
|
||||
})(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should ignore messages without attachments', async () => {
|
||||
const input = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 4,
|
||||
attachments: [],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 4,
|
||||
attachments: [],
|
||||
});
|
||||
|
||||
const actual = await Message.createAttachmentDataWriter({
|
||||
writeExistingAttachmentData,
|
||||
logger,
|
||||
})(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should write attachments to file system on original path', async () => {
|
||||
const input = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 4,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.IMAGE_GIF,
|
||||
size: 3534,
|
||||
path: 'ab/abcdefghi',
|
||||
data: Bytes.fromString('It’s easy if you try'),
|
||||
},
|
||||
],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 4,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.IMAGE_GIF,
|
||||
size: 3534,
|
||||
path: 'ab/abcdefghi',
|
||||
},
|
||||
],
|
||||
contact: [],
|
||||
preview: [],
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const writeExistingAttachmentData = async (
|
||||
attachment: Pick<AttachmentType, 'data' | 'path'>
|
||||
) => {
|
||||
assert.equal(attachment.path, 'ab/abcdefghi');
|
||||
assert.strictEqual(
|
||||
Bytes.toString(attachment.data || new Uint8Array()),
|
||||
'It’s easy if you try'
|
||||
);
|
||||
};
|
||||
|
||||
const actual = await Message.createAttachmentDataWriter({
|
||||
writeExistingAttachmentData,
|
||||
logger,
|
||||
})(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should process quote attachment thumbnails', async () => {
|
||||
const input = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 4,
|
||||
attachments: [],
|
||||
quote: {
|
||||
id: 3523,
|
||||
isViewOnce: false,
|
||||
messageId: 'some-message-id',
|
||||
referencedMessageNotFound: false,
|
||||
attachments: [
|
||||
{
|
||||
thumbnail: {
|
||||
path: 'ab/abcdefghi',
|
||||
data: Bytes.fromString('It’s easy if you try'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 4,
|
||||
attachments: [],
|
||||
quote: {
|
||||
id: 3523,
|
||||
isViewOnce: false,
|
||||
messageId: 'some-message-id',
|
||||
referencedMessageNotFound: false,
|
||||
attachments: [
|
||||
{
|
||||
thumbnail: {
|
||||
path: 'ab/abcdefghi',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
contact: [],
|
||||
preview: [],
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const writeExistingAttachmentData = async (
|
||||
attachment: Pick<AttachmentType, 'data' | 'path'>
|
||||
) => {
|
||||
assert.equal(attachment.path, 'ab/abcdefghi');
|
||||
assert.strictEqual(
|
||||
Bytes.toString(attachment.data || new Uint8Array()),
|
||||
'It’s easy if you try'
|
||||
);
|
||||
};
|
||||
|
||||
const actual = await Message.createAttachmentDataWriter({
|
||||
writeExistingAttachmentData,
|
||||
logger,
|
||||
})(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should process contact avatars', async () => {
|
||||
const input = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 4,
|
||||
attachments: [],
|
||||
contact: [
|
||||
{
|
||||
name: { givenName: 'john' },
|
||||
avatar: {
|
||||
isProfile: false,
|
||||
avatar: {
|
||||
contentType: MIME.IMAGE_PNG,
|
||||
size: 47,
|
||||
path: 'ab/abcdefghi',
|
||||
data: Bytes.fromString('It’s easy if you try'),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 4,
|
||||
attachments: [],
|
||||
contact: [
|
||||
{
|
||||
name: { givenName: 'john' },
|
||||
avatar: {
|
||||
isProfile: false,
|
||||
avatar: {
|
||||
contentType: MIME.IMAGE_PNG,
|
||||
size: 47,
|
||||
path: 'ab/abcdefghi',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
preview: [],
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const writeExistingAttachmentData = async (
|
||||
attachment: Pick<AttachmentType, 'data' | 'path'>
|
||||
) => {
|
||||
assert.equal(attachment.path, 'ab/abcdefghi');
|
||||
assert.strictEqual(
|
||||
Bytes.toString(attachment.data || new Uint8Array()),
|
||||
'It’s easy if you try'
|
||||
);
|
||||
};
|
||||
|
||||
const actual = await Message.createAttachmentDataWriter({
|
||||
writeExistingAttachmentData,
|
||||
logger,
|
||||
})(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('initializeSchemaVersion', () => {
|
||||
it('should ignore messages with previously inherited schema', () => {
|
||||
const input = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 2,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
schemaVersion: 2,
|
||||
});
|
||||
|
||||
const actual = Message.initializeSchemaVersion({
|
||||
message: input,
|
||||
logger,
|
||||
});
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
context('for message without attachments', () => {
|
||||
it('should initialize schema version to zero', () => {
|
||||
const input = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
attachments: [],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
attachments: [],
|
||||
schemaVersion: 0,
|
||||
});
|
||||
|
||||
const actual = Message.initializeSchemaVersion({
|
||||
message: input,
|
||||
logger,
|
||||
});
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
context('for message with attachments', () => {
|
||||
it('should inherit existing attachment schema version', () => {
|
||||
const input = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.IMAGE_JPEG,
|
||||
size: 45,
|
||||
fileName: 'lennon.jpg',
|
||||
schemaVersion: 7,
|
||||
},
|
||||
],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'Imagine there is no heaven…',
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.IMAGE_JPEG,
|
||||
size: 45,
|
||||
fileName: 'lennon.jpg',
|
||||
},
|
||||
],
|
||||
schemaVersion: 7,
|
||||
});
|
||||
|
||||
const actual = Message.initializeSchemaVersion({
|
||||
message: input,
|
||||
logger,
|
||||
});
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('upgradeSchema', () => {
|
||||
it('should upgrade an unversioned message to the latest version', async () => {
|
||||
const input = getDefaultMessage({
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.AUDIO_AAC,
|
||||
flags: SignalService.AttachmentPointer.Flags.VOICE_MESSAGE,
|
||||
data: Bytes.fromString('It’s easy if you try'),
|
||||
fileName: 'test\u202Dfig.exe',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
schemaVersion: 0,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.AUDIO_AAC,
|
||||
flags: 1,
|
||||
path: 'abc/abcdefg',
|
||||
fileName: 'test\uFFFDfig.exe',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
hasAttachments: 1,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: undefined,
|
||||
schemaVersion: Message.CURRENT_SCHEMA_VERSION,
|
||||
contact: [],
|
||||
});
|
||||
|
||||
const expectedAttachmentData = 'It’s easy if you try';
|
||||
const context = getDefaultContext({
|
||||
writeNewAttachmentData: async attachmentData => {
|
||||
assert.strictEqual(
|
||||
Bytes.toString(attachmentData),
|
||||
expectedAttachmentData
|
||||
);
|
||||
return 'abc/abcdefg';
|
||||
},
|
||||
});
|
||||
const actual = await Message.upgradeSchema(input, context);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
context('with multiple upgrade steps', () => {
|
||||
it('should return last valid message when any upgrade step fails', async () => {
|
||||
const input = getDefaultMessage({
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.APPLICATION_JSON,
|
||||
fileName: 'test\u202Dfig.exe',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
body: 'start',
|
||||
schemaVersion: 0,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.APPLICATION_JSON,
|
||||
fileName: 'test\u202Dfig.exe',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
body: 'start +1',
|
||||
schemaVersion: 1,
|
||||
});
|
||||
|
||||
const v1 = async (message: MessageAttributesType) => ({
|
||||
...message,
|
||||
body: `${message.body} +1`,
|
||||
});
|
||||
const v2 = async () => {
|
||||
throw new Error('boom');
|
||||
};
|
||||
const v3 = async (message: MessageAttributesType) => ({
|
||||
...message,
|
||||
body: `${message.body} +3`,
|
||||
});
|
||||
|
||||
const toVersion1 = Message._withSchemaVersion({
|
||||
schemaVersion: 1,
|
||||
upgrade: v1,
|
||||
});
|
||||
const toVersion2 = Message._withSchemaVersion({
|
||||
schemaVersion: 2,
|
||||
upgrade: v2,
|
||||
});
|
||||
const toVersion3 = Message._withSchemaVersion({
|
||||
schemaVersion: 3,
|
||||
upgrade: v3,
|
||||
});
|
||||
|
||||
const context = getDefaultContext({ logger });
|
||||
const upgradeSchema = async (message: MessageAttributesType) =>
|
||||
toVersion3(
|
||||
await toVersion2(await toVersion1(message, context), context),
|
||||
context
|
||||
);
|
||||
|
||||
const actual = await upgradeSchema(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should skip out-of-order upgrade steps', async () => {
|
||||
const input = getDefaultMessage({
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.APPLICATION_JSON,
|
||||
fileName: 'test\u202Dfig.exe',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
body: 'start',
|
||||
schemaVersion: 0,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.APPLICATION_JSON,
|
||||
fileName: 'test\u202Dfig.exe',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
body: 'start +1 +2',
|
||||
schemaVersion: 2,
|
||||
});
|
||||
|
||||
const v1 = async (message: MessageAttributesType) => ({
|
||||
...message,
|
||||
body: `${message.body} +1`,
|
||||
});
|
||||
const v2 = async (message: MessageAttributesType) => ({
|
||||
...message,
|
||||
body: `${message.body} +2`,
|
||||
});
|
||||
const v3 = async (message: MessageAttributesType) => ({
|
||||
...message,
|
||||
body: `${message.body} +3`,
|
||||
});
|
||||
|
||||
const toVersion1 = Message._withSchemaVersion({
|
||||
schemaVersion: 1,
|
||||
upgrade: v1,
|
||||
});
|
||||
const toVersion2 = Message._withSchemaVersion({
|
||||
schemaVersion: 2,
|
||||
upgrade: v2,
|
||||
});
|
||||
const toVersion3 = Message._withSchemaVersion({
|
||||
schemaVersion: 3,
|
||||
upgrade: v3,
|
||||
});
|
||||
|
||||
const context = getDefaultContext({ logger });
|
||||
const atVersion1 = await toVersion1(input, context);
|
||||
|
||||
// Note: this will fail to apply and log, since it's jumping two versions up
|
||||
const atVersion3 = await toVersion3(atVersion1, context);
|
||||
|
||||
const actual = await toVersion2(atVersion3, context);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('_withSchemaVersion', () => {
|
||||
it('should require a version number', () => {
|
||||
const toVersionX = () => null;
|
||||
assert.throws(
|
||||
() =>
|
||||
Message._withSchemaVersion({
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
schemaVersion: toVersionX as any,
|
||||
upgrade: () => Promise.resolve(getDefaultMessage()),
|
||||
}),
|
||||
'_withSchemaVersion: schemaVersion is invalid'
|
||||
);
|
||||
});
|
||||
|
||||
it('should require an upgrade function', () => {
|
||||
assert.throws(
|
||||
() =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Message._withSchemaVersion({ schemaVersion: 2, upgrade: 3 as any }),
|
||||
'_withSchemaVersion: upgrade must be a function'
|
||||
);
|
||||
});
|
||||
|
||||
it('should skip upgrading if message has already been upgraded', async () => {
|
||||
const upgrade = async (message: MessageAttributesType) => ({
|
||||
...message,
|
||||
foo: true,
|
||||
});
|
||||
const upgradeWithVersion = Message._withSchemaVersion({
|
||||
schemaVersion: 3,
|
||||
upgrade,
|
||||
});
|
||||
|
||||
const input = getDefaultMessage({
|
||||
id: 'guid-guid-guid-guid',
|
||||
schemaVersion: 4,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
id: 'guid-guid-guid-guid',
|
||||
schemaVersion: 4,
|
||||
});
|
||||
const actual = await upgradeWithVersion(
|
||||
input,
|
||||
getDefaultContext({ logger })
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should return original message if upgrade function throws', async () => {
|
||||
const upgrade = async () => {
|
||||
throw new Error('boom!');
|
||||
};
|
||||
const upgradeWithVersion = Message._withSchemaVersion({
|
||||
schemaVersion: 3,
|
||||
upgrade,
|
||||
});
|
||||
|
||||
const input = getDefaultMessage({
|
||||
id: 'guid-guid-guid-guid',
|
||||
schemaVersion: 0,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
id: 'guid-guid-guid-guid',
|
||||
schemaVersion: 0,
|
||||
});
|
||||
const actual = await upgradeWithVersion(
|
||||
input,
|
||||
getDefaultContext({ logger })
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should return original message if upgrade function returns null', async () => {
|
||||
const upgrade = async () => null;
|
||||
const upgradeWithVersion = Message._withSchemaVersion({
|
||||
schemaVersion: 3,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
upgrade: upgrade as any,
|
||||
});
|
||||
|
||||
const input = getDefaultMessage({
|
||||
id: 'guid-guid-guid-guid',
|
||||
schemaVersion: 0,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
id: 'guid-guid-guid-guid',
|
||||
schemaVersion: 0,
|
||||
});
|
||||
const actual = await upgradeWithVersion(
|
||||
input,
|
||||
getDefaultContext({ logger })
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_mapQuotedAttachments', () => {
|
||||
it('handles message with no quote', async () => {
|
||||
const upgradeAttachment = sinon
|
||||
.stub()
|
||||
.throws(new Error("Shouldn't be called"));
|
||||
const upgradeVersion = Message._mapQuotedAttachments(upgradeAttachment);
|
||||
|
||||
const message = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
});
|
||||
const result = await upgradeVersion(message, getDefaultContext());
|
||||
assert.deepEqual(result, message);
|
||||
});
|
||||
|
||||
it('handles quote with no attachments', async () => {
|
||||
const upgradeAttachment = sinon
|
||||
.stub()
|
||||
.throws(new Error("Shouldn't be called"));
|
||||
const upgradeVersion = Message._mapQuotedAttachments(upgradeAttachment);
|
||||
|
||||
const message = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
quote: {
|
||||
text: 'hey!',
|
||||
id: 34233,
|
||||
isViewOnce: false,
|
||||
messageId: 'message-id',
|
||||
referencedMessageNotFound: false,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} as any,
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
quote: {
|
||||
text: 'hey!',
|
||||
attachments: [],
|
||||
id: 34233,
|
||||
isViewOnce: false,
|
||||
messageId: 'message-id',
|
||||
referencedMessageNotFound: false,
|
||||
},
|
||||
});
|
||||
const result = await upgradeVersion(
|
||||
message,
|
||||
getDefaultContext({ logger })
|
||||
);
|
||||
assert.deepEqual(result, expected);
|
||||
});
|
||||
|
||||
it('handles zero attachments', async () => {
|
||||
const upgradeAttachment = sinon
|
||||
.stub()
|
||||
.throws(new Error("Shouldn't be called"));
|
||||
const upgradeVersion = Message._mapQuotedAttachments(upgradeAttachment);
|
||||
|
||||
const message = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
quote: {
|
||||
text: 'hey!',
|
||||
attachments: [],
|
||||
id: 34233,
|
||||
isViewOnce: false,
|
||||
messageId: 'message-id',
|
||||
referencedMessageNotFound: false,
|
||||
},
|
||||
});
|
||||
const result = await upgradeVersion(
|
||||
message,
|
||||
getDefaultContext({ logger })
|
||||
);
|
||||
assert.deepEqual(result, message);
|
||||
});
|
||||
|
||||
it('handles attachments with no thumbnail', async () => {
|
||||
const upgradeAttachment = sinon
|
||||
.stub()
|
||||
.throws(new Error("Shouldn't be called"));
|
||||
const upgradeVersion = Message._mapQuotedAttachments(upgradeAttachment);
|
||||
|
||||
const message = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
quote: {
|
||||
text: 'hey!',
|
||||
attachments: [
|
||||
{
|
||||
fileName: 'manifesto.txt',
|
||||
contentType: 'text/plain',
|
||||
},
|
||||
],
|
||||
id: 34233,
|
||||
isViewOnce: false,
|
||||
messageId: 'message-id',
|
||||
referencedMessageNotFound: false,
|
||||
},
|
||||
});
|
||||
const result = await upgradeVersion(
|
||||
message,
|
||||
getDefaultContext({ logger })
|
||||
);
|
||||
assert.deepEqual(result, message);
|
||||
});
|
||||
|
||||
it('does not eliminate thumbnails with missing data field', async () => {
|
||||
const upgradeAttachment = sinon
|
||||
.stub()
|
||||
.returns({ fileName: 'processed!' });
|
||||
const upgradeVersion = Message._mapQuotedAttachments(upgradeAttachment);
|
||||
|
||||
const message = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
quote: {
|
||||
text: 'hey!',
|
||||
attachments: [
|
||||
{
|
||||
fileName: 'cat.gif',
|
||||
contentType: 'image/gif',
|
||||
thumbnail: {
|
||||
fileName: 'not yet downloaded!',
|
||||
},
|
||||
},
|
||||
],
|
||||
id: 34233,
|
||||
isViewOnce: false,
|
||||
messageId: 'message-id',
|
||||
referencedMessageNotFound: false,
|
||||
},
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
quote: {
|
||||
text: 'hey!',
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'image/gif',
|
||||
fileName: 'cat.gif',
|
||||
thumbnail: {
|
||||
fileName: 'processed!',
|
||||
},
|
||||
},
|
||||
],
|
||||
id: 34233,
|
||||
isViewOnce: false,
|
||||
messageId: 'message-id',
|
||||
referencedMessageNotFound: false,
|
||||
},
|
||||
});
|
||||
const result = await upgradeVersion(
|
||||
message,
|
||||
getDefaultContext({ logger })
|
||||
);
|
||||
assert.deepEqual(result, expected);
|
||||
});
|
||||
|
||||
it('calls provided async function for each quoted attachment', async () => {
|
||||
const upgradeAttachment = sinon.stub().resolves({
|
||||
path: '/new/path/on/disk',
|
||||
});
|
||||
const upgradeVersion = Message._mapQuotedAttachments(upgradeAttachment);
|
||||
|
||||
const message = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
quote: {
|
||||
text: 'hey!',
|
||||
attachments: [
|
||||
{
|
||||
thumbnail: {
|
||||
data: 'data is here',
|
||||
},
|
||||
},
|
||||
],
|
||||
id: 34233,
|
||||
isViewOnce: false,
|
||||
messageId: 'message-id',
|
||||
referencedMessageNotFound: false,
|
||||
},
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
quote: {
|
||||
text: 'hey!',
|
||||
attachments: [
|
||||
{
|
||||
thumbnail: {
|
||||
path: '/new/path/on/disk',
|
||||
},
|
||||
},
|
||||
],
|
||||
id: 34233,
|
||||
isViewOnce: false,
|
||||
messageId: 'message-id',
|
||||
referencedMessageNotFound: false,
|
||||
},
|
||||
});
|
||||
const result = await upgradeVersion(
|
||||
message,
|
||||
getDefaultContext({ logger })
|
||||
);
|
||||
assert.deepEqual(result, expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_mapContact', () => {
|
||||
it('handles message with no contact field', async () => {
|
||||
const upgradeContact = sinon
|
||||
.stub()
|
||||
.throws(new Error("Shouldn't be called"));
|
||||
const upgradeVersion = Message._mapContact(upgradeContact);
|
||||
|
||||
const message = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
contact: [],
|
||||
});
|
||||
const result = await upgradeVersion(message, getDefaultContext());
|
||||
assert.deepEqual(result, expected);
|
||||
});
|
||||
|
||||
it('handles one contact', async () => {
|
||||
const upgradeContact = (contact: EmbeddedContactType) =>
|
||||
Promise.resolve(contact);
|
||||
const upgradeVersion = Message._mapContact(upgradeContact);
|
||||
|
||||
const message = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
contact: [
|
||||
{
|
||||
name: {
|
||||
displayName: 'Someone somewhere',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
body: 'hey there!',
|
||||
contact: [
|
||||
{
|
||||
name: {
|
||||
displayName: 'Someone somewhere',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const result = await upgradeVersion(message, getDefaultContext());
|
||||
assert.deepEqual(result, expected);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -4,15 +4,29 @@
|
|||
import { assert } from 'chai';
|
||||
|
||||
import * as Message from '../../../types/message/initializeAttachmentMetadata';
|
||||
import type { IncomingMessage } from '../../../types/Message';
|
||||
import { SignalService } from '../../../protobuf';
|
||||
import * as MIME from '../../../types/MIME';
|
||||
import * as Bytes from '../../../Bytes';
|
||||
import type { MessageAttributesType } from '../../../model-types.d';
|
||||
|
||||
function getDefaultMessage(
|
||||
props?: Partial<MessageAttributesType>
|
||||
): MessageAttributesType {
|
||||
return {
|
||||
id: 'some-id',
|
||||
type: 'incoming',
|
||||
sent_at: 45,
|
||||
received_at: 45,
|
||||
timestamp: 45,
|
||||
conversationId: 'some-conversation-id',
|
||||
...props,
|
||||
};
|
||||
}
|
||||
|
||||
describe('Message', () => {
|
||||
describe('initializeAttachmentMetadata', () => {
|
||||
it('should classify visual media attachments', async () => {
|
||||
const input: IncomingMessage = {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -27,8 +41,8 @@ describe('Message', () => {
|
|||
size: 1111,
|
||||
},
|
||||
],
|
||||
};
|
||||
const expected: IncomingMessage = {
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -46,14 +60,14 @@ describe('Message', () => {
|
|||
hasAttachments: 1,
|
||||
hasVisualMediaAttachments: 1,
|
||||
hasFileAttachments: undefined,
|
||||
};
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should classify file attachments', async () => {
|
||||
const input: IncomingMessage = {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -68,8 +82,8 @@ describe('Message', () => {
|
|||
size: 1111,
|
||||
},
|
||||
],
|
||||
};
|
||||
const expected: IncomingMessage = {
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -87,14 +101,14 @@ describe('Message', () => {
|
|||
hasAttachments: 1,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: 1,
|
||||
};
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should classify voice message attachments', async () => {
|
||||
const input: IncomingMessage = {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -110,8 +124,8 @@ describe('Message', () => {
|
|||
size: 1111,
|
||||
},
|
||||
],
|
||||
};
|
||||
const expected: IncomingMessage = {
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -130,14 +144,14 @@ describe('Message', () => {
|
|||
hasAttachments: 1,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: undefined,
|
||||
};
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('does not include long message attachments', async () => {
|
||||
const input: IncomingMessage = {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -152,8 +166,8 @@ describe('Message', () => {
|
|||
size: 1111,
|
||||
},
|
||||
],
|
||||
};
|
||||
const expected: IncomingMessage = {
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -171,14 +185,14 @@ describe('Message', () => {
|
|||
hasAttachments: 0,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: undefined,
|
||||
};
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('handles not attachments', async () => {
|
||||
const input: IncomingMessage = {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -186,8 +200,8 @@ describe('Message', () => {
|
|||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [],
|
||||
};
|
||||
const expected: IncomingMessage = {
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
|
@ -198,7 +212,7 @@ describe('Message', () => {
|
|||
hasAttachments: 0,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: undefined,
|
||||
};
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue