nandi/frqpublic Fork 0
3836feebf9034553dbb9ca8c2653194c322da7f3
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

tstore.nim · 144 lines · 5.0 KBNim Blame HistoryRaw
Rooms and prefs come back with you a4be36c nandi yesterday1## What survives a restart, and what deliberately does not.
2##
3## Every test here points `XDG_CONFIG_HOME` at a directory of its own, set
4## before `frq/store` is touched at all: the alternative is a suite that reads
5## and writes the config of whoever runs it, which would both lie about the
6## result and cost them their room list.
7
Find out who somebody is 4b72ad1 nandi 23h ago8import std/[json, os, tables, times, unittest]
Rooms and prefs come back with you a4be36c nandi yesterday9
10let sandbox = getTempDir() / "frq-tstore-" & $epochTime()
11putEnv("XDG_CONFIG_HOME", sandbox)
12
13import frq/[cells, clock, model, rooms, store, reducer]
14
15proc clean() =
16 removeDir(sandbox)
17 app = initState()
18
19suite "the config directory":
20 test "is under XDG_CONFIG_HOME where there is one":
21 check configDir() == sandbox / "frq"
22
23suite "a saved session":
24 setup: clean()
25 test "round-trips, and says whether there was one":
26 check loadSession()[1] == false
27 check saveSession(SavedSession(brokerToken: "durable", handle: "alice.uk",
28 did: "did:plc:a", nick: "alice"))
29 let (s, had) = loadSession()
30 check had
31 check s.brokerToken == "durable"
32 check s.did == "did:plc:a"
33 test "with no broker token is not a session":
34 # The token is the whole point of saving one; the handle beside it is
35 # only there to say whose it is.
36 check saveSession(SavedSession(handle: "alice.uk"))
37 check loadSession()[1] == false
Four more modules into Nim: members, glyphs, emoji, store 3975b4b nandi yesterday38 test "is written so nobody else can read it":
Rooms and prefs come back with you a4be36c nandi yesterday39 check saveSession(SavedSession(brokerToken: "durable"))
40 check getFilePermissions(sessionFile()) == {fpUserRead, fpUserWrite}
41 test "and restore brings it back as the Bluesky mode":
42 check saveSession(SavedSession(brokerToken: "durable", handle: "alice.uk",
43 nick: "alice"))
44 restore()
45 check app.brokerToken == "durable"
46 check app.authMode == amBluesky
47 check app.formHandle == "alice.uk"
48 check app.formNick == "alice"
49
50suite "the rooms file":
51 setup: clean()
52
53 proc saved(): seq[SavedRoom] =
54 var rooms: OrderedTable[string, Room]
55 for (name, accessed, id, at) in [("#a", 100'i64, "m1", 900'i64),
56 ("#b", 300'i64, "m2", 800'i64),
57 ("carol", 200'i64, "", 0'i64)]:
58 var r = initRoom(name)
59 r.accessed = accessed
60 r.lastReadId = id
61 r.lastReadAt = at
62 r.messages = @[Message(id: "x", frm: "bob", text: "hi", at: 1000)]
63 rooms[name] = r
64 check saveRooms(rooms)
65 loadRooms()
66
67 test "keeps the name and the marker, and not the messages":
68 # The list is the part worth keeping; the lines in it come from the
69 # server, and a client that saved them would be a second copy to go
70 # stale.
71 let rs = saved()
72 check rs.len == 3
73 check rs[0].name == "#a"
74 check rs[0].lastReadId == "m1"
75 check rs[0].lastReadAt == 900
76
77 test "restore brings them back empty, unjoined, with their markers":
78 discard saved()
79 restore()
80 check app.rooms.len == 3
81 check app.rooms["#a"].messages.len == 0
82 check not app.rooms["#a"].joined
83 check app.rooms["#a"].lastReadId == "m1"
84 check app.rooms["#a"].accessed == 100
85 check app.rooms["#b"].accessed == 300
86
87 test "and the most recently used is still top of the list":
88 discard saved()
89 restore()
90 check channelList(app.rooms, "")[0].name == "#b"
91
92 test "a record with no marker is caught up, not unread from the start":
93 # An older frq's file, or one that lost it. The alternative announces a
94 # hundred lines the reader has already seen.
95 discard saved()
96 restore()
97 let before = nowMs()
98 check app.rooms["carol"].lastReadAt >= before - 5000
99 check app.rooms["carol"].lastReadAt > 0
100
101 test "a room the reader has closed stays closed":
102 discard saved()
103 restore()
104 dispatch(%*{"id": "room.leave:#a"})
105 app = initState()
106 restore()
107 check not app.rooms.hasKey("#a")
108 check app.rooms.hasKey("#b")
109
110suite "the prefs file":
111 setup: clean()
A row is named for its message, not its place 4083860 nandi 22h ago112 test "the display toggles outlive the run":
Rooms and prefs come back with you a4be36c nandi yesterday113 restore()
114 let wasJoinPart = app.hideJoinPart
115 dispatch(%*{"id": "join-part.toggle"})
A row is named for its message, not its place 4083860 nandi 22h ago116 dispatch(%*{"id": "chat-list.toggle"})
Rooms and prefs come back with you a4be36c nandi yesterday117 app = initState()
118 restore()
119 check app.hideJoinPart == not wasJoinPart
A row is named for its message, not its place 4083860 nandi 22h ago120 check app.hideChatList
121
122 test "but the member list does not":
123 # On a narrow window the people panel is the pane rather than something
124 # beside it, so a remembered "on" opens a room and shows a list of names
125 # instead of the room.
126 restore()
127 dispatch(%*{"id": "users.toggle"})
Rooms and prefs come back with you a4be36c nandi yesterday128 check app.showUsers
A row is named for its message, not its place 4083860 nandi 22h ago129 app = initState()
130 restore()
131 check not app.showUsers
Rooms and prefs come back with you a4be36c nandi yesterday132 test "the overview is not one of them":
133 # It is a way of looking at the moment you are in rather than a
134 # preference, and reopening into it would answer a question nobody asked
135 # twice.
136 restore()
137 dispatch(%*{"id": "overview.toggle"})
138 app = initState()
139 restore()
140 check not app.overview
141 test "and a prefs file that is not there is a first run, not an error":
142 check loadPrefs().len == 0
143 restore()
144 check not app.hideJoinPart