mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			656 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			656 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Swift
		
	
| import CryptoSwift
 | |
| import PromiseKit
 | |
| @testable import SignalServiceKit
 | |
| import XCTest
 | |
| import Curve25519Kit
 | |
| 
 | |
| class FriendRequestProtocolTests : XCTestCase {
 | |
| 
 | |
|     private var storage: OWSPrimaryStorage { OWSPrimaryStorage.shared() }
 | |
|     private var messageSender: OWSFakeMessageSender { MockSSKEnvironment.shared.messageSender as! OWSFakeMessageSender }
 | |
| 
 | |
|     // MARK: - Setup
 | |
|     override func setUp() {
 | |
|         super.setUp()
 | |
| 
 | |
|         LokiTestUtilities.setUpMockEnvironment()
 | |
|     }
 | |
| 
 | |
|     // MARK: - Helpers
 | |
|     func isFriendRequestStatus(oneOf values: [LKFriendRequestStatus], for hexEncodedPublicKey: String, transaction: YapDatabaseReadWriteTransaction) -> Bool {
 | |
|         let status = storage.getFriendRequestStatus(for: hexEncodedPublicKey, transaction: transaction)
 | |
|         return values.contains(status)
 | |
|     }
 | |
| 
 | |
|     func isFriendRequestStatus(_ value: LKFriendRequestStatus, for hexEncodedPublicKey: String, transaction: YapDatabaseReadWriteTransaction) -> Bool {
 | |
|         return isFriendRequestStatus(oneOf: [ value ], for: hexEncodedPublicKey, transaction: transaction)
 | |
|     }
 | |
| 
 | |
|     // MARK: - shouldInputBarBeEnabled
 | |
|     func test_shouldInputBarBeEnabledReturnsTrueOnGroupThread() {
 | |
|         let allGroupTypes: [GroupType] = [ .closedGroup, .openGroup, .rssFeed ]
 | |
|         for groupType in allGroupTypes {
 | |
|             guard let groupThread = LokiTestUtilities.createGroupThread(groupType: groupType) else { return XCTFail() }
 | |
|             XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: groupThread))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_shouldInputBarBeEnabledReturnsTrueOnNoteToSelf() {
 | |
|         guard let master = OWSIdentityManager.shared().identityKeyPair()?.hexEncodedPublicKey else { return XCTFail() }
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
|         let slaveThread = LokiTestUtilities.createContactThread(for: slave)
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: masterThread))
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: slaveThread))
 | |
|     }
 | |
| 
 | |
|     func test_shouldInputBarBeEnabledReturnsTrueWhenStatusIsNotPending() {
 | |
|         let statuses: [LKFriendRequestStatus] = [ .none, .requestExpired, .friends ]
 | |
|         let device = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let thread = LokiTestUtilities.createContactThread(for: device)
 | |
| 
 | |
|         for status in statuses {
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(status, for: device, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: thread))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_shouldInputBarBeEnabledReturnsFalseWhenStatusIsPending() {
 | |
|         let statuses: [LKFriendRequestStatus] = [ .requestSending, .requestSent, .requestReceived ]
 | |
|         let device = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let thread = LokiTestUtilities.createContactThread(for: device)
 | |
| 
 | |
|         for status in statuses {
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(status, for: device, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             XCTAssertFalse(FriendRequestProtocol.shouldInputBarBeEnabled(for: thread))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_shouldInputBarBeEnabledReturnsTrueWhenFriendsWithOneLinkedDevice() {
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.friends, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
|         let slaveThread = LokiTestUtilities.createContactThread(for: slave)
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: masterThread))
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: slaveThread))
 | |
|     }
 | |
| 
 | |
|     func test_shouldInputBarBeEnabledReturnsFalseWhenOneLinkedDeviceIsPending() {
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.none, for: master, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
|         let slaveThread = LokiTestUtilities.createContactThread(for: slave)
 | |
| 
 | |
|         let statuses: [LKFriendRequestStatus] = [ .requestSending, .requestSent, .requestReceived ]
 | |
|         for status in statuses {
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(status, for: slave, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             XCTAssertFalse(FriendRequestProtocol.shouldInputBarBeEnabled(for: masterThread))
 | |
|             XCTAssertFalse(FriendRequestProtocol.shouldInputBarBeEnabled(for: slaveThread))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_shouldInputBarBeEnabledReturnsTrueWhenAllLinkedDevicesAreNotPendingAndNotFriends() {
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.none, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.none, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
|         let slaveThread = LokiTestUtilities.createContactThread(for: slave)
 | |
| 
 | |
|         let statuses: [LKFriendRequestStatus] = [ .requestExpired, .none ]
 | |
|         for status in statuses {
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(status, for: slave, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: masterThread))
 | |
|             XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: slaveThread))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_shouldInputBarEnabledShouldStillWorkIfLinkedDeviceThreadDoesNotExist() {
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.friends, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldInputBarBeEnabled(for: masterThread))
 | |
|     }
 | |
| 
 | |
|     // MARK: - shouldAttachmentButtonBeEnabled
 | |
|     func test_shouldAttachmentButtonBeEnabledReturnsTrueOnGroupThread() {
 | |
|         let allGroupTypes: [GroupType] = [ .closedGroup, .openGroup, .rssFeed ]
 | |
|         for groupType in allGroupTypes {
 | |
|             guard let groupThread = LokiTestUtilities.createGroupThread(groupType: groupType) else { return XCTFail() }
 | |
|             XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: groupThread))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_shouldAttachmentButtonBeEnabledReturnsTrueOnNoteToSelf() {
 | |
|         guard let master = OWSIdentityManager.shared().identityKeyPair()?.hexEncodedPublicKey else { return XCTFail() }
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
|         let slaveThread = LokiTestUtilities.createContactThread(for: slave)
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: masterThread))
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: slaveThread))
 | |
|     }
 | |
| 
 | |
|     func test_shouldAttachmentButtonBeEnabledReturnsTrueWhenFriends() {
 | |
|         let device = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let thread = LokiTestUtilities.createContactThread(for: device)
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.setFriendRequestStatus(.friends, for: device, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: thread))
 | |
|     }
 | |
| 
 | |
|     func test_shouldAttachmentButtonBeEnabledReturnsFalseWhenNotFriends() {
 | |
|         let statuses: [LKFriendRequestStatus] = [ .requestSending, .requestSent, .requestReceived, .none, .requestExpired ]
 | |
|         let device = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let thread = LokiTestUtilities.createContactThread(for: device)
 | |
| 
 | |
|         for status in statuses {
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(status, for: device, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             XCTAssertFalse(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: thread))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_shouldAttachmentButtonBeEnabledReturnsTrueWhenFriendsWithOneLinkedDevice() {
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.friends, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
|         let slaveThread = LokiTestUtilities.createContactThread(for: slave)
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: masterThread))
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: slaveThread))
 | |
|     }
 | |
| 
 | |
|     func test_shouldAttachmentButtonBeEnabledShouldStillWorkIfLinkedDeviceThreadDoesNotExist() {
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.none, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.friends, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldAttachmentButtonBeEnabled(for: masterThread))
 | |
|     }
 | |
| 
 | |
|     // MARK: - getFriendRequestUIState
 | |
|     func test_getFriendRequestUIStateShouldReturnNoneForGroupThreads() {
 | |
|         let allGroupTypes: [GroupType] = [ .closedGroup, .openGroup, .rssFeed ]
 | |
|         for groupType in allGroupTypes {
 | |
|             guard let groupThread = LokiTestUtilities.createGroupThread(groupType: groupType) else { return XCTFail() }
 | |
|             XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIStatus(for: groupThread) == .none)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_getFriendRequestUIStateShouldReturnNoneOnNoteToSelf() {
 | |
|         guard let master = OWSIdentityManager.shared().identityKeyPair()?.hexEncodedPublicKey else { return XCTFail() }
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.friends, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.friends, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
|         let slaveThread = LokiTestUtilities.createContactThread(for: slave)
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIStatus(for: masterThread) == .none)
 | |
|         XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIStatus(for: slaveThread) == .none )
 | |
|     }
 | |
| 
 | |
|     func test_getFriendRequestUIStateShouldReturnTheCorrectStates() {
 | |
|         let bob = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let bobThread = LokiTestUtilities.createContactThread(for: bob)
 | |
| 
 | |
|         let expectedStatuses: [LKFriendRequestStatus:FriendRequestProtocol.FriendRequestUIStatus] = [
 | |
|             .none: .none,
 | |
|             .requestExpired: .expired,
 | |
|             .requestSending: .sent,
 | |
|             .requestSent: .sent,
 | |
|             .requestReceived: .received,
 | |
|             .friends: .friends,
 | |
|         ]
 | |
| 
 | |
|         for (friendRequestStatus, uiState) in expectedStatuses {
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(friendRequestStatus, for: bob, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             XCTAssertEqual(FriendRequestProtocol.getFriendRequestUIStatus(for: bobThread), uiState, "Expected FriendRequestUIStatus to be \(uiState).")
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_getFriendRequestUIStateShouldWorkWithMultiDevice() {
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.none, for: master, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
|         let slaveThread = LokiTestUtilities.createContactThread(for: slave)
 | |
| 
 | |
|         let expectedStatuses: [LKFriendRequestStatus:FriendRequestProtocol.FriendRequestUIStatus] = [
 | |
|             .none: .none,
 | |
|             .requestExpired: .expired,
 | |
|             .requestSending: .sent,
 | |
|             .requestSent: .sent,
 | |
|             .requestReceived: .received,
 | |
|             .friends: .friends,
 | |
|         ]
 | |
| 
 | |
|         for (friendRequestStatus, uiState) in expectedStatuses {
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(friendRequestStatus, for: slave, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             XCTAssertEqual(FriendRequestProtocol.getFriendRequestUIStatus(for: masterThread), uiState, "Expected FriendRequestUIStatus to be \(uiState.rawValue).")
 | |
|             XCTAssertEqual(FriendRequestProtocol.getFriendRequestUIStatus(for: slaveThread), uiState, "Expected FriendRequestUIStatus to be \(uiState.rawValue).")
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_getFriendRequestUIStateShouldPreferFriendsOverRequestReceived() {
 | |
|         // Case: We don't want to confuse the user by showing a friend request box when they're already friends.
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.friends, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIStatus(for: masterThread) == .friends)
 | |
|     }
 | |
| 
 | |
|     func test_getFriendRequestUIStateShouldPreferReceivedOverSent() {
 | |
|         // Case: We sent Bob a friend request and he sent one back to us through another device.
 | |
|         // If something went wrong then we should be able to fall back to manually accepting the friend request even if we sent one.
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
| 
 | |
|         let masterThread = LokiTestUtilities.createContactThread(for: master)
 | |
| 
 | |
|         let deviceLink = DeviceLink(between: masterDevice, and: slaveDevice)
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(deviceLink, in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: slave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.getFriendRequestUIStatus(for: masterThread) == .received)
 | |
|     }
 | |
| 
 | |
|     // MARK: - acceptFriendRequest
 | |
|     func test_acceptFriendRequestShouldSetStatusToFriendsIfWeReceivedAFriendRequest() {
 | |
|         // Case: Bob sent us a friend request, we should become friends with him on accepting.
 | |
|         let bob = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: bob, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             FriendRequestProtocol.acceptFriendRequest(from: bob, using: transaction)
 | |
|             XCTAssertTrue(self.storage.getFriendRequestStatus(for: bob, transaction: transaction) == .friends)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // TODO: Add test to see if an accept message is sent out
 | |
| 
 | |
|     func test_acceptFriendRequestShouldSendAFriendRequestMessageIfStatusIsNoneOrExpired() {
 | |
|         // Case: Somehow our friend request status doesn't match the UI.
 | |
|         // Since user accepted then we should send a friend request message.
 | |
|         let statuses: [LKFriendRequestStatus] = [ .none, .requestExpired ]
 | |
|         for status in statuses {
 | |
|             let bob = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(status, for: bob, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             let expectation = self.expectation(description: "Send message")
 | |
| 
 | |
|             let messageSender = self.messageSender
 | |
|             messageSender.sendMessageWasCalledBlock = { sentMessage in
 | |
|                 guard sentMessage is FriendRequestMessage else {
 | |
|                     return XCTFail("Expected a friend request to be sent, but found: \(sentMessage).")
 | |
|                 }
 | |
|                 expectation.fulfill()
 | |
|                 messageSender.sendMessageWasCalledBlock = nil
 | |
|             }
 | |
| 
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 FriendRequestProtocol.acceptFriendRequest(from: bob, using: transaction)
 | |
|             }
 | |
| 
 | |
|             wait(for: [ expectation ], timeout: 1)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_acceptFriendRequestShouldNotSendAFriendRequestMessageToOurOwnDevice() {
 | |
|         let statuses: [LKFriendRequestStatus] = [ .none, .requestExpired ]
 | |
|         for status in statuses {
 | |
|             let ourDevice = LokiTestUtilities.getCurrentUserHexEncodedPublicKey()
 | |
| 
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(status, for: ourDevice, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             let expectation = self.expectation(description: "Send message")
 | |
| 
 | |
|             let messageSender = self.messageSender
 | |
|             messageSender.sendMessageWasCalledBlock = { sentMessage in
 | |
|                 XCTFail("Expected message not to be sent.")
 | |
|             }
 | |
| 
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 FriendRequestProtocol.acceptFriendRequest(from: ourDevice, using: transaction)
 | |
|             }
 | |
| 
 | |
|             expectation.fulfillAfter(2)
 | |
|             wait(for: [ expectation ], timeout: 2)
 | |
|             messageSender.sendMessageWasCalledBlock = nil
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_acceptFriendRequestShouldNotDoAnythingIfRequestHasBeenSent() {
 | |
|         // Case: We sent Bob a friend request.
 | |
|         // We can't accept because we don't have keys to communicate with Bob.
 | |
|         let bob = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: bob, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             FriendRequestProtocol.acceptFriendRequest(from: bob, using: transaction)
 | |
|             XCTAssertTrue(self.isFriendRequestStatus(.requestSent, for: bob, transaction: transaction))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_acceptFriendRequestShouldWorkWithMultiDevice() {
 | |
|         // Case: Bob sent a friend request from his slave device.
 | |
|         // Accepting the friend request should set it to friends.
 | |
|         // We should also send out a friend request to Bob's other devices if possible.
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let otherSlave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
|         guard let otherSlaveDevice = LokiTestUtilities.getDevice(for: otherSlave) else { return XCTFail() }
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(DeviceLink(between: masterDevice, and: slaveDevice), in: transaction)
 | |
|             self.storage.addDeviceLink(DeviceLink(between: masterDevice, and: otherSlaveDevice), in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.none, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: slave, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: otherSlave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             FriendRequestProtocol.acceptFriendRequest(from: master, using: transaction)
 | |
|         }
 | |
| 
 | |
|         eventually {
 | |
|             self.storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 // TODO: Re-enable this case when we split friend request logic from OWSMessageSender
 | |
|                 // XCTAssertTrue(self.isFriendRequestStatus([ .requestSending, .requestSent ], for: master, transaction: transaction))
 | |
|                 XCTAssertTrue(self.isFriendRequestStatus(.friends, for: slave, transaction: transaction))
 | |
|                 XCTAssertTrue(self.isFriendRequestStatus(.requestSent, for: otherSlave, transaction: transaction))
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_acceptFriendRequestShouldNotChangeStatusIfDevicesAreNotLinked() {
 | |
|         let alice = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let bob = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: alice, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: bob, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             FriendRequestProtocol.acceptFriendRequest(from: alice, using: transaction)
 | |
|             XCTAssertTrue(self.isFriendRequestStatus(.friends, for: alice, transaction: transaction))
 | |
|             XCTAssertTrue(self.isFriendRequestStatus(.requestReceived, for: bob, transaction: transaction))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // MARK: - declineFriendRequest
 | |
|     func test_declineFriendRequestShouldChangeStatusFromReceivedToNone() {
 | |
|         let bob = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: bob, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             FriendRequestProtocol.declineFriendRequest(from: bob, using: transaction)
 | |
|             XCTAssertTrue(self.isFriendRequestStatus(.none, for: bob, transaction: transaction))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_declineFriendRequestShouldNotChangeStatusToNoneFromOtherStatuses() {
 | |
|         let statuses: [LKFriendRequestStatus] = [ .none, .requestSending, .requestSent, .requestExpired, .friends ]
 | |
|         let bob = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         for status in statuses {
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setFriendRequestStatus(status, for: bob, transaction: transaction)
 | |
|             }
 | |
|             
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 FriendRequestProtocol.declineFriendRequest(from: bob, using: transaction)
 | |
|                 XCTAssertTrue(self.isFriendRequestStatus(status, for: bob, transaction: transaction))
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_declineFriendRequestShouldDeletePreKeyBundleIfNeeded() {
 | |
|         let shouldExpectDeletedPreKeyBundle: (LKFriendRequestStatus) -> Bool = { status in
 | |
|             return status == .requestReceived
 | |
|         }
 | |
| 
 | |
|         let statuses: [LKFriendRequestStatus] = [ .none, .requestSending, .requestSent, .requestReceived, .requestExpired, .friends ]
 | |
|         for status in statuses {
 | |
|             let bob = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|             let bundle = storage.generatePreKeyBundle(forContact: bob)
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 self.storage.setPreKeyBundle(bundle, forContact: bob, transaction: transaction)
 | |
|                 self.storage.setFriendRequestStatus(status, for: bob, transaction: transaction)
 | |
|             }
 | |
| 
 | |
|             storage.dbReadWriteConnection.readWrite { transaction in
 | |
|                 FriendRequestProtocol.declineFriendRequest(from: bob, using: transaction)
 | |
|             }
 | |
| 
 | |
|             let storedBundle = storage.getPreKeyBundle(forContact: bob)
 | |
|             if (shouldExpectDeletedPreKeyBundle(status)) {
 | |
|                 XCTAssertNil(storedBundle, "Expected PreKeyBundle to be deleted for friend request status \(status.rawValue).")
 | |
|             } else {
 | |
|                 XCTAssertNotNil(storedBundle, "Expected PreKeyBundle to not be deleted for friend request status \(status.rawValue).")
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_declineFriendRequestShouldWorkWithMultipleLinkedDevices() {
 | |
|         // Case: Bob sends 2 friend requests to Alice.
 | |
|         // When Alice declines, it should change the statuses from requestReceived to none so friend request logic can be re-triggered.
 | |
|         let master = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let slave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
|         let otherSlave = LokiTestUtilities.generateHexEncodedPublicKey()
 | |
| 
 | |
|         guard let masterDevice = LokiTestUtilities.getDevice(for: master) else { return XCTFail() }
 | |
|         guard let slaveDevice = LokiTestUtilities.getDevice(for: slave) else { return XCTFail() }
 | |
|         guard let otherSlaveDevice = LokiTestUtilities.getDevice(for: otherSlave) else { return XCTFail() }
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             self.storage.addDeviceLink(DeviceLink(between: masterDevice, and: slaveDevice), in: transaction)
 | |
|             self.storage.addDeviceLink(DeviceLink(between: masterDevice, and: otherSlaveDevice), in: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestSent, for: master, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: slave, transaction: transaction)
 | |
|             self.storage.setFriendRequestStatus(.requestReceived, for: otherSlave, transaction: transaction)
 | |
|         }
 | |
| 
 | |
|         storage.dbReadWriteConnection.readWrite { transaction in
 | |
|             FriendRequestProtocol.declineFriendRequest(from: master, using: transaction)
 | |
|             XCTAssertTrue(self.isFriendRequestStatus(.requestSent, for: master, transaction: transaction))
 | |
|             XCTAssertTrue(self.isFriendRequestStatus(.none, for: slave, transaction: transaction))
 | |
|             XCTAssertTrue(self.isFriendRequestStatus(.none, for: otherSlave, transaction: transaction))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // MARK: - shouldUpdateFriendRequestStatus
 | |
|     func test_shouldUpdateFriendRequestStatusReturnsTheCorrectValue() {
 | |
|         let thread = LokiTestUtilities.createContactThread(for: LokiTestUtilities.generateHexEncodedPublicKey())
 | |
| 
 | |
|         let message = TSOutgoingMessage(in: thread, messageBody: nil, attachmentId: nil)
 | |
|         let friendRequest = FriendRequestMessage(timestamp: 1, thread: thread, body: "")
 | |
|         let sessionRequest = SessionRequestMessage(thread: thread)
 | |
|         guard let deviceLinkRequest = DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: "", slaveHexEncodedPublicKey: "", masterSignature: nil, slaveSignature: Data(capacity: 0)),
 | |
|             let deviceLinkAuthorisation = DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: "", slaveHexEncodedPublicKey: "", masterSignature: Data(capacity: 0), slaveSignature: Data(capacity: 0)) else { return XCTFail() }
 | |
| 
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: friendRequest))
 | |
|         XCTAssertTrue(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: deviceLinkRequest))
 | |
|         XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: message))
 | |
|         XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: sessionRequest))
 | |
|         XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: deviceLinkAuthorisation))
 | |
|     }
 | |
| 
 | |
|     func test_shouldUpdateFriendRequestStatusReturnsFalseForGroupThreads() {
 | |
|         let allGroupTypes: [GroupType] = [ .closedGroup, .openGroup, .rssFeed ]
 | |
|         for groupType in allGroupTypes {
 | |
|             guard let groupThread = LokiTestUtilities.createGroupThread(groupType: groupType) else { return XCTFail() }
 | |
|             let friendRequest = FriendRequestMessage(timestamp: 1, thread: groupThread, body: "")
 | |
|             XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: friendRequest))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func test_shouldUpdateFriendRequestStatusReturnsFalseForCurrentDevice() {
 | |
|         let thread = LokiTestUtilities.createContactThread(for: LokiTestUtilities.getCurrentUserHexEncodedPublicKey())
 | |
|         let friendRequest = FriendRequestMessage(timestamp: 1, thread: thread, body: "")
 | |
|         XCTAssertFalse(FriendRequestProtocol.shouldUpdateFriendRequestStatus(from: friendRequest))
 | |
|     }
 | |
| }
 |