Tusker/Packages/TuskerPreferences/Tests/TuskerPreferencesTests/PreferenceStoreTests.swift

101 lines
3.1 KiB
Swift

//
// PreferenceStoreTests.swift
// TuskerPreferencesTests
//
// Created by Shadowfacts on 4/12/24.
//
import XCTest
@testable import TuskerPreferences
import Combine
final class PreferenceStoreTests: XCTestCase {
struct TestKey: PreferenceKey {
static let defaultValue = false
}
final class TestStore: Codable, ObservableObject {
private var _test = Preference<TestKey>()
// the acutal subscript expects the enclosingInstance to be a PreferenceStore, so do it manually
var test: Bool {
get {
Preference.get(enclosingInstance: self, storage: \._test)
}
set {
Preference.set(enclosingInstance: self, storage: \._test, newValue: newValue)
}
}
var testPublisher: some Publisher<TestKey.Value, Never> {
_test.projectedValue
}
init() {
}
init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self._test = try container.decode(Preference<TestKey>.self, forKey: .test)
}
enum CodingKeys: CodingKey {
case test
}
func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self._test, forKey: .test)
}
}
func testDecoding() throws {
let decoder = JSONDecoder()
let present = try decoder.decode(PreferenceCoding<TestStore>.self, from: Data("""
{"test": true}
""".utf8)).wrapped
XCTAssertEqual(present.test, true)
let absent = try decoder.decode(PreferenceCoding<TestStore>.self, from: Data("""
{}
""".utf8)).wrapped
XCTAssertEqual(absent.test, false)
}
func testEncoding() throws {
let store = TestStore()
let encoder = JSONEncoder()
XCTAssertEqual(String(data: try encoder.encode(PreferenceCoding(wrapped: store)), encoding: .utf8)!, """
{}
""")
store.test = true
XCTAssertEqual(String(data: try encoder.encode(PreferenceCoding(wrapped: store)), encoding: .utf8)!, """
{"test":true}
""")
store.test = false
XCTAssertEqual(String(data: try encoder.encode(PreferenceCoding(wrapped: store)), encoding: .utf8)!, """
{"test":false}
""")
}
func testPublisher() {
let topLevel = expectation(description: "top level publisher")
let specificPref = expectation(description: "preference publisher")
// initial and on change
specificPref.expectedFulfillmentCount = 2
let store = TestStore()
var cancellables = Set<AnyCancellable>()
store.objectWillChange.sink {
topLevel.fulfill()
// fires on will change
XCTAssertEqual(store.test, false)
}.store(in: &cancellables)
store.testPublisher.sink { _ in
specificPref.fulfill()
}.store(in: &cancellables)
store.test = true
wait(for: [topLevel, specificPref])
}
}