_ = require 'underscore' Rx = require 'rx-lite' {NylasTestUtils} = require 'nylas-exports' Contact = require '../../src/flux/models/contact' NylasAPI = require '../../src/flux/nylas-api' ContactStore = require '../../src/flux/stores/contact-store' ContactRankingStore = require '../../src/flux/stores/contact-ranking-store' DatabaseStore = require '../../src/flux/stores/database-store' AccountStore = require '../../src/flux/stores/account-store' {mockObservable} = NylasTestUtils describe "ContactStore", -> beforeEach -> spyOn(NylasEnv, "isMainWindow").andReturn true @rankings = [ ["evanA@nylas.com", 10] ["evanB@nylas.com", 1] ["evanC@nylas.com", 0.1] ] spyOn(NylasAPI, "makeRequest").andCallFake (options) => if options.path is "/contacts/rankings" return Promise.resolve(@rankings) else throw new Error("Invalid request path!") NylasEnv.testOrganizationUnit = "folder" ContactStore._contactCache = [] ContactStore._fetchOffset = 0 ContactStore._accountId = null ContactRankingStore.reset() afterEach -> NylasEnv.testOrganizationUnit = null describe "when Contacts change", -> beforeEach -> spyOn(ContactStore, "_sortContactsCacheWithRankings") spyOn(Rx.Observable, 'fromQuery').andReturn mockObservable([1, 2]) ContactStore._registerObservables() it "updates the contact cache", -> expect(ContactStore._contactCache).toEqual [1, 2] it "sorts the contacts", -> expect(ContactStore._sortContactsCacheWithRankings).toHaveBeenCalled() describe "ranking contacts", -> beforeEach -> @accountId = TEST_ACCOUNT_ID @c1 = new Contact({name: "Evan A", email: "evanA@nylas.com", @accountId}) @c2 = new Contact({name: "Evan B", email: "evanB@nylas.com", @accountId}) @c3 = new Contact({name: "Evan C", email: "evanC@nylas.com", @accountId}) @c4 = new Contact({name: "Ben", email: "ben@nylas.com"}) @contacts = [@c3, @c1, @c2, @c4] it "triggers a sort on a contact refresh", -> spyOn(ContactStore, "_sortContactsCacheWithRankings") ContactStore._onContactsChanged(@contacts) expect(ContactStore._sortContactsCacheWithRankings).toHaveBeenCalled() it "sorts the contact cache by the rankings", -> spyOn(ContactRankingStore, 'valuesForAllAccounts').andReturn "evana@nylas.com": 10 "evanb@nylas.com": 1 "evanc@nylas.com": 0.1 cache = {} cache = [@c3, @c1, @c2, @c4] ContactStore._contactCache = cache ContactStore._sortContactsCacheWithRankings() expect(ContactStore._contactCache).toEqual [@c1, @c2, @c3, @c4] describe "when ContactRankings change", -> it "sorts the contact cache", -> spyOn(ContactStore, "_sortContactsCacheWithRankings") ContactStore._registerListeners() ContactRankingStore.trigger() expect(ContactStore._sortContactsCacheWithRankings).toHaveBeenCalled() describe "when searching for a contact", -> beforeEach -> @c1 = new Contact(name: "", email: "1test@nylas.com") @c2 = new Contact(name: "First", email: "2test@nylas.com") @c3 = new Contact(name: "First Last", email: "3test@nylas.com") @c4 = new Contact(name: "Fit", email: "fit@nylas.com") @c5 = new Contact(name: "Fins", email: "fins@nylas.com") @c6 = new Contact(name: "Fill", email: "fill@nylas.com") @c7 = new Contact(name: "Fin", email: "fin@nylas.com") ContactStore._contactCache = [@c1,@c2,@c3,@c4,@c5,@c6,@c7] it "can find by first name", -> results = ContactStore.searchContacts("First", noPromise: true) expect(results.length).toBe 2 expect(results[0]).toBe @c2 expect(results[1]).toBe @c3 it "can find by last name", -> results = ContactStore.searchContacts("Last", noPromise: true) expect(results.length).toBe 1 expect(results[0]).toBe @c3 it "can find by email", -> results = ContactStore.searchContacts("1test", noPromise: true) expect(results.length).toBe 1 expect(results[0]).toBe @c1 it "is case insensitive", -> results = ContactStore.searchContacts("FIrsT", noPromise: true) expect(results.length).toBe 2 expect(results[0]).toBe @c2 expect(results[1]).toBe @c3 it "only returns the number requested", -> results = ContactStore.searchContacts("FIrsT", limit: 1, noPromise: true) expect(results.length).toBe 1 expect(results[0]).toBe @c2 it "returns no more than 5 by default", -> results = ContactStore.searchContacts("fi", noPromise: true) expect(results.length).toBe 5 it "can return more than 5 if requested", -> results = ContactStore.searchContacts("fi", limit: 6, noPromise: true) expect(results.length).toBe 6 describe 'isValidContact', -> it "should return true for a variety of valid contacts", -> expect(ContactStore.isValidContact(new Contact(name: 'Ben', email: 'ben@nylas.com'))).toBe(true) expect(ContactStore.isValidContact(new Contact(email: 'ben@nylas.com'))).toBe(true) expect(ContactStore.isValidContact(new Contact(email: 'ben+123@nylas.com'))).toBe(true) it "should return false for non-Contact objects", -> expect(ContactStore.isValidContact({name: 'Ben', email: 'ben@nylas.com'})).toBe(false) it "should return false if the contact has no email", -> expect(ContactStore.isValidContact(new Contact(name: 'Ben'))).toBe(false) it "should return false if the contact has an email that is not valid", -> expect(ContactStore.isValidContact(new Contact(name: 'Ben', email:'Ben '))).toBe(false) expect(ContactStore.isValidContact(new Contact(name: 'Ben', email:''))).toBe(false) expect(ContactStore.isValidContact(new Contact(name: 'Ben', email:'"ben@nylas.com"'))).toBe(false) it "returns false if we're not passed a contact", -> expect(ContactStore.isValidContact()).toBe false it "returns false if the contact doesn't have an email", -> expect(ContactStore.isValidContact(new Contact(name: "test"))).toBe false it "returns false if the email doesn't satisfy the regex", -> expect(ContactStore.isValidContact(new Contact(name: "test", email: "foo"))).toBe false it "returns false if the email doesn't match", -> expect(ContactStore.isValidContact(new Contact(name: "test", email: "foo@"))).toBe false describe 'parseContactsInString', -> testCases = # Single contact test cases "evan@nylas.com": [new Contact(name: "evan@nylas.com", email: "evan@nylas.com")] "Evan Morikawa": [] "'evan@nylas.com'": [new Contact(name: "evan@nylas.com", email: "evan@nylas.com")] "\"evan@nylas.com\"": [new Contact(name: "evan@nylas.com", email: "evan@nylas.com")] "'evan@nylas.com": [new Contact(name: "'evan@nylas.com", email: "'evan@nylas.com")] "Evan Morikawa ": [new Contact(name: "Evan Morikawa", email: "evan@nylas.com")] "Evan Morikawa (evan@nylas.com)": [new Contact(name: "Evan Morikawa", email: "evan@nylas.com")] "spang (Christine Spang) ": [new Contact(name: "spang (Christine Spang)", email: "noreply+phabricator@nilas.com")] "spang 'Christine Spang' ": [new Contact(name: "spang 'Christine Spang'", email: "noreply+phabricator@nilas.com")] "spang \"Christine Spang\" ": [new Contact(name: "spang \"Christine Spang\"", email: "noreply+phabricator@nilas.com")] "Evan (evan@nylas.com)": [new Contact(name: "Evan", email: "evan@nylas.com")] "\"Michael\" (mg@nylas.com)": [new Contact(name: "Michael", email: "mg@nylas.com")] "announce-uc.1440659566.kankcagcmaacemjlnoma-security=nylas.com@lists.openwall.com": [new Contact(name: "announce-uc.1440659566.kankcagcmaacemjlnoma-security=nylas.com@lists.openwall.com", email: "announce-uc.1440659566.kankcagcmaacemjlnoma-security=nylas.com@lists.openwall.com")] # Multiple contact test cases "Evan Morikawa , Ben ": [ new Contact(name: "Evan Morikawa", email: "evan@nylas.com") new Contact(name: "Ben", email: "ben@nylas.com") ] "mark@nylas.com\nGleb (gleb@nylas.com)\rEvan Morikawa , spang (Christine Spang) ": [ new Contact(name: "", email: "mark@nylas.com") new Contact(name: "Gleb", email: "gleb@nylas.com") new Contact(name: "Evan Morikawa", email: "evan@nylas.com") new Contact(name: "spang (Christine Spang)", email: "noreply+phabricator@nilas.com") ] _.forEach testCases, (value, key) -> it "works for #{key}", -> waitsForPromise -> ContactStore.parseContactsInString(key).then (contacts) -> contacts = contacts.map (c) -> c.toString() expectedContacts = value.map (c) -> c.toString() expect(contacts).toEqual expectedContacts