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

129 lines
4.1 KiB
Swift
Raw Permalink Normal View History

2024-04-13 22:44:43 +00:00
//
// 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
}
2024-04-15 14:50:08 +00:00
final class TestStore<Key: PreferenceKey>: Codable, ObservableObject {
private var _test = Preference<Key>()
2024-04-13 22:44:43 +00:00
// the acutal subscript expects the enclosingInstance to be a PreferenceStore, so do it manually
2024-04-15 14:50:08 +00:00
var test: Key.Value {
2024-04-13 22:44:43 +00:00
get {
2024-04-14 02:36:42 +00:00
Preference.get(enclosingInstance: self, storage: \._test)
2024-04-13 22:44:43 +00:00
}
set {
2024-04-14 02:36:42 +00:00
Preference.set(enclosingInstance: self, storage: \._test, newValue: newValue)
2024-04-13 22:44:43 +00:00
}
}
2024-04-15 14:50:08 +00:00
var testPublisher: some Publisher<Key.Value, Never> {
2024-04-13 22:44:43 +00:00
_test.projectedValue
}
init() {
}
init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
2024-04-15 14:50:08 +00:00
self._test = try container.decode(Preference<Key>.self, forKey: .test)
2024-04-13 22:44:43 +00:00
}
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()
2024-04-15 14:50:08 +00:00
let present = try decoder.decode(PreferenceCoding<TestStore<TestKey>>.self, from: Data("""
2024-04-13 22:44:43 +00:00
{"test": true}
""".utf8)).wrapped
XCTAssertEqual(present.test, true)
2024-04-15 14:50:08 +00:00
let absent = try decoder.decode(PreferenceCoding<TestStore<TestKey>>.self, from: Data("""
2024-04-13 22:44:43 +00:00
{}
""".utf8)).wrapped
XCTAssertEqual(absent.test, false)
}
func testEncoding() throws {
2024-04-15 14:50:08 +00:00
let store = TestStore<TestKey>()
2024-04-13 22:44:43 +00:00
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
2024-04-15 14:50:08 +00:00
let store = TestStore<TestKey>()
2024-04-13 22:44:43 +00:00
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])
}
2024-04-15 14:50:08 +00:00
func testCustomCodable() throws {
struct Key: CustomCodablePreferenceKey {
static let defaultValue = 1
static func encode(value: Int, to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(2)
}
static func decode(from decoder: any Decoder) throws -> Int? {
3
}
}
let store = TestStore<Key>()
store.test = 123
let encoder = JSONEncoder()
XCTAssertEqual(String(data: try encoder.encode(PreferenceCoding(wrapped: store)), encoding: .utf8)!, """
{"test":2}
""")
let decoder = JSONDecoder()
let present = try decoder.decode(PreferenceCoding<TestStore<Key>>.self, from: Data("""
{"test":2}
""".utf8)).wrapped
XCTAssertEqual(present.test, 3)
let absent = try decoder.decode(PreferenceCoding<TestStore<Key>>.self, from: Data("""
{}
""".utf8)).wrapped
XCTAssertEqual(absent.test, 1)
}
2024-04-13 22:44:43 +00:00
}