/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ const { ReceiptType } = ChromeUtils.importESModule( "resource:///modules/matrix-sdk.sys.mjs" ); const kSendReadPref = "purple.conversations.im.send_read"; loadMatrix(); add_task(function test_whenDisplayed() { const mockConv = { _account: { _client: { sendReadReceipt(event, receiptType) { mockConv.readEvent = event; mockConv.receiptType = receiptType; return Promise.resolve(); }, }, }, }; const message = new MatrixMessage( "foo", "bar", { event: "baz", }, mockConv ); message.whenDisplayed(); equal(mockConv.readEvent, "baz"); equal( mockConv.receiptType, message.hideReadReceipts ? ReceiptType.ReadPrivate : ReceiptType.Read ); mockConv.readEvent = false; message.whenDisplayed(); ok(!mockConv.readEvent); }); add_task(async function test_whenDisplayedError() { let resolveError; const errorPromise = new Promise(resolve => { resolveError = resolve; }); const readReceiptRejection = "foo bar"; const mockConv = { ERROR(error) { resolveError(error); }, _account: { _client: { sendReadReceipt() { return Promise.reject(readReceiptRejection); }, }, }, }; const message = new MatrixMessage( "foo", "bar", { event: "baz", }, mockConv ); message.whenDisplayed(); const error = await errorPromise; equal(error, readReceiptRejection); }); add_task(function test_whenRead() { const mockConv = { _roomId: "lorem", _account: { _client: { setRoomReadMarkers(roomId, eventId) { mockConv.readRoomId = roomId; mockConv.readEventId = eventId; return Promise.resolve(); }, }, }, }; const message = new MatrixMessage( "foo", "bar", { event: { getId() { return "baz"; }, }, }, mockConv ); message.whenRead(); equal(mockConv.readEventId, "baz"); equal(mockConv.readRoomId, "lorem"); mockConv.readEventId = false; message.whenRead(); ok(!mockConv.readEventId); }); add_task(async function test_whenReadError() { let resolveError; const errorPromise = new Promise(resolve => { resolveError = resolve; }); const readReceiptRejection = "foo bar"; const mockConv = { ERROR(error) { resolveError(error); }, _account: { _client: { setRoomReadMarkers() { return Promise.reject(readReceiptRejection); }, }, }, }; const message = new MatrixMessage( "foo", "bar", { event: { getId() { return "baz"; }, }, }, mockConv ); message.whenRead(); const error = await errorPromise; equal(error, readReceiptRejection); }); add_task(async function test_whenDisplayedNoEvent() { const message = new MatrixMessage("foo", "bar", { system: true, }); message.whenDisplayed(); ok(!message._displayed); }); add_task(async function test_whenReadNoEvent() { const message = new MatrixMessage("foo", "bar", { system: true, }); message.whenRead(); ok(!message._read); }); add_task(async function test_hideReadReceipts() { const message = new MatrixMessage("foo", "bar", {}); const initialSendRead = Services.prefs.getBoolPref(kSendReadPref); strictEqual(message.hideReadReceipts, !initialSendRead); Services.prefs.setBoolPref(kSendReadPref, !initialSendRead); const message2 = new MatrixMessage("lorem", "ipsum", {}); strictEqual(message2.hideReadReceipts, initialSendRead); strictEqual(message.hideReadReceipts, !initialSendRead); Services.prefs.setBoolPref(kSendReadPref, initialSendRead); }); add_task(async function test_getActions() { const event = makeEvent({ type: MatrixSDK.EventType.RoomMessage, }); const message = new MatrixMessage( "foo", "bar", { event }, { roomState: { maySendRedactionForEvent() { return false; }, }, } ); const actions = message.getActions(); ok(Array.isArray(actions)); equal(actions.length, 0); }); add_task(async function test_getActions_decryptionFailure() { const event = makeEvent({ type: MatrixSDK.EventType.RoomMessage, content: { msgtype: "m.bad.encrypted", }, }); let eventKeysWereRequestedFor; const message = new MatrixMessage( "foo", "bar", { event }, { _account: { _client: { cancelAndResendEventRoomKeyRequest(matrixEvent) { eventKeysWereRequestedFor = matrixEvent; return Promise.resolve(); }, }, }, roomState: { maySendRedactionForEvent() { return false; }, }, } ); const actions = message.getActions(); ok(Array.isArray(actions)); equal(actions.length, 1); const [action] = actions; ok(action.label); action.run(); strictEqual(eventKeysWereRequestedFor, event); }); add_task(async function test_getActions_redact() { const event = makeEvent({ type: MatrixSDK.EventType.RoomMessage, content: { msgtype: MatrixSDK.MsgType.Text, body: "foo bar", }, roomId: "!actions:example.com", threadRootId: "$thread:example.com", id: "$ev:example.com", }); let eventRedacted = false; const message = new MatrixMessage( "foo", "bar", { event }, { _account: { userId: 0, _client: { redactEvent(roomId, threadRootId, eventId) { equal(roomId, "!actions:example.com"); equal(threadRootId, "$thread:example.com"); equal(eventId, "$ev:example.com"); eventRedacted = true; return Promise.resolve(); }, }, }, roomState: { maySendRedactionForEvent(ev, userId) { equal(ev, event); equal(userId, 0); return true; }, }, } ); const actions = message.getActions(); ok(Array.isArray(actions)); equal(actions.length, 1); const [action] = actions; ok(action.label); action.run(); ok(eventRedacted); }); add_task(async function test_getActions_noEvent() { const message = new MatrixMessage("system", "test", { system: true, }); const actions = message.getActions(); ok(Array.isArray(actions)); deepEqual(actions, []); }); add_task(async function test_getActions_report() { const event = makeEvent({ type: MatrixSDK.EventType.RoomMessage, content: { msgtype: MatrixSDK.MsgType.Text, body: "lorem ipsum", }, roomId: "!actions:example.com", id: "$ev:example.com", }); let eventReported = false; const message = new MatrixMessage( "user", "lorem ipsum", { event, incoming: true }, { _account: { _client: { reportEvent(roomId, eventId, score, reason) { equal(roomId, "!actions:example.com"); equal(eventId, "$ev:example.com"); equal(score, -100); equal(reason, ""); eventReported = true; return Promise.resolve(); }, }, }, roomState: { maySendRedactionForEvent(ev, userId) { return false; }, }, } ); const actions = message.getActions(); ok(Array.isArray(actions)); const [action] = actions; ok(action.label); action.run(); ok(eventReported); }); add_task(async function test_getActions_notSent() { let resendCalled = false; let cancelCalled = false; const event = makeEvent({ status: MatrixSDK.EventStatus.NOT_SENT, type: MatrixSDK.EventType.RoomMessage, content: { msgtype: MatrixSDK.MsgType.Text, body: "foo bar", }, }); const message = new MatrixMessage( "!test:example.com", "Error sending message", { event, error: true, }, { _account: { _client: { resendEvent(ev, room) { equal(ev, event); ok(room); resendCalled = true; }, cancelPendingEvent(ev) { equal(ev, event); cancelCalled = true; }, }, }, roomState: { maySendRedactionForEvent(ev, userId) { return false; }, }, room: {}, } ); const actions = message.getActions(); ok(Array.isArray(actions)); equal(actions.length, 2); const [retryAction, cancelAction] = actions; ok(retryAction.label); ok(cancelAction.label); retryAction.run(); ok(resendCalled); ok(!cancelCalled); cancelAction.run(); ok(cancelCalled); }); add_task(function test_whenDisplayedUnsent() { const mockConv = { _account: { _client: { sendReadReceipt(event, options) { ok(false, "Should not send read receipt for unsent event"); }, }, }, }; const message = new MatrixMessage( "foo", "bar", { event: makeEvent({ status: MatrixSDK.EventStatus.NOT_SENT, }), }, mockConv ); message.whenDisplayed(); ok(!message._displayed); }); add_task(function test_whenReadUnsent() { const mockConv = { _account: { _client: { setRoomReadMarkers(event, options) { ok(false, "Should not send read marker for unsent event"); }, }, }, }; const message = new MatrixMessage( "foo", "bar", { event: makeEvent({ status: MatrixSDK.EventStatus.NOT_SENT, }), }, mockConv ); message.whenRead(); ok(!message._read); });