import * as sinon from 'sinon'; import * as crypto from 'crypto'; import * as window from '../../window'; import * as DataShape from '../../../js/modules/data'; import { v4 as uuid } from 'uuid'; import { OpenGroup, PubKey } from '../../../ts/session/types'; import { ChatMessage, ClosedGroupChatMessage, OpenGroupMessage, } from '../../session/messages/outgoing'; import { Integer } from '../../types/Util'; import { ConversationModel, ConversationAttributes } from '../../../js/models/conversation'; const globalAny: any = 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'); type DataFunction = typeof DataShape; /** * Stub a function inside Data. * * Note: This uses a custom sandbox. * Please call `restoreStubs()` or `stub.restore()` to restore original functionality. */ export function stubData(fn: K): sinon.SinonStub { return sandbox.stub(Data, fn); } type WindowValue = Partial | undefined; /** * Stub a window object. * * Note: This uses a custom sandbox. * Please call `restoreStubs()` or `stub.restore()` to restore original functionality. */ export function stubWindow( fn: K, value: WindowValue ) { // tslint:disable-next-line: no-typeof-undefined if (typeof globalAny.window === 'undefined') { globalAny.window = {}; } const set = (newValue: WindowValue) => { globalAny.window[fn] = newValue; }; const get = () => { return globalAny.window[fn] as WindowValue; }; globalAny.window[fn] = value; return { get, set, }; } export function restoreStubs() { globalAny.window = undefined; sandbox.restore(); } export function generateFakePubKey(): PubKey { // Generates a mock pubkey for testing const numBytes = PubKey.PUBKEY_LEN / 2 - 1; const hexBuffer = crypto.randomBytes(numBytes).toString('hex'); const pubkeyString = `05${hexBuffer}`; return new PubKey(pubkeyString); } export function generateFakePubKeys(amount: Integer): Array { const numPubKeys = amount > 0 ? Math.floor(amount) : 0; // tslint:disable-next-line: no-unnecessary-callback-wrapper return new Array(amount).fill(0).map(() => generateFakePubKey()); } export function generateChatMessage(identifier?: string): ChatMessage { return new ChatMessage({ body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', identifier: identifier ?? uuid(), timestamp: Date.now(), attachments: undefined, quote: undefined, expireTimer: undefined, lokiProfile: undefined, preview: undefined, }); } export function generateOpenGroupMessage(): OpenGroupMessage { const group = new OpenGroup({ server: 'chat.example.server', channel: 0, conversationId: '0', }); return new OpenGroupMessage({ timestamp: Date.now(), group, attachments: undefined, preview: undefined, body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', quote: undefined, }); } export function generateClosedGroupMessage( groupId?: string ): ClosedGroupChatMessage { return new ClosedGroupChatMessage({ identifier: uuid(), groupId: groupId ?? generateFakePubKey().key, chatMessage: generateChatMessage(), }); } // Mock ConversationModel export class MockPrivateConversation implements ConversationModel { public id: string; public isPrimary: boolean; public attributes: ConversationAttributes; constructor(isPrimary: boolean) { this.isPrimary = isPrimary; this.id = TestUtils.generateFakePubKey().key; this.attributes = { members } } public isPrivate() { return true; } public isOurLocalDevice() { return false; } public isBlocked() { return false; } public getPrimaryDevicePubKey() { return this.isPrimary ? this.id : TestUtils.generateFakePubKey().key; } } const myconv = new MockPrivateConversation(false) ;