Skip to content

Commit

Permalink
chore: adding tests, refactoring KnockFeedStatus, updates to batchMes…
Browse files Browse the repository at this point in the history
…sageStatus Updates
  • Loading branch information
matgar26 committed May 29, 2024
1 parent f8a76bf commit 1de224f
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 554 deletions.
2 changes: 1 addition & 1 deletion Sources/Components/Feed/InAppFeedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ extension Knock {
}
.onDisappear {
Task {
await viewModel.markAllAsSeen()
await viewModel.bulkUpdateMessageEngagementStatus(updatedStatus: .seen)
}
}
}
Expand Down
607 changes: 107 additions & 500 deletions Sources/Components/Feed/InAppFeedViewModel.swift

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Sources/FeedManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ public extension Knock {
- type: The kind of update
- options: All the options currently set on the feed to scope as much as possible the bulk update
*/
public func makeBulkStatusUpdate(type: KnockMessageStatusBatchUpdateType, options: FeedClientOptions) async throws -> BulkOperation {
public func makeBulkStatusUpdate(type: KnockMessageStatusUpdateType, options: FeedClientOptions) async throws -> BulkOperation {
try await feedModule.makeBulkStatusUpdate(type: type, options: options)
}

public func makeBulkStatusUpdate(type: KnockMessageStatusBatchUpdateType, options: FeedClientOptions, completionHandler: @escaping ((Result<BulkOperation, Error>) -> Void)) {
public func makeBulkStatusUpdate(type: KnockMessageStatusUpdateType, options: FeedClientOptions, completionHandler: @escaping ((Result<BulkOperation, Error>) -> Void)) {
Task {
do {
let operation = try await makeBulkStatusUpdate(type: type, options: options)
Expand Down
11 changes: 1 addition & 10 deletions Sources/Models/Messages/KnockMessageStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,13 @@ public extension Knock {
case archived
}

enum KnockMessageStatusUpdateType: String {
enum KnockMessageStatusUpdateType: String, Codable {
case seen
case read
case interacted
case archived
case unread
case unseen
}

enum KnockMessageStatusBatchUpdateType: String, Codable {
case seen
case read
case interacted
case archived
case unseen
case unread
case unarchived
}
}
2 changes: 1 addition & 1 deletion Sources/Modules/FeedModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ internal class FeedModule {
}
}

func makeBulkStatusUpdate(type: Knock.KnockMessageStatusBatchUpdateType, options: Knock.FeedClientOptions) async throws -> Knock.BulkOperation {
func makeBulkStatusUpdate(type: Knock.KnockMessageStatusUpdateType, options: Knock.FeedClientOptions) async throws -> Knock.BulkOperation {
// TODO: check https://docs.knock.app/reference#bulk-update-channel-message-status
// older_than: ISO-8601, check milliseconds
// newer_than: ISO-8601, check milliseconds
Expand Down
10 changes: 5 additions & 5 deletions Sources/Modules/MessageModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ internal class MessageModule {
}
}

internal func batchUpdateStatuses(messageIds: [String], status: Knock.KnockMessageStatusBatchUpdateType) async throws -> [Knock.KnockMessage] {
internal func batchUpdateStatuses(messageIds: [String], status: Knock.KnockMessageStatusUpdateType) async throws -> [Knock.KnockMessage] {
do {
let messages = try await messageService.batchUpdateStatuses(messageIds: messageIds, status: status)
Knock.shared.log(type: .debug, category: .message, message: "batchUpdateStatuses", status: .success)
Expand Down Expand Up @@ -182,11 +182,11 @@ public extension Knock {

*Note:* Knock scopes this batch rate limit by message_ids and status. This allows for 1 update per second per message per status.
*/
func batchUpdateStatuses(messageIds: [String], status: KnockMessageStatusBatchUpdateType) async throws -> [KnockMessage] {
func batchUpdateStatuses(messageIds: [String], status: KnockMessageStatusUpdateType) async throws -> [KnockMessage] {
try await self.messageModule.batchUpdateStatuses(messageIds: messageIds, status: status)
}

func batchUpdateStatuses(messageIds: [String], status: KnockMessageStatusBatchUpdateType, completionHandler: @escaping ((Result<[KnockMessage], Error>) -> Void)) {
func batchUpdateStatuses(messageIds: [String], status: KnockMessageStatusUpdateType, completionHandler: @escaping ((Result<[KnockMessage], Error>) -> Void)) {
Task {
do {
let messages = try await batchUpdateStatuses(messageIds: messageIds, status: status)
Expand All @@ -207,12 +207,12 @@ public extension Knock {

*Note:* Knock scopes this batch rate limit by message_ids and status. This allows for 1 update per second per message per status.
*/
func batchUpdateStatuses(messages: [KnockMessage], status: KnockMessageStatusBatchUpdateType) async throws -> [KnockMessage] {
func batchUpdateStatuses(messages: [KnockMessage], status: KnockMessageStatusUpdateType) async throws -> [KnockMessage] {
let messageIds = messages.map{$0.id}
return try await self.messageModule.batchUpdateStatuses(messageIds: messageIds, status: status)
}

func batchUpdateStatuses(messages: [KnockMessage], status: KnockMessageStatusBatchUpdateType, completionHandler: @escaping ((Result<[KnockMessage], Error>) -> Void)) {
func batchUpdateStatuses(messages: [KnockMessage], status: KnockMessageStatusUpdateType, completionHandler: @escaping ((Result<[KnockMessage], Error>) -> Void)) {
Task {
do {
let messages = try await batchUpdateStatuses(messages: messages, status: status)
Expand Down
2 changes: 1 addition & 1 deletion Sources/Services/FeedService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal class FeedService: KnockAPIService {
try await get(path: "/users/\(userId)/feeds/\(feedId)", queryItems: queryItems)
}

func makeBulkStatusUpdate(feedId: String, type: Knock.KnockMessageStatusBatchUpdateType, body: AnyEncodable?) async throws -> Knock.BulkOperation {
func makeBulkStatusUpdate(feedId: String, type: Knock.KnockMessageStatusUpdateType, body: AnyEncodable?) async throws -> Knock.BulkOperation {
try await post(path: "/channels/\(feedId)/messages/bulk/\(type.rawValue)", body: body)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Services/MessageService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class MessageService: KnockAPIService {
try await delete(path: "/messages/\(messageId)/\(status.rawValue)", body: nil)
}

internal func batchUpdateStatuses(messageIds: [String], status: Knock.KnockMessageStatusBatchUpdateType) async throws -> [Knock.KnockMessage] {
internal func batchUpdateStatuses(messageIds: [String], status: Knock.KnockMessageStatusUpdateType) async throws -> [Knock.KnockMessage] {
let body = ["message_ids": messageIds]
return try await post(path: "/messages/batch/\(status.rawValue)", body: body)
}
Expand Down
56 changes: 23 additions & 33 deletions Tests/KnockTests/InAppFeedViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,14 @@ import XCTest

final class InAppFeedViewModelTests: XCTestCase {
var viewModel: Knock.InAppFeedViewModel!
var feedManager: Knock.FeedManager!

override func setUp() {
super.setUp()
feedManager = try! Knock.FeedManager(feedId: "")
Knock.shared.feedManager = feedManager
viewModel = Knock.InAppFeedViewModel()
}

override func tearDown() {
viewModel = nil
feedManager = nil
super.tearDown()
}

Expand Down Expand Up @@ -94,44 +90,38 @@ final class InAppFeedViewModelTests: XCTestCase {
XCTAssertTrue(viewModel.feed.entries.isEmpty)
}

func testOptimisticBulkMarkItemAsRead() async {
func testOptimisticBulkMarkItemsAsRead() async {
let item = generateTestFeedItem(status: .unread)
let item2 = generateTestFeedItem(status: .seen)
let item3 = generateTestFeedItem(status: .unread)
let item4 = generateTestFeedItem(status: .read)

viewModel.feed.entries = [item, item2, item3, item4]
viewModel.feed.meta.unreadCount = 3
await viewModel.optimisticallyBulkUpdateStatus(status: .read)
await viewModel.optimisticallyBulkUpdateStatus(updatedStatus: .read)
XCTAssertTrue(viewModel.feed.entries.first!.read_at != nil)
XCTAssertTrue(viewModel.feed.meta.unreadCount == 0)
}
}

func testOptimisticBulkMarkItemAsArchived() async {
let item = generateTestFeedItem(status: .unread)
let item2 = generateTestFeedItem(status: .seen)
let item3 = generateTestFeedItem(status: .unread)
let item4 = generateTestFeedItem(status: .read)

//class MockFeedManager: FeedManagerProtocol { // Conform to the actual protocol used by Knock.FeedManager
// var connectedToFeed = false
// var messages = PassthroughSubject<Void, Never>()
//
// func connectToFeed() {
// connectedToFeed = true
// }
//
// func on(eventName: String, handler: @escaping (Any) -> Void) {
// messages.sink(receiveValue: { _ in handler(()) }).store(in: &cancellables)
// }
//
// func getUserFeedContent(options: Knock.FeedClientOptions, completion: @escaping (Result<Knock.Feed, Error>) -> Void) {
// // Simulate API response
// let feed = Knock.Feed(entries: [Knock.FeedItem(id: "1", title: "Test")], pageInfo: Knock.PageInfo(before: nil, after: nil), meta: Knock.FeedMeta())
// completion(.success(feed))
// }
//
// func makeBulkStatusUpdate(type: Knock.KnockMessageStatusBatchUpdateType, options: Knock.FeedClientOptions) async throws {
// // Simulate bulk update
// }
//}
//
//protocol FeedManagerProtocol {
//
//}
viewModel.feed.entries = [item, item2, item3, item4]
await viewModel.optimisticallyBulkUpdateStatus(updatedStatus: .archived)
XCTAssertTrue(viewModel.feed.meta.unreadCount == 0)
}

func testOptimisticBulkMarkItemAsArchivedWithReadScope() async {
let item = generateTestFeedItem(status: .unread)
let item2 = generateTestFeedItem(status: .unread)
let item3 = generateTestFeedItem(status: .unread)
let item4 = generateTestFeedItem(status: .read)

viewModel.feed.entries = [item, item2, item3, item4]
await viewModel.optimisticallyBulkUpdateStatus(updatedStatus: .archived, archivedScope: .unread)
XCTAssertTrue(viewModel.feed.entries.count == 1)
}
}

0 comments on commit 1de224f

Please sign in to comment.