fix(ci): align plugin inventory with current contracts
This commit is contained in:
8 files changed
+35
-13
No files matched your search
@@ -0,0 +1,93 @@
|
||||
// @vitest-environment jsdom
|
||||
import { Context, Service } from '@deepseek-ai/cordis'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { cleanup } from '@testing-library/react'
|
||||
import { LocaleService } from '@deepseek-ai/dsh-client-locale/client'
|
||||
import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client'
|
||||
import { resolveSlotLabel } from '@deepseek-ai/dsh-client-ui-slots'
|
||||
import { usePinnedBrowserLanguages } from '@deepseek-ai/dsh-client-test-runtime'
|
||||
import { apply, inject, NS } from '../src/client/index.ts'
|
||||
import { PluginSettingsSection } from '../src/client/PluginSettingsSection.tsx'
|
||||
import type { PluginSettingsSectionInjected } from '../src/client/PluginSettingsSection.tsx'
|
||||
|
||||
usePinnedBrowserLanguages('zh-CN')
|
||||
afterEach(cleanup)
|
||||
|
||||
const EMPTY = { entries: [] }
|
||||
type ListResult =
|
||||
| { readonly ok: true; readonly value: typeof EMPTY }
|
||||
| { readonly ok: false; readonly error: { readonly code: string; readonly message: string } }
|
||||
|
||||
async function bench() {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SlotsService).await()
|
||||
const locale = new LocaleService(ctx)
|
||||
ctx.provide('locale', locale)
|
||||
class RemoteService extends Service {
|
||||
constructor(serviceCtx: Context) {
|
||||
super(serviceCtx, 'remote')
|
||||
}
|
||||
}
|
||||
new RemoteService(ctx)
|
||||
const list = vi.fn<() => Promise<ListResult>>()
|
||||
.mockResolvedValue({ ok: true, value: EMPTY })
|
||||
ctx.provide('remote.pluginInventory', { list })
|
||||
return { ctx, slots: ctx.get('slots') as SlotsService, locale, list }
|
||||
}
|
||||
|
||||
function declare(slots: SlotsService): () => void {
|
||||
return slots.register({
|
||||
name: 'root',
|
||||
children: { 'settings.section': { kind: 'list', scope: 'root' } },
|
||||
} as never, () => null)
|
||||
}
|
||||
|
||||
describe('ui-plugins browser plugin', () => {
|
||||
it('declares only the services used by the Settings Remote contribution', () => {
|
||||
expect(inject).toEqual(['slots', 'locale', 'remote', 'remote.pluginInventory'])
|
||||
})
|
||||
|
||||
it('registers a localized section without reading the Remote eagerly', async () => {
|
||||
const b = await bench()
|
||||
declare(b.slots)
|
||||
await b.ctx.plugin({ inject: [...inject], apply }).await()
|
||||
|
||||
const entry = b.slots.entries('settings.section')[0]!
|
||||
expect(entry.component).toBe(PluginSettingsSection)
|
||||
expect(entry.options).toMatchObject({ id: 'plugin-inventory', order: 15 })
|
||||
expect(entry.locale).toBe(NS)
|
||||
expect(resolveSlotLabel(entry.options.label)).toBe('插件')
|
||||
expect(b.list).not.toHaveBeenCalled()
|
||||
|
||||
const injected = (entry.inject as unknown as () => PluginSettingsSectionInjected)()
|
||||
await expect(injected.list()).resolves.toEqual(EMPTY)
|
||||
expect(b.list).toHaveBeenCalledOnce()
|
||||
b.list.mockResolvedValueOnce({ ok: false, error: { code: 'REMOTE_ERROR', message: 'unavailable' } })
|
||||
await expect(injected.list()).rejects.toThrow('pluginInventory.list failed: REMOTE_ERROR: unavailable')
|
||||
await b.ctx.fiber.dispose()
|
||||
})
|
||||
|
||||
it('follows locale and recovers across late declaration and declarer reload', async () => {
|
||||
const b = await bench()
|
||||
const fiber = b.ctx.plugin({ inject: [...inject], apply })
|
||||
await fiber.await()
|
||||
expect(b.slots.entries('settings.section')).toHaveLength(0)
|
||||
|
||||
const stop = declare(b.slots)
|
||||
await vi.waitFor(() => { expect(b.slots.entries('settings.section')).toHaveLength(1) })
|
||||
b.locale.setLocale('en')
|
||||
expect(resolveSlotLabel(b.slots.entries('settings.section')[0]!.options.label)).toBe('Plugins')
|
||||
|
||||
stop()
|
||||
expect(b.slots.entries('settings.section')).toHaveLength(0)
|
||||
declare(b.slots)
|
||||
await vi.waitFor(() => {
|
||||
expect(b.slots.entries('settings.section')[0]?.component).toBe(PluginSettingsSection)
|
||||
})
|
||||
|
||||
await fiber.dispose()
|
||||
expect(b.slots.entries('settings.section')).toHaveLength(0)
|
||||
expect(() => b.locale.register(NS, 'zh', {})).not.toThrow()
|
||||
await b.ctx.fiber.dispose()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user