M5: roll Energy chart window for live auto-refresh (English label); render boolean config fields as switches
This commit is contained in:
@@ -418,4 +418,78 @@ describe('useReadings', () => {
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Rolling window: spanMs causes queryFn to compute end=now() on each call
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
it('when spanMs is provided, sends computed start/end (rolling window) instead of fixed params', async () => {
|
||||
const tBefore = Date.now()
|
||||
mockGet.mockResolvedValue({ data: { items: [] } })
|
||||
|
||||
const { Wrapper } = makeWrapper()
|
||||
const { useReadings } = await import('./hooks')
|
||||
const SPAN_MS = 60 * 60 * 1000 // 1 hour
|
||||
const { result } = renderHook(
|
||||
() => useReadings('test-uuid-1', { spanMs: SPAN_MS }),
|
||||
{ wrapper: Wrapper },
|
||||
)
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
const tAfter = Date.now()
|
||||
|
||||
// The GET should have been called with start and end computed from now().
|
||||
expect(mockGet).toHaveBeenCalledWith(
|
||||
'/api/modbus/devices/{uuid}/readings',
|
||||
expect.objectContaining({
|
||||
params: expect.objectContaining({
|
||||
query: expect.objectContaining({
|
||||
end: expect.any(String),
|
||||
start: expect.any(String),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
const call = mockGet.mock.calls[mockGet.mock.calls.length - 1]
|
||||
const query = call[1].params.query as { start: string; end: string }
|
||||
const endMs = new Date(query.end).getTime()
|
||||
const startMs = new Date(query.start).getTime()
|
||||
|
||||
// end must be within the test window (tBefore..tAfter).
|
||||
expect(endMs).toBeGreaterThanOrEqual(tBefore)
|
||||
expect(endMs).toBeLessThanOrEqual(tAfter + 100) // small tolerance
|
||||
|
||||
// start must be approximately end - spanMs.
|
||||
expect(endMs - startMs).toBeCloseTo(SPAN_MS, -2) // within 100ms
|
||||
})
|
||||
|
||||
it('when spanMs is provided, queryKey uses spanMs (not absolute timestamps) for stable caching', async () => {
|
||||
mockGet.mockResolvedValue({ data: { items: [] } })
|
||||
|
||||
const { Wrapper, qc } = makeWrapper()
|
||||
const { useReadings } = await import('./hooks')
|
||||
const SPAN_MS = 3600000 // 1 hour
|
||||
|
||||
const { result } = renderHook(
|
||||
() => useReadings('test-uuid-1', { spanMs: SPAN_MS }),
|
||||
{ wrapper: Wrapper },
|
||||
)
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
// The query cache should have a key containing spanMs, not an absolute timestamp.
|
||||
const queries = qc.getQueryCache().findAll({
|
||||
predicate: (q) => {
|
||||
const key = q.queryKey as unknown[]
|
||||
return key[0] === 'modbus-readings' && key[1] === 'test-uuid-1'
|
||||
},
|
||||
})
|
||||
expect(queries).toHaveLength(1)
|
||||
const keyParams = queries[0].queryKey[2] as Record<string, unknown>
|
||||
expect(keyParams).toHaveProperty('spanMs', SPAN_MS)
|
||||
expect(keyParams).not.toHaveProperty('start')
|
||||
expect(keyParams).not.toHaveProperty('end')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user