@nextsparkjs/ai-workflow 0.1.0-beta.100

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.
Files changed (272) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/claude/_docs/workflows-optimizations.md +359 -0
  4. package/claude/agents/api-tester.md +634 -0
  5. package/claude/agents/architecture-supervisor.md +1351 -0
  6. package/claude/agents/backend-developer.md +997 -0
  7. package/claude/agents/backend-validator.md +417 -0
  8. package/claude/agents/bdd-docs-writer.md +737 -0
  9. package/claude/agents/block-developer.md +677 -0
  10. package/claude/agents/code-reviewer.md +1432 -0
  11. package/claude/agents/db-developer.md +721 -0
  12. package/claude/agents/db-validator.md +407 -0
  13. package/claude/agents/demo-video-generator.md +493 -0
  14. package/claude/agents/documentation-writer.md +1268 -0
  15. package/claude/agents/frontend-developer.md +1234 -0
  16. package/claude/agents/frontend-validator.md +777 -0
  17. package/claude/agents/functional-validator.md +630 -0
  18. package/claude/agents/mock-analyst.md +387 -0
  19. package/claude/agents/product-manager.md +963 -0
  20. package/claude/agents/qa-automation.md +1762 -0
  21. package/claude/agents/release-manager.md +634 -0
  22. package/claude/agents/selectors-translator.md +262 -0
  23. package/claude/agents/unit-test-writer.md +785 -0
  24. package/claude/agents/visual-comparator.md +329 -0
  25. package/claude/agents/workflow-maintainer.md +352 -0
  26. package/claude/commands/do/README.md +88 -0
  27. package/claude/commands/do/create-api.md +64 -0
  28. package/claude/commands/do/create-entity.md +66 -0
  29. package/claude/commands/do/create-migration.md +64 -0
  30. package/claude/commands/do/create-plugin.md +56 -0
  31. package/claude/commands/do/create-theme.md +70 -0
  32. package/claude/commands/do/mock-data.md +67 -0
  33. package/claude/commands/do/reset-db.md +71 -0
  34. package/claude/commands/do/setup-scheduled-action.md +75 -0
  35. package/claude/commands/do/sync-code-review.md +117 -0
  36. package/claude/commands/do/update-selectors.md +112 -0
  37. package/claude/commands/do/use-skills.md +90 -0
  38. package/claude/commands/do/validate-blocks.md +69 -0
  39. package/claude/commands/how-to/README.md +261 -0
  40. package/claude/commands/how-to/add-metadata.md +692 -0
  41. package/claude/commands/how-to/add-taxonomies.md +806 -0
  42. package/claude/commands/how-to/add-translations.md +571 -0
  43. package/claude/commands/how-to/create-api.md +577 -0
  44. package/claude/commands/how-to/create-block.md +575 -0
  45. package/claude/commands/how-to/create-child-entities.md +771 -0
  46. package/claude/commands/how-to/create-entity.md +597 -0
  47. package/claude/commands/how-to/create-migrations.md +605 -0
  48. package/claude/commands/how-to/create-plugin.md +654 -0
  49. package/claude/commands/how-to/customize-app.md +481 -0
  50. package/claude/commands/how-to/customize-dashboard.md +553 -0
  51. package/claude/commands/how-to/customize-theme.md +438 -0
  52. package/claude/commands/how-to/define-features-flows.md +632 -0
  53. package/claude/commands/how-to/deploy.md +507 -0
  54. package/claude/commands/how-to/handle-file-uploads.md +746 -0
  55. package/claude/commands/how-to/implement-search.md +1001 -0
  56. package/claude/commands/how-to/install-plugins.md +352 -0
  57. package/claude/commands/how-to/manage-test-coverage.md +984 -0
  58. package/claude/commands/how-to/run-tests.md +400 -0
  59. package/claude/commands/how-to/set-app-languages.md +601 -0
  60. package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
  61. package/claude/commands/how-to/set-scheduled-actions.md +527 -0
  62. package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
  63. package/claude/commands/how-to/setup-authentication.md +388 -0
  64. package/claude/commands/how-to/setup-claude-code.md +440 -0
  65. package/claude/commands/how-to/setup-database.md +274 -0
  66. package/claude/commands/how-to/setup-email-providers.md +598 -0
  67. package/claude/commands/how-to/setup-mobile-dev.md +627 -0
  68. package/claude/commands/how-to/start.md +500 -0
  69. package/claude/commands/how-to/use-devtools.md +639 -0
  70. package/claude/commands/how-to/use-superadmin.md +622 -0
  71. package/claude/commands/session/README.md +193 -0
  72. package/claude/commands/session/block-create.md +190 -0
  73. package/claude/commands/session/block-list.md +203 -0
  74. package/claude/commands/session/block-update.md +192 -0
  75. package/claude/commands/session/block-validate.md +218 -0
  76. package/claude/commands/session/changelog.md +115 -0
  77. package/claude/commands/session/close.md +225 -0
  78. package/claude/commands/session/commit.md +174 -0
  79. package/claude/commands/session/db-entity.md +206 -0
  80. package/claude/commands/session/db-fix.md +212 -0
  81. package/claude/commands/session/db-sample.md +206 -0
  82. package/claude/commands/session/demo.md +178 -0
  83. package/claude/commands/session/doc-bdd.md +207 -0
  84. package/claude/commands/session/doc-feature.md +218 -0
  85. package/claude/commands/session/doc-read.md +225 -0
  86. package/claude/commands/session/execute.md +204 -0
  87. package/claude/commands/session/explain.md +202 -0
  88. package/claude/commands/session/fix-bug.md +210 -0
  89. package/claude/commands/session/fix-build.md +182 -0
  90. package/claude/commands/session/fix-test.md +189 -0
  91. package/claude/commands/session/pending.md +232 -0
  92. package/claude/commands/session/refine.md +188 -0
  93. package/claude/commands/session/resume.md +192 -0
  94. package/claude/commands/session/review.md +192 -0
  95. package/claude/commands/session/scope-change.md +181 -0
  96. package/claude/commands/session/start-blocks.md +347 -0
  97. package/claude/commands/session/start.md +604 -0
  98. package/claude/commands/session/status.md +169 -0
  99. package/claude/commands/session/test-fix.md +221 -0
  100. package/claude/commands/session/test-run.md +203 -0
  101. package/claude/commands/session/test-write.md +242 -0
  102. package/claude/commands/session/validate.md +162 -0
  103. package/claude/config/context.json +40 -0
  104. package/claude/config/github.json +69 -0
  105. package/claude/config/github.schema.json +106 -0
  106. package/claude/config/team.json +46 -0
  107. package/claude/config/team.schema.json +106 -0
  108. package/claude/config/workspace.json +43 -0
  109. package/claude/config/workspace.schema.json +75 -0
  110. package/claude/skills/README.md +228 -0
  111. package/claude/skills/accessibility/SKILL.md +573 -0
  112. package/claude/skills/api-bypass-layers/SKILL.md +550 -0
  113. package/claude/skills/asana-integration/SKILL.md +499 -0
  114. package/claude/skills/better-auth/SKILL.md +666 -0
  115. package/claude/skills/billing-subscriptions/SKILL.md +660 -0
  116. package/claude/skills/block-decision-matrix/SKILL.md +359 -0
  117. package/claude/skills/clickup-integration/SKILL.md +434 -0
  118. package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
  119. package/claude/skills/create-plugin/SKILL.md +425 -0
  120. package/claude/skills/create-theme/SKILL.md +331 -0
  121. package/claude/skills/cypress-api/SKILL.md +511 -0
  122. package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
  123. package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
  124. package/claude/skills/cypress-e2e/SKILL.md +526 -0
  125. package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
  126. package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
  127. package/claude/skills/cypress-selectors/SKILL.md +309 -0
  128. package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
  129. package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
  130. package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
  131. package/claude/skills/database-migrations/SKILL.md +335 -0
  132. package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
  133. package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
  134. package/claude/skills/design-system/SKILL.md +682 -0
  135. package/claude/skills/documentation/SKILL.md +540 -0
  136. package/claude/skills/entity-api/SKILL.md +482 -0
  137. package/claude/skills/entity-system/SKILL.md +635 -0
  138. package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
  139. package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
  140. package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
  141. package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
  142. package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
  143. package/claude/skills/github/SKILL.md +467 -0
  144. package/claude/skills/i18n-nextintl/SKILL.md +302 -0
  145. package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
  146. package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
  147. package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
  148. package/claude/skills/impact-analysis/SKILL.md +203 -0
  149. package/claude/skills/jest-unit/SKILL.md +306 -0
  150. package/claude/skills/jest-unit/references/component-testing.md +371 -0
  151. package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
  152. package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
  153. package/claude/skills/jira-integration/SKILL.md +539 -0
  154. package/claude/skills/media-library/SKILL.md +743 -0
  155. package/claude/skills/mock-analysis/SKILL.md +276 -0
  156. package/claude/skills/monorepo-architecture/SKILL.md +162 -0
  157. package/claude/skills/nextjs-api-development/SKILL.md +364 -0
  158. package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
  159. package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
  160. package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
  161. package/claude/skills/notion-integration/SKILL.md +641 -0
  162. package/claude/skills/npm-development-workflow/SKILL.md +480 -0
  163. package/claude/skills/page-builder-blocks/SKILL.md +530 -0
  164. package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
  165. package/claude/skills/permissions-system/SKILL.md +619 -0
  166. package/claude/skills/plugins/SKILL.md +340 -0
  167. package/claude/skills/plugins/references/plugin-templates.md +414 -0
  168. package/claude/skills/plugins/references/plugin-testing.md +353 -0
  169. package/claude/skills/plugins/references/plugin-types.md +198 -0
  170. package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
  171. package/claude/skills/pom-patterns/SKILL.md +452 -0
  172. package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
  173. package/claude/skills/rate-limiting/SKILL.md +342 -0
  174. package/claude/skills/react-best-practices/AGENTS.md +2410 -0
  175. package/claude/skills/react-best-practices/README.md +123 -0
  176. package/claude/skills/react-best-practices/SKILL.md +125 -0
  177. package/claude/skills/react-best-practices/metadata.json +15 -0
  178. package/claude/skills/react-best-practices/rules/_sections.md +46 -0
  179. package/claude/skills/react-best-practices/rules/_template.md +28 -0
  180. package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  181. package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  182. package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
  183. package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
  184. package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
  185. package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
  186. package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  187. package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  188. package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  189. package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  190. package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  191. package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
  192. package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  193. package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  194. package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  195. package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  196. package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  197. package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  198. package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  199. package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  200. package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  201. package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  202. package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  203. package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  204. package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  205. package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  206. package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  207. package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  208. package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  209. package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  210. package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  211. package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  212. package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  213. package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  214. package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  215. package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  216. package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  217. package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  218. package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  219. package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  220. package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  221. package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  222. package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  223. package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  224. package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
  225. package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  226. package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  227. package/claude/skills/react-patterns/SKILL.md +688 -0
  228. package/claude/skills/registry-system/SKILL.md +331 -0
  229. package/claude/skills/scheduled-actions/SKILL.md +671 -0
  230. package/claude/skills/scope-enforcement/SKILL.md +542 -0
  231. package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
  232. package/claude/skills/server-actions/SKILL.md +493 -0
  233. package/claude/skills/service-layer/SKILL.md +587 -0
  234. package/claude/skills/session-management/SKILL.md +266 -0
  235. package/claude/skills/session-management/scripts/create-session.py +166 -0
  236. package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
  237. package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
  238. package/claude/skills/session-management/scripts/session-archive.sh +87 -0
  239. package/claude/skills/session-management/scripts/session-close.sh +133 -0
  240. package/claude/skills/session-management/scripts/session-init.sh +225 -0
  241. package/claude/skills/session-management/scripts/session-list.sh +163 -0
  242. package/claude/skills/session-management/scripts/split-plan.sh +116 -0
  243. package/claude/skills/shadcn-components/SKILL.md +586 -0
  244. package/claude/skills/shadcn-theming/SKILL.md +446 -0
  245. package/claude/skills/suspense-loading/SKILL.md +280 -0
  246. package/claude/skills/tailwind-theming/SKILL.md +507 -0
  247. package/claude/skills/tanstack-query/SKILL.md +608 -0
  248. package/claude/skills/test-coverage/SKILL.md +239 -0
  249. package/claude/skills/web-design-guidelines/SKILL.md +39 -0
  250. package/claude/skills/zod-validation/SKILL.md +537 -0
  251. package/claude/templates/blocks/progress.md +86 -0
  252. package/claude/templates/iteration/changes.md +61 -0
  253. package/claude/templates/iteration/progress.md +55 -0
  254. package/claude/templates/log.md +31 -0
  255. package/claude/templates/story/context.md +77 -0
  256. package/claude/templates/story/pendings.md +37 -0
  257. package/claude/templates/story/plan.md +299 -0
  258. package/claude/templates/story/requirements.md +109 -0
  259. package/claude/templates/story/scope.json +10 -0
  260. package/claude/templates/story/tests.md +91 -0
  261. package/claude/templates/task/progress.md +58 -0
  262. package/claude/templates/task/requirements.md +54 -0
  263. package/claude/workflows/README.md +154 -0
  264. package/claude/workflows/blocks.md +614 -0
  265. package/claude/workflows/story.md +1207 -0
  266. package/claude/workflows/task.md +927 -0
  267. package/claude/workflows/tweak.md +527 -0
  268. package/cursor/.gitkeep +0 -0
  269. package/package.json +35 -0
  270. package/scripts/postinstall.mjs +198 -0
  271. package/scripts/setup.mjs +282 -0
  272. package/scripts/sync.mjs +209 -0
@@ -0,0 +1,456 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Generate CRUD Tests Script
4
+
5
+ Generates Cypress API tests for entity CRUD operations.
6
+ Uses the project's API Controller pattern with BaseAPIController.
7
+
8
+ Usage:
9
+ python generate-crud-tests.py --entity ENTITY_NAME [--with-controller]
10
+
11
+ Options:
12
+ --entity ENTITY_NAME Name of the entity (kebab-case)
13
+ --theme THEME Theme name for theme-specific tests
14
+ --with-controller Also generate the API Controller class
15
+ --dry-run Preview without creating files
16
+ """
17
+
18
+ import os
19
+ import sys
20
+ import argparse
21
+ from pathlib import Path
22
+ from datetime import datetime
23
+
24
+
25
+ def to_camel_case(name: str) -> str:
26
+ """Convert kebab-case to camelCase."""
27
+ components = name.split('-')
28
+ return components[0] + ''.join(x.title() for x in components[1:])
29
+
30
+
31
+ def to_pascal_case(name: str) -> str:
32
+ """Convert kebab-case to PascalCase."""
33
+ return ''.join(x.title() for x in name.split('-'))
34
+
35
+
36
+ def get_active_theme() -> str:
37
+ """Get active theme from environment or default."""
38
+ return os.environ.get('NEXT_PUBLIC_ACTIVE_THEME', 'default')
39
+
40
+
41
+ def generate_api_controller(entity: str) -> str:
42
+ """Generate API Controller class following BaseAPIController pattern."""
43
+ pascal = to_pascal_case(entity)
44
+ singular = entity.rstrip('s')
45
+
46
+ return f'''/**
47
+ * {pascal}APIController - Controller for interacting with the {pascal} API
48
+ * Encapsulates all CRUD operations for /api/v1/{entity} endpoints
49
+ *
50
+ * Requires:
51
+ * - API Key with {entity}:read, {entity}:write scopes (or superadmin with *)
52
+ * - x-team-id header for team context
53
+ */
54
+ const BaseAPIController = require('./BaseAPIController')
55
+ const entitiesConfig = require('../../fixtures/entities.json')
56
+
57
+ const {{ slug }} = entitiesConfig.entities.{to_camel_case(entity)} || {{ slug: '{entity}' }}
58
+
59
+ class {pascal}APIController extends BaseAPIController {{
60
+ /**
61
+ * @param {{string}} baseUrl - Base URL for API requests
62
+ * @param {{string|null}} apiKey - API key for authentication
63
+ * @param {{string|null}} teamId - Team ID for x-team-id header
64
+ */
65
+ constructor(baseUrl = 'http://localhost:5173', apiKey = null, teamId = null) {{
66
+ super(baseUrl, apiKey, teamId, {{ slug }})
67
+ }}
68
+
69
+ // ============================================================
70
+ // SEMANTIC ALIASES
71
+ // ============================================================
72
+
73
+ /**
74
+ * GET /api/v1/{entity} - Get list of {entity}
75
+ * @param {{Object}} options - Query options
76
+ * @returns {{Cypress.Chainable}} Cypress response
77
+ */
78
+ get{pascal}(options = {{}}) {{
79
+ return this.list(options)
80
+ }}
81
+
82
+ /**
83
+ * GET /api/v1/{entity}/{{id}} - Get specific {singular} by ID
84
+ * @param {{string}} id - {pascal} ID
85
+ * @param {{Object}} options - Additional options
86
+ * @returns {{Cypress.Chainable}} Cypress response
87
+ */
88
+ get{pascal}ById(id, options = {{}}) {{
89
+ return this.getById(id, options)
90
+ }}
91
+
92
+ /**
93
+ * POST /api/v1/{entity} - Create new {singular}
94
+ * @param {{Object}} data - {pascal} data
95
+ * @param {{Object}} options - Additional options
96
+ * @returns {{Cypress.Chainable}} Cypress response
97
+ */
98
+ create{pascal}(data, options = {{}}) {{
99
+ return this.create(data, options)
100
+ }}
101
+
102
+ /**
103
+ * PATCH /api/v1/{entity}/{{id}} - Update {singular}
104
+ * @param {{string}} id - {pascal} ID
105
+ * @param {{Object}} data - Data to update
106
+ * @param {{Object}} options - Additional options
107
+ * @returns {{Cypress.Chainable}} Cypress response
108
+ */
109
+ update{pascal}(id, data, options = {{}}) {{
110
+ return this.update(id, data, options)
111
+ }}
112
+
113
+ /**
114
+ * DELETE /api/v1/{entity}/{{id}} - Delete {singular}
115
+ * @param {{string}} id - {pascal} ID
116
+ * @param {{Object}} options - Additional options
117
+ * @returns {{Cypress.Chainable}} Cypress response
118
+ */
119
+ delete{pascal}(id, options = {{}}) {{
120
+ return this.delete(id, options)
121
+ }}
122
+
123
+ // ============================================================
124
+ // DATA GENERATORS
125
+ // ============================================================
126
+
127
+ /**
128
+ * Generate random valid {singular} data
129
+ * @param {{Object}} overrides - Properties to override
130
+ * @returns {{Object}} Valid {singular} data
131
+ */
132
+ generateRandom{pascal}Data(overrides = {{}}) {{
133
+ const timestamp = Date.now()
134
+ return {{
135
+ title: `Test {singular.title()} ${{timestamp}}`,
136
+ description: `Test description for {singular} created at ${{new Date().toISOString()}}`,
137
+ // Add more default fields as needed
138
+ ...overrides
139
+ }}
140
+ }}
141
+ }}
142
+
143
+ module.exports = {pascal}APIController
144
+ '''
145
+
146
+
147
+ def generate_api_test(entity: str) -> str:
148
+ """Generate Cypress API test file following project conventions."""
149
+ pascal = to_pascal_case(entity)
150
+ singular = entity.rstrip('s')
151
+ camel = to_camel_case(entity)
152
+ upper = entity.upper().replace('-', '_')
153
+
154
+ return f'''/// <reference types="cypress" />
155
+
156
+ /**
157
+ * {pascal} API - CRUD Tests
158
+ *
159
+ * Basic CRUD operations for /api/v1/{entity} endpoints
160
+ * Uses superadmin API key for full access with team context
161
+ */
162
+
163
+ import * as allure from 'allure-cypress'
164
+
165
+ const {pascal}APIController = require('../../../src/controllers/{pascal}APIController.js')
166
+
167
+ describe('{pascal} API - CRUD Operations', {{
168
+ tags: ['@api', '@feat-{entity}', '@crud', '@regression']
169
+ }}, () => {{
170
+ let {camel}API: any
171
+ let createdItems: any[] = []
172
+
173
+ // Superadmin API key for testing
174
+ const SUPERADMIN_API_KEY = Cypress.env('SUPERADMIN_API_KEY') || 'sk_test_62fc9942407698cbe1d637c2ea91b5cf3e3e50b9052c432087a7f06f14173f62'
175
+ const TEAM_ID = Cypress.env('TEAM_ID') || 'team-tmt-001'
176
+ const BASE_URL = Cypress.config('baseUrl') || 'http://localhost:5173'
177
+
178
+ before(() => {{
179
+ // Initialize API controller with superadmin API key and team context
180
+ {camel}API = new {pascal}APIController(BASE_URL, SUPERADMIN_API_KEY, TEAM_ID)
181
+ cy.log('{pascal}APIController initialized')
182
+ cy.log(`Base URL: ${{BASE_URL}}`)
183
+ cy.log(`Team ID: ${{TEAM_ID}}`)
184
+ }})
185
+
186
+ beforeEach(() => {{
187
+ allure.epic('API')
188
+ allure.feature('{pascal}')
189
+ }})
190
+
191
+ afterEach(() => {{
192
+ // Cleanup: Delete items created during tests
193
+ if (createdItems.length > 0) {{
194
+ createdItems.forEach((item: any) => {{
195
+ if (item && item.id) {{
196
+ {camel}API.delete{pascal}(item.id)
197
+ }}
198
+ }})
199
+ createdItems = []
200
+ }}
201
+ }})
202
+
203
+ // ============================================================
204
+ // GET /api/v1/{entity} - List
205
+ // ============================================================
206
+ describe('GET /api/v1/{entity} - List', () => {{
207
+ it('{upper}_API_001: Should list {entity} with valid API key', {{ tags: '@smoke' }}, () => {{
208
+ allure.story('CRUD Operations')
209
+ allure.severity('critical')
210
+ {camel}API.get{pascal}().then((response: any) => {{
211
+ {camel}API.validateSuccessResponse(response, 200)
212
+ {camel}API.validatePaginatedResponse(response)
213
+ expect(response.body.data).to.be.an('array')
214
+
215
+ cy.log(`Found ${{response.body.data.length}} {entity}`)
216
+ cy.log(`Total: ${{response.body.info.total}}`)
217
+ }})
218
+ }})
219
+
220
+ it('{upper}_API_002: Should list {entity} with pagination', () => {{
221
+ allure.story('CRUD Operations')
222
+ {camel}API.get{pascal}({{ page: 1, limit: 5 }}).then((response: any) => {{
223
+ {camel}API.validatePaginatedResponse(response)
224
+ expect(response.body.info.page).to.eq(1)
225
+ expect(response.body.info.limit).to.eq(5)
226
+ expect(response.body.data.length).to.be.at.most(5)
227
+ }})
228
+ }})
229
+
230
+ it('{upper}_API_003: Should return 401 without API key', () => {{
231
+ allure.story('Authentication')
232
+ allure.severity('critical')
233
+ const noAuthAPI = new {pascal}APIController(BASE_URL, null, TEAM_ID)
234
+ noAuthAPI.get{pascal}({{ failOnStatusCode: false }}).then((response: any) => {{
235
+ expect(response.status).to.eq(401)
236
+ expect(response.body.success).to.be.false
237
+ }})
238
+ }})
239
+ }})
240
+
241
+ // ============================================================
242
+ // POST /api/v1/{entity} - Create
243
+ // ============================================================
244
+ describe('POST /api/v1/{entity} - Create', () => {{
245
+ it('{upper}_API_010: Should create {singular} with valid data', {{ tags: '@smoke' }}, () => {{
246
+ allure.story('CRUD Operations')
247
+ allure.severity('critical')
248
+ const data = {camel}API.generateRandom{pascal}Data()
249
+
250
+ {camel}API.create{pascal}(data).then((response: any) => {{
251
+ {camel}API.validateSuccessResponse(response, 201)
252
+ expect(response.body.data.id).to.exist
253
+ expect(response.body.data.title).to.eq(data.title)
254
+
255
+ // Track for cleanup
256
+ createdItems.push(response.body.data)
257
+
258
+ cy.log(`Created {singular}: ${{response.body.data.id}}`)
259
+ }})
260
+ }})
261
+
262
+ it('{upper}_API_011: Should return 400 with invalid data', () => {{
263
+ allure.story('Validation')
264
+ const invalidData = {{ title: '' }} // Empty title should fail
265
+
266
+ {camel}API.create{pascal}(invalidData, {{ failOnStatusCode: false }}).then((response: any) => {{
267
+ expect(response.status).to.eq(400)
268
+ expect(response.body.success).to.be.false
269
+ }})
270
+ }})
271
+ }})
272
+
273
+ // ============================================================
274
+ // GET /api/v1/{entity}/[id] - Read
275
+ // ============================================================
276
+ describe('GET /api/v1/{entity}/[id] - Read', () => {{
277
+ let testItem: any
278
+
279
+ beforeEach(() => {{
280
+ // Create a test item first
281
+ const data = {camel}API.generateRandom{pascal}Data()
282
+ {camel}API.create{pascal}(data).then((response: any) => {{
283
+ testItem = response.body.data
284
+ createdItems.push(testItem)
285
+ }})
286
+ }})
287
+
288
+ it('{upper}_API_020: Should get single {singular} by ID', () => {{
289
+ allure.story('CRUD Operations')
290
+ {camel}API.get{pascal}ById(testItem.id).then((response: any) => {{
291
+ {camel}API.validateSuccessResponse(response, 200)
292
+ expect(response.body.data.id).to.eq(testItem.id)
293
+ }})
294
+ }})
295
+
296
+ it('{upper}_API_021: Should return 404 for non-existent ID', () => {{
297
+ allure.story('Error Handling')
298
+ {camel}API.get{pascal}ById('non-existent-id', {{ failOnStatusCode: false }}).then((response: any) => {{
299
+ expect(response.status).to.eq(404)
300
+ }})
301
+ }})
302
+ }})
303
+
304
+ // ============================================================
305
+ // PATCH /api/v1/{entity}/[id] - Update
306
+ // ============================================================
307
+ describe('PATCH /api/v1/{entity}/[id] - Update', () => {{
308
+ let testItem: any
309
+
310
+ beforeEach(() => {{
311
+ const data = {camel}API.generateRandom{pascal}Data()
312
+ {camel}API.create{pascal}(data).then((response: any) => {{
313
+ testItem = response.body.data
314
+ createdItems.push(testItem)
315
+ }})
316
+ }})
317
+
318
+ it('{upper}_API_030: Should update {singular} with valid data', () => {{
319
+ allure.story('CRUD Operations')
320
+ const updateData = {{ title: 'Updated Title ' + Date.now() }}
321
+
322
+ {camel}API.update{pascal}(testItem.id, updateData).then((response: any) => {{
323
+ {camel}API.validateSuccessResponse(response, 200)
324
+ expect(response.body.data.title).to.eq(updateData.title)
325
+ }})
326
+ }})
327
+
328
+ it('{upper}_API_031: Should return 400 with invalid data', () => {{
329
+ allure.story('Validation')
330
+ const invalidData = {{ title: '' }}
331
+
332
+ {camel}API.update{pascal}(testItem.id, invalidData, {{ failOnStatusCode: false }}).then((response: any) => {{
333
+ expect(response.status).to.eq(400)
334
+ }})
335
+ }})
336
+ }})
337
+
338
+ // ============================================================
339
+ // DELETE /api/v1/{entity}/[id] - Delete
340
+ // ============================================================
341
+ describe('DELETE /api/v1/{entity}/[id] - Delete', () => {{
342
+ it('{upper}_API_040: Should delete {singular}', () => {{
343
+ allure.story('CRUD Operations')
344
+ const data = {camel}API.generateRandom{pascal}Data()
345
+
346
+ // Create then delete
347
+ {camel}API.create{pascal}(data).then((createResponse: any) => {{
348
+ const itemId = createResponse.body.data.id
349
+
350
+ {camel}API.delete{pascal}(itemId).then((deleteResponse: any) => {{
351
+ {camel}API.validateSuccessResponse(deleteResponse, 200)
352
+ expect(deleteResponse.body.data.deleted).to.be.true
353
+ }})
354
+
355
+ // Verify deletion
356
+ {camel}API.get{pascal}ById(itemId, {{ failOnStatusCode: false }}).then((getResponse: any) => {{
357
+ expect(getResponse.status).to.eq(404)
358
+ }})
359
+ }})
360
+ }})
361
+ }})
362
+
363
+ // ============================================================
364
+ // Edge Cases
365
+ // ============================================================
366
+ describe('Edge Cases', () => {{
367
+ it('{upper}_API_050: Should enforce max limit on pagination', () => {{
368
+ allure.story('Pagination')
369
+ {camel}API.get{pascal}({{ limit: 1000 }}).then((response: any) => {{
370
+ {camel}API.validateSuccessResponse(response, 200)
371
+ expect(response.body.info.limit).to.be.lte(100)
372
+ }})
373
+ }})
374
+
375
+ it('{upper}_API_051: Should handle special characters in search', () => {{
376
+ allure.story('Security')
377
+ {camel}API.get{pascal}({{ search: "<script>alert('xss')</script>" }}).then((response: any) => {{
378
+ {camel}API.validateSuccessResponse(response, 200)
379
+ // Should not crash or execute XSS
380
+ }})
381
+ }})
382
+ }})
383
+ }})
384
+ '''
385
+
386
+
387
+ def main():
388
+ parser = argparse.ArgumentParser(description='Generate CRUD API tests')
389
+ parser.add_argument('--entity', required=True, help='Entity name (kebab-case)')
390
+ parser.add_argument('--theme', default=None, help='Theme name')
391
+ parser.add_argument('--with-controller', action='store_true', help='Also generate API Controller')
392
+ parser.add_argument('--dry-run', action='store_true', help='Preview without creating files')
393
+
394
+ args = parser.parse_args()
395
+
396
+ theme = args.theme or get_active_theme()
397
+ entity = args.entity.lower()
398
+ pascal = to_pascal_case(entity)
399
+
400
+ print(f"\n{'=' * 60}")
401
+ print(f"GENERATING CRUD TESTS: {entity}")
402
+ print(f"{'=' * 60}")
403
+ print(f"Theme: {theme}")
404
+ print(f"With Controller: {args.with_controller}")
405
+ print(f"{'=' * 60}\n")
406
+
407
+ # Files to generate
408
+ base_path = Path(f'contents/themes/{theme}/tests/cypress')
409
+ files = {
410
+ f'e2e/api/entities/{entity}-crud.cy.ts': generate_api_test(entity)
411
+ }
412
+
413
+ if args.with_controller:
414
+ files[f'src/controllers/{pascal}APIController.js'] = generate_api_controller(entity)
415
+
416
+ if args.dry_run:
417
+ print("DRY RUN - Files that would be created:\n")
418
+ for file_path, content in files.items():
419
+ full_path = base_path / file_path
420
+ print(f" {full_path}")
421
+ print(f" Lines: {len(content.splitlines())}")
422
+ print("\n" + "-" * 60)
423
+ print(f"TEST FILE PREVIEW ({entity}-crud.cy.ts):")
424
+ print("-" * 60)
425
+ print(files[f'e2e/api/entities/{entity}-crud.cy.ts'][:2000])
426
+ print("...")
427
+ print("-" * 60)
428
+ print("\nRun without --dry-run to create files.")
429
+ return 0
430
+
431
+ # Create files
432
+ for file_path, content in files.items():
433
+ full_path = base_path / file_path
434
+ full_path.parent.mkdir(parents=True, exist_ok=True)
435
+
436
+ if full_path.exists():
437
+ print(f" SKIP (exists): {full_path}")
438
+ else:
439
+ with open(full_path, 'w', encoding='utf-8') as f:
440
+ f.write(content)
441
+ print(f" CREATED: {full_path}")
442
+
443
+ print(f"\n{'=' * 60}")
444
+ print("NEXT STEPS:")
445
+ print("=" * 60)
446
+ print("1. Update the API Controller with entity-specific fields")
447
+ print("2. Add entity to fixtures/entities.json if not present")
448
+ print("3. Update test data generators with real field requirements")
449
+ print("4. Run: pnpm cypress run --spec 'contents/themes/{}/tests/cypress/e2e/api/entities/{}-crud.cy.ts'".format(theme, entity))
450
+ print("=" * 60 + "\n")
451
+
452
+ return 0
453
+
454
+
455
+ if __name__ == '__main__':
456
+ sys.exit(main())