M8-R09: add meter close unbind and transfer workflows
This commit is contained in:
@@ -106,7 +106,9 @@ describe('useDeclareMeter source binding invalidation', () => {
|
||||
const { qc, Wrapper } = makeWrapper()
|
||||
const affectedKeys = [
|
||||
['energy-meters'], ['energy-source-channels'], ['energy-meter-bindings', 9],
|
||||
['energy-sources'], ['expose-catalog'], ['energy-costs'], ['energy-costs-summary'],
|
||||
['energy-sources'], ['energy-source', 'source-1'], ['energy-channel-readings', 'source-1', 'channel-1'],
|
||||
['expose-catalog'], ['energy-costs', 'electricity'], ['energy-costs-summary', 'electricity'],
|
||||
['meter-costs', 'thermal', 'month'], ['meter-cost-summary', 'thermal'],
|
||||
]
|
||||
for (const queryKey of affectedKeys) qc.setQueryData(queryKey, { cached: true })
|
||||
const { useDeclareMeter } = await import('./hooks')
|
||||
@@ -117,6 +119,37 @@ describe('useDeclareMeter source binding invalidation', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('meter lifecycle mutations', () => {
|
||||
beforeEach(() => vi.clearAllMocks())
|
||||
|
||||
it.each([
|
||||
['Declare auto-handoff', 'post', async (hooks: typeof import('./hooks')) => hooks.useDeclareMeter, { label: 'swap', commodity: 'electricity', started_at: '2026-08-24T12:34', reason: 'meter_swap' }],
|
||||
['Close meter', 'post', async (hooks: typeof import('./hooks')) => hooks.useCloseMeter, { id: 9, ended_at: '2026-08-24T12:34' }],
|
||||
['Unbind', 'patch', async (hooks: typeof import('./hooks')) => hooks.useCloseBinding, { uuid: 'old', ended_at: '2026-08-24T12:34' }],
|
||||
['Transfer', 'post', async (hooks: typeof import('./hooks')) => hooks.useTransferBinding, { id: 10, body: { from_binding_uuid: 'old', to_source_channel_uuid: 'new', effective_at: '2026-08-24T12:34' } }],
|
||||
['Direct bind', 'post', async (hooks: typeof import('./hooks')) => hooks.useCreateBinding, { id: 10, body: { source_channel_uuid: 'new', started_at: '2026-08-24T12:34' } }],
|
||||
['Update electricity start', 'patch', async (hooks: typeof import('./hooks')) => hooks.useUpdateMeter, { id: 10, body: { started_at: '2026-08-24T12:34' } }],
|
||||
['Update heating label', 'patch', async (hooks: typeof import('./hooks')) => hooks.useUpdateMeter, { id: 11, body: { label: 'Heating meter' } }],
|
||||
['Update hot water start', 'patch', async (hooks: typeof import('./hooks')) => hooks.useUpdateMeter, { id: 12, body: { started_at: '2026-08-24T12:34' } }],
|
||||
])('%s invalidates every lifecycle view using a fresh QueryClient', async (_name, method, getHook, payload) => {
|
||||
mockPost.mockResolvedValue({ data: {} })
|
||||
mockPatch.mockResolvedValue({ data: {} })
|
||||
const { qc, Wrapper } = makeWrapper()
|
||||
const affectedKeys = [
|
||||
['energy-meters'], ['energy-sources'], ['energy-source', 'source-1'], ['energy-source-channels'], ['energy-meter-bindings'],
|
||||
['energy-channel-readings', 'source-1', 'channel-1'], ['energy-costs', 'electricity'], ['energy-costs-summary', 'electricity'],
|
||||
['meter-costs', 'thermal', 'month'], ['meter-cost-summary', 'thermal'], ['expose-catalog'],
|
||||
]
|
||||
for (const key of affectedKeys) qc.setQueryData(key, { cached: true })
|
||||
const hooks = await import('./hooks')
|
||||
const useHook = await getHook(hooks)
|
||||
const result = renderHook(() => useHook(), { wrapper: Wrapper })
|
||||
await act(async () => { await result.result.current.mutateAsync(payload as never) })
|
||||
expect(method === 'post' ? mockPost : mockPatch).toHaveBeenCalled()
|
||||
for (const key of affectedKeys) expect(qc.getQueryState(key)?.isInvalidated).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('useProfiles', () => {
|
||||
beforeEach(() => vi.clearAllMocks())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user