157 lines
5.2 KiB
Swift
157 lines
5.2 KiB
Swift
// SPDX-FileCopyrightText: 2026 Kaede Akino
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
import Foundation
|
|
import TermindDomain
|
|
import Testing
|
|
|
|
@testable import TermindApplication
|
|
|
|
@Suite @MainActor
|
|
struct LibraryExpansionStateTests {
|
|
@Test
|
|
func legacyExpansionMigratesOnceAndThenPersistsOnlyLocally() throws {
|
|
let fixture = try DefaultsFixture()
|
|
defer { fixture.remove() }
|
|
let group = HostGroup(name: "Production", isExpanded: false)
|
|
let package = SnippetPackage(name: "Operations", isExpanded: false)
|
|
let persistence = ExpansionVaultPersistence(
|
|
snapshot: VaultSnapshot(groups: [group], snippetPackages: [package])
|
|
)
|
|
let library = HostLibraryModel(
|
|
persistence: persistence,
|
|
localDefaults: fixture.defaults
|
|
)
|
|
|
|
#expect(!library.isHostGroupExpanded(group.id))
|
|
#expect(!library.isSnippetPackageExpanded(package.id))
|
|
#expect(library.isUngroupedExpanded)
|
|
#expect(library.isSnippetsUngroupedExpanded)
|
|
|
|
library.setExpanded(true, for: group.id)
|
|
library.setSnippetPackageExpanded(true, for: package.id)
|
|
library.setUngroupedExpanded(false)
|
|
library.setSnippetsUngroupedExpanded(false)
|
|
|
|
#expect(persistence.saveCount == 0)
|
|
let reopened = HostLibraryModel(
|
|
persistence: persistence,
|
|
localDefaults: fixture.defaults
|
|
)
|
|
#expect(reopened.isHostGroupExpanded(group.id))
|
|
#expect(reopened.isSnippetPackageExpanded(package.id))
|
|
#expect(!reopened.isUngroupedExpanded)
|
|
#expect(!reopened.isSnippetsUngroupedExpanded)
|
|
}
|
|
|
|
@Test
|
|
func installationsKeepIndependentExpansionState() throws {
|
|
let first = try DefaultsFixture()
|
|
let second = try DefaultsFixture()
|
|
defer {
|
|
first.remove()
|
|
second.remove()
|
|
}
|
|
let group = HostGroup(name: "Production")
|
|
let snapshot = VaultSnapshot(groups: [group])
|
|
let firstLibrary = HostLibraryModel(
|
|
persistence: ExpansionVaultPersistence(snapshot: snapshot),
|
|
localDefaults: first.defaults
|
|
)
|
|
firstLibrary.setExpanded(false, for: group.id)
|
|
|
|
let secondLibrary = HostLibraryModel(
|
|
persistence: ExpansionVaultPersistence(snapshot: snapshot),
|
|
localDefaults: second.defaults
|
|
)
|
|
|
|
#expect(!firstLibrary.isHostGroupExpanded(group.id))
|
|
#expect(secondLibrary.isHostGroupExpanded(group.id))
|
|
}
|
|
|
|
@Test
|
|
func remoteSnapshotsCannotReplaceLocalExpansionAndRemoveStaleIDs() throws {
|
|
let fixture = try DefaultsFixture()
|
|
defer { fixture.remove() }
|
|
let group = HostGroup(name: "Production")
|
|
let package = SnippetPackage(name: "Operations")
|
|
let library = HostLibraryModel(
|
|
groups: [group], snippetPackages: [package],
|
|
localDefaults: fixture.defaults
|
|
)
|
|
library.setExpanded(false, for: group.id)
|
|
library.setSnippetPackageExpanded(false, for: package.id)
|
|
|
|
var remoteGroup = group
|
|
remoteGroup.isExpanded = true
|
|
var remotePackage = package
|
|
remotePackage.isExpanded = true
|
|
library.replacePersistedSnapshot(
|
|
VaultSnapshot(groups: [remoteGroup], snippetPackages: [remotePackage])
|
|
)
|
|
|
|
#expect(!library.isHostGroupExpanded(group.id))
|
|
#expect(!library.isSnippetPackageExpanded(package.id))
|
|
|
|
library.replacePersistedSnapshot(VaultSnapshot())
|
|
library.replacePersistedSnapshot(
|
|
VaultSnapshot(groups: [remoteGroup], snippetPackages: [remotePackage])
|
|
)
|
|
#expect(library.isHostGroupExpanded(group.id))
|
|
#expect(library.isSnippetPackageExpanded(package.id))
|
|
}
|
|
|
|
@Test
|
|
func corruptLocalStateFallsBackToExpandedWithoutRepeatingLegacyMigration() throws {
|
|
let fixture = try DefaultsFixture()
|
|
defer { fixture.remove() }
|
|
fixture.defaults.set(Data("not-json".utf8), forKey: LibraryExpansionState.storageKey)
|
|
fixture.defaults.set(true, forKey: LibraryExpansionState.migrationKey)
|
|
let group = HostGroup(name: "Production", isExpanded: false)
|
|
let package = SnippetPackage(name: "Operations", isExpanded: false)
|
|
|
|
let library = HostLibraryModel(
|
|
groups: [group], snippetPackages: [package],
|
|
localDefaults: fixture.defaults
|
|
)
|
|
|
|
#expect(library.isHostGroupExpanded(group.id))
|
|
#expect(library.isSnippetPackageExpanded(package.id))
|
|
}
|
|
}
|
|
|
|
private struct DefaultsFixture {
|
|
let name: String
|
|
let defaults: UserDefaults
|
|
|
|
init() throws {
|
|
name = "LibraryExpansionStateTests.\(UUID().uuidString)"
|
|
defaults = try #require(UserDefaults(suiteName: name))
|
|
}
|
|
|
|
func remove() {
|
|
defaults.removePersistentDomain(forName: name)
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
private final class ExpansionVaultPersistence: VaultPersisting {
|
|
var snapshot: VaultSnapshot
|
|
var saveCount = 0
|
|
|
|
init(snapshot: VaultSnapshot) {
|
|
self.snapshot = snapshot
|
|
}
|
|
|
|
func load() throws -> VaultSnapshot { snapshot }
|
|
|
|
func save(
|
|
_ snapshot: VaultSnapshot, touching keys: Set<VaultRecordKey>
|
|
) throws -> VaultMutationSet {
|
|
saveCount += 1
|
|
self.snapshot = snapshot
|
|
return .empty
|
|
}
|
|
|
|
}
|