-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathplugin-smoke.mjs
More file actions
137 lines (123 loc) · 5 KB
/
Copy pathplugin-smoke.mjs
File metadata and controls
137 lines (123 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env node
/**
* Packaged plugin-shell smoke test.
*
* Packs the REAL pnpm tarball, installs it into a fresh host project,
* imports the installed lib/plugin.js bundle, registers plugin_check through
* apply()/ctx.tools.register, executes the real handler on a fixture, and
* asserts the canonical result. A missing module, an API mismatch, or a
* handler failure fails this script — this is NOT a src-level unit test.
*/
import { mkdtempSync, rmSync, writeFileSync, existsSync } from 'node:fs'
import { tmpdir } from 'node:os'
import path from 'node:path'
import { fileURLToPath, pathToFileURL } from 'node:url'
import { spawnSync } from 'node:child_process'
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
const fixture = path.resolve(root, 'tests', 'fixtures', 'good-plugin')
function runPnpm(args, cwd) {
if (process.platform === 'win32') {
return spawnSync(`pnpm ${args.join(' ')}`, { cwd, stdio: 'inherit', shell: true })
}
return spawnSync('pnpm', args, { cwd, stdio: 'inherit' })
}
console.log('[plugin-smoke] packing the real tarball...')
const pack = process.platform === 'win32'
? spawnSync('pnpm pack --silent', { cwd: root, encoding: 'utf8', shell: true })
: spawnSync('pnpm', ['pack', '--silent'], { cwd: root, encoding: 'utf8' })
if (pack.status !== 0) {
console.error('[plugin-smoke] pnpm pack failed')
process.stderr.write(String(pack.stderr ?? ''))
process.exit(1)
}
const tgzName = String(pack.stdout ?? '').trim().split(/\r?\n/).pop()
if (!tgzName || !existsSync(path.join(root, tgzName))) {
console.error(`[plugin-smoke] could not locate packed tarball (got: ${String(tgzName)})`)
process.exit(1)
}
const tgz = path.join(root, tgzName)
const host = mkdtempSync(path.join(tmpdir(), 'dsh-doctor-host-'))
try {
writeFileSync(
path.join(host, 'package.json'),
JSON.stringify(
{
name: 'dsh-plugin-doctor-smoke-host',
private: true,
version: '1.0.0',
dependencies: {
'@deepseek-ai/cordis': '^4.0.1',
'@deepseek-ai/dsh-tools': '0.1.0-rc.6',
'@deepseek-ai/schemastery': '^3.18.1',
'dsh-plugin-doctor': `file:${tgz.replaceAll('\\', '/')}`,
},
},
null,
2,
),
)
console.log('[plugin-smoke] installing packed tarball into a fresh host project...')
const install = runPnpm(['install'], host)
if (install.status !== 0) {
console.error('[plugin-smoke] pnpm install failed')
process.exit(1)
}
const pluginEntry = path.join(host, 'node_modules', 'dsh-plugin-doctor', 'lib', 'plugin.js')
if (!existsSync(pluginEntry)) {
throw new Error('packed plugin entry lib/plugin.js missing after install')
}
if (!existsSync(path.join(host, 'node_modules', 'dsh-plugin-doctor', 'cordis.patch.yml'))) {
throw new Error('packed plugin is missing cordis.patch.yml')
}
console.log('[plugin-smoke] loading packed plugin shell bundle...')
const plugin = await import(pathToFileURL(pluginEntry).href)
if (plugin.name !== 'dsh-plugin-doctor') {
throw new Error(`unexpected plugin name: ${plugin.name}`)
}
if (plugin.inject?.includes('tools') !== true) {
throw new Error('plugin shell does not declare the tools service')
}
const registered = []
const ctx = {
tools: {
register: (definition) => {
registered.push(definition)
return () => {}
},
},
}
console.log('[plugin-smoke] calling apply(ctx, config) through the real registration path...')
plugin.apply(ctx, { timeoutMs: 120_000 })
const tool = registered.find((definition) => definition.name === 'plugin_check')
if (tool === undefined) {
throw new Error('plugin_check was not registered via apply/ctx.tools.register')
}
if (tool.parameters?.properties?.dir === undefined) {
throw new Error('plugin_check schema missing the dir parameter')
}
console.log('[plugin-smoke] executing the real plugin_check handler on a fixture...')
const result = await tool.execute(
{ dir: fixture.replaceAll('\\', '/') },
{ signal: new AbortController().signal },
)
if (result?.ok !== true) {
throw new Error(`plugin_check did not pass the good fixture: ${JSON.stringify(result)}`)
}
const checks = result.checks
if (checks.find((check) => check.name === 'manifest')?.status !== 'PASS') {
throw new Error('manifest check did not PASS')
}
if (checks.find((check) => check.name === 'patch')?.status !== 'PASS') {
throw new Error('patch check did not PASS')
}
console.log('[plugin-smoke] rendering through the real output.render...')
const blocks = tool.output.render({ dir: fixture }, result)
const text = blocks.map((block) => block.text ?? '').join('\n')
if (!text.includes('ALL CHECKS PASSED')) {
throw new Error(`render output missing pass summary: ${JSON.stringify(text)}`)
}
console.log('PASS [plugin-smoke] packed plugin loaded, plugin_check registered, handler executed, result asserted')
console.log('PASS [plugin-smoke] result:', JSON.stringify(result))
} finally {
rmSync(host, { recursive: true, force: true })
}