From 32015eeab6126678d6bec967e5af66aac49cde2d Mon Sep 17 00:00:00 2001 From: Vincent Date: Fri, 26 Jun 2020 03:10:25 +1000 Subject: [PATCH] ptests --- integration_test/integration_test.js | 20 ++- js/modules/data.d.ts | 2 +- ts/session/sending/MessageQueue.ts | 1 - .../utils/.syncthing.SyncMessage.js.map.tmp | 1 + ts/test/session/utils/Promise_test.ts | 117 ++++++++++++-- .../.syncthing.testUtils.js.map.tmp | 1 + .../test-utils/.syncthing.testUtils.js.tmp | 145 ++++++++++++++++++ 7 files changed, 263 insertions(+), 24 deletions(-) create mode 100644 ts/session/utils/.syncthing.SyncMessage.js.map.tmp create mode 100644 ts/test/test-utils/.syncthing.testUtils.js.map.tmp create mode 100644 ts/test/test-utils/.syncthing.testUtils.js.tmp diff --git a/integration_test/integration_test.js b/integration_test/integration_test.js index 7a0208eea..e37cac9ae 100644 --- a/integration_test/integration_test.js +++ b/integration_test/integration_test.js @@ -6,17 +6,15 @@ const { before } = require('mocha'); const common = require('./common'); -// require('./registration_test'); -// require('./open_group_test'); -// require('./add_friends_test'); -// require('./link_device_test'); -// require('./closed_group_test'); -// require('./message_functions_test'); -// require('./settings_test'); -// require('./message_sync_test'); -// require('./sender_keys_test'); - -require('./utils/sync_message_test'); +require('./registration_test'); +require('./open_group_test'); +require('./add_friends_test'); +require('./link_device_test'); +require('./closed_group_test'); +require('./message_functions_test'); +require('./settings_test'); +require('./message_sync_test'); +require('./sender_keys_test'); before(async () => { // start the app once before all tests to get the platform-dependent diff --git a/js/modules/data.d.ts b/js/modules/data.d.ts index d91ecb45a..711cb0a29 100644 --- a/js/modules/data.d.ts +++ b/js/modules/data.d.ts @@ -233,7 +233,7 @@ export function saveSeenMessageHash(data: { hash: string; }): Promise; -// TODO: Strictly export type the following +// TODO: Strictly type the following export function updateLastHash(data: any): Promise; export function saveSeenMessageHashes(data: any): Promise; export function saveLegacyMessage(data: any): Promise; diff --git a/ts/session/sending/MessageQueue.ts b/ts/session/sending/MessageQueue.ts index e5780456a..457506d28 100644 --- a/ts/session/sending/MessageQueue.ts +++ b/ts/session/sending/MessageQueue.ts @@ -21,7 +21,6 @@ import { PubKey } from '../types'; import { MessageSender } from '.'; import { MultiDeviceProtocol, SessionProtocol } from '../protocols'; import { UserUtil } from '../../util'; -import promise from 'redux-promise-middleware'; export class MessageQueue implements MessageQueueInterface { public readonly events: TypedEventEmitter; diff --git a/ts/session/utils/.syncthing.SyncMessage.js.map.tmp b/ts/session/utils/.syncthing.SyncMessage.js.map.tmp new file mode 100644 index 000000000..657d07ed5 --- /dev/null +++ b/ts/session/utils/.syncthing.SyncMessage.js.map.tmp @@ -0,0 +1 @@ +{"version":3,"file":"SyncMessage.js","sourceRoot":"","sources":["SyncMessage.ts"],"names":[],"mappings":";;;;;;;;;AAAA,0CAA4B;AAC5B,qCAAsC;AACtC,mDAA+D;AAC/D,mDAAmE;AACnE,4CAAmD;AAEnD,SAAgB,aAAa,CAC3B,OAAuB;IAEvB,IAAI,OAAO,YAAY,sBAAW,EAAE;QAClC,OAAO,OAAO,CAAC;KAChB;IAED,kBAAkB;IAClB,OAAO,SAAS,CAAC;AACnB,CAAC;AATD,sCASC;AAED,SAAgB,OAAO,CAAC,OAAuB;IAC7C,oEAAoE;IACpE,8BAA8B;IAE9B,kBAAkB;IAClB,OAAO,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;AACzC,CAAC;AAND,0BAMC;AAEM,KAAK,UAAU,eAAe;IACnC,MAAM,UAAU,GAAG,MAAM,eAAQ,CAAC,sBAAsB,EAAE,CAAC;IAE3D,IAAI,CAAC,UAAU,EAAE;QACf,OAAO,EAAE,CAAC;KACX;IAED,MAAM,aAAa,GAAG,MAAM,+BAAmB,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC7E,MAAM,aAAa,GAAG,MAAM,0BAAmB,CAAC;QAC9C,sBAAsB,EAAE,MAAM,CAAC,OAAO,CAAC,sBAAsB;KAC9D,CAAC,CAAC;IAEH,wCAAwC;IACxC,MAAM,eAAe,GACnB,aAAa,CAAC,MAAM,CAClB,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,SAAS,EAAE;QACb,CAAC,CAAC,CAAC,gBAAgB,EAAE;QACrB,CAAC,CAAC,CAAC,SAAS,EAAE;QACd,CAAC,CAAC,CAAC,UAAU,CAAC,eAAe,CAChC,IAAI,EAAE,CAAC;IAEV,MAAM,wBAAwB,GAAG,aAAa,CAAC,MAAM,CACnD,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,SAAS,EAAE;QACb,CAAC,CAAC,CAAC,gBAAgB,EAAE;QACrB,CAAC,CAAC,CAAC,SAAS,EAAE;QACd,CAAC,CAAC,UAAU,CAAC,eAAe,CAC/B,CAAC;IAEF,MAAM,wBAAwB,GAAG,wBAAwB,CAAC,GAAG,CAAC,KAAK,EAAC,CAAC,EAAC,EAAE,CACtE,MAAM,CAAC,sBAAsB,CAAC,kBAAkB,CAC9C,CAAC,CAAC,sBAAsB,EAAE,EAC1B,SAAS,CACV,CACF,CAAC;IAEF,MAAM,iBAAiB,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACrE,kDAAkD;SACjD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,aAAa,CAAC,GAAG,CAAC,CAAC;IAE3C,yBAAyB;IACzB,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,eAAe,EAAE,GAAG,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;AACpE,CAAC;AA3CD,0CA2CC"} \ No newline at end of file diff --git a/ts/test/session/utils/Promise_test.ts b/ts/test/session/utils/Promise_test.ts index 229f64873..2ea801a80 100644 --- a/ts/test/session/utils/Promise_test.ts +++ b/ts/test/session/utils/Promise_test.ts @@ -1,11 +1,7 @@ import chai from 'chai'; import * as sinon from 'sinon'; -import { PubKey } from '../../../session/types/'; -import { SyncMessageUtils } from '../../../session/utils/'; -import { SyncMessage } from '../../../session/messages/outgoing'; -import { TestUtils } from '../../test-utils'; -import { UserUtil } from '../../../util'; +import { PromiseUtils } from '../../../session/utils/'; // tslint:disable-next-line: no-require-imports no-var-requires const chaiAsPromised = require('chai-as-promised'); @@ -14,21 +10,120 @@ chai.use(chaiAsPromised); const { expect } = chai; describe('Promise Utils', () => { + const sandbox = sinon.createSandbox(); + let pollSpy: sinon.SinonSpy; + let waitForTaskSpy: sinon.SinonSpy; + let waitUntilSpy: sinon.SinonSpy; + + beforeEach(() => { + pollSpy = sandbox.spy(PromiseUtils, 'poll'); + waitForTaskSpy = sandbox.spy(PromiseUtils, 'waitForTask'); + waitUntilSpy = sandbox.spy(PromiseUtils, 'waitUntil'); + }); + + afterEach(() => { + sandbox.restore(); + }); + describe('poll', () => { - it('', async () => { - // + it('will call done on finished', async () => { + // completionSpy will be called on done + const completionSpy = sandbox.spy(); + + // tslint:disable-next-line: mocha-unneeded-done + const task = (done: any) => { + completionSpy(); + done(); + }; + + const promise = PromiseUtils.poll(task, {}); + + await expect(promise).to.be.fulfilled; + expect(pollSpy.callCount).to.equal(1); + expect(completionSpy.callCount).to.equal(1); + }); + + it('can timeout a task', async () => { + // completionSpy will be called on done + const completionSpy = sandbox.spy(); + const task = (_done: any) => undefined; + + const promise = PromiseUtils.poll(task, {timeout: 1}); + + await expect(promise).to.be.rejectedWith('Periodic check timeout'); + expect(pollSpy.callCount).to.equal(1); + expect(completionSpy.callCount).to.equal(0); + }); + + it('will recur according to interval option', async () => { + const expectedRecurrences = 4; + const timeout = 1000; + const interval = timeout / expectedRecurrences; + + const recurrenceSpy = sandbox.spy(); + const task = (done: any) => { + recurrenceSpy(); + + // Done after we've been called `expectedRecurrences` times + if (recurrenceSpy.callCount === expectedRecurrences) { + done(); + } + }; + + const promise = PromiseUtils.poll(task, {timeout, interval}); + + await expect(promise).to.be.fulfilled; + expect(pollSpy.callCount).to.equal(1); + expect(recurrenceSpy.callCount).to.equal(expectedRecurrences); }); }); describe('waitForTask', () => { - it('', async () => { - // + it('can wait for a task', async () => { + // completionSpy will be called on done + const completionSpy = sandbox.spy(); + + // tslint:disable-next-line: mocha-unneeded-done + const task = (done: any) => { + completionSpy(); + done(); + }; + + const promise = PromiseUtils.waitForTask(task); + + await expect(promise).to.be.fulfilled; + expect(waitForTaskSpy.callCount).to.equal(1); + expect(completionSpy.callCount).to.equal(1); + }); + + it('can timeout a task', async () => { + // completionSpy will be called on done + const completionSpy = sandbox.spy(); + const task = async (_done: any) => undefined; + + const promise = PromiseUtils.waitForTask(task, 1); + + await expect(promise).to.be.rejectedWith('Task timed out.'); + expect(waitForTaskSpy.callCount).to.equal(1); + expect(completionSpy.callCount).to.equal(0); }); }); describe('waitUntil', () => { - it('', async () => { - // + it('can wait for check', async () => { + const check = () => true; + const promise = PromiseUtils.waitUntil(check); + + await expect(promise).to.be.fulfilled; + expect(waitUntilSpy.callCount).to.equal(1); + }); + + it('can timeout a check', async () => { + const check = () => false; + const promise = PromiseUtils.waitUntil(check, 1); + + await expect(promise).to.be.rejectedWith('Periodic check timeout'); + expect(waitUntilSpy.callCount).to.equal(1); }); }); }); diff --git a/ts/test/test-utils/.syncthing.testUtils.js.map.tmp b/ts/test/test-utils/.syncthing.testUtils.js.map.tmp new file mode 100644 index 000000000..4b666e271 --- /dev/null +++ b/ts/test/test-utils/.syncthing.testUtils.js.map.tmp @@ -0,0 +1 @@ +{"version":3,"file":"testUtils.js","sourceRoot":"","sources":["testUtils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ts/test/test-utils/.syncthing.testUtils.js.tmp b/ts/test/test-utils/.syncthing.testUtils.js.tmp new file mode 100644 index 000000000..b4b3fd08c --- /dev/null +++ b/ts/test/test-utils/.syncthing.testUtils.js.tmp @@ -0,0 +1,145 @@ +"use strict"; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const sinon = __importStar(require("sinon")); +const crypto = __importStar(require("crypto")); +const uuid_1 = require("uuid"); +const types_1 = require("../../../ts/session/types"); +const outgoing_1 = require("../../session/messages/outgoing"); +const _1 = require("."); +const globalAny = global; +const sandbox = sinon.createSandbox(); +// We have to do this in a weird way because Data uses module.exports +// which doesn't play well with sinon or ImportMock +// tslint:disable-next-line: no-require-imports no-var-requires +const Data = require('../../../js/modules/data'); +/** + * Stub a function inside Data. + * + * Note: This uses a custom sandbox. + * Please call `restoreStubs()` or `stub.restore()` to restore original functionality. + */ +function stubData(fn) { + return sandbox.stub(Data, fn); +} +exports.stubData = stubData; +/** + * Stub a window object. + * + * Note: This uses a custom sandbox. + * Please call `restoreStubs()` or `stub.restore()` to restore original functionality. + */ +function stubWindow(fn, value) { + // tslint:disable-next-line: no-typeof-undefined + if (typeof globalAny.window === 'undefined') { + globalAny.window = {}; + } + const set = (newValue) => { + globalAny.window[fn] = newValue; + }; + const get = () => { + return globalAny.window[fn]; + }; + globalAny.window[fn] = value; + return { + get, + set, + }; +} +exports.stubWindow = stubWindow; +function restoreStubs() { + globalAny.window = undefined; + sandbox.restore(); +} +exports.restoreStubs = restoreStubs; +function generateFakePubKey() { + // Generates a mock pubkey for testing + const numBytes = types_1.PubKey.PUBKEY_LEN / 2 - 1; + const hexBuffer = crypto.randomBytes(numBytes).toString('hex'); + const pubkeyString = `05${hexBuffer}`; + return new types_1.PubKey(pubkeyString); +} +exports.generateFakePubKey = generateFakePubKey; +function generateFakePubKeys(amount) { + const numPubKeys = amount > 0 ? Math.floor(amount) : 0; + // tslint:disable-next-line: no-unnecessary-callback-wrapper + return new Array(numPubKeys).fill(0).map(() => generateFakePubKey()); +} +exports.generateFakePubKeys = generateFakePubKeys; +function generateChatMessage(identifier) { + return new outgoing_1.ChatMessage({ + body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', + identifier: (identifier !== null && identifier !== void 0 ? identifier : uuid_1.v4()), + timestamp: Date.now(), + attachments: undefined, + quote: undefined, + expireTimer: undefined, + lokiProfile: undefined, + preview: undefined, + }); +} +exports.generateChatMessage = generateChatMessage; +function generateOpenGroupMessage() { + const group = new types_1.OpenGroup({ + server: 'chat.example.server', + channel: 0, + conversationId: '0', + }); + return new outgoing_1.OpenGroupMessage({ + timestamp: Date.now(), + group, + attachments: undefined, + preview: undefined, + body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', + quote: undefined, + }); +} +exports.generateOpenGroupMessage = generateOpenGroupMessage; +function generateClosedGroupMessage(groupId) { + return new outgoing_1.ClosedGroupChatMessage({ + identifier: uuid_1.v4(), + groupId: (groupId !== null && groupId !== void 0 ? groupId : generateFakePubKey().key), + chatMessage: generateChatMessage(), + }); +} +exports.generateClosedGroupMessage = generateClosedGroupMessage; +class MockPrivateConversation { + constructor(params) { + var _a; + const dayInSeconds = 86400; + this.isPrimary = params.isPrimary; + this.id = (_a = params.id, (_a !== null && _a !== void 0 ? _a : _1.TestUtils.generateFakePubKey().key)); + this.attributes = { + members: [], + left: false, + expireTimer: dayInSeconds, + profileSharing: true, + mentionedUs: false, + unreadCount: 99, + isArchived: false, + active_at: Date.now(), + timestamp: Date.now(), + secondaryStatus: !this.isPrimary, + }; + } + isPrivate() { + return true; + } + isOurLocalDevice() { + return false; + } + isBlocked() { + return false; + } + getPrimaryDevicePubKey() { + return this.isPrimary ? this.id : _1.TestUtils.generateFakePubKey().key; + } +} +exports.MockPrivateConversation = MockPrivateConversation; +//# sourceMappingURL=testUtils.js.map \ No newline at end of file