Path: blob/main/Signal/test/Badge/BadgeManagerTest.swift
1 views
//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import XCTest
@testable import Signal
@testable import SignalServiceKit
class BadgeManagerTest: XCTestCase {
private class MockBadgeObserver: BadgeObserver {
var badgeValues = [UInt]()
func didUpdateBadgeCount(_ badgeManager: BadgeManager, badgeCount: BadgeCount) {
badgeValues.append(badgeCount.unreadChatCount)
}
}
@MainActor
func testMultipleRequestsReuseResults() async {
var fetchCount: UInt = 0
let badgeManager = BadgeManager(
fetchIntBadgeValue: {
fetchCount += 1
return fetchCount
},
)
let observer1 = MockBadgeObserver()
badgeManager.addObserver(observer1)
let observer2 = MockBadgeObserver()
badgeManager.addObserver(observer2)
await badgeManager.flush()
XCTAssertEqual(observer1.badgeValues, [1])
XCTAssertEqual(observer2.badgeValues, [1])
XCTAssertEqual(fetchCount, 1)
let observer3 = MockBadgeObserver()
badgeManager.addObserver(observer3)
await badgeManager.flush()
XCTAssertEqual(observer1.badgeValues, [1])
XCTAssertEqual(observer2.badgeValues, [1])
XCTAssertEqual(observer3.badgeValues, [1])
XCTAssertEqual(fetchCount, 1)
}
@MainActor
func testPendingRequestsCoalesce() async {
var fetchCount: UInt = 0
let badgeManager = BadgeManager(
fetchIntBadgeValue: {
fetchCount += 1
return fetchCount
},
)
let observer = MockBadgeObserver()
badgeManager.addObserver(observer)
await badgeManager.flush()
XCTAssertEqual(observer.badgeValues, [1])
badgeManager.serialQueue.sync {
badgeManager.invalidateBadgeValue()
badgeManager.invalidateBadgeValue()
badgeManager.invalidateBadgeValue()
}
await badgeManager.flush()
await badgeManager.flush()
XCTAssertEqual(observer.badgeValues, [1, 2, 3])
XCTAssertEqual(fetchCount, 3)
}
}
private extension BadgeManager {
convenience init(
fetchIntBadgeValue: @escaping () -> UInt,
) {
self.init(
fetchBadgeCountBlock: { BadgeCount(unreadChatCount: fetchIntBadgeValue(), unreadCallsCount: 0) },
)
}
func flush() async {
await withCheckedContinuation { continuation in
self.serialQueue.async {
DispatchQueue.main.async {
continuation.resume()
}
}
}
}
}