From 76d01863dbb13d597b0963942c5956210985ef54 Mon Sep 17 00:00:00 2001 From: Daniel Rosado Date: Sat, 3 Dec 2016 15:14:19 +0100 Subject: [PATCH] [Invite Flow] Use email address to collate contacts when no given or family name is provided * Add tests to ContactsPicker collate contacts functionality --- Signal.xcodeproj/project.pbxproj | 4 + .../src/view controllers/ContactsPicker.swift | 4 + Signal/test/contact/ContactsPickerTest.swift | 89 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 Signal/test/contact/ContactsPickerTest.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index f87907c37..0b4180aeb 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -179,6 +179,7 @@ 76EB064818170B33006006FC /* Zid.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04FD18170B33006006FC /* Zid.m */; }; 76EB065618170B34006006FC /* InCallViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB050C18170B33006006FC /* InCallViewController.m */; }; 76EB068618170B34006006FC /* ContactTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB052F18170B33006006FC /* ContactTableViewCell.m */; }; + 954AEE6A1DF33E01002E5410 /* ContactsPickerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954AEE681DF33D32002E5410 /* ContactsPickerTest.swift */; }; A10FDF79184FB4BB007FF963 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76C87F18181EFCE600C4ACAB /* MediaPlayer.framework */; }; A11CD70D17FA230600A2D1B1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */; }; A123C14916F902EE000AE905 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A163E8AA16F3F6A90094D68B /* Security.framework */; }; @@ -844,6 +845,7 @@ 76EB052E18170B33006006FC /* ContactTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactTableViewCell.h; sourceTree = ""; }; 76EB052F18170B33006006FC /* ContactTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactTableViewCell.m; sourceTree = ""; }; 80CD5E19DD23200E7926EEA7 /* libPods-Signal.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Signal.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 954AEE681DF33D32002E5410 /* ContactsPickerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactsPickerTest.swift; sourceTree = ""; }; A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; A163E8AA16F3F6A90094D68B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; A1C32D4D17A0652C000A904E /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; @@ -2025,6 +2027,7 @@ children = ( B660F6761C29867F00687D6E /* OWSContactsManagerTest.m */, 45843D211D223BA10013E85A /* OWSContactsSearcherTest.m */, + 954AEE681DF33D32002E5410 /* ContactsPickerTest.swift */, ); path = contact; sourceTree = ""; @@ -3180,6 +3183,7 @@ B660F7751C29988E00687D6E /* UIColor+OWS.m in Sources */, B660F7761C29988E00687D6E /* UIFont+OWS.m in Sources */, B660F7771C29988E00687D6E /* UIImage+normalizeImage.m in Sources */, + 954AEE6A1DF33E01002E5410 /* ContactsPickerTest.swift in Sources */, B660F7781C29988E00687D6E /* ArrayUtil.m in Sources */, B660F7791C29988E00687D6E /* CyclicalBuffer.m in Sources */, B660F77A1C29988E00687D6E /* PriorityQueue.m in Sources */, diff --git a/Signal/src/view controllers/ContactsPicker.swift b/Signal/src/view controllers/ContactsPicker.swift index 08186ed34..c67b9a2bd 100644 --- a/Signal/src/view controllers/ContactsPicker.swift +++ b/Signal/src/view controllers/ContactsPicker.swift @@ -367,6 +367,10 @@ fileprivate extension CNContact { */ @objc var nameForCollating: String { get { + if self.familyName.isEmpty && self.givenName.isEmpty { + return self.emailAddresses.first?.value as? String ?? "" + } + let compositeName: String if ContactSortOrder == .familyName { compositeName = "\(self.familyName) \(self.givenName)" diff --git a/Signal/test/contact/ContactsPickerTest.swift b/Signal/test/contact/ContactsPickerTest.swift new file mode 100644 index 000000000..f8f1d9d0e --- /dev/null +++ b/Signal/test/contact/ContactsPickerTest.swift @@ -0,0 +1,89 @@ +// +// ContactsPickerTest.swift +// Signal +// +// Created by Daniel Rosado on 03/12/16. +// Copyright © 2016 Open Whisper Systems. All rights reserved. +// + +import XCTest +@testable import Signal + +final class ContactsPickerTest: XCTestCase { + private var prevLang: Any? + + override func setUp() { + super.setUp() + + prevLang = getLang() + } + + override func tearDown() { + super.tearDown() + + if let prevLang = prevLang { + setLang(value: prevLang) + } + } + + @available(iOS 9.0, *) + func testContactSectionMatchesEmailFirstLetterWhenOnlyEmailContact() { + setLangEN() + + let emailOnlyContactB = CNMutableContact() + emailOnlyContactB.emailAddresses.append(CNLabeledValue(label: nil, value: "bla@bla.com")) + + let emailOnlyContactD = CNMutableContact() + emailOnlyContactD.emailAddresses.append(CNLabeledValue(label: nil, value: "dude@bla.com")) + + let contactsPicker = ContactsPicker(delegate: nil) + let collatedContacts = contactsPicker.collatedContacts([emailOnlyContactB, emailOnlyContactD]) + + let sectionTitles = contactsPicker.collation.sectionTitles + if let bIndex = sectionTitles.index(of: "B") { + let bSectionContacts = collatedContacts[bIndex] + XCTAssertEqual(bSectionContacts.first, emailOnlyContactB) + } + + if let dIndex = sectionTitles.index(of: "D") { + let dSectionContacts = collatedContacts[dIndex] + XCTAssertEqual(dSectionContacts.first, emailOnlyContactD) + } + } + + @available(iOS 9.0, *) + func testContactSectionMatchesNameFirstLetterWhenNameExistsInContact() { + setLangEN() + + let nameAndEmailContact = CNMutableContact() + nameAndEmailContact.givenName = "Alice" + nameAndEmailContact.emailAddresses.append(CNLabeledValue(label: nil, value: "nameAndEmail@bla.com")) + + let contactsPicker = ContactsPicker(delegate: nil) + let collatedContacts = contactsPicker.collatedContacts([nameAndEmailContact]) + + let sectionTitles = contactsPicker.collation.sectionTitles + if let aIndex = sectionTitles.index(of: "A") { + let aSectionContacts = collatedContacts[aIndex] + XCTAssertEqual(aSectionContacts.first, nameAndEmailContact) + } + } + + + private func setLangEN() { + setLang(value: "en") + } + + private func setLang(value: Any) { + UserDefaults.standard.set(value, forKey: "AppleLanguages") + UserDefaults.standard.synchronize() + } + + private func setLang(value: String) { + setLang(value: [value]) + } + + private func getLang() -> Any? { + return UserDefaults.standard.value(forKey: "AppleLanguages") + } +}