NotificationTask/Tests/NotificationTaskTests/NotificationTaskTests.swift
2025-04-18 13:22:18 -07:00

84 lines
2.7 KiB
Swift

import Foundation
import Testing
@testable import NotificationTask
@MainActor class NotificationTaskTests {
let center = NotificationCenter()
let name = Notification.Name("a random notification")
private var subject: NotificationTask?
@Test func callsBlockWhenNotificationsArePosted() async throws {
await withCheckedContinuation { [center, name] continuation in
subject = NotificationTask(name: name, center: center) { notification in
#expect(notification.name == name)
continuation.resume()
}
Task {
center.post(name: name, object: nil)
}
}
}
@Test func doesNotCallBlockWhenOtherNotificationsArePosted() async throws {
subject = NotificationTask(name: name, center: center) { notification in
Issue.record("Called for irrelevant notification \(notification.name)")
}
Task {
center.post(name: Notification.Name("something else"), object: nil)
}
try await Task.sleep(for: .milliseconds(10))
}
@Test func stopsCallingBlockWhenDeallocated() async throws {
subject = NotificationTask(name: name, center: center) { notification in
Issue.record("Called after deallocation")
}
Task {
subject = nil
center.post(name: name, object: nil)
}
try await Task.sleep(for: .milliseconds(10))
}
class Owner {
let deinitHook: () -> Void
private var task: NotificationTask?
@MainActor init(center: NotificationCenter, deinitHook: @escaping () -> Void) {
self.deinitHook = deinitHook
let name = Notification.Name("irrelevant name")
self.task = NotificationTask(name: name, context: self, center: center) { _, _ in }
}
deinit {
deinitHook()
}
}
private var owner: Owner?
@Test(.timeLimit(.minutes(1))) func doesNotCreateReferenceCyclesWithContext() async throws {
await withCheckedContinuation { continuation in
self.owner = Owner(center: center) {
continuation.resume()
}
self.owner = nil
}
}
@Test func stopsCallingBlockWhenContextIsDeallocated() async throws {
var context: NSObject? = NSObject()
subject = NotificationTask(name: name, context: context!, center: center) { context, notification in
Issue.record("Called after context was deallocated")
}
context = nil
Task {
center.post(name: name, object: nil)
}
try await Task.sleep(for: .milliseconds(10))
}
}