@abarcenas/ai-workflow-template 1.49.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/instructions/knowledgebase.instructions.md +2 -2
- package/.agents/instructions/learned-knowledge.instructions.md +47 -2
- package/.agents/instructions/memory-schema.instructions.md +1 -1
- package/.github/workflows/npm-publish.yml +69 -1
- package/.opencode/plugins/graphify.js +22 -0
- package/LICENSE +15 -0
- package/README.md +56 -22
- package/memory-bank/.vocabulary.json +3 -0
- package/opencode.mcp.example.json +13 -0
- package/package.json +20 -10
- package/scripts/bump-version.js +18 -2
- package/scripts/mcp/playwright-mcp-launcher.js +45 -2
- package/scripts/bump-version.test.js +0 -238
- package/scripts/knowledgebase-cli.test.js +0 -576
- package/scripts/knowledgebase-index.test.js +0 -759
- package/scripts/mcp/playwright-mcp-launcher.test.js +0 -217
- package/scripts/mcp-knowledgebase-server.test.js +0 -745
- package/scripts/mcp-memory-server.test.js +0 -398
- package/scripts/memory-cli.test.js +0 -297
- package/scripts/memory-index.test.js +0 -1173
- package/scripts/normalize-memory.test.js +0 -753
- package/scripts/setup/discover.test.js +0 -530
- package/scripts/setup/hooks.test.js +0 -722
- package/scripts/setup/husky-init.test.js +0 -311
- package/scripts/setup/index.test.js +0 -1021
- package/scripts/setup/knowledgebase.test.js +0 -352
- package/scripts/setup/prepare.test.js +0 -718
- package/scripts/setup/skills-phase.test.js +0 -1274
- package/scripts/setup/sync-phase.test.js +0 -373
- package/scripts/setup/ui.test.js +0 -579
- package/scripts/setup/utils.test.js +0 -586
- package/scripts/sync-unit.test.js +0 -1881
- package/scripts/sync.test.js +0 -472
- package/scripts/validate-memory-schema.test.js +0 -328
- package/scripts/vocab-sync.test.js +0 -902
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
// ═════════════════════════════════════════════════════════════════════════════
|
|
2
|
-
// playwright-mcp-launcher.test.js — Unit tests for the MCP launcher
|
|
3
|
-
// ═════════════════════════════════════════════════════════════════════════════
|
|
4
|
-
//
|
|
5
|
-
// `spawn` is mocked so no MCP server is ever launched. Signal handling and
|
|
6
|
-
// exit-code propagation are exercised through injected fakes (an EventEmitter
|
|
7
|
-
// double for the process and a fake child), plus a direct-run import that
|
|
8
|
-
// verifies the CLI bootstrap branch.
|
|
9
|
-
//
|
|
10
|
-
// Covered scenarios:
|
|
11
|
-
// 1. default args (no env flags)
|
|
12
|
-
// 2. HEADLESS=true adds --headless
|
|
13
|
-
// 3. HEADLESS=false does not
|
|
14
|
-
// 4. VIEWPORT adds --viewport <size>
|
|
15
|
-
// 5. HEADLESS + VIEWPORT together
|
|
16
|
-
// 6. spawn is called as `npx <args>` with inherited stdio + shell
|
|
17
|
-
// 7. exit code 0 is forwarded
|
|
18
|
-
// 8. non-zero exit code is forwarded
|
|
19
|
-
// 9. missing exit code falls back to 0
|
|
20
|
-
// 10. SIGINT / SIGTERM are forwarded to the child
|
|
21
|
-
// 11. launch returns the child
|
|
22
|
-
// 12. direct run auto-launches; imported elsewhere it does not
|
|
23
|
-
// ═════════════════════════════════════════════════════════════════════════════
|
|
24
|
-
|
|
25
|
-
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
26
|
-
import { EventEmitter } from 'node:events'
|
|
27
|
-
import { fileURLToPath } from 'node:url'
|
|
28
|
-
|
|
29
|
-
const cp = vi.hoisted(() => ({ spawn: vi.fn() }))
|
|
30
|
-
|
|
31
|
-
vi.mock('node:child_process', () => ({
|
|
32
|
-
spawn: cp.spawn,
|
|
33
|
-
}))
|
|
34
|
-
|
|
35
|
-
import { spawn } from 'node:child_process'
|
|
36
|
-
import { buildArgs, launch } from './playwright-mcp-launcher.js'
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Creates a fake ChildProcess.
|
|
40
|
-
*
|
|
41
|
-
* @returns {object} Fake child with kill/on and a helper to emit 'exit'.
|
|
42
|
-
*/
|
|
43
|
-
function makeChild() {
|
|
44
|
-
const handlers = {}
|
|
45
|
-
return {
|
|
46
|
-
kill: vi.fn(),
|
|
47
|
-
on: vi.fn((event, handler) => {
|
|
48
|
-
handlers[event] = handler
|
|
49
|
-
}),
|
|
50
|
-
emitExit(code) {
|
|
51
|
-
handlers.exit?.(code)
|
|
52
|
-
},
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
describe('playwright-mcp-launcher', () => {
|
|
57
|
-
let child
|
|
58
|
-
|
|
59
|
-
beforeEach(() => {
|
|
60
|
-
vi.clearAllMocks()
|
|
61
|
-
child = makeChild()
|
|
62
|
-
spawn.mockReturnValue(child)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
afterEach(() => {
|
|
66
|
-
vi.restoreAllMocks()
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
// ── buildArgs ────────────────────────────────────────────────────────────
|
|
70
|
-
|
|
71
|
-
it('buildArgs: returns only the package when no env flags are set', () => {
|
|
72
|
-
expect(buildArgs({})).toEqual(['@playwright/mcp@latest'])
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('buildArgs: HEADLESS=true adds --headless', () => {
|
|
76
|
-
expect(buildArgs({ HEADLESS: 'true' })).toEqual([
|
|
77
|
-
'@playwright/mcp@latest',
|
|
78
|
-
'--headless',
|
|
79
|
-
])
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('buildArgs: HEADLESS=false does not add --headless', () => {
|
|
83
|
-
expect(buildArgs({ HEADLESS: 'false' })).toEqual(['@playwright/mcp@latest'])
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it('buildArgs: VIEWPORT adds a two-token viewport flag', () => {
|
|
87
|
-
expect(buildArgs({ VIEWPORT: '1280x720' })).toEqual([
|
|
88
|
-
'@playwright/mcp@latest',
|
|
89
|
-
'--viewport',
|
|
90
|
-
'1280x720',
|
|
91
|
-
])
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('buildArgs: combines headless and viewport flags', () => {
|
|
95
|
-
expect(buildArgs({ HEADLESS: 'true', VIEWPORT: '800x600' })).toEqual([
|
|
96
|
-
'@playwright/mcp@latest',
|
|
97
|
-
'--headless',
|
|
98
|
-
'--viewport',
|
|
99
|
-
'800x600',
|
|
100
|
-
])
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
// ── launch ───────────────────────────────────────────────────────────────
|
|
104
|
-
|
|
105
|
-
it('launch: spawns npx with inherited stdio and shell', () => {
|
|
106
|
-
launch({ env: {}, proc: new EventEmitter(), exit: vi.fn() })
|
|
107
|
-
|
|
108
|
-
expect(spawn).toHaveBeenCalledWith('npx', ['@playwright/mcp@latest'], {
|
|
109
|
-
stdio: 'inherit',
|
|
110
|
-
shell: true,
|
|
111
|
-
})
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
it('launch: returns the spawned child', () => {
|
|
115
|
-
const returned = launch({
|
|
116
|
-
env: {},
|
|
117
|
-
proc: new EventEmitter(),
|
|
118
|
-
exit: vi.fn(),
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
expect(returned).toBe(child)
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('launch: forwards exit code 0', () => {
|
|
125
|
-
const exit = vi.fn()
|
|
126
|
-
launch({ env: {}, proc: new EventEmitter(), exit })
|
|
127
|
-
|
|
128
|
-
child.emitExit(0)
|
|
129
|
-
|
|
130
|
-
expect(exit).toHaveBeenCalledWith(0)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
it('launch: forwards a non-zero exit code', () => {
|
|
134
|
-
const exit = vi.fn()
|
|
135
|
-
launch({ env: {}, proc: new EventEmitter(), exit })
|
|
136
|
-
|
|
137
|
-
child.emitExit(5)
|
|
138
|
-
|
|
139
|
-
expect(exit).toHaveBeenCalledWith(5)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
it('launch: falls back to 0 when no exit code is provided', () => {
|
|
143
|
-
const exit = vi.fn()
|
|
144
|
-
launch({ env: {}, proc: new EventEmitter(), exit })
|
|
145
|
-
|
|
146
|
-
child.emitExit(undefined)
|
|
147
|
-
|
|
148
|
-
expect(exit).toHaveBeenCalledWith(0)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
it('launch: forwards SIGINT to the child', () => {
|
|
152
|
-
const proc = new EventEmitter()
|
|
153
|
-
launch({ env: {}, proc, exit: vi.fn() })
|
|
154
|
-
|
|
155
|
-
proc.emit('SIGINT')
|
|
156
|
-
|
|
157
|
-
expect(child.kill).toHaveBeenCalledWith('SIGINT')
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
it('launch: forwards SIGTERM to the child', () => {
|
|
161
|
-
const proc = new EventEmitter()
|
|
162
|
-
launch({ env: {}, proc, exit: vi.fn() })
|
|
163
|
-
|
|
164
|
-
proc.emit('SIGTERM')
|
|
165
|
-
|
|
166
|
-
expect(child.kill).toHaveBeenCalledWith('SIGTERM')
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
// ── Direct-run guard ─────────────────────────────────────────────────────
|
|
170
|
-
|
|
171
|
-
it('direct run: auto-launches when argv[1] is this module', async () => {
|
|
172
|
-
const modulePath = fileURLToPath(
|
|
173
|
-
new URL('./playwright-mcp-launcher.js', import.meta.url),
|
|
174
|
-
)
|
|
175
|
-
const originalArgv1 = process.argv[1]
|
|
176
|
-
const intListeners = process.listeners('SIGINT')
|
|
177
|
-
const termListeners = process.listeners('SIGTERM')
|
|
178
|
-
process.argv[1] = modulePath
|
|
179
|
-
|
|
180
|
-
try {
|
|
181
|
-
vi.resetModules()
|
|
182
|
-
await import('./playwright-mcp-launcher.js')
|
|
183
|
-
|
|
184
|
-
expect(spawn).toHaveBeenCalledWith(
|
|
185
|
-
'npx',
|
|
186
|
-
expect.arrayContaining(['@playwright/mcp@latest']),
|
|
187
|
-
{ stdio: 'inherit', shell: true },
|
|
188
|
-
)
|
|
189
|
-
} finally {
|
|
190
|
-
process.argv[1] = originalArgv1
|
|
191
|
-
for (const listener of process.listeners('SIGINT')) {
|
|
192
|
-
if (!intListeners.includes(listener)) {
|
|
193
|
-
process.removeListener('SIGINT', listener)
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
for (const listener of process.listeners('SIGTERM')) {
|
|
197
|
-
if (!termListeners.includes(listener)) {
|
|
198
|
-
process.removeListener('SIGTERM', listener)
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
it('imported with an empty argv[1]: does not launch', async () => {
|
|
205
|
-
const originalArgv1 = process.argv[1]
|
|
206
|
-
process.argv[1] = ''
|
|
207
|
-
|
|
208
|
-
try {
|
|
209
|
-
vi.resetModules()
|
|
210
|
-
await import('./playwright-mcp-launcher.js')
|
|
211
|
-
|
|
212
|
-
expect(spawn).not.toHaveBeenCalled()
|
|
213
|
-
} finally {
|
|
214
|
-
process.argv[1] = originalArgv1
|
|
215
|
-
}
|
|
216
|
-
})
|
|
217
|
-
})
|