Skip to content

Commit 25ad742

Browse files
committed
fix: unsubscribe in tests
1 parent 5c2fa45 commit 25ad742

2 files changed

Lines changed: 47 additions & 29 deletions

File tree

lua/opencode/state/store.lua

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
---@field source? 'helper'|'raw'
33
---@field silent? boolean
44

5+
---@alias StateValue<K> K extends keyof OpencodeState and StateValue<K> or never
6+
57
local M = {}
68

9+
---@type OpencodeState
710
local _state = {
811
windows = nil,
912
is_opening = false,
@@ -62,16 +65,20 @@ function M.state()
6265
return _state
6366
end
6467

65-
---@param key string
66-
---@return any
68+
---@generic K extends keyof OpencodeState
69+
---@param key K
70+
---@return OpencodeState[K]
6771
function M.get(key)
6872
return _state[key]
6973
end
7074

71-
---@param key string
72-
---@param value any
75+
local c = M.get('user_message_counte')
76+
77+
---@generic K extends keyof OpencodeState
78+
---@param key K
79+
---@param value StateValue<K>
7380
---@param opts? OpencodeProtectedStateSetOptions
74-
---@return any
81+
---@return StateValue<K>
7582
function M.set(key, value, opts)
7683
local old = _state[key]
7784
opts = opts or { source = 'helper' }
@@ -88,28 +95,30 @@ function M.set(key, value, opts)
8895
return value
8996
end
9097

91-
---@param key string
92-
---@param value any
98+
---@generic K extends keyof OpencodeState
99+
---@param key K
100+
---@param value StateValue<K>
93101
---@param opts? OpencodeProtectedStateSetOptions
94-
---@return any
102+
---@return StateValue<K>
95103
function M.set_raw(key, value, opts)
96104
local next_opts = vim.tbl_extend('force', { source = 'raw' }, opts or {})
97105
return M.set(key, value, next_opts)
98106
end
99107

100-
---@generic T
101-
---@param key string
102-
---@param updater fun(current: T): T
108+
---@generic K extends keyof OpencodeState
109+
---@param key K
110+
---@param updater fun(current: StateValue<K>): StateValue<K>
103111
---@param opts? OpencodeProtectedStateSetOptions
104-
---@return T
112+
---@return StateValue<K>
105113
function M.update(key, updater, opts)
106114
local next_value = updater(_state[key])
107115
M.set(key, next_value, opts)
108116
return next_value
109117
end
110118

111-
---@param key string|string[]|nil
112-
---@param cb fun(key:string, new_val:any, old_val:any)
119+
---@generic K extends keyof OpencodeState
120+
---@param key K|K[]|nil
121+
---@param cb fun(key:K, new_val:StateValue<K>, old_val:StateValue<K>)
113122
function M.subscribe(key, cb)
114123
if type(key) == 'table' then
115124
for _, current_key in ipairs(key) do
@@ -132,8 +141,9 @@ function M.subscribe(key, cb)
132141
table.insert(_listeners[key], cb)
133142
end
134143

135-
---@param key string|nil
136-
---@param cb fun(key:string, new_val:any, old_val:any)
144+
---@generic K extends keyof OpencodeState
145+
---@param key K|nil
146+
---@param cb fun(key:K, new_val:StateValue<K>, old_val:StateValue<K>)
137147
function M.unsubscribe(key, cb)
138148
key = key or '*'
139149
local list = _listeners[key]
@@ -148,6 +158,10 @@ function M.unsubscribe(key, cb)
148158
end
149159
end
150160

161+
---@generic K extends keyof OpencodeState
162+
---@param key K
163+
---@param new_val StateValue<K>
164+
---@param old_val StateValue<K>
151165
function M.emit(key, new_val, old_val)
152166
vim.schedule(function()
153167
if _listeners[key] then
@@ -167,8 +181,9 @@ function M.emit(key, new_val, old_val)
167181
end)
168182
end
169183

170-
---@param key string
171-
---@param value any
184+
---@generic K extends keyof OpencodeState
185+
---@param key K
186+
---@param value StateValue<K> extends any[] and StateValue<K>[integer] or never
172187
function M.append(key, value)
173188
if type(value) ~= 'table' then
174189
error('Value must be a table to append')
@@ -185,7 +200,8 @@ function M.append(key, value)
185200
M.emit(key, _state[key], old)
186201
end
187202

188-
---@param key string
203+
---@generic K extends keyof OpencodeState
204+
---@param key K
189205
---@param idx integer
190206
function M.remove(key, idx)
191207
if not _state[key] then

tests/unit/state_spec.lua

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
-- Tests for the observable state module
33

44
local state = require('opencode.state')
5-
local store = require('opencode.state.store')
65

76
describe('opencode.state (observable)', function()
87
it('notifies listeners on key change', function()
98
local called = false
109
local changed_key, new_val, old_val
11-
state.subscribe('messages', function(key, newv, oldv)
10+
local cb = function(key, newv, oldv)
1211
called = true
1312
changed_key = key
1413
new_val = newv
1514
old_val = oldv
16-
end)
15+
end
16+
state.subscribe('messages', cb)
1717
state.renderer.set_messages({ { id = 'test' } })
1818
vim.wait(50, function()
1919
return called == true
@@ -23,18 +23,19 @@ describe('opencode.state (observable)', function()
2323
assert.same({ { id = 'test' } }, new_val)
2424
-- Clean up
2525
state.renderer.set_messages(nil)
26-
state.unsubscribe('messages', nil)
26+
state.unsubscribe('messages', cb)
2727
end)
2828

2929
it('notifies wildcard listeners on any key change', function()
3030
local called = false
3131
local changed_key, new_val, old_val
32-
state.subscribe('*', function(key, newv, oldv)
32+
local cb = function(key, newv, oldv)
3333
called = true
3434
changed_key = key
3535
new_val = newv
3636
old_val = oldv
37-
end)
37+
end
38+
state.subscribe('*', cb)
3839
state.renderer.set_cost(99)
3940
vim.wait(50, function()
4041
return called == true
@@ -44,7 +45,7 @@ describe('opencode.state (observable)', function()
4445
assert.equals(99, new_val)
4546
-- Clean up
4647
state.renderer.set_cost(0)
47-
state.unsubscribe('*', nil)
48+
state.unsubscribe('*', cb)
4849
end)
4950

5051
it('can unregister listeners', function()
@@ -87,9 +88,10 @@ describe('opencode.state (observable)', function()
8788

8889
it('does not notify if value is unchanged', function()
8990
local called = false
90-
state.subscribe('tokens_count', function()
91+
local cb = function()
9192
called = true
92-
end)
93+
end
94+
state.subscribe('tokens_count', cb)
9395
state.renderer.set_tokens_count(42)
9496
vim.wait(50, function()
9597
return called == true
@@ -100,7 +102,7 @@ describe('opencode.state (observable)', function()
100102
assert.is_false(called)
101103
-- Clean up
102104
state.renderer.set_tokens_count(0)
103-
state.unsubscribe('tokens_count', nil)
105+
state.unsubscribe('tokens_count', cb)
104106
end)
105107

106108
it('errors on direct state write', function()

0 commit comments

Comments
 (0)