Skip to content

Commit ac396e3

Browse files
committed
Add observer lifecycle regression tests
1 parent ff574be commit ac396e3

3 files changed

Lines changed: 33 additions & 0 deletions

File tree

Tests/ObservableDefaultsMacroTests/MacroStructureTests.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ struct MacroStructureTests {
1818
let classes = tree.statements.compactMap { $0.item.as(ClassDeclSyntax.self) }
1919
#expect(classes.count == 1)
2020
#expect(classes.first?.name.text == "DefaultsBasicFixture")
21+
#expect(result.expandedSource.contains("private var notificationObserver: NSObjectProtocol?"))
22+
#expect(result.expandedSource.contains("NotificationCenter.default.removeObserver(observer)"))
23+
#expect(!result.expandedSource.contains("NotificationCenter.default.removeObserver(self)"))
2124
}
2225

2326
@Test("ObserveFirst defaults only maps explicitly backed properties")
@@ -42,6 +45,9 @@ struct MacroStructureTests {
4245
#expect(result.expandedSource.contains("var _ephemeral: String = \"scratch\""))
4346
#expect(result.expandedSource.contains(#"case prefix + "theme":"#))
4447
#expect(!result.expandedSource.contains(#"case prefix + "ephemeral":"#))
48+
#expect(result.expandedSource.contains("private var notificationObserver: NSObjectProtocol?"))
49+
#expect(result.expandedSource.contains("NotificationCenter.default.removeObserver(observer)"))
50+
#expect(!result.expandedSource.contains("NotificationCenter.default.removeObserver(self)"))
4551
}
4652

4753
@Test("defaultIsolationIsMainActor adds MainActor-specific generated code for defaults")

Tests/ObservableDefaultsTests/ObservableCloudTests.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,19 @@ struct ObservableCloudTests {
9292
#expect(userDefaults.string(forKey: "test_name") == "Test2")
9393
}
9494

95+
@Test("Model with cloud observer infrastructure deallocates", .testMode)
96+
func cloudObserverInfrastructureDeallocates() {
97+
weak var weakModel: MockModelCloud?
98+
99+
do {
100+
let model = MockModelCloud(developmentMode: false)
101+
weakModel = model
102+
#expect(weakModel != nil)
103+
}
104+
105+
#expect(weakModel == nil)
106+
}
107+
95108
@Test("syncImmediately macro default is preserved by generated init", .testMode)
96109
func syncImmediatelyMacroDefaultIsPreserved() {
97110
let model = MockModelCloudSyncImmediately()

Tests/ObservableDefaultsTests/ObservableDefaultsTests.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ struct ObservableDefaultsTests {
7979
#expect(model.name == "Test1", "name should be observable by setting value by UserDefaults")
8080
}
8181

82+
@Test("Model with defaults observer infrastructure deallocates")
83+
func defaultsObserverInfrastructureDeallocates() {
84+
let userDefaults = UserDefaults.getTestInstance(suiteName: #function)
85+
weak var weakModel: MockModel?
86+
87+
do {
88+
let model = MockModel(userDefaults: userDefaults)
89+
weakModel = model
90+
#expect(weakModel != nil)
91+
}
92+
93+
#expect(weakModel == nil)
94+
}
95+
8296
@Test("Observable Only")
8397
func observableOnly() {
8498
let userDefaults = UserDefaults.getTestInstance(suiteName: #function)

0 commit comments

Comments
 (0)