mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-11-09 20:07:43 +08:00
45 lines
2.3 KiB
TypeScript
45 lines
2.3 KiB
TypeScript
/** Vendor HMR containment of Include refresh rejections. */
|
|
import { mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { pathToFileURL } from 'node:url'
|
|
import { Context, type Plugin } from '@deepseek-ai/cordis'
|
|
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
|
import Include from '@deepseek-ai/cordis-plugin-include'
|
|
import Timer from '@deepseek-ai/cordis-plugin-timer'
|
|
import { expect, it, onTestFinished, vi } from 'vitest'
|
|
|
|
// A literal import would add vendor HMR's `Context.hmr` declaration to the
|
|
// repository type program, where DSH HMR declares the same property.
|
|
const vendorHmr: string = '@deepseek-ai/cordis-plugin-hmr'
|
|
|
|
it('logs a rejected Include refresh instead of leaving it unhandled', async () => {
|
|
const dir = realpathSync(mkdtempSync(join(tmpdir(), 'dsh-vendor-hmr-include-')))
|
|
const ctx = new Context()
|
|
ctx.baseUrl = pathToFileURL(dir).href + '/'
|
|
onTestFinished(async () => { await ctx.fiber.dispose(); rmSync(dir, { recursive: true, force: true }) })
|
|
await ctx.plugin(Loader)
|
|
await ctx.plugin(Timer)
|
|
ctx.loader.builtins.include = Include
|
|
const file = join(dir, 'nested.yml')
|
|
writeFileSync(file, '[]\n')
|
|
const id = await ctx.loader.create({ name: 'cordis:include', config: { path: './nested.yml' } })
|
|
await ctx.loader.await()
|
|
const { default: Hmr } = await import(vendorHmr) as { default: Plugin }
|
|
await ctx.plugin(Hmr, { root: [], ignored: [], debounce: 0 })
|
|
// The service keeps its chokidar watcher private; the test drives its change listener directly.
|
|
const watcher = Reflect.get(ctx.get('hmr') as object, 'watcher') as { emit(event: 'change', path: string): boolean }
|
|
const include = ctx.loader.resolve(id).subtree as Include
|
|
const failure = new Error('config file has 1 unsaved change(s)')
|
|
const refresh = vi.spyOn(include, 'refresh').mockRejectedValue(failure)
|
|
const warn = vi.spyOn(ctx.logger, 'warn')
|
|
const unhandled = vi.fn()
|
|
process.on('unhandledRejection', unhandled)
|
|
onTestFinished(() => { process.off('unhandledRejection', unhandled) })
|
|
watcher.emit('change', file)
|
|
await vi.waitFor(() => { expect(warn).toHaveBeenCalledWith(failure) })
|
|
await new Promise(resolve => setImmediate(resolve))
|
|
expect(refresh).toHaveBeenCalledOnce()
|
|
expect(unhandled).not.toHaveBeenCalled()
|
|
})
|