@hustle-together/api-dev-tools 3.12.3 → 3.12.16
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/.claude/commands/hustle-build.md +259 -0
- package/.claude/commands/hustle-combine.md +1089 -0
- package/.claude/commands/hustle-ui-create-page.md +1078 -0
- package/.claude/commands/hustle-ui-create.md +1058 -0
- package/.claude/hooks/auto-answer.py +305 -0
- package/.claude/hooks/cache-research.py +337 -0
- package/.claude/hooks/check-api-routes.py +168 -0
- package/.claude/hooks/check-playwright-setup.py +103 -0
- package/.claude/hooks/check-storybook-setup.py +81 -0
- package/.claude/hooks/check-update.py +132 -0
- package/.claude/hooks/completion-promise-detector.py +293 -0
- package/.claude/hooks/context-capacity-warning.py +171 -0
- package/.claude/hooks/detect-interruption.py +165 -0
- package/.claude/hooks/docs-update-check.py +120 -0
- package/.claude/hooks/enforce-a11y-audit.py +202 -0
- package/.claude/hooks/enforce-brand-guide.py +241 -0
- package/.claude/hooks/enforce-component-type-confirm.py +97 -0
- package/.claude/hooks/enforce-dry-run.py +134 -0
- package/.claude/hooks/enforce-freshness.py +184 -0
- package/.claude/hooks/enforce-page-components.py +186 -0
- package/.claude/hooks/enforce-page-data-schema.py +155 -0
- package/.claude/hooks/enforce-questions-sourced.py +146 -0
- package/.claude/hooks/enforce-schema-from-interview.py +248 -0
- package/.claude/hooks/enforce-ui-disambiguation.py +108 -0
- package/.claude/hooks/enforce-ui-interview.py +130 -0
- package/.claude/hooks/generate-adr-options.py +282 -0
- package/.claude/hooks/generate-manifest-entry.py +1161 -0
- package/.claude/hooks/hook_utils.py +609 -0
- package/.claude/hooks/lib/__init__.py +1 -0
- package/.claude/hooks/lib/__pycache__/__init__.cpython-314.pyc +0 -0
- package/.claude/hooks/lib/__pycache__/greptile.cpython-314.pyc +0 -0
- package/.claude/hooks/lib/__pycache__/ntfy.cpython-314.pyc +0 -0
- package/.claude/hooks/lib/greptile.py +355 -0
- package/.claude/hooks/lib/ntfy.py +209 -0
- package/.claude/hooks/notify-input-needed.py +73 -0
- package/.claude/hooks/notify-phase-complete.py +90 -0
- package/.claude/hooks/ntfy-on-question.py +240 -0
- package/.claude/hooks/orchestrator-completion.py +313 -0
- package/.claude/hooks/orchestrator-handoff.py +267 -0
- package/.claude/hooks/orchestrator-session-startup.py +146 -0
- package/.claude/hooks/parallel-orchestrator.py +451 -0
- package/.claude/hooks/project-document-prompt.py +302 -0
- package/.claude/hooks/remote-question-proxy.py +284 -0
- package/.claude/hooks/remote-question-server.py +1224 -0
- package/.claude/hooks/run-code-review.py +393 -0
- package/.claude/hooks/run-visual-qa.py +338 -0
- package/.claude/hooks/session-logger.py +323 -0
- package/.claude/hooks/test-orchestrator-reground.py +248 -0
- package/.claude/hooks/track-scope-coverage.py +220 -0
- package/.claude/hooks/track-token-usage.py +121 -0
- package/.claude/hooks/update-adr-decision.py +236 -0
- package/.claude/hooks/update-api-showcase.py +161 -0
- package/.claude/hooks/update-registry.py +352 -0
- package/.claude/hooks/update-testing-checklist.py +195 -0
- package/.claude/hooks/update-ui-showcase.py +224 -0
- package/.claude/settings.local.json +7 -1
- package/.claude/test-auto-answer-bot.py +183 -0
- package/.claude/test-completion-detector.py +263 -0
- package/.claude/test-orchestrator-state.json +20 -0
- package/.claude/test-orchestrator.sh +271 -0
- package/.skills/api-create/SKILL.md +88 -3
- package/.skills/docs-sync/SKILL.md +260 -0
- package/.skills/hustle-build/SKILL.md +459 -0
- package/.skills/hustle-build-review/SKILL.md +518 -0
- package/CHANGELOG.md +87 -0
- package/README.md +86 -9
- package/bin/cli.js +1302 -88
- package/commands/hustle-api-create.md +22 -0
- package/commands/hustle-combine.md +81 -2
- package/commands/hustle-ui-create-page.md +84 -2
- package/commands/hustle-ui-create.md +82 -2
- package/hooks/auto-answer.py +228 -0
- package/hooks/check-update.py +132 -0
- package/hooks/ntfy-on-question.py +227 -0
- package/hooks/orchestrator-completion.py +313 -0
- package/hooks/orchestrator-handoff.py +189 -0
- package/hooks/orchestrator-session-startup.py +146 -0
- package/hooks/periodic-reground.py +230 -67
- package/hooks/update-api-showcase.py +13 -1
- package/hooks/update-ui-showcase.py +13 -1
- package/package.json +7 -3
- package/scripts/extract-schema-docs.cjs +322 -0
- package/templates/CLAUDE-SECTION.md +89 -64
- package/templates/api-showcase/_components/APIModal.tsx +100 -8
- package/templates/api-showcase/_components/APIShowcase.tsx +36 -4
- package/templates/api-showcase/_components/APITester.tsx +367 -58
- package/templates/docs/page.tsx +230 -0
- package/templates/hustle-build-defaults.json +84 -0
- package/templates/hustle-dev-dashboard/page.tsx +365 -0
- package/templates/playwright-report/page.tsx +258 -0
- package/templates/settings.json +88 -7
- package/templates/test-results/page.tsx +237 -0
- package/templates/typedoc.json +19 -0
- package/templates/ui-showcase/_components/UIShowcase.tsx +1 -1
- package/templates/ui-showcase/page.tsx +1 -1
- package/.claude/api-dev-state.json +0 -466
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Playwright Report Page
|
|
7
|
+
*
|
|
8
|
+
* Shows Playwright E2E test results or instructions to run tests.
|
|
9
|
+
* Links to the HTML report when available.
|
|
10
|
+
*
|
|
11
|
+
* Created with Hustle API Dev Tools (v3.12.12)
|
|
12
|
+
*/
|
|
13
|
+
export default function PlaywrightReportPage() {
|
|
14
|
+
// In a real implementation, check if playwright-report/ exists
|
|
15
|
+
const hasReport = false;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div className="min-h-screen bg-white dark:bg-gray-950">
|
|
19
|
+
{/* Header */}
|
|
20
|
+
<header className="border-b-4 border-black bg-[#BA0C2F] px-6 py-8 dark:border-gray-600">
|
|
21
|
+
<div className="mx-auto max-w-4xl">
|
|
22
|
+
<div className="flex items-center gap-2">
|
|
23
|
+
<Link
|
|
24
|
+
href="/hustle-dev-dashboard"
|
|
25
|
+
className="text-white/80 hover:text-white"
|
|
26
|
+
>
|
|
27
|
+
Dashboard
|
|
28
|
+
</Link>
|
|
29
|
+
<span className="text-white/60">/</span>
|
|
30
|
+
<span className="text-white">Playwright</span>
|
|
31
|
+
</div>
|
|
32
|
+
<h1 className="mt-2 text-3xl font-black text-white">
|
|
33
|
+
PLAYWRIGHT REPORTS
|
|
34
|
+
</h1>
|
|
35
|
+
<p className="mt-2 text-white/80">End-to-end test results</p>
|
|
36
|
+
</div>
|
|
37
|
+
</header>
|
|
38
|
+
|
|
39
|
+
{/* Main Content */}
|
|
40
|
+
<main className="mx-auto max-w-4xl px-6 py-8">
|
|
41
|
+
{hasReport ? <ReportContent /> : <EmptyState />}
|
|
42
|
+
</main>
|
|
43
|
+
|
|
44
|
+
{/* Footer */}
|
|
45
|
+
<footer className="border-t-2 border-black px-6 py-4 dark:border-gray-600">
|
|
46
|
+
<div className="mx-auto max-w-4xl text-center text-sm text-gray-600 dark:text-gray-400">
|
|
47
|
+
Built with{" "}
|
|
48
|
+
<a
|
|
49
|
+
href="https://github.com/hustle-together/api-dev-tools"
|
|
50
|
+
className="font-bold text-[#BA0C2F] hover:underline"
|
|
51
|
+
>
|
|
52
|
+
Hustle API Dev Tools
|
|
53
|
+
</a>
|
|
54
|
+
</div>
|
|
55
|
+
</footer>
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function ReportContent() {
|
|
61
|
+
return (
|
|
62
|
+
<div className="space-y-6">
|
|
63
|
+
<div className="border-2 border-black p-6 dark:border-gray-600">
|
|
64
|
+
<h2 className="mb-4 text-xl font-bold text-black dark:text-white">
|
|
65
|
+
View Report
|
|
66
|
+
</h2>
|
|
67
|
+
<p className="mb-4 text-gray-600 dark:text-gray-400">
|
|
68
|
+
Playwright has generated an HTML report. Click below to view it:
|
|
69
|
+
</p>
|
|
70
|
+
<a
|
|
71
|
+
href="/playwright-report/index.html"
|
|
72
|
+
target="_blank"
|
|
73
|
+
rel="noopener noreferrer"
|
|
74
|
+
className="inline-block rounded bg-[#BA0C2F] px-6 py-3 font-bold text-white transition-colors hover:bg-[#8a0923]"
|
|
75
|
+
>
|
|
76
|
+
Open HTML Report
|
|
77
|
+
</a>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function EmptyState() {
|
|
84
|
+
return (
|
|
85
|
+
<div className="space-y-6">
|
|
86
|
+
{/* Status Card */}
|
|
87
|
+
<div className="border-2 border-black p-6 dark:border-gray-600">
|
|
88
|
+
<div className="flex items-center gap-3">
|
|
89
|
+
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 text-2xl dark:bg-gray-800">
|
|
90
|
+
0
|
|
91
|
+
</div>
|
|
92
|
+
<div>
|
|
93
|
+
<h2 className="text-xl font-bold text-black dark:text-white">
|
|
94
|
+
No Playwright Reports
|
|
95
|
+
</h2>
|
|
96
|
+
<p className="text-gray-600 dark:text-gray-400">
|
|
97
|
+
Run E2E tests to generate a report
|
|
98
|
+
</p>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
{/* Instructions */}
|
|
104
|
+
<div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
|
|
105
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">
|
|
106
|
+
Run E2E Tests
|
|
107
|
+
</h3>
|
|
108
|
+
<div className="space-y-4">
|
|
109
|
+
<Step
|
|
110
|
+
number={1}
|
|
111
|
+
title="Run All E2E Tests"
|
|
112
|
+
command="pnpm test:e2e"
|
|
113
|
+
description="Runs all Playwright tests and generates a report"
|
|
114
|
+
/>
|
|
115
|
+
<Step
|
|
116
|
+
number={2}
|
|
117
|
+
title="Run with UI"
|
|
118
|
+
command="pnpm playwright test --ui"
|
|
119
|
+
description="Opens Playwright's interactive test runner"
|
|
120
|
+
/>
|
|
121
|
+
<Step
|
|
122
|
+
number={3}
|
|
123
|
+
title="View Report"
|
|
124
|
+
command="pnpm playwright show-report"
|
|
125
|
+
description="Opens the HTML report in your browser"
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
{/* Available Commands */}
|
|
131
|
+
<div className="border-2 border-black p-6 dark:border-gray-600">
|
|
132
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">
|
|
133
|
+
Playwright Commands
|
|
134
|
+
</h3>
|
|
135
|
+
<div className="space-y-3">
|
|
136
|
+
<CommandItem
|
|
137
|
+
command="pnpm test:e2e"
|
|
138
|
+
description="Run all E2E tests"
|
|
139
|
+
/>
|
|
140
|
+
<CommandItem
|
|
141
|
+
command="pnpm playwright test --ui"
|
|
142
|
+
description="Interactive test runner"
|
|
143
|
+
/>
|
|
144
|
+
<CommandItem
|
|
145
|
+
command="pnpm playwright test --headed"
|
|
146
|
+
description="Run with visible browser"
|
|
147
|
+
/>
|
|
148
|
+
<CommandItem
|
|
149
|
+
command="pnpm playwright show-report"
|
|
150
|
+
description="Open HTML report"
|
|
151
|
+
/>
|
|
152
|
+
<CommandItem
|
|
153
|
+
command="pnpm playwright codegen"
|
|
154
|
+
description="Generate tests by recording"
|
|
155
|
+
/>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
|
|
159
|
+
{/* Test Types */}
|
|
160
|
+
<div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
|
|
161
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">
|
|
162
|
+
E2E Test Types
|
|
163
|
+
</h3>
|
|
164
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
165
|
+
<TestTypeCard
|
|
166
|
+
icon="🖥️"
|
|
167
|
+
title="Page Tests"
|
|
168
|
+
description="Full page navigation and interaction tests"
|
|
169
|
+
pattern="*.e2e.test.ts"
|
|
170
|
+
/>
|
|
171
|
+
<TestTypeCard
|
|
172
|
+
icon="📸"
|
|
173
|
+
title="Visual Tests"
|
|
174
|
+
description="Screenshot comparison for UI changes"
|
|
175
|
+
pattern="*.visual.spec.ts"
|
|
176
|
+
/>
|
|
177
|
+
<TestTypeCard
|
|
178
|
+
icon="♿"
|
|
179
|
+
title="Accessibility"
|
|
180
|
+
description="WCAG compliance and a11y checks"
|
|
181
|
+
pattern="*.a11y.spec.ts"
|
|
182
|
+
/>
|
|
183
|
+
<TestTypeCard
|
|
184
|
+
icon="📱"
|
|
185
|
+
title="Responsive"
|
|
186
|
+
description="Mobile, tablet, and desktop viewports"
|
|
187
|
+
pattern="--project=mobile"
|
|
188
|
+
/>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function Step({
|
|
196
|
+
number,
|
|
197
|
+
title,
|
|
198
|
+
command,
|
|
199
|
+
description,
|
|
200
|
+
}: {
|
|
201
|
+
number: number;
|
|
202
|
+
title: string;
|
|
203
|
+
command: string;
|
|
204
|
+
description: string;
|
|
205
|
+
}) {
|
|
206
|
+
return (
|
|
207
|
+
<div className="flex gap-4">
|
|
208
|
+
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-[#BA0C2F] text-sm font-bold text-white">
|
|
209
|
+
{number}
|
|
210
|
+
</div>
|
|
211
|
+
<div>
|
|
212
|
+
<p className="font-medium text-black dark:text-white">{title}</p>
|
|
213
|
+
<code className="mt-1 block rounded bg-white px-3 py-1 font-mono text-sm text-[#BA0C2F] dark:bg-gray-800">
|
|
214
|
+
{command}
|
|
215
|
+
</code>
|
|
216
|
+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
|
217
|
+
{description}
|
|
218
|
+
</p>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function CommandItem({
|
|
225
|
+
command,
|
|
226
|
+
description,
|
|
227
|
+
}: {
|
|
228
|
+
command: string;
|
|
229
|
+
description: string;
|
|
230
|
+
}) {
|
|
231
|
+
return (
|
|
232
|
+
<div className="flex items-center justify-between rounded bg-white px-4 py-2 dark:bg-gray-800">
|
|
233
|
+
<code className="font-mono text-[#BA0C2F]">{command}</code>
|
|
234
|
+
<span className="text-sm text-gray-500">{description}</span>
|
|
235
|
+
</div>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function TestTypeCard({
|
|
240
|
+
icon,
|
|
241
|
+
title,
|
|
242
|
+
description,
|
|
243
|
+
pattern,
|
|
244
|
+
}: {
|
|
245
|
+
icon: string;
|
|
246
|
+
title: string;
|
|
247
|
+
description: string;
|
|
248
|
+
pattern: string;
|
|
249
|
+
}) {
|
|
250
|
+
return (
|
|
251
|
+
<div className="rounded border border-gray-200 bg-white p-4 dark:border-gray-700 dark:bg-gray-800">
|
|
252
|
+
<div className="mb-2 text-2xl">{icon}</div>
|
|
253
|
+
<h4 className="font-medium text-black dark:text-white">{title}</h4>
|
|
254
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">{description}</p>
|
|
255
|
+
<code className="mt-2 block text-xs text-[#BA0C2F]">{pattern}</code>
|
|
256
|
+
</div>
|
|
257
|
+
);
|
|
258
|
+
}
|
package/templates/settings.json
CHANGED
|
@@ -1,18 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"permissions": {
|
|
3
3
|
"allow": [
|
|
4
|
+
"Read(*)",
|
|
5
|
+
"Write(*)",
|
|
6
|
+
"Edit(*)",
|
|
7
|
+
"Glob(*)",
|
|
8
|
+
"Grep(*)",
|
|
9
|
+
"LSP(*)",
|
|
10
|
+
"NotebookEdit(*)",
|
|
4
11
|
"WebSearch",
|
|
5
12
|
"WebFetch",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
13
|
+
"Task",
|
|
14
|
+
"TodoWrite",
|
|
15
|
+
"AskUserQuestion",
|
|
16
|
+
"Skill",
|
|
17
|
+
"mcp__context7__*",
|
|
18
|
+
"mcp__github__*",
|
|
19
|
+
"mcp__linear__*",
|
|
20
|
+
"mcp__supabase__*",
|
|
21
|
+
"mcp__playwright__*",
|
|
10
22
|
"Bash(claude mcp:*)",
|
|
11
|
-
"Bash(pnpm
|
|
12
|
-
"Bash(npm
|
|
23
|
+
"Bash(pnpm *)",
|
|
24
|
+
"Bash(npm *)",
|
|
25
|
+
"Bash(npx *)",
|
|
13
26
|
"Bash(git status:*)",
|
|
14
27
|
"Bash(git diff:*)",
|
|
15
|
-
"Bash(git log:*)"
|
|
28
|
+
"Bash(git log:*)",
|
|
29
|
+
"Bash(git add:*)",
|
|
30
|
+
"Bash(git commit:*)",
|
|
31
|
+
"Bash(git branch:*)",
|
|
32
|
+
"Bash(git checkout:*)",
|
|
33
|
+
"Bash(curl:*)",
|
|
34
|
+
"Bash(tree:*)",
|
|
35
|
+
"Bash(ls:*)",
|
|
36
|
+
"Bash(cat:*)",
|
|
37
|
+
"Bash(echo:*)",
|
|
38
|
+
"Bash(mkdir:*)",
|
|
39
|
+
"Bash(touch:*)",
|
|
40
|
+
"Bash(cp:*)",
|
|
41
|
+
"Bash(mv:*)",
|
|
42
|
+
"Bash(chmod:*)"
|
|
43
|
+
],
|
|
44
|
+
"deny": [
|
|
45
|
+
"Read(.env*)",
|
|
46
|
+
"Read(**/.env*)",
|
|
47
|
+
"Read(**/secrets/**)",
|
|
48
|
+
"Read(**/credentials*)",
|
|
49
|
+
"Write(.env*)",
|
|
50
|
+
"Edit(.env*)",
|
|
51
|
+
"Bash(rm -rf *)",
|
|
52
|
+
"Bash(sudo *)",
|
|
53
|
+
"Bash(git push --force *)",
|
|
54
|
+
"Bash(git reset --hard *)",
|
|
55
|
+
"Bash(> /dev/*)",
|
|
56
|
+
"Bash(curl * | bash)",
|
|
57
|
+
"Bash(wget * | bash)"
|
|
16
58
|
]
|
|
17
59
|
},
|
|
18
60
|
"hooks": {
|
|
@@ -26,6 +68,14 @@
|
|
|
26
68
|
{
|
|
27
69
|
"type": "command",
|
|
28
70
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/detect-interruption.py"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"type": "command",
|
|
74
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/check-update.py"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"type": "command",
|
|
78
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-session-startup.py"
|
|
29
79
|
}
|
|
30
80
|
]
|
|
31
81
|
}
|
|
@@ -140,6 +190,19 @@
|
|
|
140
190
|
{
|
|
141
191
|
"type": "command",
|
|
142
192
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-questions-sourced.py"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"type": "command",
|
|
196
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/auto-answer.py"
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"matcher": "Skill",
|
|
202
|
+
"hooks": [
|
|
203
|
+
{
|
|
204
|
+
"type": "command",
|
|
205
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-handoff.py"
|
|
143
206
|
}
|
|
144
207
|
]
|
|
145
208
|
}
|
|
@@ -162,6 +225,15 @@
|
|
|
162
225
|
}
|
|
163
226
|
]
|
|
164
227
|
},
|
|
228
|
+
{
|
|
229
|
+
"matcher": "AskUserQuestion",
|
|
230
|
+
"hooks": [
|
|
231
|
+
{
|
|
232
|
+
"type": "command",
|
|
233
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/ntfy-on-question.py"
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
},
|
|
165
237
|
{
|
|
166
238
|
"matcher": "Bash",
|
|
167
239
|
"hooks": [
|
|
@@ -199,6 +271,15 @@
|
|
|
199
271
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-a11y-audit.py"
|
|
200
272
|
}
|
|
201
273
|
]
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"matcher": "Skill",
|
|
277
|
+
"hooks": [
|
|
278
|
+
{
|
|
279
|
+
"type": "command",
|
|
280
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-completion.py"
|
|
281
|
+
}
|
|
282
|
+
]
|
|
202
283
|
}
|
|
203
284
|
],
|
|
204
285
|
"Stop": [
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Test Results Page
|
|
7
|
+
*
|
|
8
|
+
* Shows Vitest unit test results or instructions to run tests.
|
|
9
|
+
* Designed to work with vitest --reporter=json output.
|
|
10
|
+
*
|
|
11
|
+
* Created with Hustle API Dev Tools (v3.12.12)
|
|
12
|
+
*/
|
|
13
|
+
export default function TestResultsPage() {
|
|
14
|
+
// In a real implementation, this would fetch test results from a JSON file
|
|
15
|
+
// For now, we show the empty state with instructions
|
|
16
|
+
const hasResults = false;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="min-h-screen bg-white dark:bg-gray-950">
|
|
20
|
+
{/* Header */}
|
|
21
|
+
<header className="border-b-4 border-black bg-[#BA0C2F] px-6 py-8 dark:border-gray-600">
|
|
22
|
+
<div className="mx-auto max-w-4xl">
|
|
23
|
+
<div className="flex items-center gap-2">
|
|
24
|
+
<Link
|
|
25
|
+
href="/hustle-dev-dashboard"
|
|
26
|
+
className="text-white/80 hover:text-white"
|
|
27
|
+
>
|
|
28
|
+
Dashboard
|
|
29
|
+
</Link>
|
|
30
|
+
<span className="text-white/60">/</span>
|
|
31
|
+
<span className="text-white">Test Results</span>
|
|
32
|
+
</div>
|
|
33
|
+
<h1 className="mt-2 text-3xl font-black text-white">TEST RESULTS</h1>
|
|
34
|
+
<p className="mt-2 text-white/80">Vitest unit test results</p>
|
|
35
|
+
</div>
|
|
36
|
+
</header>
|
|
37
|
+
|
|
38
|
+
{/* Main Content */}
|
|
39
|
+
<main className="mx-auto max-w-4xl px-6 py-8">
|
|
40
|
+
{hasResults ? <TestResults /> : <EmptyState />}
|
|
41
|
+
</main>
|
|
42
|
+
|
|
43
|
+
{/* Footer */}
|
|
44
|
+
<footer className="border-t-2 border-black px-6 py-4 dark:border-gray-600">
|
|
45
|
+
<div className="mx-auto max-w-4xl text-center text-sm text-gray-600 dark:text-gray-400">
|
|
46
|
+
Built with{" "}
|
|
47
|
+
<a
|
|
48
|
+
href="https://github.com/hustle-together/api-dev-tools"
|
|
49
|
+
className="font-bold text-[#BA0C2F] hover:underline"
|
|
50
|
+
>
|
|
51
|
+
Hustle API Dev Tools
|
|
52
|
+
</a>
|
|
53
|
+
</div>
|
|
54
|
+
</footer>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function TestResults() {
|
|
60
|
+
// Placeholder for actual test results display
|
|
61
|
+
return (
|
|
62
|
+
<div className="space-y-6">
|
|
63
|
+
<div className="grid gap-4 sm:grid-cols-3">
|
|
64
|
+
<StatCard label="Passed" value={0} color="green" />
|
|
65
|
+
<StatCard label="Failed" value={0} color="red" />
|
|
66
|
+
<StatCard label="Skipped" value={0} color="yellow" />
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function EmptyState() {
|
|
73
|
+
return (
|
|
74
|
+
<div className="space-y-6">
|
|
75
|
+
{/* Status Card */}
|
|
76
|
+
<div className="border-2 border-black p-6 dark:border-gray-600">
|
|
77
|
+
<div className="flex items-center gap-3">
|
|
78
|
+
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 text-2xl dark:bg-gray-800">
|
|
79
|
+
0
|
|
80
|
+
</div>
|
|
81
|
+
<div>
|
|
82
|
+
<h2 className="text-xl font-bold text-black dark:text-white">
|
|
83
|
+
No Test Results
|
|
84
|
+
</h2>
|
|
85
|
+
<p className="text-gray-600 dark:text-gray-400">
|
|
86
|
+
Run your tests to see results here
|
|
87
|
+
</p>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
{/* Instructions */}
|
|
93
|
+
<div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
|
|
94
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">Run Tests</h3>
|
|
95
|
+
<div className="space-y-4">
|
|
96
|
+
<Step
|
|
97
|
+
number={1}
|
|
98
|
+
title="Run Unit Tests"
|
|
99
|
+
command="pnpm test"
|
|
100
|
+
description="Runs Vitest in watch mode for development"
|
|
101
|
+
/>
|
|
102
|
+
<Step
|
|
103
|
+
number={2}
|
|
104
|
+
title="Run Tests Once"
|
|
105
|
+
command="pnpm test:run"
|
|
106
|
+
description="Runs all tests once and exits"
|
|
107
|
+
/>
|
|
108
|
+
<Step
|
|
109
|
+
number={3}
|
|
110
|
+
title="Run with Coverage"
|
|
111
|
+
command="pnpm test:coverage"
|
|
112
|
+
description="Generates code coverage report"
|
|
113
|
+
/>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
{/* Test Commands Reference */}
|
|
118
|
+
<div className="border-2 border-black p-6 dark:border-gray-600">
|
|
119
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">
|
|
120
|
+
Available Commands
|
|
121
|
+
</h3>
|
|
122
|
+
<div className="space-y-3">
|
|
123
|
+
<CommandItem
|
|
124
|
+
command="pnpm test"
|
|
125
|
+
description="Watch mode - reruns on file changes"
|
|
126
|
+
/>
|
|
127
|
+
<CommandItem
|
|
128
|
+
command="pnpm test:run"
|
|
129
|
+
description="Single run - CI/CD friendly"
|
|
130
|
+
/>
|
|
131
|
+
<CommandItem
|
|
132
|
+
command="pnpm test:coverage"
|
|
133
|
+
description="With coverage report"
|
|
134
|
+
/>
|
|
135
|
+
<CommandItem
|
|
136
|
+
command="pnpm test [file]"
|
|
137
|
+
description="Run specific test file"
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
{/* Test File Conventions */}
|
|
143
|
+
<div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
|
|
144
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">
|
|
145
|
+
Test File Conventions
|
|
146
|
+
</h3>
|
|
147
|
+
<ul className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
|
|
148
|
+
<li className="flex items-center gap-2">
|
|
149
|
+
<code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
|
|
150
|
+
*.test.ts
|
|
151
|
+
</code>
|
|
152
|
+
Unit tests
|
|
153
|
+
</li>
|
|
154
|
+
<li className="flex items-center gap-2">
|
|
155
|
+
<code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
|
|
156
|
+
*.api.test.ts
|
|
157
|
+
</code>
|
|
158
|
+
API route tests
|
|
159
|
+
</li>
|
|
160
|
+
<li className="flex items-center gap-2">
|
|
161
|
+
<code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
|
|
162
|
+
__tests__/
|
|
163
|
+
</code>
|
|
164
|
+
Test directory convention
|
|
165
|
+
</li>
|
|
166
|
+
</ul>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function StatCard({
|
|
173
|
+
label,
|
|
174
|
+
value,
|
|
175
|
+
color,
|
|
176
|
+
}: {
|
|
177
|
+
label: string;
|
|
178
|
+
value: number;
|
|
179
|
+
color: "green" | "red" | "yellow";
|
|
180
|
+
}) {
|
|
181
|
+
const colorClasses = {
|
|
182
|
+
green: "text-green-600",
|
|
183
|
+
red: "text-red-600",
|
|
184
|
+
yellow: "text-yellow-600",
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div className="border-2 border-black bg-white p-4 dark:border-gray-600 dark:bg-gray-900">
|
|
189
|
+
<p className={`text-3xl font-black ${colorClasses[color]}`}>{value}</p>
|
|
190
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">{label}</p>
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function Step({
|
|
196
|
+
number,
|
|
197
|
+
title,
|
|
198
|
+
command,
|
|
199
|
+
description,
|
|
200
|
+
}: {
|
|
201
|
+
number: number;
|
|
202
|
+
title: string;
|
|
203
|
+
command: string;
|
|
204
|
+
description: string;
|
|
205
|
+
}) {
|
|
206
|
+
return (
|
|
207
|
+
<div className="flex gap-4">
|
|
208
|
+
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-[#BA0C2F] text-sm font-bold text-white">
|
|
209
|
+
{number}
|
|
210
|
+
</div>
|
|
211
|
+
<div>
|
|
212
|
+
<p className="font-medium text-black dark:text-white">{title}</p>
|
|
213
|
+
<code className="mt-1 block rounded bg-white px-3 py-1 font-mono text-sm text-[#BA0C2F] dark:bg-gray-800">
|
|
214
|
+
{command}
|
|
215
|
+
</code>
|
|
216
|
+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
|
217
|
+
{description}
|
|
218
|
+
</p>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function CommandItem({
|
|
225
|
+
command,
|
|
226
|
+
description,
|
|
227
|
+
}: {
|
|
228
|
+
command: string;
|
|
229
|
+
description: string;
|
|
230
|
+
}) {
|
|
231
|
+
return (
|
|
232
|
+
<div className="flex items-center justify-between rounded bg-white px-4 py-2 dark:bg-gray-800">
|
|
233
|
+
<code className="font-mono text-[#BA0C2F]">{command}</code>
|
|
234
|
+
<span className="text-sm text-gray-500">{description}</span>
|
|
235
|
+
</div>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://typedoc.org/schema.json",
|
|
3
|
+
"entryPoints": ["src/lib/schemas/*.ts", "src/app/api/**/*.ts"],
|
|
4
|
+
"out": "docs/api",
|
|
5
|
+
"plugin": ["typedoc-plugin-markdown"],
|
|
6
|
+
"exclude": ["**/*.test.ts", "**/__tests__/**", "**/node_modules/**"],
|
|
7
|
+
"excludePrivate": true,
|
|
8
|
+
"excludeInternal": true,
|
|
9
|
+
"readme": "none",
|
|
10
|
+
"name": "API Documentation",
|
|
11
|
+
"includeVersion": true,
|
|
12
|
+
"categorizeByGroup": true,
|
|
13
|
+
"sort": ["alphabetical"],
|
|
14
|
+
"validation": {
|
|
15
|
+
"notExported": false,
|
|
16
|
+
"invalidLink": false,
|
|
17
|
+
"notDocumented": false
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState, useMemo } from "react";
|
|
4
|
-
import { HeroHeader } from "
|
|
4
|
+
import { HeroHeader } from "../../shared/HeroHeader";
|
|
5
5
|
import { PreviewCard } from "./PreviewCard";
|
|
6
6
|
import { PreviewModal } from "./PreviewModal";
|
|
7
7
|
|