test(settings): cover the section directory's disposal, stale-read, and invalidation paths
The per-file coverage gate flagged four uncovered locations the new section directory introduced: refresh() after disposal, a read superseded by a newer one, and the two invalidation handlers that make the served namespaces re-read (settings/document-updated and connection/reset).
This commit is contained in:
@@ -116,6 +116,33 @@ describe('ui-plugin-config apply', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('re-reads the served namespaces when the Host commits a settings document', async () => {
|
||||||
|
// Which namespaces the Host serves is a registration fact the wire never
|
||||||
|
// announces on its own, so the section rides the invalidation that can
|
||||||
|
// accompany a changed composition.
|
||||||
|
const { ctx, slots, describeSettings } = await bench(['bash'])
|
||||||
|
declareRoot(slots)
|
||||||
|
await ctx.plugin({ inject: [...inject], apply }).await()
|
||||||
|
await vi.waitFor(() => { expect(describeSettings).toHaveBeenCalled() })
|
||||||
|
describeSettings.mockClear()
|
||||||
|
|
||||||
|
ctx.remote.$dispatch('settings/document-updated', ['bash', 1])
|
||||||
|
|
||||||
|
await vi.waitFor(() => { expect(describeSettings).toHaveBeenCalled() })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('re-reads the served namespaces after a reconnect', async () => {
|
||||||
|
const { ctx, slots, describeSettings } = await bench(['bash'])
|
||||||
|
declareRoot(slots)
|
||||||
|
await ctx.plugin({ inject: [...inject], apply }).await()
|
||||||
|
await vi.waitFor(() => { expect(describeSettings).toHaveBeenCalled() })
|
||||||
|
describeSettings.mockClear()
|
||||||
|
|
||||||
|
ctx.emit('connection/reset')
|
||||||
|
|
||||||
|
await vi.waitFor(() => { expect(describeSettings).toHaveBeenCalled() })
|
||||||
|
})
|
||||||
|
|
||||||
it('re-reads the credential when the Host reports the watched reference changed', async () => {
|
it('re-reads the credential when the Host reports the watched reference changed', async () => {
|
||||||
const { ctx, slots, describeCredentials } = await bench()
|
const { ctx, slots, describeCredentials } = await bench()
|
||||||
declareRoot(slots)
|
declareRoot(slots)
|
||||||
|
|||||||
@@ -622,6 +622,41 @@ describe('PluginConfigSectionController', () => {
|
|||||||
expect(settings.describe).not.toHaveBeenCalled()
|
expect(settings.describe).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('ignores a slot-ledger change that arrives after disposal', async () => {
|
||||||
|
const settings = settingsApi(['bash'])
|
||||||
|
let entries = ledger()
|
||||||
|
const controller = new PluginConfigSectionController(settings.api, () => entries)
|
||||||
|
await controller.load()
|
||||||
|
|
||||||
|
controller.dispose()
|
||||||
|
entries = ledger('bash')
|
||||||
|
controller.refresh()
|
||||||
|
|
||||||
|
expect(controller.inject().hooks.pluginConfigSection.getSnapshot().namespaces).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('drops a read a newer one superseded', async () => {
|
||||||
|
// The section re-reads on every settings-document invalidation, so a slow
|
||||||
|
// first answer must not overwrite the newer one that already landed.
|
||||||
|
const settings = settingsApi(['bash'])
|
||||||
|
const controller = new PluginConfigSectionController(settings.api, () => ledger('bash', 'agent-loop'))
|
||||||
|
const slow = Promise.withResolvers<unknown>()
|
||||||
|
settings.describe.mockReturnValueOnce(slow.promise as never)
|
||||||
|
const stale = controller.load()
|
||||||
|
|
||||||
|
await controller.load()
|
||||||
|
expect(controller.inject().hooks.pluginConfigSection.getSnapshot().namespaces).toEqual(['bash'])
|
||||||
|
slow.resolve({
|
||||||
|
rpcId: 's-0',
|
||||||
|
result: { ok: true, value: { writable: true, hasDocument: true, namespaces: [
|
||||||
|
{ ns: 'agent-loop', schema: {}, value: {}, applies: 'live', secrets: [], revision: 0 },
|
||||||
|
] } },
|
||||||
|
})
|
||||||
|
await stale
|
||||||
|
|
||||||
|
expect(controller.inject().hooks.pluginConfigSection.getSnapshot().namespaces).toEqual(['bash'])
|
||||||
|
})
|
||||||
|
|
||||||
it('reports the Host answered even when it serves nothing this section shows', async () => {
|
it('reports the Host answered even when it serves nothing this section shows', async () => {
|
||||||
const settings = settingsApi(['ui-theme'])
|
const settings = settingsApi(['ui-theme'])
|
||||||
const controller = new PluginConfigSectionController(settings.api, () => ledger('bash'))
|
const controller = new PluginConfigSectionController(settings.api, () => ledger('bash'))
|
||||||
|
|||||||
Reference in New Issue
Block a user