1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
## What survives a restart. Every case runs against a real directory under a
## temporary XDG_CONFIG_HOME, because the thing being tested is files.
import std/[os, tables, unittest]
import frq/[store, model]
template withTempConfig(body: untyped) =
let dir = getTempDir() / "frq-test-store-" & $getCurrentProcessId()
removeDir(dir)
createDir(dir)
putEnv("XDG_CONFIG_HOME", dir)
defer:
delEnv("XDG_CONFIG_HOME")
removeDir(dir)
body
suite "the session":
test "absent when nothing was saved":
withTempConfig:
check loadSession()[1] == false
test "round-trips":
withTempConfig:
check saveSession(SavedSession(brokerToken: "tok", handle: "alice",
did: "did:plc:x", nick: "alice"))
let (s, ok) = loadSession()
check ok
check s.brokerToken == "tok"
check s.handle == "alice"
check s.did == "did:plc:x"
test "one with no broker token is not a session":
# The token is the whole point of saving one.
withTempConfig:
check saveSession(SavedSession(handle: "alice"))
check loadSession()[1] == false
test "a file that will not parse is treated as absent":
# A stale credential is not worth an error at startup.
withTempConfig:
createDir(configDir())
writeFile(sessionFile(), "{ this is not json")
check loadSession()[1] == false
test "is written so nobody else can read it":
withTempConfig:
check saveSession(SavedSession(brokerToken: "tok"))
let perms = getFilePermissions(sessionFile())
check fpGroupRead notin perms
check fpOthersRead notin perms
test "clearing it leaves nothing behind":
withTempConfig:
check saveSession(SavedSession(brokerToken: "tok"))
clearSession()
check loadSession()[1] == false
test "clearing one that is not there is not an error":
withTempConfig:
clearSession()
suite "the rooms":
test "none when nothing was saved":
withTempConfig:
check loadRooms().len == 0
test "round-trip, with the markers":
# A phone that kept the names and lost the markers comes back to a
# hundred lines it has already read.
withTempConfig:
var rooms = initOrderedTable[string, Room]()
var a = initRoom("#one")
a.accessed = 5
a.lastReadId = "m1"
a.lastReadAt = 1234
rooms["#one"] = a
rooms["#two"] = initRoom("#two")
check saveRooms(rooms)
let got = loadRooms()
check got.len == 2
check got[0].name == "#one"
check got[0].accessed == 5
check got[0].lastReadId == "m1"
check got[0].lastReadAt == 1234
test "order is kept — most recently used first is the file's own order":
withTempConfig:
var rooms = initOrderedTable[string, Room]()
for n in ["#c", "#a", "#b"]: rooms[n] = initRoom(n)
check saveRooms(rooms)
check loadRooms().len == 3
check loadRooms()[0].name == "#c"
test "a record with no name is dropped rather than defaulted":
withTempConfig:
createDir(configDir())
writeFile(roomsFile(), """[{"name":"#ok"},{"accessed":3}]""")
let got = loadRooms()
check got.len == 1
check got[0].name == "#ok"
test "a file that will not parse is no rooms, not an error":
withTempConfig:
createDir(configDir())
writeFile(roomsFile(), "not json at all")
check loadRooms().len == 0
suite "the preferences":
test "round-trip":
withTempConfig:
check savePrefs({"hideJoinPart": true, "showUsers": false}.toTable)
let got = loadPrefs()
check got["hideJoinPart"] == true
check got["showUsers"] == false
test "absent is empty":
withTempConfig:
check loadPrefs().len == 0
|