From 04cf441c5ae18400c6b4865b0b37a71718dc9d46 Mon Sep 17 00:00:00 2001 From: Ola Bini Date: Thu, 31 Jul 2014 19:29:33 -0300 Subject: Add web-ui based on previous code --- .../spec/dispatchers/left_pane_dispatcher.spec.js | 79 ++++++ .../dispatchers/middle_pane_dispatchers.spec.js | 27 ++ .../spec/dispatchers/right_pane_dispatcher.spec.js | 90 ++++++ web-ui/test/spec/helpers/view_helper.spec.js | 76 +++++ .../ui/mail_items/generic_mail_item.spec.js | 136 +++++++++ .../spec/mail_list/ui/mail_items/mail_item.spec.js | 40 +++ web-ui/test/spec/mail_list/ui/mail_list.spec.js | 275 ++++++++++++++++++ .../mail_list_actions/ui/compose_trigger.spec.js | 16 ++ .../spec/mail_list_actions/ui/mail_actions.spec.js | 9 + .../ui/pagination_trigger.spec.js | 26 ++ .../test/spec/mail_view/data/mail_builder.spec.js | 110 ++++++++ .../test/spec/mail_view/data/mail_sender.spec.js | 70 +++++ web-ui/test/spec/mail_view/ui/compose_box.spec.js | 132 +++++++++ web-ui/test/spec/mail_view/ui/draft_box.spec.js | 67 +++++ .../spec/mail_view/ui/draft_save_status.spec.js | 26 ++ web-ui/test/spec/mail_view/ui/forward_box.spec.js | 90 ++++++ web-ui/test/spec/mail_view/ui/mail_actions.spec.js | 63 +++++ web-ui/test/spec/mail_view/ui/mail_view.spec.js | 247 +++++++++++++++++ .../mail_view/ui/recipients/recipients.spec.js | 36 +++ .../ui/recipients/recipients_input.spec.js | 104 +++++++ .../ui/recipients/recipients_iterator.spec.js | 101 +++++++ web-ui/test/spec/mail_view/ui/reply_box.spec.js | 105 +++++++ .../test/spec/mail_view/ui/reply_section.spec.js | 97 +++++++ web-ui/test/spec/mail_view/ui/send_button.spec.js | 91 ++++++ .../test/spec/mixins/with_mail_edit_base.spec.js | 94 +++++++ web-ui/test/spec/page/pane_contract_expand.spec.js | 67 +++++ web-ui/test/spec/page/router.spec.js | 70 +++++ web-ui/test/spec/page/router/url_params.spec.js | 68 +++++ web-ui/test/spec/search/search_trigger.spec.js | 78 ++++++ web-ui/test/spec/services/delete_service.spec.js | 54 ++++ web-ui/test/spec/services/mail_service.spec.js | 307 +++++++++++++++++++++ web-ui/test/spec/services/model/mail.spec.js | 116 ++++++++ web-ui/test/spec/tags/data/tags.spec.js | 39 +++ web-ui/test/spec/tags/ui/tag.spec.js | 151 ++++++++++ web-ui/test/spec/tags/ui/tag_list.spec.js | 75 +++++ web-ui/test/spec/tags/ui/tag_shortcut.spec.js | 35 +++ .../test/spec/user_alerts/ui/user_alerts.spec.js | 23 ++ web-ui/test/test-main.js | 57 ++++ web-ui/test/test_data.js | 170 ++++++++++++ 39 files changed, 3517 insertions(+) create mode 100644 web-ui/test/spec/dispatchers/left_pane_dispatcher.spec.js create mode 100644 web-ui/test/spec/dispatchers/middle_pane_dispatchers.spec.js create mode 100644 web-ui/test/spec/dispatchers/right_pane_dispatcher.spec.js create mode 100644 web-ui/test/spec/helpers/view_helper.spec.js create mode 100644 web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js create mode 100644 web-ui/test/spec/mail_list/ui/mail_items/mail_item.spec.js create mode 100644 web-ui/test/spec/mail_list/ui/mail_list.spec.js create mode 100644 web-ui/test/spec/mail_list_actions/ui/compose_trigger.spec.js create mode 100644 web-ui/test/spec/mail_list_actions/ui/mail_actions.spec.js create mode 100644 web-ui/test/spec/mail_list_actions/ui/pagination_trigger.spec.js create mode 100644 web-ui/test/spec/mail_view/data/mail_builder.spec.js create mode 100644 web-ui/test/spec/mail_view/data/mail_sender.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/compose_box.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/draft_box.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/draft_save_status.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/forward_box.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/mail_actions.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/mail_view.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/reply_box.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/reply_section.spec.js create mode 100644 web-ui/test/spec/mail_view/ui/send_button.spec.js create mode 100644 web-ui/test/spec/mixins/with_mail_edit_base.spec.js create mode 100644 web-ui/test/spec/page/pane_contract_expand.spec.js create mode 100644 web-ui/test/spec/page/router.spec.js create mode 100644 web-ui/test/spec/page/router/url_params.spec.js create mode 100644 web-ui/test/spec/search/search_trigger.spec.js create mode 100644 web-ui/test/spec/services/delete_service.spec.js create mode 100644 web-ui/test/spec/services/mail_service.spec.js create mode 100644 web-ui/test/spec/services/model/mail.spec.js create mode 100644 web-ui/test/spec/tags/data/tags.spec.js create mode 100644 web-ui/test/spec/tags/ui/tag.spec.js create mode 100644 web-ui/test/spec/tags/ui/tag_list.spec.js create mode 100644 web-ui/test/spec/tags/ui/tag_shortcut.spec.js create mode 100644 web-ui/test/spec/user_alerts/ui/user_alerts.spec.js create mode 100644 web-ui/test/test-main.js create mode 100644 web-ui/test/test_data.js (limited to 'web-ui/test') diff --git a/web-ui/test/spec/dispatchers/left_pane_dispatcher.spec.js b/web-ui/test/spec/dispatchers/left_pane_dispatcher.spec.js new file mode 100644 index 00000000..fb5b169a --- /dev/null +++ b/web-ui/test/spec/dispatchers/left_pane_dispatcher.spec.js @@ -0,0 +1,79 @@ +/*global Smail */ + +describeComponent('dispatchers/left_pane_dispatcher', function () { + 'use strict'; + + describe('initialize', function () { + it('asks for tags', function () { + var tagWantEvent = spyOnEvent(document, Smail.events.tags.want); + + setupComponent(); + + expect(tagWantEvent).toHaveBeenTriggeredOn(document); + expect(tagWantEvent.mostRecentCall.data.caller[0]).toEqual(this.$node[0]); + }); + }); + + describe('after initialization', function () { + beforeEach(function () { + setupComponent(); + }); + + it('pushes the url state when a tag is selected but not for the first tag', function () { + var pushStateEvent = spyOnEvent(document, Smail.events.router.pushState); + + $(document).trigger(Smail.events.ui.tag.selected, { tag: 'Drafts'}); + $(document).trigger(Smail.events.ui.tag.selected, { tag: 'inbox'}); + + expect(pushStateEvent).toHaveBeenTriggeredOn(document, { tag: 'inbox'}); + }); + + it('fetches mails by tag when a tag is selected', function () { + var fetchByTagEvent = spyOnEvent(document, Smail.events.ui.mails.fetchByTag); + + $(document).trigger(Smail.events.ui.tag.selected, { tag: 'Drafts'}); + + expect(fetchByTagEvent).toHaveBeenTriggeredOn(document, { tag: 'Drafts'}); + }); + + it('doesnt fetch mails by tag when skipMailListRefresh is sent on tag.selected', function () { + var fetchByTagEvent = spyOnEvent(document, Smail.events.ui.mails.fetchByTag); + + $(document).trigger(Smail.events.ui.tag.selected, { tag: 'Drafts', skipMailListRefresh: true}); + + expect(fetchByTagEvent).not.toHaveBeenTriggeredOn(document, { tag: 'Drafts'}); + }); + + it('asks for more tags when refreshTagList is fired', function () { + var tagWantEvent = spyOnEvent(document, Smail.events.tags.want); + + $(document).trigger(Smail.events.dispatchers.tags.refreshTagList); + + expect(tagWantEvent).toHaveBeenTriggeredOn(document); + }); + + it('fires tagLoad when the tags are received', function () { + var tagListLoadEvent = spyOnEvent(document, Smail.events.ui.tagList.load); + + this.$node.trigger(Smail.events.tags.received, { tags: ['tags']}); + + expect(tagListLoadEvent).toHaveBeenTriggeredOn(document, { tags: ['tags']}); + }); + + it('on tags loaded selects the inbox tag if no data is provided', function () { + var selectTagEvent = spyOnEvent(document, Smail.events.ui.tag.select); + + $(document).trigger(Smail.events.ui.tags.loaded); + + expect(selectTagEvent).toHaveBeenTriggeredOnAndWith(document, { tag: 'inbox' }); + }); + + it('on tags loaded selects the a different tag if tag is provided', function () { + var selectTagEvent = spyOnEvent(document, Smail.events.ui.tag.select); + + $(document).trigger(Smail.events.ui.tags.loaded, { tag: 'Drafts' }); + + expect(selectTagEvent).toHaveBeenTriggeredOnAndWith(document, { tag: 'Drafts' }); + }); + }); +}); diff --git a/web-ui/test/spec/dispatchers/middle_pane_dispatchers.spec.js b/web-ui/test/spec/dispatchers/middle_pane_dispatchers.spec.js new file mode 100644 index 00000000..2dd0de2e --- /dev/null +++ b/web-ui/test/spec/dispatchers/middle_pane_dispatchers.spec.js @@ -0,0 +1,27 @@ +/*global Smail */ + +describeComponent('dispatchers/middle_pane_dispatcher', function () { + 'use strict'; + + beforeEach(function() { + setupComponent('
'); + }); + + it ('listens to refresh mail list event', function() { + var mailsListRefreshEventSpy = spyOnEvent(document, Smail.events.ui.mails.fetchByTag); + this.component.trigger(document, Smail.events.dispatchers.middlePane.refreshMailList); + expect(mailsListRefreshEventSpy).toHaveBeenTriggeredOn(document); + }); + + it ('listens to unselect event', function() { + var mailListUnselectEvent = spyOnEvent(document, Smail.events.ui.mails.cleanSelected); + this.component.trigger(document, Smail.events.dispatchers.middlePane.cleanSelected); + expect(mailListUnselectEvent).toHaveBeenTriggeredOn(document); + }); + + it('resets the scrollTop value when asked to', function() { + this.component.select('middlePane').scrollTop(200); + this.component.trigger(document, Smail.events.dispatchers.middlePane.resetScroll); + expect(this.component.select('middlePane').scrollTop()).toEqual(0); + }); +}); diff --git a/web-ui/test/spec/dispatchers/right_pane_dispatcher.spec.js b/web-ui/test/spec/dispatchers/right_pane_dispatcher.spec.js new file mode 100644 index 00000000..5fc7ecd7 --- /dev/null +++ b/web-ui/test/spec/dispatchers/right_pane_dispatcher.spec.js @@ -0,0 +1,90 @@ +/*global Smail */ + +describeComponent('dispatchers/right_pane_dispatcher', function () { + 'use strict'; + + describe('after initialization', function () { + beforeEach(function () { + setupComponent(); + }); + + it('listens to open compose box event and creates a compose box', function () { + var composeBox = require('mail_view/ui/compose_box'); + spyOn(composeBox, 'attachTo'); + + this.component.trigger(document, Smail.events.dispatchers.rightPane.openComposeBox); + + expect(composeBox.attachTo).toHaveBeenCalled(); + }); + + describe('no message selected', function () { + var noMessageSelectedPane; + beforeEach(function () { + noMessageSelectedPane = require('mail_view/ui/no_message_selected_pane'); + spyOn(noMessageSelectedPane, 'attachTo'); + }); + + it('listen to open no message selected event and creates a no-message-selected-pane', function () { + this.component.trigger(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + + expect(noMessageSelectedPane.attachTo).toHaveBeenCalled(); + }); + + it('sends an dispatchers.middlePane.unselect event', function () { + var unselectEvent = spyOnEvent(document, Smail.events.dispatchers.middlePane.cleanSelected); + this.component.trigger(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + + expect(unselectEvent).toHaveBeenTriggeredOn(document); + }); + + it('pushes the current state with the current tag', function () { + var pushStateEvent = spyOnEvent(document, Smail.events.router.pushState); + + this.component.attr.currentTag = 'sometag'; + this.component.trigger(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + + expect(pushStateEvent).toHaveBeenTriggeredOnAndWith(document, jasmine.objectContaining({tag: this.component.attr.currentTag })); + }); + + it('pushes the current state stating that it meant to close the right pane', function () { + var pushStateEvent = spyOnEvent(document, Smail.events.router.pushState); + + this.component.attr.currentTag = 'sometag'; + this.component.trigger(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + + expect(pushStateEvent).toHaveBeenTriggeredOnAndWith(document, jasmine.objectContaining({ isDisplayNoMessageSelected: true })); + }); + + + }); + + it('listens to open a draft and creates it', function () { + var draftBox = require('mail_view/ui/draft_box'); + spyOn(draftBox, 'attachTo'); + + this.component.trigger(document, Smail.events.dispatchers.rightPane.openDraft, { ident: '1' }); + + expect(draftBox.attachTo).toHaveBeenCalled(); + }); + }); + + describe('on initialization', function () { + var noMessageSelectedPane; + + beforeEach(function () { + noMessageSelectedPane = require('mail_view/ui/no_message_selected_pane'); + spyOn(noMessageSelectedPane, 'attachTo'); + }); + + it('opens the no message selected pane but doesnt push the state', function () { + var pushStateEvent = spyOnEvent(document, Smail.events.router.pushState); + + setupComponent(); + + expect(noMessageSelectedPane.attachTo).toHaveBeenCalled(); + expect(pushStateEvent).not.toHaveBeenTriggeredOn(document); + + }); + }); + +}); diff --git a/web-ui/test/spec/helpers/view_helper.spec.js b/web-ui/test/spec/helpers/view_helper.spec.js new file mode 100644 index 00000000..7fa10e56 --- /dev/null +++ b/web-ui/test/spec/helpers/view_helper.spec.js @@ -0,0 +1,76 @@ +/*global Smail */ + +define(['helpers/view_helper'], function (viewHelper) { + 'use strict'; + + var testData; + describe('view helper', function() { + beforeEach(function () { + testData = Smail.testData(); + }); + + describe('quote email', function() { + it('should add > to body text', function() { + testData.rawMail.mail.body = 'First Line\nSecond Line'; + + var quotedMail = viewHelper.quoteMail(testData.rawMail.mail); + + expect(quotedMail).toContain('> First Line\n> Second Line'); + }); + }); + + describe('getFormmattedDate', function() { + it('formats correctly a Date for today', function() { + var d = new Date(); + var dtest = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 14, 2, 36); + + var res = viewHelper.getFormattedDate(dtest); + + expect(res).toEqual('14:02'); + + }); + + it('formats correctly a Date for a specific day', function() { + var dtest = new Date(2013, 2, 13, 7, 56, 1); + + var res = viewHelper.getFormattedDate(dtest); + + // This expectation is weird for the month - JS Dates have date numbers be zero-indexed, thus the discrepency + // Specifically, the 2 in the constructor DOES match the 3 in the expectation below. + expect(res).toEqual('2013-03-13'); + }); + }); + + describe('format status classes', function () { + it('formats all the status of the email to css classes', function () { + var statuses = ['read', 'banana']; + + expect(viewHelper.formatStatusClasses(statuses)).toEqual('status-read status-banana'); + }); + + it('formats a single status of the email to a css class', function () { + var statuses = ['read']; + + expect(viewHelper.formatStatusClasses(statuses)).toEqual('status-read'); + }); + }); + + it('formats the body of a multipart email', function () { + expect(viewHelper.formatMailBody(testData.parsedMail.html)).toContainHtml('

Hello everyone!

'); + }); + + it('decodes a quoted-printable email body', function () { + var result = viewHelper.formatMailBody(testData.parsedMail.htmlQuotedPrintable); + + expect(result).toContainHtml('

Hello everyone!

'); + }); + + it('move caret to the end of text after 1ms', function () { + spyOn(window, 'setTimeout'); + + viewHelper.moveCaretToEndOfText(); + + expect(window.setTimeout.calls[0].args[1]).toEqual(1); + }); + }); +}); diff --git a/web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js b/web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js new file mode 100644 index 00000000..b49bc7f0 --- /dev/null +++ b/web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js @@ -0,0 +1,136 @@ +describeComponent('mail_list/ui/mail_items/generic_mail_item', function () { + 'use strict'; + + var mail; + + beforeEach(function () { + mail = Smail.testData().parsedMail.simpleTextPlain; + mail.tags = ['inbox']; + + setupComponent('
  • ', { + mail: mail, + selected: false, + tag: 'inbox' + }); + }); + + it('should trigger ui:openMail on click', function () { + var spyEvent = spyOnEvent(document, Smail.events.ui.mail.open); + + this.component.$node.find('a').click(); + + expect(spyEvent).toHaveBeenTriggeredOn(document); + expect(spyEvent.mostRecentCall.data).toEqual({ ident: mail.ident }); + }); + + it('should add selected class when selecting', function () { + this.$node.find('a').click(); + + expect(this.$node).toHaveClass('selected'); + }); + + it('should remove selected class when selecting a different mail', function () { + $(document).trigger(Smail.events.ui.mail.updateSelected, { ident: 2 }); + + expect(this.$node).not.toHaveClass('selected'); + }); + + it('should remove selected class when enabling compose box', function () { + this.$node.find('a').click(); + + $(document).trigger(Smail.events.ui.composeBox.newMessage); + + expect(this.$node).not.toHaveClass('selected'); + }); + + it('should have the href link with mail ident and tag name', function () { + expect(this.$node.find('a')[0].href).toMatch('inbox/mail/' + mail.ident); + }); + + describe('clicking on a mail', function () { + + function createClickEvent(options) { + var clickEvent = $.Event('click'); + _.merge(clickEvent, options); + spyOn(clickEvent, 'preventDefault'); + return clickEvent; + } + + it('triggers mail open and pushes the state', function () { + var clickEvent = createClickEvent(); + var mailOpenEvent = spyOnEvent(document, Smail.events.ui.mail.open); + var pushStateEvent = spyOnEvent(document, Smail.events.router.pushState); + + $(this.$node.find('a')).trigger(clickEvent); + + expect(mailOpenEvent).toHaveBeenTriggeredOnAndWith(document, { ident: mail.ident }); + expect(pushStateEvent).toHaveBeenTriggeredOnAndWith(document, { mailIdent: mail.ident }); + expect(clickEvent.preventDefault).toHaveBeenCalled(); + }); + + describe('when opening on a new tab', function () { + + _.each([ + {metaKey: true}, + {which: 2}, + {ctrlKey: true} + ], function (specialKey) { + it('doesnt trigger mail open and nor pushes the state', function () { + var clickEvent = createClickEvent(specialKey); + var mailOpenEvent = spyOnEvent(document, Smail.events.ui.mail.open); + var pushStateEvent = spyOnEvent(document, Smail.events.router.pushState); + + $(this.$node.find('a')).trigger(clickEvent); + + expect(mailOpenEvent).not.toHaveBeenTriggeredOnAndWith(document, { ident: mail.ident }); + expect(pushStateEvent).not.toHaveBeenTriggeredOnAndWith(document, { mailIdent: mail.ident }); + expect(clickEvent.preventDefault).not.toHaveBeenCalled(); + }); + + it('marks the email as read', function () { + debugger; + var mailReadEvent = spyOnEvent(document, Smail.events.mail.read); + var clickEvent = createClickEvent(specialKey); + + $(this.$node.find('a')).trigger(clickEvent); + + expect(this.component.attr.mail.status).toContain(this.component.status.READ); + expect(this.$node.attr('class')).toMatch('status-read'); + expect(mailReadEvent).toHaveBeenTriggeredOnAndWith(document, { ident: mail.ident, tags: ['inbox'] }); + }); + + }); + + }); + + }); + + describe('marking emails as read', function () { + it('should trigger mail:read event when unread is clicked', function () { + var mailReadEvent = spyOnEvent(document, Smail.events.mail.read); + + this.$node.find('a').click(); + + expect(mailReadEvent).toHaveBeenTriggeredOnAndWith(document, jasmine.objectContaining({ident: mail.ident})); + }); + + it('should not trigger mail:read event when clicking mail that is already read', function () { + var mailReadEvent = spyOnEvent(document, Smail.events.mail.read); + this.component.attr.mail.status.push(this.component.status.READ); + + this.$node.find('a').click(); + + expect(mailReadEvent).not.toHaveBeenTriggeredOnAndWith(document, {ident: mail.ident}); + }); + + it('should add status-read class to email when clicking an unread email', function () { + this.$node.find('a').click(); + + expect(this.$node).toHaveClass('status-read'); + }); + + it('should not have status-read class when initializing email without read status', function () { + expect(this.$node).not.toHaveClass('status-read'); + }); + }); +}); diff --git a/web-ui/test/spec/mail_list/ui/mail_items/mail_item.spec.js b/web-ui/test/spec/mail_list/ui/mail_items/mail_item.spec.js new file mode 100644 index 00000000..1b5899a1 --- /dev/null +++ b/web-ui/test/spec/mail_list/ui/mail_items/mail_item.spec.js @@ -0,0 +1,40 @@ +/*global Smail */ + +describeMixin('mail_list/ui/mail_items/mail_item', function () { + 'use strict'; + + beforeEach(function () { + var mail = Smail.testData().parsedMail.simpleTextPlain; + mail.tags = ['inbox']; + + setupComponent('
  • ', { + mail: mail, + selected: false, + tag: 'inbox' + }); + }); + + describe('mail checkbox', function () { + var mailCheckedEvent, mailUncheckedEvent, checkbox; + beforeEach(function () { + mailCheckedEvent = spyOnEvent(document, Smail.events.ui.mail.checked); + mailUncheckedEvent = spyOnEvent(document, Smail.events.ui.mail.unchecked); + checkbox = this.component.$node.find('input[type=checkbox]'); + }); + + it('checkCheckbox checks it and triggers events.ui.mail.checked', function () { + this.component.checkCheckbox(); + + expect(checkbox.prop('checked')).toBe(true); + expect(mailCheckedEvent).toHaveBeenTriggeredOn(document); + }); + + it('uncheckCheckbox checks it and triggers events.ui.mail.checked', function () { + checkbox.prop('checked', true); + this.component.uncheckCheckbox(); + + expect(checkbox.prop('checked')).toBe(false); + expect(mailUncheckedEvent).toHaveBeenTriggeredOn(document); + }); + }); +}); diff --git a/web-ui/test/spec/mail_list/ui/mail_list.spec.js b/web-ui/test/spec/mail_list/ui/mail_list.spec.js new file mode 100644 index 00000000..f383d540 --- /dev/null +++ b/web-ui/test/spec/mail_list/ui/mail_list.spec.js @@ -0,0 +1,275 @@ +/*global Smail */ + +describeComponent('mail_list/ui/mail_list', function () { + 'use strict'; + + var mailList; + + beforeEach(function () { + setupComponent('
    ', { + urlParams: { + hasMailIdent: function () { + return false; + } + } + }); + mailList = + [ + createMail('the mail subject', 'from@mail.com', '1', '2012-12-26T01:38:46-08:00'), + createMail('another mail subject', 'from_another@mail.com', '2', '2012-12-28T01:38:46-08:00') + ]; + }); + + + it('should open mail at first mail:available if there is a mailIdent in the url hash', function () { + this.component.attr.urlParams = { + hasMailIdent: function () { + return true; + }, + getMailIdent: function () { + return '10'; + } + }; + var openMailEvent = spyOnEvent(document, Smail.events.ui.mail.open); + + this.$node.trigger(Smail.events.mails.available, { mails: mailList }); + expect(openMailEvent).toHaveBeenTriggeredOnAndWith(document, { ident: '10' }); + + this.$node.trigger(Smail.events.mails.available, { mails: mailList }); + expect(openMailEvent.calls.length).toEqual(1); + }); + + it('should push the state if there is a mail ident in the hash url', function () { + this.component.attr.urlParams = { + hasMailIdent: function () { + return true; + }, + getMailIdent: function () { + return '10'; + } + }; + var pushState = spyOnEvent(document, Smail.events.router.pushState); + this.component.attr.currentTag = 'inbox'; + + this.$node.trigger(Smail.events.mails.available, { mails: mailList }); + + expect(pushState).toHaveBeenTriggeredOnAndWith(document, { tag: 'inbox', mailIdent: '10' }); + }); + + describe('checking/unchecking mails in the list', function () { + + it('keeps a list with the currently checked mails', function () { + var checkedMails = {}; + + this.component.attr.checkedMails = {}; + + $(document).trigger(Smail.events.ui.mail.checked, {mail: mailList[0]}); + + checkedMails[mailList[0].ident] = mailList[0]; + + expect(this.component.attr.checkedMails).toEqual(checkedMails); + }); + + it('returns the list of checked mails to whomever requests them', function () { + var caller = {}; + this.component.attr.checkedMails = {'1': {}}; + var mailHereCheckedEvent = spyOnEvent(caller, Smail.events.ui.mail.hereChecked); + + $(document).trigger(Smail.events.ui.mail.wantChecked, caller); + + expect(mailHereCheckedEvent).toHaveBeenTriggeredOnAndWith(caller, { checkedMails: {'1': {} }}); + }); + + it('returns an empty list to whomever requests the checked mails if there are no checked mails', function () { + var caller = {}; + var mailHereCheckedEvent = spyOnEvent(caller, Smail.events.ui.mail.hereChecked); + + $(document).trigger(Smail.events.ui.mail.wantChecked, caller); + + expect(mailHereCheckedEvent).toHaveBeenTriggeredOnAndWith(caller, { checkedMails: {} }); + }); + + it('removes for the checked mails when mail is unchecked', function () { + this.component.attr.checkedMails = { + '1': {}, + '2': {}, + '3': {} + }; + + $(document).trigger(Smail.events.ui.mail.unchecked, {mail: {ident: '1'}}); + + expect(this.component.attr.checkedMails).toEqual({'2': {}, '3': {} }); + }); + + it('checks the check all checkbox if at least one mail is checked', function () { + var setCheckAllCheckboxEvent = spyOnEvent(document, Smail.events.ui.mails.hasMailsChecked); + + $(document).trigger(Smail.events.ui.mail.checked, {mail: mailList[0]}); + + expect(setCheckAllCheckboxEvent).toHaveBeenTriggeredOnAndWith(document, true); + }); + + it('unchecks the check all checkbox if no mail is left checked', function () { + this.component.attr.checkedMails = {1: {}}; + + var setCheckAllCheckboxEvent = spyOnEvent(document, Smail.events.ui.mails.hasMailsChecked); + + $(document).trigger(Smail.events.ui.mail.unchecked, {mail: {ident: '1'}}); + + expect(setCheckAllCheckboxEvent).toHaveBeenTriggeredOnAndWith(document, false); + }); + }); + + describe('when mails are available', function () { + it('should open email if popstate event happened (when mailIdent isnt undefined)', function () { + var openMailEvent = spyOnEvent(document, Smail.events.ui.mail.open); + + this.component.$node.trigger(Smail.events.mails.available, { mails: mailList, mailIdent: '30' }); + + expect(openMailEvent).toHaveBeenTriggeredOnAndWith(document, { ident: '30'}); + }); + + it('should open draft in popstate event if tag is Drafts', function () { + var openDraftEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openDraft); + + this.component.$node.trigger(Smail.events.mails.available, { mails: mailList, mailIdent: '30', tag: 'drafts' }); + + expect(openDraftEvent).toHaveBeenTriggeredOnAndWith(document, { ident: '30'}); + }); + }); + + it('should not append emails when another mails:available event is triggered', function () { + this.component.$node.trigger(Smail.events.mails.available, { mails: mailList }); + + expect(this.component.$node.find('a').length).toEqual(2); + + this.component.$node.trigger(Smail.events.mails.available, { mails: mailList }); + + expect(this.component.$node.find('a').length).toEqual(2); + }); + + it('resets scroll when opening a new tag or choosing a new tag', function () { + var eventSpy = spyOnEvent(document, Smail.events.dispatchers.middlePane.resetScroll); + this.component.$node.trigger(Smail.events.mails.available, { mails: mailList }); + expect(eventSpy).toHaveBeenTriggeredOn(document); + }); + + describe('rendering the mails', function () { + + describe('when mails are available for refreshing', function () { + it('renders the new mails', function () { + this.component.$node.trigger(Smail.events.mails.availableForRefresh, { mails: mailList }); + + matchMail(mailList[0], this.component.$node); + matchMail(mailList[1], this.component.$node); + }); + + }); + + it('should render all mails sent in ui:mails:show event', function () { + this.component.$node.trigger(Smail.events.mails.available, { mails: mailList }); + + matchMail(mailList[0], this.component.$node); + matchMail(mailList[1], this.component.$node); + }); + + it('should select the current email when mails are available', function () { + this.component.attr.currentMailIdent = '1'; + + this.component.trigger(Smail.events.mails.available, { mails: mailList }); + + matchSelectedMail(mailList[0], this.component.$node); + matchMail(mailList[1], this.component.$node); + }); + + it('should keep the mail checked when it was previously checked (so refresh works)', function () { + var checkbox, mailIdent; + + mailIdent = mailList[0].ident; + this.component.attr.checkedMails[mailIdent] = mailList[0]; + this.component.$node.trigger(Smail.events.mails.available, { mails: [mailList[0]] }); + checkbox = this.$node.find('input[type=checkbox]'); + + expect(checkbox.prop('checked')).toBe(true); + }); + + it('should render links for the emails', function () { + this.component.$node.trigger(Smail.events.mails.available, { mails: mailList, tag: 'inbox' }); + + expect(this.$node.html()).toMatch('href="/#/inbox/mail/1'); + expect(this.$node.html()).toMatch('href="/#/inbox/mail/2'); + }); + + it('should clean the selected email', function () { + this.component.attr.currentMailIdent = '1'; + this.component.trigger(Smail.events.ui.mails.cleanSelected); + + expect(this.component.attr.currentMailIdent).toEqual(''); + }); + + function matchMail(mail, node) { + expect(node.html()).toMatch('id="mail-' + mail.ident + '"'); + expect(node.html()).toMatch('
    '); + expect(node.html()).toMatch('
    ' + mail.header.from + '
    '); + expect(node.html()).toMatch('' + mail.header.formattedDate + ''); + } + + function matchSelectedMail(mail, node) { + expect(node.html()).toMatch(['id="mail-', mail.ident, '" class="selected"'].join('')); + } + }); + + describe('when saving a draft', function () { + it('refreshes the list if the current tag is drafts', function () { + this.component.attr.currentTag = 'drafts'; + var spyRefresh = spyOnEvent(document, Smail.events.ui.mails.refresh); + var spyScroll = spyOnEvent(document, Smail.events.dispatchers.middlePane.resetScroll); + this.component.trigger(Smail.events.mail.draftSaved, {ident: 1}); + expect(spyRefresh).toHaveBeenTriggeredOn(document); + expect(spyScroll).toHaveBeenTriggeredOn(document); + }); + + it('does not refresh the list if the current tag is not drafts', function() { + this.component.attr.currentTag = 'sent'; + var spyRefresh = spyOnEvent(document, Smail.events.ui.mails.refresh); + var spyScroll = spyOnEvent(document, Smail.events.dispatchers.middlePane.resetScroll); + this.component.trigger(Smail.events.mail.draftSaved, {ident: 1}); + expect(spyRefresh).not.toHaveBeenTriggeredOn(document); + expect(spyScroll).not.toHaveBeenTriggeredOn(document); + }); + }); + + describe('when sending a mail', function () { + it('refreshes the list if the current tag is drafts', function () { + this.component.attr.currentTag = 'drafts'; + var spyRefresh = spyOnEvent(document, Smail.events.ui.mails.refresh); + var spyScroll = spyOnEvent(document, Smail.events.dispatchers.middlePane.resetScroll); + this.component.trigger(Smail.events.mail.sent); + expect(spyRefresh).toHaveBeenTriggeredOn(document); + expect(spyScroll).toHaveBeenTriggeredOn(document); + }); + + it('refreshes the list if the current tag is sent', function() { + this.component.attr.currentTag = 'sent'; + var spyRefresh = spyOnEvent(document, Smail.events.ui.mails.refresh); + var spyScroll = spyOnEvent(document, Smail.events.dispatchers.middlePane.resetScroll); + this.component.trigger(Smail.events.mail.sent); + expect(spyRefresh).toHaveBeenTriggeredOn(document); + expect(spyScroll).toHaveBeenTriggeredOn(document); + }); + }); + + function createMail(subject, from, ident, date) { + var mail = Smail.testData().parsedMail.simpleTextPlain; + + return _.merge(mail, { + header: { + subject: subject, + from: from, + date: date + }, + ident: ident, + tags: ['inbox'] + }); + } +}); diff --git a/web-ui/test/spec/mail_list_actions/ui/compose_trigger.spec.js b/web-ui/test/spec/mail_list_actions/ui/compose_trigger.spec.js new file mode 100644 index 00000000..4942b5b6 --- /dev/null +++ b/web-ui/test/spec/mail_list_actions/ui/compose_trigger.spec.js @@ -0,0 +1,16 @@ +describeComponent('mail_list_actions/ui/compose_trigger', function () { + 'use strict'; + + beforeEach(function () { + setupComponent('
    '); + }); + + it('triggers the enableComposebox event when clicked', function () { + var spyEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openComposeBox); + + this.component.trigger('click'); + + expect(spyEvent).toHaveBeenTriggeredOn(document); + }); + +}); diff --git a/web-ui/test/spec/mail_list_actions/ui/mail_actions.spec.js b/web-ui/test/spec/mail_list_actions/ui/mail_actions.spec.js new file mode 100644 index 00000000..f7a0ed72 --- /dev/null +++ b/web-ui/test/spec/mail_list_actions/ui/mail_actions.spec.js @@ -0,0 +1,9 @@ +describeComponent('mail_list_actions/ui/mail_actions', function () { + 'use strict'; + + beforeEach(function () { + setupComponent(); + }); + + +}); diff --git a/web-ui/test/spec/mail_list_actions/ui/pagination_trigger.spec.js b/web-ui/test/spec/mail_list_actions/ui/pagination_trigger.spec.js new file mode 100644 index 00000000..67c2f3ef --- /dev/null +++ b/web-ui/test/spec/mail_list_actions/ui/pagination_trigger.spec.js @@ -0,0 +1,26 @@ +describeComponent('mail_list_actions/ui/pagination_trigger', function () { + 'use strict'; + + beforeEach(function () { + setupComponent(); + }); + + it('triggers the ui:page:previous event when the left arrow is clicked', function () { + var eventSpy = spyOnEvent(document, Smail.events.ui.page.previous); + this.component.select('previous').click(); + expect(eventSpy).toHaveBeenTriggeredOn(document); + }); + + + it('triggers the ui:page:next event when the right arrow is clicked', function () { + var eventSpy = spyOnEvent(document, Smail.events.ui.page.next); + this.component.select('next').click(); + expect(eventSpy).toHaveBeenTriggeredOn(document); + }); + + it('re-renders with current page number when page changes', function () { + this.component.trigger(document, Smail.events.ui.page.changed, {currentPage: 0}); + + expect(this.component.select('currentPage').text()).toBe('1'); + }); +}); diff --git a/web-ui/test/spec/mail_view/data/mail_builder.spec.js b/web-ui/test/spec/mail_view/data/mail_builder.spec.js new file mode 100644 index 00000000..bf17d598 --- /dev/null +++ b/web-ui/test/spec/mail_view/data/mail_builder.spec.js @@ -0,0 +1,110 @@ +define(['mail_view/data/mail_builder'], function (mailBuilder) { + describe('mail builder', function () { + 'use strict'; + + it('sets ident if passed to constructor', function() { + var mail = mailBuilder.newMail('12345').build(); + + expect(mail.ident).toBe('12345'); + }); + + it('sets ident to empty if not passed to constructor', function() { + var mail = mailBuilder.newMail().build(); + + expect(mail.ident).toBe(''); + }); + + it('sets the subject', function() { + var mail = mailBuilder.newMail().subject("subject").build(); + + expect(mail.header.subject).toBe("subject"); + }); + + it('sets the body', function() { + var mail = mailBuilder.newMail().body("some body text").build(); + + expect(mail.body).toBe("some body text"); + }); + + describe('to field', function() { + it('adds a single address', function() { + var mail = mailBuilder.newMail().to('foo@bar.com').build(); + + expect(mail.header.to).toContain('foo@bar.com'); + }); + + it('adds multiple addresses', function() { + var mail = mailBuilder.newMail().to('foo@bar.com bar@foo.com').build(); + + expect(mail.header.to).toContain('foo@bar.com'); + expect(mail.header.to).toContain('bar@foo.com'); + }); + + it('accepts undefined without breaking', function() { + var mail = mailBuilder.newMail().to(undefined).build(); + + expect(mail.header.to).toEqual([]); + }); + }); + + describe('cc field', function() { + it('adds a single address', function() { + var mail = mailBuilder.newMail().cc('foo@bar.com').build(); + + expect(mail.header.cc).toContain('foo@bar.com'); + }); + + it('adds multiple addresses', function() { + var mail = mailBuilder.newMail().cc('foo@bar.com bar@foo.com').build(); + + expect(mail.header.cc).toContain('foo@bar.com'); + expect(mail.header.cc).toContain('bar@foo.com'); + }); + + it('accepts undefined without breaking', function() { + var mail = mailBuilder.newMail().cc(undefined).build(); + + expect(mail.header.cc).toEqual([]); + }); + }); + + describe('bcc field', function() { + it('adds a single address', function() { + var mail = mailBuilder.newMail().bcc('foo@bar.com').build(); + + expect(mail.header.bcc).toContain('foo@bar.com'); + }); + + it('adds multiple addresses', function() { + var mail = mailBuilder.newMail().bcc('foo@bar.com bar@foo.com').build(); + + expect(mail.header.bcc).toContain('foo@bar.com'); + expect(mail.header.bcc).toContain('bar@foo.com'); + }); + + it('accepts undefined without breaking', function() { + var mail = mailBuilder.newMail().bcc(undefined).build(); + + expect(mail.header.bcc).toEqual([]); + }); + }); + + it('adds arbitrary headers', function() { + var mail = mailBuilder.newMail() + .header('Reply-To', 'something') + .header('In-Reply-To', '12345') + .build(); + + expect(mail.header['Reply-To']).toBe('something'); + expect(mail.header['In-Reply-To']).toBe('12345'); + }); + + it('adds tag', function() { + var mail = mailBuilder.newMail() + .tag('tag1') + .build(); + + expect(mail.tags).toContain('tag1'); + }); + }); +}); diff --git a/web-ui/test/spec/mail_view/data/mail_sender.spec.js b/web-ui/test/spec/mail_view/data/mail_sender.spec.js new file mode 100644 index 00000000..3bdc1934 --- /dev/null +++ b/web-ui/test/spec/mail_view/data/mail_sender.spec.js @@ -0,0 +1,70 @@ +/*global Smail */ + +describeComponent('mail_view/data/mail_sender', function () { + 'use strict'; + + var mailBuilder; + var mail; + + beforeEach(function () { + mailBuilder = require('mail_view/data/mail_builder'); + mail = Smail.testData().parsedMail.simpleTextPlain; + setupComponent(); + }); + + it('sends mail data with a POST to the server when asked to send email', function() { + var mailSentEventSpy = spyOnEvent(document, Smail.events.mail.sent); + var g; + + spyOn($, 'ajax').andReturn({done: function(f) { g = f; return {fail: function(){}};}}); + + this.component.trigger(Smail.events.mail.send, mail); + + g(); + + expect(mailSentEventSpy).toHaveBeenTriggeredOn(document); + + expect($.ajax.mostRecentCall.args[0]).toEqual('/mails'); + expect($.ajax.mostRecentCall.args[1].type).toEqual('POST'); + expect(JSON.parse($.ajax.mostRecentCall.args[1].data).header).toEqual(mail.header); + expect(JSON.parse($.ajax.mostRecentCall.args[1].data).body).toEqual(mail.body); + }); + + it('save draft data with a POST to the server when asked to save draft for the first time', function() { + var draftSavedEventSpy = spyOnEvent(document, Smail.events.mail.draftSaved); + var g; + + spyOn($, 'ajax').andReturn({done: function(f) { g = f; return {fail: function(){}};}}); + + mail.ident = ''; + this.component.trigger(Smail.events.mail.saveDraft, mail); + + g(); + + expect(draftSavedEventSpy).toHaveBeenTriggeredOn(document); + + expect($.ajax.mostRecentCall.args[0]).toEqual('/mails'); + expect($.ajax.mostRecentCall.args[1].type).toEqual('POST'); + expect(JSON.parse($.ajax.mostRecentCall.args[1].data).header).toEqual(mail.header); + expect(JSON.parse($.ajax.mostRecentCall.args[1].data).body).toEqual(mail.body); + }); + + it('save draft data with a PUT to the server when asked to save draft for the second time', function() { + var draftSavedEventSpy = spyOnEvent(document, Smail.events.mail.draftSaved); + var g; + + spyOn($, 'ajax').andReturn({done: function(f) { g = f; return {fail: function(){}};}}); + + mail.ident = 0; + this.component.trigger(Smail.events.mail.saveDraft, mail); + + g(); + + expect(draftSavedEventSpy).toHaveBeenTriggeredOn(document); + + expect($.ajax.mostRecentCall.args[0]).toEqual('/mails'); + expect($.ajax.mostRecentCall.args[1].type).toEqual('PUT'); + expect(JSON.parse($.ajax.mostRecentCall.args[1].data).header).toEqual(mail.header); + expect(JSON.parse($.ajax.mostRecentCall.args[1].data).body).toEqual(mail.body); + }); +}); diff --git a/web-ui/test/spec/mail_view/ui/compose_box.spec.js b/web-ui/test/spec/mail_view/ui/compose_box.spec.js new file mode 100644 index 00000000..a131d2cf --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/compose_box.spec.js @@ -0,0 +1,132 @@ +/*global jasmine */ +/*global Smail */ + +describeComponent('mail_view/ui/compose_box', function () { + 'use strict'; + beforeEach(function () { + Smail.mockBloodhound(); + setupComponent('
    '); + }); + + + describe('compose new mail', function() { + + it('only sends if all the recipients are valid emails', function() { + $(document).trigger(Smail.events.ui.recipients.updated, {recipientsName: 'to', newRecipients: ['valid@email.example']}); + + var eventSpy = spyOnEvent(document, Smail.events.mail.send); + + $(document).trigger(Smail.events.ui.mail.send); + + expect(eventSpy).toHaveBeenTriggeredOn(document); + }); + + it('sends the recipient entered', function () { + $(document).trigger(Smail.events.ui.recipients.updated, {recipientsName: 'to', newRecipients: ['fox@somewhere.com']}); + + var eventSpy = spyOnEvent(document, Smail.events.mail.send); + + $(document).trigger(Smail.events.ui.mail.send); + + expect(eventSpy).toHaveBeenTriggeredOn(document); + expect(eventSpy.mostRecentCall.data.header).toEqual(jasmine.objectContaining({ + to: ['fox@somewhere.com'] + })); + }); + + it('sends the multiple recipients entered', function () { + $(document).trigger(Smail.events.ui.recipients.updated, {recipientsName: 'to', newRecipients: ['fox@somewhere.com', 'blarg@someone.com', 'fox2@google.se']}); + var eventSpy = spyOnEvent(document, Smail.events.mail.send); + + $(document).trigger(Smail.events.ui.mail.send); + + expect(eventSpy).toHaveBeenTriggeredOn(document); + expect(eventSpy.mostRecentCall.data.header).toEqual(jasmine.objectContaining({ + to: ['fox@somewhere.com', 'blarg@someone.com', 'fox2@google.se'] + })); + }); + + it('sends the subject line entered', function () { + $(document).trigger(Smail.events.ui.recipients.updated, {recipientsName: 'to', newRecipients: ['aa@aa.com']}); + this.component.select('subjectBox').val('A new fancy subject!'); + var eventSpy = spyOnEvent(document, Smail.events.mail.send); + + $(document).trigger(Smail.events.ui.mail.send); + + expect(eventSpy).toHaveBeenTriggeredOn(document); + expect(eventSpy.mostRecentCall.data.header).toEqual(jasmine.objectContaining({ + subject: 'A new fancy subject!' + })); + }); + + it('sends the multiple CCs entered', function () { + $(document).trigger(Smail.events.ui.recipients.updated, {recipientsName: 'cc', newRecipients: ['cc1@foo.bar', 'cc2@bar.foo', 'cc3@zz.top']}); + var eventSpy = spyOnEvent(document, Smail.events.mail.send); + + $(document).trigger(Smail.events.ui.mail.send); + + expect(eventSpy).toHaveBeenTriggeredOn(document); + expect(eventSpy.mostRecentCall.data.header).toEqual(jasmine.objectContaining({ + cc: ['cc1@foo.bar', 'cc2@bar.foo', 'cc3@zz.top'] + })); + }); + + it('sends the multiple BCCs entered', function () { + $(document).trigger(Smail.events.ui.recipients.updated, {recipientsName: 'bcc', newRecipients: ['bcc1@foo.bar', 'bcc2@bar.foo', 'bcc3@zz.top']}); + var eventSpy = spyOnEvent(document, Smail.events.mail.send); + + $(document).trigger(Smail.events.ui.mail.send); + + expect(eventSpy).toHaveBeenTriggeredOn(document); + expect(eventSpy.mostRecentCall.data.header).toEqual(jasmine.objectContaining({ + bcc: ['bcc1@foo.bar', 'bcc2@bar.foo', 'bcc3@zz.top'] + })); + }); + + it('shows no message selected pane when deleting the email being composed', function() { + var openNoMessageSelectedPaneEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + var mails = [{ident: 123}]; + this.component.attr.ident = 123; + + this.component.trigger(document, Smail.events.mail.deleted, {mails: mails}); + + expect(openNoMessageSelectedPaneEvent).toHaveBeenTriggeredOn(document); + }); + + it('does not show no message selected pane when deleting a different set of emails', function() { + var openNoMessageSelectedPaneEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + var mails = [{ident: 321}]; + this.component.attr.ident = 123; + + this.component.trigger(document, Smail.events.mail.deleted, {mails: mails}); + + expect(openNoMessageSelectedPaneEvent).not.toHaveBeenTriggeredOn(document); + }); + }); + + describe('close button behavior', function() { + + it('should fire Show no message selected if the close button is clicked', function() { + var spy = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + this.component.select('closeButton').click(); + expect(spy).toHaveBeenTriggeredOn(document); + }); + + }); + + describe('draft compose box', function() { + it('should save a draft when click on draft button', function () { + $(document).trigger(Smail.events.ui.recipients.updated, {recipientsName: 'to', newRecipients: ['fox@somewhere.com']}); + + this.component.select('subjectBox').val('A new fancy subject!'); + var eventSpy = spyOnEvent(document, Smail.events.mail.saveDraft); + + this.component.select('draftButton').click(); + + expect(eventSpy).toHaveBeenTriggeredOn(document); + expect(eventSpy.mostRecentCall.data.header).toEqual(jasmine.objectContaining({ + to: ['fox@somewhere.com'] + })); + }); + }); +}); diff --git a/web-ui/test/spec/mail_view/ui/draft_box.spec.js b/web-ui/test/spec/mail_view/ui/draft_box.spec.js new file mode 100644 index 00000000..3e02f752 --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/draft_box.spec.js @@ -0,0 +1,67 @@ +/* global Smail */ + +describeComponent('mail_view/ui/draft_box', function () { + 'use strict'; + + var mail; + + beforeEach(function () { + Smail.mockBloodhound(); + mail = Smail.testData().parsedMail.simpleTextPlain; + }); + + describe('when initializing', function () { + it('fetches the email to draft', function () { + var mailWantEvent = spyOnEvent(document, Smail.events.mail.want); + + setupComponent({mailIdent: '1'}); + + expect(mailWantEvent).toHaveBeenTriggeredOnAndWith(document, { + mail: '1', caller: this.component + }); + }); + }); + + describe('after initialize', function () { + beforeEach(function () { + setupComponent({mailIdent: '1'}); + }); + + it('renders the compose box when mail is received', function () { + var templates = require('views/templates'); + + spyOn(this.component, 'render'); + + this.component.trigger(this.component, Smail.events.mail.here, { mail: mail}); + + expect(this.component.render).toHaveBeenCalledWith(templates.compose.box, { + recipients: { to: mail.header.to, cc: mail.header.cc, bcc: mail.header.bcc }, + subject: mail.header.subject, + body: mail.body + }); + }); + + }); + + it('sending a draft sends the correct mailIdent', function () { + setupComponent({mailIdent: mail.ident}); + this.component.trigger(this.component, Smail.events.mail.here, { mail: mail}); + + var sendDraftEvent = spyOnEvent(document, Smail.events.mail.saveDraft); + this.component.select('draftButton').click(); + + expect(sendDraftEvent).toHaveBeenTriggeredOnAndWith(document, jasmine.objectContaining({ident: mail.ident})); + }); + + it('shows no message selected pane when draft is sent', function() { + var openNoMessageSelectedEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + + setupComponent({mailIdent: mail.ident}); + this.component.trigger(this.component, Smail.events.mail.here, { mail: mail}); + + this.component.trigger(document, Smail.events.mail.sent); + + expect(openNoMessageSelectedEvent).toHaveBeenTriggeredOn(document); + }); + +}); diff --git a/web-ui/test/spec/mail_view/ui/draft_save_status.spec.js b/web-ui/test/spec/mail_view/ui/draft_save_status.spec.js new file mode 100644 index 00000000..fb989f4c --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/draft_save_status.spec.js @@ -0,0 +1,26 @@ +/* global Smail */ + +describeComponent('mail_view/ui/draft_save_status', function () { + 'use strict'; + + beforeEach(setupComponent); + + it('should be empty on initialization', function() { + expect(this.$node.text()).toBe(''); + }); + + it('should display status when saving a draft', function() { + $(document).trigger(Smail.events.mail.saveDraft); + expect(this.$node.text()).toBe('Saving to Drafts...'); + }); + + it('should display status when draft is saved', function() { + $(document).trigger(Smail.events.mail.draftSaved); + expect(this.$node.text()).toBe('Draft Saved.'); + }); + + it('should reset status when mail is changed since last save', function() { + $(document).trigger(Smail.events.ui.mail.changedSinceLastSave); + expect(this.$node.text()).toBe(''); + }); +}); diff --git a/web-ui/test/spec/mail_view/ui/forward_box.spec.js b/web-ui/test/spec/mail_view/ui/forward_box.spec.js new file mode 100644 index 00000000..fc878447 --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/forward_box.spec.js @@ -0,0 +1,90 @@ +/*global jasmine */ +/*global Smail */ + +describeComponent('mail_view/ui/forward_box', function () { + 'use strict'; + + var attrs; + var testMail; + beforeEach(function () { + testMail = Smail.testData().parsedMail.simpleTextPlain; + + Smail.mockBloodhound(); + }); + + it('should have a subject of Fwd: ', function() { + testMail.header.subject = 'Very interesting'; + setupComponent({ mail: testMail }); + + expect(this.component.select('subjectDisplay').text()).toEqual('Fwd: '+ testMail.header.subject); + }); + + it('should have no recipients', function () { + var Recipients = require('mail_view/ui/recipients/recipients'); + spyOn(Recipients, 'attachTo'); + + setupComponent({ mail: testMail }); + + expect(Recipients.attachTo.calls[0].args[1]).toEqual({name: 'to', addresses: []}); + expect(Recipients.attachTo.calls[1].args[1]).toEqual({name: 'cc', addresses: []}); + expect(Recipients.attachTo.calls[2].args[1]).toEqual({name: 'bcc', addresses: []}); + }); + + it('should populate body text area with quote of email being forwarded', function() { + var viewHelper = require('helpers/view_helper'); + spyOn(viewHelper, 'quoteMail').andReturn('quoted email'); + + setupComponent({ mail: testMail }); + + expect(viewHelper.quoteMail).toHaveBeenCalledWith(testMail); + expect(this.component.select('bodyBox').val()).toBe('quoted email'); + }); + + it('should show subject field when clicking on subject display', function() { + setupComponent({ mail: testMail }); + + this.component.select('subjectDisplay').click(); + + expect(this.component.select('subjectInput')).not.toBeHidden(); + expect(this.component.select('subjectDisplay')).toBeHidden(); + }); + + it('should copy original message headers', function() { + var mailSendEvent = spyOnEvent(document, Smail.events.mail.send); + + testMail.header.bcc = 'original_bcc@email.com'; + testMail.header.cc = 'original_cc@email.com'; + testMail.header.date = 'original_date'; + testMail.header.from = 'original_from'; + testMail.header.message_id = 'original_message_id'; + testMail.header.reply_to = 'original_reply_to@email.com'; + testMail.header.sender = 'original_sender'; + testMail.header.to = 'original_to@email.com'; + + setupComponent({ mail: testMail }); + + this.component.attr.recipientValues.to.push('forward_to@email.com'); + $(document).trigger(Smail.events.ui.mail.send); + + expect(mailSendEvent).toHaveBeenTriggeredOn(document); + var sentMail = mailSendEvent.mostRecentCall.data; + + expect(sentMail.header).toEqual(jasmine.objectContaining({ + resent_bcc: 'original_bcc@email.com', + resent_cc: 'original_cc@email.com', + resent_date: 'original_date', + resent_from: 'original_from', + resent_message_id: 'original_message_id', + resent_reply_to: 'original_reply_to@email.com', + resent_sender: 'original_sender', + resent_to: 'original_to@email.com' + })); + }); + + it('triggers openMail when email is sent', function() { + var eventSpy = spyOnEvent(document, Smail.events.ui.mail.open); + setupComponent({ mail: testMail }); + $(document).trigger(Smail.events.mail.sent, {ident: testMail.ident}); + expect(eventSpy).toHaveBeenTriggeredOnAndWith(document, {ident: testMail.ident}); + }); +}); diff --git a/web-ui/test/spec/mail_view/ui/mail_actions.spec.js b/web-ui/test/spec/mail_view/ui/mail_actions.spec.js new file mode 100644 index 00000000..93db0193 --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/mail_actions.spec.js @@ -0,0 +1,63 @@ +/*global Smail */ + +describeComponent('mail_view/ui/mail_actions', function () { + 'use strict'; + + var testData; + + beforeEach(function(){ + testData = Smail.testData(); + setupComponent(testData); + }); + + it('verifies if more actions list is hidden when rendering mail view', function() { + + var moreActionsComponent = this.component.select('moreActions'); + expect(moreActionsComponent.attr('style').trim()).toEqual('display: none;'); + + }); + + it('show more actions list when click on view more actions button', function(){ + + this.component.select('viewMoreActions').click(); + + var moreActionsComponent = this.component.select('moreActions'); + expect(moreActionsComponent.attr('style').trim()).not.toEqual('display: none;'); + }); + + it('triggers a show reply box event when clicking on reply-button-top', function(){ + + var showReplyBoxEvent = spyOnEvent(document, Smail.events.ui.replyBox.showReply); + + this.component.select('replyButtonTop').click(); + + expect(showReplyBoxEvent).toHaveBeenTriggeredOn(document); + }); + + it('triggers a show reply all box event when clicking on reply-button-top and hide more actions list', function(){ + + var showReplyAllEvent = spyOnEvent(document, Smail.events.ui.replyBox.showReplyAll); + + this.component.select('viewMoreActions').click(); + this.component.select('replyAllButtonTop').click(); + + expect(showReplyAllEvent).toHaveBeenTriggeredOn(document); + + var moreActionsComponent = this.component.select('moreActions'); + expect(moreActionsComponent.attr('style').trim()).toEqual('display: none;'); + }); + + it('triggers a delete event when clicking on delete-button-top', function(){ + + var deleteEvent = spyOnEvent(document, Smail.events.ui.mail.delete); + + this.component.select('viewMoreActions').click(); + this.component.select('deleteButtonTop').click(); + + expect(deleteEvent).toHaveBeenTriggeredOnAndWith(document, {mail: testData.mail}); + + var moreActionsComponent = this.component.select('moreActions'); + expect(moreActionsComponent.attr('style').trim()).toEqual('display: none;'); + }); + +}); diff --git a/web-ui/test/spec/mail_view/ui/mail_view.spec.js b/web-ui/test/spec/mail_view/ui/mail_view.spec.js new file mode 100644 index 00000000..80f253e0 --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/mail_view.spec.js @@ -0,0 +1,247 @@ +/*global Smail */ + +describeComponent('mail_view/ui/mail_view', function () { + 'use strict'; + + var mail; + + var testData; + + beforeEach(function () { + mail = {ident: 1, header: { date: '12/12/12T12:12' }, tags: ['inbox']}; + testData = {mail: Smail.testData().parsedMail.simpleTextPlain}; + Smail.mockBloodhound(); + setupComponent('
    ', {mail: mail}); + }); + + it('triggers mail:want on ui:openMail', function () { + var spyEvent = spyOnEvent(document, Smail.events.mail.want); + + setupComponent('
    ', {ident: mail.ident }); + + expect(spyEvent).toHaveBeenTriggeredOn(document); + expect(spyEvent.mostRecentCall.data.mail).toEqual(1); + }); + + it('triggers dispatchers.rightPane.openNoMessageSelected when getting mail.notFound', function () { + var openNoMessageSelectedEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + + this.component.trigger(this.component, Smail.events.mail.notFound); + + expect(openNoMessageSelectedEvent).toHaveBeenTriggeredOn(document); + }); + + + it('removes the tag from the mail when the tag label is clicked', function() { + var updateSpy = spyOnEvent(document, Smail.events.mail.tags.update); + + this.component.displayMail({}, testData); + this.component.removeTag('inbox'); + + expect(updateSpy).toHaveBeenTriggeredOn(document); + }); + + it('verifies if new tag input is hidden when rendering mail view', function() { + + this.component.displayMail({}, testData); + + var newTagInputComponent = this.component.select('newTagInput'); + expect(newTagInputComponent.attr('style').trim()).toEqual('display: none;'); + }); + + it('verifies if new tag input is shown when clicking on new tag button ', function() { + this.component.displayMail({}, testData); + + var newTagInputComponent = this.component.select('newTagInput'); + var addNewComponent = this.component.select('addNew'); + + this.component.select('newTagButton').click(); + + expect(newTagInputComponent.attr('style').trim()).not.toEqual('display: none;'); + expect(addNewComponent.attr('style').trim()).toEqual('display: none;'); + }); + + it('hides new tag button when pressing esc key', function(){ + this.component.displayMail({}, testData); + this.component.select('newTagButton').click(); + + var e = creatingEvent("keydown", 27); + var newTagInputComponent = this.component.select('newTagInput'); + var addNewComponent = this.component.select('addNew'); + + newTagInputComponent.trigger(e); + + expect(newTagInputComponent.attr('style').trim()).toEqual('display: none;'); + expect(addNewComponent.attr('style').trim()).not.toEqual('display: none;'); + }); + + it('assumes that the mail is encrypted and valid if at least one of the locks are valid', function() { + var email = testData; + email.security_casing = {locks: [{state: 'valid'}, {state: 'failure'}]}; + expect(this.component.checkEncrypted(email)).toEqual('encrypted encryption-valid'); + }); + + it('assumes that the mail is encrypted and failure if all the locks are failed', function() { + var email = testData; + email.security_casing = {locks: [{state: 'failure'}, {state: 'failure'}]}; + expect(this.component.checkEncrypted(email)).toEqual('encrypted encryption-failure'); + }); + + it('assumes that the mail is not encrypted if it doesn\'t have any locks', function() { + var email = testData; + email.security_casing = {locks: []}; + expect(this.component.checkEncrypted(email)).toEqual('not-encrypted'); + }); + + it('assumes that the mail is signed only if all imprints are valid', function() { + var email = testData; + email.security_casing = {imprints: [{state: 'valid', seal: {trust: 'marginal', validity: 'marginal'}}, {state: 'valid', seal: {trust: 'marginal', validity: 'marginal'}}]}; + expect(this.component.checkSigned(email)).toEqual('signed'); + }); + + it('assumes that the mail is signed with failures if there is a revoke or expire', function() { + var email = testData; + email.security_casing = {imprints: [{state: 'valid', seal: {trust: 'marginal', validity: 'marginal'}}, {state: 'from_revoked', seal: {trust: 'marginal', validity: 'marginal'}}]}; + expect(this.component.checkSigned(email)).toEqual('signed signature-revoked'); + }); + + it('assumes that mail is not trusted if its signature contains no_trust from the user', function() { + var email = testData; + email.security_casing = {imprints: [{seal: {trust: "no_trust", validity: "ultimate"}}]}; + expect(this.component.checkSigned(email)).toEqual('signed signature-not-trusted'); + }); + + it('uses validity when trust is not present', function() { + var email = testData; + email.security_casing = {imprints: [{seal: { validity: "no_trust"}}]}; + expect(this.component.checkSigned(email)).toEqual('signed signature-not-trusted'); + }); + + it('assumes not trusted when the signature is not found', function(){ + var email = testData; + email.security_casing = {imprints: [{seal: null}]}; + expect(this.component.checkSigned(email)).toEqual('signed signature-not-trusted'); + }); + + it('assumes that the mail is not signed if there are no imprints', function() { + var email = testData + email.security_casing = {imprints: []} + expect(this.component.checkSigned(email)).toEqual('not-signed'); + }); + + it('shows that mail is encrypted if it is', function() { + spyOn(this.component, 'checkEncrypted').andReturn('encrypted'); + this.component.displayMail({}, testData); + expect(this.component.$node.find('.encrypted')).toExist(); + }); + + it('shows that mail is signed if it is', function() { + spyOn(this.component, 'checkSigned').andReturn('signed'); + this.component.displayMail({}, testData); + expect(this.component.$node.find('.signed')).toExist(); + }); + + it('shows that mail is not encrypted if it isn\'t', function() { + spyOn(this.component, 'checkEncrypted').andReturn('not-encrypted'); + this.component.displayMail({}, testData); + expect(this.component.$node.find('.not-encrypted')).toExist(); + }); + + it('shows that mail is not signed if it isn\'t', function() { + spyOn(this.component, 'checkEncrypted').andReturn('not-signed'); + this.component.displayMail({}, testData); + expect(this.component.$node.find('.not-signed')).toExist(); + }); + + it('creates new tag when pressing Enter key on new tag input', function(){ + var tagsUpdateEvent = spyOnEvent(document, Smail.events.mail.tags.update); + var tagListRefreshEvent = spyOnEvent(document, Smail.events.dispatchers.tags.refreshTagList); + var e = creatingEvent("keydown", 13); + + this.component.displayMail({}, testData); + this.component.select('newTagButton').click(); + + var newTagInputComponent = this.component.select('newTagInput'); + newTagInputComponent.val('Test'); + newTagInputComponent.trigger(e); + + var tags = testData.mail.tags.slice(); + tags.push('Test'); + + expect(tagListRefreshEvent).toHaveBeenTriggeredOn(document); + expect(tagsUpdateEvent).toHaveBeenTriggeredOnAndWith(document, { ident: testData.mail.ident, tags: tags}); + }); + + it('trigger mail delete event when moving email to trash', function(){ + var mailDeleteEvent = spyOnEvent(document, Smail.events.ui.mail.delete); + + Foundation.global.namespace = ''; + $(document).foundation(); + + this.component.displayMail({}, testData); + this.component.moveToTrash(); + + expect(mailDeleteEvent).toHaveBeenTriggeredOnAndWith(document, { mail: this.component.attr.mail }); + }); + + it('shows no message selected pane when deleting the email being composed', function() { + var openNoMessageSelectedPaneEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + var mails = [{ident: 123}]; + this.component.attr.mail = mails[0]; + + this.component.trigger(document, Smail.events.mail.deleted, {mails: mails}); + + expect(openNoMessageSelectedPaneEvent).toHaveBeenTriggeredOn(document); + }); + + it('does not show no message selected pane when deleting a different set of emails', function() { + var openNoMessageSelectedPaneEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + var mails = [{ident: 321}]; + this.component.attr.mail = {ident: 123}; + + this.component.trigger(document, Smail.events.mail.deleted, {mails: mails}); + + expect(openNoMessageSelectedPaneEvent).not.toHaveBeenTriggeredOn(document); + }); + + describe('archiving email', function() { + it('trigger tag updates events with no tags', function(){ + var tagsUpdateEvent = spyOnEvent(document, Smail.events.mail.tags.update); + + Foundation.global.namespace = ''; + $(document).foundation(); + + this.component.displayMail({}, testData); + this.component.archiveIt(); + + expect(tagsUpdateEvent).toHaveBeenTriggeredOnAndWith(document, { ident: testData.mail.ident, tags: []}); + }); + + it('opens no message selected pane', function() { + var openNoMessageSelectedEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + + Foundation.global.namespace = ''; + $(document).foundation(); + + this.component.displayMail({}, testData); + this.component.archiveIt(); + + expect(openNoMessageSelectedEvent).toHaveBeenTriggeredOn(document); + }); + }); + + it('opens the no message selected pane when clicking the close button', function() { + var openNoMessageSelectedEvent = spyOnEvent(document, Smail.events.dispatchers.rightPane.openNoMessageSelected); + + this.component.displayMail({}, testData); + this.component.select('closeMailButton').click(); + + expect(openNoMessageSelectedEvent).toHaveBeenTriggeredOn(document); + }); + + function creatingEvent(event, keyCode) { + var e = $.Event(event); + e.which = keyCode; + return e; + } +}); diff --git a/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js b/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js new file mode 100644 index 00000000..692bf0eb --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js @@ -0,0 +1,36 @@ +/* global Smail */ + +describeComponent('mail_view/ui/recipients/recipients',function () { + 'use strict'; + var recipientsUpdatedEvent; + + describe('initialization', function() { + it('adds recipients', function() { + setupComponent({name: 'to', addresses: ['foobar@gmail.com'] }); + expect(this.component.attr.recipients.length).toBe(1); + }); + + it('does not trigger recipients updated events on initialization', function() { + recipientsUpdatedEvent = spyOnEvent(document, Smail.events.ui.recipients.updated); + + setupComponent({name: 'to', addresses: ['foobar@gmail.com'] }); + expect(recipientsUpdatedEvent).not.toHaveBeenTriggeredOn(document); + }); + }); + + describe('adding recipients from the ui', function() { + beforeEach(function () { + setupComponent(); + recipientsUpdatedEvent = spyOnEvent(document, Smail.events.ui.recipients.updated); + this.component.trigger(Smail.events.ui.recipients.entered, {name: 'to', addresses: ['foobar@gmail.com'] }); + }); + + it('triggers recipients updated', function() { + expect(recipientsUpdatedEvent).toHaveBeenTriggeredOn(document); + }); + + it('adds recipients', function() { + expect(this.component.attr.recipients.length).toBe(1); + }); + }); +}); diff --git a/web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js b/web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js new file mode 100644 index 00000000..0f98d007 --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js @@ -0,0 +1,104 @@ +/* global Smail */ + +describeComponent('mail_view/ui/recipients/recipients_input',function () { + 'use strict'; + + beforeEach(function () { + setupComponent({name: 'to'}); + }); + + describe('keys that finish address input', function () { + + _.each([ + [186, 'semicolon'], + [188, 'comma'], + [32, 'space'] + + ], function (keycode) { + + it(': ' + keycode[1], function () { + var addressEnteredEvent = spyOnEvent(this.$node, Smail.events.ui.recipients.entered); + + var enterAddressKeyPressEvent = $.Event('keydown', { which: keycode[0] }); + this.$node.val('a@b.c'); + this.$node.trigger(enterAddressKeyPressEvent); + + expect(addressEnteredEvent).toHaveBeenTriggeredOnAndWith(this, { name: 'to', address: 'a@b.c' }); + }); + + it('wont add address if val is empty: ' + keycode[1], function () { + var addressEnteredEvent = spyOnEvent(this.$node, Smail.events.ui.recipients.entered); + + var enterAddressKeyPressEvent = $.Event('keydown', { which: keycode[0] }); + this.$node.val(''); + this.$node.trigger(enterAddressKeyPressEvent); + + expect(addressEnteredEvent).not.toHaveBeenTriggeredOnAndWith(this, { name: 'to', address: '' }); + }); + + it('prevents event default regardless on input val when key is ' + keycode[1], function () { + var enterAddressKeyPressEvent = $.Event('keydown', { which: keycode[0] }); + spyOn(enterAddressKeyPressEvent, 'preventDefault'); + + this.$node.val('') + this.$node.trigger(enterAddressKeyPressEvent); + expect(enterAddressKeyPressEvent.preventDefault).toHaveBeenCalled(); + + enterAddressKeyPressEvent.preventDefault.reset(); + this.$node.val('anything') + this.$node.trigger(enterAddressKeyPressEvent); + expect(enterAddressKeyPressEvent.preventDefault).toHaveBeenCalled(); + }); + + }); + + describe('when tab is pressed', function () { + it('enters an address and prevents event default if there is an input val', function () { + var addressEnteredEvent = spyOnEvent(this.$node, Smail.events.ui.recipients.entered); + + var tabKeyPressEvent = $.Event('keydown', { which: 9}); + spyOn(tabKeyPressEvent, 'preventDefault'); + + this.$node.val('a@b.c'); + this.$node.trigger(tabKeyPressEvent); + + expect(tabKeyPressEvent.preventDefault).toHaveBeenCalled(); + expect(addressEnteredEvent).toHaveBeenTriggeredOnAndWith(this, { name: 'to', address: 'a@b.c'}); + }); + + it('doesnt enter an address and doesnt prevent event default if input val is empty (so tab moves it to the next input)', function () { + var addressEnteredEvent = spyOnEvent(this.$node, Smail.events.ui.recipients.entered); + + var tabKeyPressEvent = $.Event('keydown', { which: 9}); + spyOn(tabKeyPressEvent, 'preventDefault'); + + this.$node.val(''); + this.$node.trigger(tabKeyPressEvent); + + expect(tabKeyPressEvent.preventDefault).not.toHaveBeenCalled(); + expect(addressEnteredEvent).not.toHaveBeenTriggeredOnAndWith(this, { name: 'to', address: ''}); + }); + }); + }); + + describe('on keyup', function () { + it('triggers inputHasNoMail if input is empty', function () { + var inputHasNoMailEvent = spyOnEvent(document, Smail.events.ui.recipients.inputHasNoMail); + this.$node.val(''); + + this.$node.trigger('keyup'); + + expect(inputHasNoMailEvent).toHaveBeenTriggeredOn(document); + }); + + it('triggers inputHasMail if input is not empty', function () { + var inputHasMailEvent = spyOnEvent(document, Smail.events.ui.recipients.inputHasMail); + this.$node.val('lalala'); + + this.$node.trigger('keyup'); + + expect(inputHasMailEvent).toHaveBeenTriggeredOn(document, { name: 'to' }); + }); + }); + +}); diff --git a/web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js b/web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js new file mode 100644 index 00000000..480ea256 --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js @@ -0,0 +1,101 @@ +/* global Smail */ + +define(['mail_view/ui/recipients/recipients_iterator'], function (RecipientsIterator) { + 'use strict'; + + function createRecipient() { + return jasmine.createSpyObj('recipient', ['select', 'unselect', 'destroy']); + } + + var recipientsIterator, + exitInput; + + function createIterator(elements) { + return recipientsIterator = new RecipientsIterator({ elements: elements, exitInput: exitInput }); + } + + function resetMock(m) { + m.destroy.reset();m.select.reset();m.unselect.reset(); + } + + beforeEach(function () { + exitInput = $(''); + }); + + describe('moving left', function () { + it('unselects the current element and selects the element in the left if there is one', function () { + var elements = _.times(2, createRecipient); + + recipientsIterator = createIterator(elements); + recipientsIterator.moveLeft(); + + expect(elements[0].select).toHaveBeenCalled(); + expect(elements[1].unselect).toHaveBeenCalled(); + }); + + it('doesnt do anything if there are no elements in the left', function () { + var elements = _.times(2, createRecipient); + recipientsIterator = createIterator(elements); + recipientsIterator.moveLeft(); + _.each(elements, resetMock); + + recipientsIterator.moveLeft(); + + expect(elements[0].select).not.toHaveBeenCalled(); + expect(elements[0].unselect).not.toHaveBeenCalled(); + expect(elements[1].select).not.toHaveBeenCalled(); + expect(elements[1].unselect).not.toHaveBeenCalled(); + }); + + }); + + describe('moving right', function () { + it('unselects the current element and selects the one in the right if there is one', function () { + var elements = _.times(2, createRecipient); + recipientsIterator = createIterator(elements); + recipientsIterator.moveLeft(); + _.each(elements, resetMock); + + recipientsIterator.moveRight(); + + expect(elements[0].unselect).toHaveBeenCalled(); + expect(elements[1].select).toHaveBeenCalled(); + }); + + it('unselects current element and focus on exit input if there are no elements on the right', function () { + var elements = _.times(2, createRecipient); + spyOn(exitInput, 'focus'); + + recipientsIterator = createIterator(elements); + recipientsIterator.moveRight(); + + expect(elements[1].unselect).toHaveBeenCalled(); + expect(exitInput.focus).toHaveBeenCalled(); + }); + }); + + describe('delete current', function () { + it('selects what is left in the right after deleting the current element', function () { + var elements = _.times(2, createRecipient); + var toBeDeleted = elements[0]; + recipientsIterator = createIterator(elements); + recipientsIterator.moveLeft(); + + recipientsIterator.deleteCurrent(); + + expect(toBeDeleted.destroy).toHaveBeenCalled(); + expect(elements[0].select).toHaveBeenCalled(); + }); + + it('focus on the input if there are no more elements', function () { + recipientsIterator = createIterator([createRecipient()]); + spyOn(exitInput, 'focus'); + + recipientsIterator.deleteCurrent(); + + expect(exitInput.focus).toHaveBeenCalled(); + }); + }); + + +}); \ No newline at end of file diff --git a/web-ui/test/spec/mail_view/ui/reply_box.spec.js b/web-ui/test/spec/mail_view/ui/reply_box.spec.js new file mode 100644 index 00000000..c6db4de3 --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/reply_box.spec.js @@ -0,0 +1,105 @@ +/*global jasmine */ +/*global Smail */ + +describeComponent('mail_view/ui/reply_box', function () { + 'use strict'; + + var attrs, i18n; + beforeEach(function () { + attrs = { + mail: Smail.testData().parsedMail.simpleTextPlain + }; + setupComponent(attrs); + i18n = require('views/i18n'); + }); + + describe('reply compose box', function() { + it('should display subject of the reply', function() { + expect(this.component.select('subjectDisplay').text()).toBe(i18n('Re: ') + attrs.mail.header.subject); + }); + + it('should show recipient fields when clicking on recipient display', function() { + this.component.select('recipientsDisplay').click(); + + expect(this.component.select('recipientsFields')).not.toBeHidden(); + expect(this.component.select('recipientsDisplay')).toBeHidden(); + }); + + it('should show subject field when clicking on subject display', function() { + this.component.select('subjectDisplay').click(); + + expect(this.component.select('subjectInput')).not.toBeHidden(); + expect(this.component.select('subjectDisplay')).toBeHidden(); + }); + + it('should use the from field when Reply-To header does not exist', function() { + attrs.mail.header.reply_to = undefined; + + setupComponent(attrs); + + expect(this.component.attr.recipientValues['to']).toEqual([attrs.mail.header.from]); + }); + + it('should have a subject of Re: ', function() { + attrs.mail.header.subject = 'Very interesting'; + + setupComponent(attrs); + + expect(this.component.select('subjectDisplay').text()).toEqual(i18n('Re: ')+ attrs.mail.header.subject); + }); + + it('should use set In-Reply-To header when Message-Id header is set', function() { + var mailSendEvent = spyOnEvent(document, Smail.events.mail.send); + + attrs.mail.header.message_id = '12345'; + setupComponent(attrs); + + $(document).trigger(Smail.events.ui.mail.send); + + expect(mailSendEvent).toHaveBeenTriggeredOn(document); + expect(mailSendEvent.mostRecentCall.data.header).toEqual(jasmine.objectContaining({ + in_reply_to: '12345' + })); + }); + + it('keeps the List-Id header when it exists', function() { + var mailSendEvent = spyOnEvent(document, Smail.events.mail.send); + attrs.mail.header.list_id = 'somelist'; + + setupComponent(attrs); + $(document).trigger(Smail.events.ui.mail.send); + + expect(mailSendEvent.mostRecentCall.data.header).toEqual(jasmine.objectContaining({ + list_id: 'somelist' + })); + }); + + it('populates body text area with quote of email being replied', function() { + var viewHelper = require('helpers/view_helper'); + spyOn(viewHelper, 'quoteMail').andReturn('quoted email'); + + setupComponent(attrs); + + expect(viewHelper.quoteMail).toHaveBeenCalledWith(attrs.mail); + expect(this.component.select('bodyBox').val()).toBe('quoted email'); + }); + + it('triggers mail when cancelling a reply', function () { + var mailSaveEvent = spyOnEvent(document, Smail.events.mail.save); + + this.component.select('trashButton').click(); + + expect(mailSaveEvent).toHaveBeenTriggeredOn(document); + }); + + it('reopens the mail after the reply is sent', function () { + var mailOpenEvent = spyOnEvent(document, Smail.events.ui.mail.open); + + this.component.trigger(document, Smail.events.mail.sent); + + expect(mailOpenEvent).toHaveBeenTriggeredOnAndWith(document, { + ident: this.component.attr.mail.ident + }); + }); + }); +}); diff --git a/web-ui/test/spec/mail_view/ui/reply_section.spec.js b/web-ui/test/spec/mail_view/ui/reply_section.spec.js new file mode 100644 index 00000000..e5571e2c --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/reply_section.spec.js @@ -0,0 +1,97 @@ +/*global jasmine */ +/*global Smail */ + +describeComponent('mail_view/ui/reply_section', function () { + 'use strict'; + + beforeEach(function () { + setupComponent(); + }); + + describe('clicking reply buttons', function() { + var mailWantEvent, expectEventData; + + beforeEach(function () { + mailWantEvent = spyOnEvent(document, Smail.events.mail.want); + expectEventData = { + mail: '12345', + caller: this.component + }; + this.component.attr.ident = '12345'; + }); + + it('should ask for email when clicking on reply button', function() { + this.component.select('replyButton').click(); + + expect(mailWantEvent).toHaveBeenTriggeredOnAndWith(document, expectEventData); + }); + + it('should ask for email when clicking on replyAll button', function() { + this.component.select('replyAllButton').click(); + + expect(mailWantEvent).toHaveBeenTriggeredOnAndWith(document, expectEventData); + }); + }); + + describe('creating reply box when getting email back', function() { + var mailData, ReplyBox, ForwardBox; + + beforeEach(function () { + mailData = Smail.testData().mail; + ReplyBox = require('mail_view/ui/reply_box'); + ForwardBox = require('mail_view/ui/forward_box'); + spyOn(ReplyBox, 'attachTo'); + spyOn(ForwardBox, 'attachTo'); + }); + + it('for normal reply', function() { + this.component.attr.replyType = 'reply'; + this.component.trigger(this.component, Smail.events.mail.here, { mail: mailData }); + + expect(ReplyBox.attachTo).toHaveBeenCalledWith(jasmine.any(Object), { + mail: mailData, + replyType: 'reply' + }); + }); + + it('for reply to all', function() { + this.component.attr.replyType = 'replyall'; + this.component.trigger(this.component, Smail.events.mail.here, { mail: mailData }); + + expect(ReplyBox.attachTo).toHaveBeenCalledWith(jasmine.any(Object), { + mail: mailData, + replyType: 'replyall' + }); + }); + + it('creates a forward box', function() { + this.component.attr.replyType = 'forward'; + this.component.trigger(this.component, Smail.events.mail.here, { mail: mailData }); + + expect(ForwardBox.attachTo).toHaveBeenCalledWith(jasmine.any(Object), { + mail: mailData + }); + }); + }); + + it('hides the buttons when clicked', function() { + this.component.attr.mailIdent = 12345; + + this.component.select('replyButton').click(); + + expect(this.component.select('replyButton')).toBeHidden(); + expect(this.component.select('replyAllButton')).toBeHidden(); + expect(this.component.select('forwardButton')).toBeHidden(); + }); + + it('shows the buttons when reply is cancelled', function() { + this.component.attr.mailIdent = 12345; + this.component.select('replyButton').click(); + + $(document).trigger(Smail.events.ui.composeBox.trashReply); + + expect(this.component.select('replyButton')).not.toBeHidden(); + expect(this.component.select('replyAllButton')).not.toBeHidden(); + expect(this.component.select('forwardButton')).not.toBeHidden(); + }); +}); diff --git a/web-ui/test/spec/mail_view/ui/send_button.spec.js b/web-ui/test/spec/mail_view/ui/send_button.spec.js new file mode 100644 index 00000000..27bee0f3 --- /dev/null +++ b/web-ui/test/spec/mail_view/ui/send_button.spec.js @@ -0,0 +1,91 @@ +describeComponent('mail_view/ui/send_button', function () { + + describe('send button', function () { + beforeEach(function () { + setupComponent('