diff --git a/js/models/conversations.js b/js/models/conversations.js index b5766a723..9dc3ea3ba 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -135,6 +135,8 @@ this.on('read', this.updateLastMessage); this.on('sent', this.updateLastMessage); this.on('expired', this.onExpired); + + this.updateLastMessage(); }, isMe() { @@ -198,8 +200,8 @@ isSelected: this.isSelected, lastMessage: { - status: this.get('lastMessageStatus'), - text: this.get('lastMessage'), + status: this.lastMessageStatus, + text: this.lastMessage, }, onClick: () => this.trigger('select', this), @@ -899,6 +901,10 @@ }, async updateLastMessage() { + if (!this.id) { + return; + } + const messages = await window.Signal.Data.getMessagesByConversation( this.id, { limit: 1, MessageCollection: Whisper.MessageCollection } @@ -907,26 +913,41 @@ return; } - const lastMessage = messages.at(0); + const lastMessageModel = messages.at(0); - const lastMessageJSON = lastMessage ? lastMessage.toJSON() : null; - const lastMessageStatus = lastMessage - ? lastMessage.getMessagePropStatus() + const lastMessageJSON = lastMessageModel + ? lastMessageModel.toJSON() + : null; + const lastMessageStatusModel = lastMessageModel + ? lastMessageModel.getMessagePropStatus() : null; const lastMessageUpdate = Conversation.createLastMessageUpdate({ currentLastMessageText: this.get('lastMessage') || null, currentTimestamp: this.get('timestamp') || null, lastMessage: lastMessageJSON, - lastMessageStatus, - lastMessageNotificationText: lastMessage - ? lastMessage.getNotificationText() + lastMessageStatus: lastMessageStatusModel, + lastMessageNotificationText: lastMessageModel + ? lastMessageModel.getNotificationText() : null, }); + let hasChanged = false; + const { lastMessage, lastMessageStatus } = lastMessageUpdate; + lastMessageUpdate.lastMessage = null; + lastMessageUpdate.lastMessageStatus = null; + + hasChanged = hasChanged || lastMessage !== this.lastMessage; + this.lastMessage = lastMessage; + + hasChanged = hasChanged || lastMessageStatus !== this.lastMessageStatus; + this.lastMessageStatus = lastMessageStatus; + this.set(lastMessageUpdate); - if (this.hasChanged('lastMessage') || this.hasChanged('timestamp')) { + if (this.hasChanged()) { this.save(); + } else if (hasChanged) { + this.trigger('change'); } }, diff --git a/js/views/conversation_list_item_view.js b/js/views/conversation_list_item_view.js index 530b955c5..7b7618b3d 100644 --- a/js/views/conversation_list_item_view.js +++ b/js/views/conversation_list_item_view.js @@ -15,7 +15,6 @@ templateName: 'conversation-preview', initialize() { this.listenTo(this.model, 'destroy', this.remove); - this.model.updateLastMessage(); }, remove() { diff --git a/test/_test.js b/test/_test.js index e03fadb2a..b3315a797 100644 --- a/test/_test.js +++ b/test/_test.js @@ -60,25 +60,26 @@ function hexToArrayBuffer(str) { return ret; } -/* Delete the database before running any tests */ -before(function(done) { - var idbReq = indexedDB.deleteDatabase('test'); - idbReq.onsuccess = function() { - done(); - }; -}); +function deleteDatabase() { + return new Promise((resolve, reject) => { + var idbReq = indexedDB.deleteDatabase('test'); + idbReq.onsuccess = resolve; + idbReq.error = reject; + }); +} + +/* Delete the database before running any tests */ +before(async () => { + await deleteDatabase(); -async function clearDatabase() { await Signal.Migrations.Migrations0DatabaseWithAttachmentData.run({ Backbone, databaseName: Whisper.Database.id, logger: window.log, }); +}); - const convos = new Whisper.ConversationCollection(); - await wrapDeferred(convos.fetch()); - await wrapDeferred(convos.destroyAll()); - const messages = new Whisper.MessageCollection(); - await wrapDeferred(messages.fetch()); - await wrapDeferred(messages.destroyAll()); +async function clearDatabase() { + const db = await Whisper.Database.open(); + await Whisper.Database.clear(); } diff --git a/test/fixtures_test.js b/test/fixtures_test.js index ecf815ffe..20d4986b5 100644 --- a/test/fixtures_test.js +++ b/test/fixtures_test.js @@ -1,32 +1,26 @@ 'use strict'; describe('Fixtures', function() { - before(function(done) { + before(function() { // NetworkStatusView checks this method every five seconds while showing window.getSocketStatus = function() { return WebSocket.OPEN; }; - - Whisper.Fixtures() - .saveAll() - .then(function() { - done(); - }); }); - it('renders', function(done) { - ConversationController.reset(); - ConversationController.load() - .then(function() { - var view = new Whisper.InboxView({ window: window }); - view.onEmpty(); - view.$el.prependTo($('#render-light-theme')); + it('renders', async () => { + await Whisper.Fixtures().saveAll(); - var view = new Whisper.InboxView({ window: window }); - view.$el.removeClass('light-theme').addClass('dark-theme'); - view.onEmpty(); - view.$el.prependTo($('#render-dark-theme')); - }) - .then(done, done); + ConversationController.reset(); + await ConversationController.load(); + + var view = new Whisper.InboxView({ window: window }); + view.onEmpty(); + view.$el.prependTo($('#render-light-theme')); + + var view = new Whisper.InboxView({ window: window }); + view.$el.removeClass('light-theme').addClass('dark-theme'); + view.onEmpty(); + view.$el.prependTo($('#render-dark-theme')); }); }); diff --git a/test/models/conversations_test.js b/test/models/conversations_test.js index 98066877c..4e52743c2 100644 --- a/test/models/conversations_test.js +++ b/test/models/conversations_test.js @@ -36,15 +36,15 @@ .then(done); }); - it('fetches persistent convos', function(done) { + it('fetches persistent convos', async () => { var convos = new Whisper.ConversationCollection(); assert.strictEqual(convos.length, 0); - convos.fetch().then(function() { - var m = convos.at(0).attributes; - _.each(conversation_attributes, function(val, key) { - assert.deepEqual(m[key], val); - }); - done(); + + await wrapDeferred(convos.fetch()); + + var m = convos.at(0).attributes; + _.each(conversation_attributes, function(val, key) { + assert.deepEqual(m[key], val); }); }); @@ -226,14 +226,18 @@ }); describe('Conversation search', function() { - var convo = new Whisper.ConversationCollection().add({ - id: '+14155555555', - type: 'private', - name: 'John Doe', - }); - before(function(done) { + let convo; + + beforeEach(function(done) { + convo = new Whisper.ConversationCollection().add({ + id: '+14155555555', + type: 'private', + name: 'John Doe', + }); convo.save().then(done); }); + afterEach(clearDatabase); + function testSearch(queries, done) { return Promise.all( queries.map(function(query) { diff --git a/test/views/attachment_view_test.js b/test/views/attachment_view_test.js index 4d8279ab0..fbc1f1f8e 100644 --- a/test/views/attachment_view_test.js +++ b/test/views/attachment_view_test.js @@ -9,6 +9,7 @@ describe('AttachmentView', () => { before(async () => { await clearDatabase(); + convo = new Whisper.Conversation({ id: 'foo' }); message = convo.messageCollection.add({ conversationId: convo.id, diff --git a/test/views/conversation_search_view_test.js b/test/views/conversation_search_view_test.js index 63c26c5e7..98770ee06 100644 --- a/test/views/conversation_search_view_test.js +++ b/test/views/conversation_search_view_test.js @@ -24,20 +24,26 @@ describe('ConversationSearchView', function() { }); }); describe('Searching for left groups', function() { - var convo = new Whisper.ConversationCollection().add({ - id: 'a-left-group', - name: 'i left this group', - members: [], - type: 'group', - left: true, - }); + let convo; + before(() => { + convo = new Whisper.ConversationCollection().add({ + id: 'a-left-group', + name: 'i left this group', + members: [], + type: 'group', + left: true, + }); + return wrapDeferred(convo.save()); }); describe('with no messages', function() { - var input = $(''); - var view = new Whisper.ConversationSearchView({ input: input }).render(); + var input; + var view; + before(function(done) { + input = $(''); + view = new Whisper.ConversationSearchView({ input: input }).render(); view.$input.val('left'); view.filterContacts(); view.typeahead_view.collection.on('reset', function() { @@ -52,9 +58,11 @@ describe('ConversationSearchView', function() { }); }); describe('with messages', function() { - var input = $(''); - var view = new Whisper.ConversationSearchView({ input: input }).render(); + var input; + var view; before(function(done) { + input = $(''); + view = new Whisper.ConversationSearchView({ input: input }).render(); convo.save({ lastMessage: 'asdf' }).then(function() { view.$input.val('left'); view.filterContacts(); @@ -72,17 +80,22 @@ describe('ConversationSearchView', function() { }); }); describe('Showing all contacts', function() { - var input = $(''); - var view = new Whisper.ConversationSearchView({ input: input }).render(); - view.showAllContacts = true; - var convo = new Whisper.ConversationCollection().add({ - id: 'a-left-group', - name: 'i left this group', - members: [], - type: 'group', - left: true, - }); + let input; + let view; + let convo; + before(() => { + input = $(''); + view = new Whisper.ConversationSearchView({ input: input }).render(); + view.showAllContacts = true; + convo = new Whisper.ConversationCollection().add({ + id: 'a-left-group', + name: 'i left this group', + members: [], + type: 'group', + left: true, + }); + return wrapDeferred(convo.save()); }); describe('with no messages', function() { diff --git a/test/views/inbox_view_test.js b/test/views/inbox_view_test.js index 1eb05a7ec..1e834c04b 100644 --- a/test/views/inbox_view_test.js +++ b/test/views/inbox_view_test.js @@ -1,11 +1,19 @@ describe('InboxView', function() { - var inboxView = new Whisper.InboxView({ - model: {}, - window: window, - initialLoadComplete: function() {}, - }).render(); + let inboxView; + let conversation; - var conversation = new Whisper.Conversation({ id: '1234', type: 'private' }); + before(() => { + inboxView = new Whisper.InboxView({ + model: {}, + window: window, + initialLoadComplete: function() {}, + }).render(); + + conversation = new Whisper.Conversation({ + id: '1234', + type: 'private', + }); + }); describe('the conversation stack', function() { it('should be rendered', function() {