Tests/KeycaskCoreTests/VaultTests.swift
88 lines · 3240 bytes
1import Foundation
2import Testing
3
4@testable import KeycaskCore
5
6@Suite struct VaultTests {
7 func idA() -> EntryID { EntryID("aaaa2222")! }
8 func idB() -> EntryID { EntryID("bbbb3333")! }
9
10 @Test func addRejectsDuplicateID() throws {
11 var v = Vault()
12 try v.add(Entry(id: idA(), name: "gh", password: "p"))
13 #expect(throws: KeycaskError.duplicateID(idA())) {
14 try v.add(Entry(id: idA(), name: "other", password: "p"))
15 }
16 #expect(v.entries.count == 1)
17 }
18
19 @Test func removeUnknownIsNotFound() {
20 var v = Vault()
21 #expect(throws: KeycaskError.notFound("aaaa2222")) { try v.remove(id: idA()) }
22 }
23
24 @Test func updateSetsUpdatedAndNormalizesTags() throws {
25 let t0 = Date(timeIntervalSince1970: 1_000)
26 let t1 = Date(timeIntervalSince1970: 2_000.9)
27 var v = Vault()
28 try v.add(Entry(id: idA(), name: "gh", password: "p", now: t0))
29 try v.update(id: idA(), now: t1) { e in
30 e.tags = ["z", "A", "a"]
31 e.password = "q"
32 }
33 let e = v.entry(id: idA())!
34 #expect(e.password == "q")
35 #expect(e.tags == ["A", "z"])
36 #expect(e.created == t0)
37 #expect(e.updated == Date(timeIntervalSince1970: 2_000))
38 }
39
40 @Test func resolvePrefersIDThenUniqueName() throws {
41 var v = Vault()
42 try v.add(Entry(id: idA(), name: "gh", password: "p"))
43 try v.add(Entry(id: idB(), name: "aaaa2222", password: "p"))
44 #expect(try v.resolve("aaaa2222").id == idA())
45 #expect(try v.resolve("gh").id == idA())
46 #expect(try v.resolve("bbbb3333").id == idB())
47 }
48
49 @Test func resolveReportsAmbiguousWithAllCandidates() throws {
50 var v = Vault()
51 let a = Entry(id: idA(), name: "gh", password: "p")
52 let b = Entry(id: idB(), name: "gh", password: "p")
53 try v.add(a)
54 try v.add(b)
55 #expect(throws: KeycaskError.ambiguous(name: "gh", candidates: [a, b])) {
56 try v.resolve("gh")
57 }
58 }
59
60 @Test func resolveUnknownIsNotFound() {
61 #expect(throws: KeycaskError.notFound("nope")) { try Vault().resolve("nope") }
62 }
63
64 @Test func filterAndSearch() throws {
65 var v = Vault()
66 try v.add(Entry(id: idA(), name: "GitHub", password: "p", tags: ["dev"]))
67 try v.add(Entry(id: idB(), name: "bank", password: "p", url: "https://bank.example"))
68 #expect(v.filter(tag: "DEV").map(\.id) == [idA()])
69 #expect(v.search("example").map(\.id) == [idB()])
70 #expect(v.search("zzz").isEmpty)
71 }
72
73 @Test func sortedEntriesOrderByNameThenID() throws {
74 var v = Vault()
75 try v.add(Entry(id: idB(), name: "gh", password: "p"))
76 try v.add(Entry(id: idA(), name: "gh", password: "p"))
77 try v.add(Entry(id: EntryID("cccc4444")!, name: "Alpha", password: "p"))
78 #expect(v.sortedEntries.map(\.id.rawValue) == ["cccc4444", "aaaa2222", "bbbb3333"])
79 }
80
81 @Test func addNormalizesTagsSetAfterInit() throws {
82 var e = Entry(id: idA(), name: "gh", password: "p")
83 e.tags = ["z", "A", "a", " b "]
84 var v = Vault()
85 try v.add(e)
86 #expect(v.entry(id: idA())!.tags == ["A", "b", "z"])
87 }
88}