mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Further work on OpenGroupManager tests
Added tests for the OpenGroupManager handleMessages logic Updated some logic to do an optional unwrap instead of a forced one to prevent the code from crashing when running unit tests Fixed some tests which were flaky (could fail if other tests ran at the same time on other threads) Fixed a minor potential bug where a message with no sender data wouldn't get deleted (shouldn't be dependant on the sender value being populated)
This commit is contained in:
parent
b1684f6b23
commit
37f4d2ecca
8 changed files with 416 additions and 33 deletions
|
@ -781,6 +781,7 @@
|
|||
FD078E4F27E175F1000769AF /* DependencyExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E4E27E175F1000769AF /* DependencyExtensions.swift */; };
|
||||
FD078E5227E1760A000769AF /* OGMDependencyExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E5127E1760A000769AF /* OGMDependencyExtensions.swift */; };
|
||||
FD078E5427E197CA000769AF /* OpenGroupManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909D27D85751005DAE71 /* OpenGroupManagerSpec.swift */; };
|
||||
FD078E5827E1B831000769AF /* TestIncomingMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD078E5727E1B831000769AF /* TestIncomingMessage.swift */; };
|
||||
FD0BA51B27CD88EC00CC6805 /* BlindedIdMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0BA51A27CD88EC00CC6805 /* BlindedIdMapping.swift */; };
|
||||
FD0BA51D27CDC34600CC6805 /* SOGSV4Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0BA51C27CDC34600CC6805 /* SOGSV4Migration.swift */; };
|
||||
FD5D200F27AA2B6000FEA984 /* MessageRequestResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5D200E27AA2B6000FEA984 /* MessageRequestResponse.swift */; };
|
||||
|
@ -1926,6 +1927,7 @@
|
|||
FD078E4C27E17156000769AF /* MockOGMCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockOGMCache.swift; sourceTree = "<group>"; };
|
||||
FD078E4E27E175F1000769AF /* DependencyExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependencyExtensions.swift; sourceTree = "<group>"; };
|
||||
FD078E5127E1760A000769AF /* OGMDependencyExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OGMDependencyExtensions.swift; sourceTree = "<group>"; };
|
||||
FD078E5727E1B831000769AF /* TestIncomingMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestIncomingMessage.swift; sourceTree = "<group>"; };
|
||||
FD0BA51A27CD88EC00CC6805 /* BlindedIdMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlindedIdMapping.swift; sourceTree = "<group>"; };
|
||||
FD0BA51C27CDC34600CC6805 /* SOGSV4Migration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOGSV4Migration.swift; sourceTree = "<group>"; };
|
||||
FD5D200E27AA2B6000FEA984 /* MessageRequestResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestResponse.swift; sourceTree = "<group>"; };
|
||||
|
@ -4060,6 +4062,7 @@
|
|||
FDC2909F27D85826005DAE71 /* TestThread.swift */,
|
||||
FDC290B627E00FDB005DAE71 /* TestGroupThread.swift */,
|
||||
FDC290A127D85890005DAE71 /* TestInteraction.swift */,
|
||||
FD078E5727E1B831000769AF /* TestIncomingMessage.swift */,
|
||||
FDC290AB27DB0B1C005DAE71 /* MockedExtensions.swift */,
|
||||
FD078E4E27E175F1000769AF /* DependencyExtensions.swift */,
|
||||
FD078E5127E1760A000769AF /* OGMDependencyExtensions.swift */,
|
||||
|
@ -5657,6 +5660,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
FDC290AC27DB0B1C005DAE71 /* MockedExtensions.swift in Sources */,
|
||||
FD078E5827E1B831000769AF /* TestIncomingMessage.swift in Sources */,
|
||||
FD859EFA27C2F5C500510D0C /* MockGenericHash.swift in Sources */,
|
||||
FDC2909427D710B4005DAE71 /* SOGSEndpointSpec.swift in Sources */,
|
||||
FDC290AF27DFEE97005DAE71 /* TestTransaction.swift in Sources */,
|
||||
|
|
|
@ -321,6 +321,7 @@ public final class OpenGroupManager: NSObject {
|
|||
// Sorting the messages by server ID before importing them fixes an issue where messages
|
||||
// that quote older messages can't find those older messages
|
||||
let openGroupID = "\(server).\(roomToken)"
|
||||
let openGroupIdData: Data = LKGroupUtilities.getEncodedOpenGroupIDAsData(openGroupID)
|
||||
let sortedMessages: [OpenGroupAPI.Message] = messages
|
||||
.sorted { lhs, rhs in lhs.id < rhs.id }
|
||||
let seqNo: Int64? = sortedMessages.map { $0.seqNo }.max()
|
||||
|
@ -333,11 +334,12 @@ public final class OpenGroupManager: NSObject {
|
|||
|
||||
// Process the messages
|
||||
sortedMessages.forEach { message in
|
||||
guard let base64EncodedString: String = message.base64EncodedData, let data = Data(base64Encoded: base64EncodedString), let sender: String = message.sender else {
|
||||
guard let base64EncodedString: String = message.base64EncodedData, let data = Data(base64Encoded: base64EncodedString) else {
|
||||
// A message with no data has been deleted so add it to the list to remove
|
||||
messageServerIDsToRemove.append(UInt64(message.id))
|
||||
return
|
||||
}
|
||||
guard let sender: String = message.sender else { return } // Need a sender in order to process the message
|
||||
|
||||
// Note: The `posted` value is in seconds but all messages in the database use milliseconds for timestamps
|
||||
let envelope = SNProtoEnvelope.builder(type: .sessionMessage, timestamp: UInt64(floor(message.posted * 1000)))
|
||||
|
@ -356,7 +358,7 @@ public final class OpenGroupManager: NSObject {
|
|||
|
||||
// Handle any deletions that are needed
|
||||
guard !messageServerIDsToRemove.isEmpty else { return }
|
||||
guard let thread = TSGroupThread.fetch(groupId: openGroupID, transaction: transaction) else { return }
|
||||
guard let thread = TSGroupThread.fetch(groupId: openGroupIdData, transaction: transaction) else { return }
|
||||
|
||||
var messagesToRemove: [TSMessage] = []
|
||||
|
||||
|
|
|
@ -411,12 +411,17 @@ extension MessageReceiver {
|
|||
}
|
||||
|
||||
// Notify the user if needed
|
||||
guard let tsIncomingMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) as? TSIncomingMessage,
|
||||
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return tsMessageID }
|
||||
guard
|
||||
let tsIncomingMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) as? TSIncomingMessage,
|
||||
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction)
|
||||
else {
|
||||
return tsMessageID
|
||||
}
|
||||
|
||||
// Use the same identifier for notifications when in backgroud polling to prevent spam
|
||||
let notificationIdentifier = isBackgroundPoll ? thread.uniqueId : UUID().uuidString
|
||||
tsIncomingMessage.setNotificationIdentifier(notificationIdentifier, transaction: transaction)
|
||||
SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction)
|
||||
SSKEnvironment.shared.notificationsManager?.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction)
|
||||
return tsMessageID
|
||||
}
|
||||
|
||||
|
|
|
@ -79,10 +79,12 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
var dependencies: OpenGroupManager.OGMDependencies!
|
||||
|
||||
var testInteraction: TestInteraction!
|
||||
var testIncomingMessage: TestIncomingMessage!
|
||||
var testGroupThread: TestGroupThread!
|
||||
var testTransaction: TestTransaction!
|
||||
var testOpenGroup: OpenGroup!
|
||||
var testPollInfo: OpenGroupAPI.RoomPollInfo!
|
||||
var testMessage: OpenGroupAPI.Message!
|
||||
|
||||
var cache: OpenGroupManager.Cache!
|
||||
var openGroupManager: OpenGroupManager!
|
||||
|
@ -116,6 +118,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
testInteraction.mockData[.uniqueId] = "TestInteractionId"
|
||||
testInteraction.mockData[.timestamp] = UInt64(123)
|
||||
|
||||
testIncomingMessage = TestIncomingMessage(uniqueId: "TestMessageId")
|
||||
testIncomingMessage.openGroupServerMessageID = 127
|
||||
|
||||
testGroupThread = TestGroupThread()
|
||||
testGroupThread.mockData[.uniqueId] = "TestGroupId"
|
||||
testGroupThread.mockData[.groupModel] = TSGroupModel(
|
||||
|
@ -127,7 +132,7 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
adminIds: [],
|
||||
moderatorIds: []
|
||||
)
|
||||
testGroupThread.mockData[.interactions] = [testInteraction]
|
||||
testGroupThread.mockData[.interactions] = [testInteraction, testIncomingMessage]
|
||||
|
||||
testTransaction = TestTransaction()
|
||||
testTransaction.mockData[.objectForKey] = testGroupThread
|
||||
|
@ -157,6 +162,30 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
defaultUpload: nil,
|
||||
details: TestCapabilitiesAndRoomApi.roomData
|
||||
)
|
||||
testMessage = OpenGroupAPI.Message(
|
||||
id: 127,
|
||||
sender: "05\(TestConstants.publicKey)",
|
||||
posted: 123,
|
||||
edited: nil,
|
||||
seqNo: 124,
|
||||
whisper: false,
|
||||
whisperMods: false,
|
||||
whisperTo: nil,
|
||||
base64EncodedData: [
|
||||
"Cg0KC1Rlc3RNZXNzYWdlg",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AAAAAAAAAAAAAAAAAAAAA",
|
||||
"AA"
|
||||
].joined(),
|
||||
base64EncodedSignature: nil
|
||||
)
|
||||
|
||||
mockStorage
|
||||
.when { $0.write(with: { _ in }) }
|
||||
|
@ -407,6 +436,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
|
||||
// MARK: - Adding & Removing
|
||||
|
||||
// MARK: - --add
|
||||
|
||||
context("when adding") {
|
||||
beforeEach {
|
||||
mockStorage.when { $0.removeOpenGroupSequenceNumber(for: any(), on: any(), using: anyAny()) }.thenReturn(())
|
||||
|
@ -428,6 +459,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("resets the sequence number of the open group") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
openGroupManager
|
||||
.add(
|
||||
roomToken: "testRoom",
|
||||
|
@ -437,21 +470,25 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
.map { _ -> Void in didComplete = true }
|
||||
.retainUntilComplete()
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.to(
|
||||
call(.exactly(times: 1)) {
|
||||
$0.removeOpenGroupSequenceNumber(
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
using: testTransaction as Any
|
||||
using: testTransaction! as Any
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
it("sets the public key of the open group server") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
openGroupManager
|
||||
.add(
|
||||
roomToken: "testRoom",
|
||||
|
@ -461,21 +498,25 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
.map { _ -> Void in didComplete = true }
|
||||
.retainUntilComplete()
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.to(
|
||||
call(.exactly(times: 1)) {
|
||||
$0.setOpenGroupPublicKey(
|
||||
for: "testRoom",
|
||||
to: "testKey",
|
||||
using: testTransaction as Any
|
||||
using: testTransaction! as Any
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
it("adds a poller") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
openGroupManager
|
||||
.add(
|
||||
roomToken: "testRoom",
|
||||
|
@ -485,8 +526,10 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
.map { _ -> Void in didComplete = true }
|
||||
.retainUntilComplete()
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockOGMCache)
|
||||
.toEventually(
|
||||
call(matchingParameters: true) {
|
||||
|
@ -502,6 +545,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("does not reset the sequence number or update the public key") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
openGroupManager
|
||||
.add(
|
||||
roomToken: "testRoom",
|
||||
|
@ -511,15 +556,17 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
.map { _ -> Void in didComplete = true }
|
||||
.retainUntilComplete()
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.toEventuallyNot(
|
||||
call {
|
||||
$0.removeOpenGroupSequenceNumber(
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
using: testTransaction as Any
|
||||
using: testTransaction! as Any
|
||||
)
|
||||
},
|
||||
timeout: .milliseconds(100)
|
||||
|
@ -530,7 +577,7 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
$0.setOpenGroupPublicKey(
|
||||
for: "testRoom",
|
||||
to: "testKey",
|
||||
using: testTransaction as Any
|
||||
using: testTransaction! as Any
|
||||
)
|
||||
},
|
||||
timeout: .milliseconds(100)
|
||||
|
@ -574,8 +621,12 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
}
|
||||
|
||||
context("when removing") {
|
||||
// MARK: - --delete
|
||||
|
||||
context("when deleting") {
|
||||
beforeEach {
|
||||
testGroupThread.mockData[.interactions] = [testInteraction]
|
||||
|
||||
mockStorage
|
||||
.when { $0.updateMessageIDCollectionByPruningMessagesWithIDs(anySet(), using: anyAny()) }
|
||||
.thenReturn(())
|
||||
|
@ -838,6 +889,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("attempts to retrieve the existing thread") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
testPollInfo,
|
||||
publicKey: TestConstants.publicKey,
|
||||
|
@ -845,13 +898,15 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
// The 'testGroupThread' should be the one retrieved
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(testGroupThread.numSaveCalls).to(equal(1))
|
||||
}
|
||||
|
||||
it("attempts to retrieve the existing open group") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
testPollInfo,
|
||||
publicKey: TestConstants.publicKey,
|
||||
|
@ -859,12 +914,15 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage).to(call { $0.getOpenGroup(for: any()) })
|
||||
}
|
||||
|
||||
it("saves the thread") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
testPollInfo,
|
||||
publicKey: TestConstants.publicKey,
|
||||
|
@ -872,12 +930,15 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(testGroupThread.numSaveCalls).to(equal(1))
|
||||
}
|
||||
|
||||
it("saves the open group") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
testPollInfo,
|
||||
publicKey: TestConstants.publicKey,
|
||||
|
@ -885,12 +946,15 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage).to(call { $0.setOpenGroup(any(), for: any(), using: anyAny()) })
|
||||
}
|
||||
|
||||
it("saves the updated user count") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
testPollInfo,
|
||||
publicKey: TestConstants.publicKey,
|
||||
|
@ -898,8 +962,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.to(call(matchingParameters: true) {
|
||||
$0.setUserCount(to: 10, forOpenGroupWithID: "testServer.testRoom", using: testTransaction! as Any)
|
||||
|
@ -929,6 +994,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
|
||||
context("and updating the moderator list") {
|
||||
it("successfully updates") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockOGMCache.when { $0.moderators }.thenReturn([:])
|
||||
testPollInfo = OpenGroupAPI.RoomPollInfo(
|
||||
token: "testRoom",
|
||||
|
@ -954,8 +1021,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockOGMCache)
|
||||
.toEventually(
|
||||
call(matchingParameters: true) {
|
||||
|
@ -966,6 +1034,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("defaults to an empty array if no moderators are provided") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockOGMCache.when { $0.moderators }.thenReturn([:])
|
||||
testPollInfo = OpenGroupAPI.RoomPollInfo(
|
||||
token: "testRoom",
|
||||
|
@ -991,8 +1061,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockOGMCache)
|
||||
.toEventually(
|
||||
call(matchingParameters: true) {
|
||||
|
@ -1005,6 +1076,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
|
||||
context("and updating the admin list") {
|
||||
it("successfully updates") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockOGMCache.when { $0.admins }.thenReturn([:])
|
||||
testPollInfo = OpenGroupAPI.RoomPollInfo(
|
||||
token: "testRoom",
|
||||
|
@ -1030,8 +1103,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockOGMCache)
|
||||
.toEventually(
|
||||
call(matchingParameters: true) {
|
||||
|
@ -1042,6 +1116,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("defaults to an empty array if no moderators are provided") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockOGMCache.when { $0.admins }.thenReturn([:])
|
||||
testPollInfo = OpenGroupAPI.RoomPollInfo(
|
||||
token: "testRoom",
|
||||
|
@ -1067,8 +1143,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockOGMCache)
|
||||
.toEventually(
|
||||
call(matchingParameters: true) {
|
||||
|
@ -1098,6 +1175,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
|
||||
context("when not given a public key") {
|
||||
it("saves the open group with the existing public key") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
testPollInfo,
|
||||
publicKey: nil,
|
||||
|
@ -1105,8 +1184,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.to(call(matchingParameters: true) {
|
||||
$0.setOpenGroup(
|
||||
|
@ -1145,6 +1225,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
|
||||
context("when storing the open group") {
|
||||
it("defaults the infoUpdates to zero") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockStorage.when { $0.getOpenGroup(for: any()) }.thenReturn(nil)
|
||||
testPollInfo = OpenGroupAPI.RoomPollInfo(
|
||||
token: "testRoom",
|
||||
|
@ -1170,8 +1252,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.to(call(matchingParameters: true) {
|
||||
$0.setOpenGroup(
|
||||
|
@ -1193,6 +1276,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
|
||||
context("when checking to start polling") {
|
||||
it("starts a new poller when not already polling") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockOGMCache.when { $0.pollers }.thenReturn([:])
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
|
@ -1202,8 +1287,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockOGMCache)
|
||||
.to(call(matchingParameters: true) {
|
||||
$0.pollers = ["testServer": OpenGroupAPI.Poller(for: "testServer")]
|
||||
|
@ -1211,6 +1297,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("does not start a new poller when already polling") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockOGMCache.when { $0.pollers }.thenReturn(["testServer": OpenGroupAPI.Poller(for: "testServer")])
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
|
@ -1220,8 +1308,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockOGMCache).to(call(.exactly(times: 1)) { $0.pollers })
|
||||
}
|
||||
}
|
||||
|
@ -1237,6 +1326,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("uses the provided room image id if available") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
testPollInfo = OpenGroupAPI.RoomPollInfo(
|
||||
token: "testRoom",
|
||||
activeUsers: 10,
|
||||
|
@ -1287,8 +1378,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.to(call(matchingParameters: true) {
|
||||
$0.setOpenGroup(
|
||||
|
@ -1318,6 +1410,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("uses the existing room image id if none is provided") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockStorage
|
||||
.when { $0.getOpenGroup(for: any()) }
|
||||
.thenReturn(
|
||||
|
@ -1355,8 +1449,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.to(call(matchingParameters: true) {
|
||||
$0.setOpenGroup(
|
||||
|
@ -1386,6 +1481,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("uses the new room image id if there is an existing one") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
testGroupThread.mockData[.groupModel] = TSGroupModel(
|
||||
title: "TestTitle",
|
||||
memberIds: [],
|
||||
|
@ -1458,8 +1555,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(mockStorage)
|
||||
.to(call(matchingParameters: true) {
|
||||
$0.setOpenGroup(
|
||||
|
@ -1489,6 +1587,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("does nothing if there is no room image") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
OpenGroupManager.handlePollInfo(
|
||||
testPollInfo,
|
||||
publicKey: TestConstants.publicKey,
|
||||
|
@ -1496,8 +1596,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(testGroupThread.groupModel.groupImage)
|
||||
.toEventually(
|
||||
beNil(),
|
||||
|
@ -1511,6 +1612,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("does nothing if it fails to retrieve the room image") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
mockOGMCache.when { $0.groupImagePromises }
|
||||
.thenReturn(["testServer.testRoom": Promise(error: HTTP.Error.generic)])
|
||||
|
||||
|
@ -1564,8 +1667,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(testGroupThread.groupModel.groupImage)
|
||||
.toEventually(
|
||||
beNil(),
|
||||
|
@ -1579,6 +1683,8 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
}
|
||||
|
||||
it("saves the retrieved room image") {
|
||||
var didComplete: Bool = false // Prevent multi-threading test bugs
|
||||
|
||||
testPollInfo = OpenGroupAPI.RoomPollInfo(
|
||||
token: "testRoom",
|
||||
activeUsers: 10,
|
||||
|
@ -1629,8 +1735,9 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
on: "testServer",
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
) { didComplete = true }
|
||||
|
||||
expect(didComplete).toEventually(beTrue(), timeout: .milliseconds(100))
|
||||
expect(testGroupThread.groupModel.groupImage)
|
||||
.toEventuallyNot(
|
||||
beNil(),
|
||||
|
@ -1649,6 +1756,11 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
|
||||
context("when handling messages") {
|
||||
beforeEach {
|
||||
testTransaction.mockData[.objectForKey] = [
|
||||
"TestGroupId": testGroupThread,
|
||||
"TestMessageId": testIncomingMessage
|
||||
]
|
||||
|
||||
mockStorage
|
||||
.when {
|
||||
$0.setOpenGroupSequenceNumber(
|
||||
|
@ -1659,6 +1771,33 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
)
|
||||
}
|
||||
.thenReturn(())
|
||||
mockStorage.when { $0.getUserPublicKey() }.thenReturn("05\(TestConstants.publicKey)")
|
||||
mockStorage.when { $0.getReceivedMessageTimestamps(using: testTransaction as Any) }.thenReturn([])
|
||||
mockStorage.when { $0.addReceivedMessageTimestamp(any(), using: testTransaction as Any) }.thenReturn(())
|
||||
mockStorage.when { $0.persist(anyArray(), using: testTransaction as Any) }.thenReturn([])
|
||||
mockStorage
|
||||
.when {
|
||||
$0.getOrCreateThread(
|
||||
for: any(),
|
||||
groupPublicKey: any(),
|
||||
openGroupID: any(),
|
||||
using: testTransaction as Any
|
||||
)
|
||||
}
|
||||
.thenReturn("TestGroupId")
|
||||
mockStorage
|
||||
.when {
|
||||
$0.persist(
|
||||
any(),
|
||||
quotedMessage: nil,
|
||||
linkPreview: nil,
|
||||
groupPublicKey: any(),
|
||||
openGroupID: any(),
|
||||
using: testTransaction as Any
|
||||
)
|
||||
}
|
||||
.thenReturn("TestMessageId")
|
||||
mockStorage.when { $0.getContact(with: any()) }.thenReturn(nil)
|
||||
}
|
||||
|
||||
it("updates the sequence number when there are messages") {
|
||||
|
@ -1690,7 +1829,7 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
for: "testRoom",
|
||||
on: "testServer",
|
||||
to: 124,
|
||||
using: testTransaction as Any
|
||||
using: testTransaction! as Any
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -1710,6 +1849,208 @@ class OpenGroupManagerSpec: QuickSpec {
|
|||
$0.setOpenGroupSequenceNumber(for: any(), on: any(), to: any(), using: testTransaction as Any)
|
||||
})
|
||||
}
|
||||
|
||||
it("ignores a message with no sender") {
|
||||
OpenGroupManager.handleMessages(
|
||||
[
|
||||
OpenGroupAPI.Message(
|
||||
id: 1,
|
||||
sender: nil,
|
||||
posted: 123,
|
||||
edited: nil,
|
||||
seqNo: 124,
|
||||
whisper: false,
|
||||
whisperMods: false,
|
||||
whisperTo: nil,
|
||||
base64EncodedData: Data([1, 2, 3]).base64EncodedString(),
|
||||
base64EncodedSignature: nil
|
||||
)
|
||||
],
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
isBackgroundPoll: false,
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
|
||||
expect(testIncomingMessage.didCallSave).toEventuallyNot(beTrue(), timeout: .milliseconds(50))
|
||||
expect(testIncomingMessage.didCallRemove).toEventuallyNot(beTrue(), timeout: .milliseconds(50))
|
||||
}
|
||||
|
||||
it("ignores a message with invalid data") {
|
||||
OpenGroupManager.handleMessages(
|
||||
[
|
||||
OpenGroupAPI.Message(
|
||||
id: 1,
|
||||
sender: "05\(TestConstants.publicKey)",
|
||||
posted: 123,
|
||||
edited: nil,
|
||||
seqNo: 124,
|
||||
whisper: false,
|
||||
whisperMods: false,
|
||||
whisperTo: nil,
|
||||
base64EncodedData: Data([1, 2, 3]).base64EncodedString(),
|
||||
base64EncodedSignature: nil
|
||||
)
|
||||
],
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
isBackgroundPoll: false,
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
|
||||
expect(testIncomingMessage.didCallSave).toEventuallyNot(beTrue(), timeout: .milliseconds(50))
|
||||
expect(testIncomingMessage.didCallRemove).toEventuallyNot(beTrue(), timeout: .milliseconds(50))
|
||||
}
|
||||
|
||||
it("processes a message with valid data") {
|
||||
OpenGroupManager.handleMessages(
|
||||
[testMessage],
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
isBackgroundPoll: false,
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
|
||||
expect(testIncomingMessage.didCallSave)
|
||||
.toEventually(
|
||||
beTrue(),
|
||||
timeout: .milliseconds(100)
|
||||
)
|
||||
}
|
||||
|
||||
it("processes valid messages when combined with invalid ones") {
|
||||
OpenGroupManager.handleMessages(
|
||||
[
|
||||
OpenGroupAPI.Message(
|
||||
id: 2,
|
||||
sender: "05\(TestConstants.publicKey)",
|
||||
posted: 122,
|
||||
edited: nil,
|
||||
seqNo: 123,
|
||||
whisper: false,
|
||||
whisperMods: false,
|
||||
whisperTo: nil,
|
||||
base64EncodedData: Data([1, 2, 3]).base64EncodedString(),
|
||||
base64EncodedSignature: nil
|
||||
),
|
||||
testMessage,
|
||||
],
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
isBackgroundPoll: false,
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
|
||||
expect(testIncomingMessage.didCallSave)
|
||||
.toEventually(
|
||||
beTrue(),
|
||||
timeout: .milliseconds(100)
|
||||
)
|
||||
}
|
||||
|
||||
context("with no data") {
|
||||
it("deletes the message if we have the message") {
|
||||
testTransaction.mockData[.objectForKey] = testGroupThread
|
||||
|
||||
OpenGroupManager.handleMessages(
|
||||
[
|
||||
OpenGroupAPI.Message(
|
||||
id: 127,
|
||||
sender: "05\(TestConstants.publicKey)",
|
||||
posted: 123,
|
||||
edited: nil,
|
||||
seqNo: 123,
|
||||
whisper: false,
|
||||
whisperMods: false,
|
||||
whisperTo: nil,
|
||||
base64EncodedData: nil,
|
||||
base64EncodedSignature: nil
|
||||
)
|
||||
],
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
isBackgroundPoll: false,
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
|
||||
expect(testIncomingMessage.didCallRemove)
|
||||
.toEventually(
|
||||
beTrue(),
|
||||
timeout: .milliseconds(100)
|
||||
)
|
||||
}
|
||||
|
||||
it("does nothing if we do not have the thread") {
|
||||
testTransaction.mockData[.objectForKey] = nil
|
||||
|
||||
OpenGroupManager.handleMessages(
|
||||
[
|
||||
OpenGroupAPI.Message(
|
||||
id: 1,
|
||||
sender: "05\(TestConstants.publicKey)",
|
||||
posted: 123,
|
||||
edited: nil,
|
||||
seqNo: 123,
|
||||
whisper: false,
|
||||
whisperMods: false,
|
||||
whisperTo: nil,
|
||||
base64EncodedData: nil,
|
||||
base64EncodedSignature: nil
|
||||
)
|
||||
],
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
isBackgroundPoll: false,
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
|
||||
expect(testIncomingMessage.didCallRemove)
|
||||
.toEventuallyNot(
|
||||
beTrue(),
|
||||
timeout: .milliseconds(100)
|
||||
)
|
||||
}
|
||||
|
||||
it("does nothing if we do not have the message") {
|
||||
testGroupThread.mockData[.interactions] = [testInteraction]
|
||||
testTransaction.mockData[.objectForKey] = testGroupThread
|
||||
|
||||
OpenGroupManager.handleMessages(
|
||||
[
|
||||
OpenGroupAPI.Message(
|
||||
id: 127,
|
||||
sender: "05\(TestConstants.publicKey)",
|
||||
posted: 123,
|
||||
edited: nil,
|
||||
seqNo: 123,
|
||||
whisper: false,
|
||||
whisperMods: false,
|
||||
whisperTo: nil,
|
||||
base64EncodedData: nil,
|
||||
base64EncodedSignature: nil
|
||||
)
|
||||
],
|
||||
for: "testRoom",
|
||||
on: "testServer",
|
||||
isBackgroundPoll: false,
|
||||
using: testTransaction,
|
||||
dependencies: dependencies
|
||||
)
|
||||
|
||||
expect(testIncomingMessage.didCallRemove)
|
||||
.toEventuallyNot(
|
||||
beTrue(),
|
||||
timeout: .milliseconds(100)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,3 +21,7 @@ extension OpenGroupAPI.Server: Mocked {
|
|||
capabilities: OpenGroupAPI.Capabilities(capabilities: anyArray(), missing: anyArray())
|
||||
)
|
||||
}
|
||||
|
||||
extension VisibleMessage: Mocked {
|
||||
static var mockValue: VisibleMessage = VisibleMessage()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import SessionMessagingKit
|
||||
|
||||
// FIXME: Turn this into a protocol to make mocking possible
|
||||
class TestIncomingMessage: TSIncomingMessage, Mockable {
|
||||
// MARK: - Mockable
|
||||
|
||||
enum DataKey: Hashable {
|
||||
}
|
||||
|
||||
typealias Key = DataKey
|
||||
|
||||
var mockData: [DataKey: Any] = [:]
|
||||
var didCallSave: Bool = false
|
||||
var didCallRemove: Bool = false
|
||||
|
||||
// MARK: - TSInteraction
|
||||
|
||||
override func save(with transaction: YapDatabaseReadWriteTransaction) { didCallSave = true }
|
||||
override func remove(with transaction: YapDatabaseReadWriteTransaction) { didCallRemove = true }
|
||||
}
|
|
@ -15,7 +15,7 @@ class TestInteraction: TSInteraction, Mockable {
|
|||
typealias Key = DataKey
|
||||
|
||||
var mockData: [DataKey: Any] = [:]
|
||||
var didCallSave: Bool = true
|
||||
var didCallSave: Bool = false
|
||||
|
||||
// MARK: - TSInteraction
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ final class TestTransaction: YapDatabaseReadWriteTransaction, Mockable {
|
|||
// MARK: - YapDatabaseReadWriteTransaction
|
||||
|
||||
override func object(forKey key: String, inCollection collection: String?) -> Any? {
|
||||
if let dictionary: [String: Any] = mockData[.objectForKey] as? [String: Any] {
|
||||
return dictionary[key]
|
||||
}
|
||||
|
||||
return mockData[.objectForKey]
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue