@nextsparkjs/core 0.1.0-beta.33 → 0.1.0-beta.36

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 (112) hide show
  1. package/dist/components/auth/forms/LoginForm.js +1 -1
  2. package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
  3. package/dist/components/auth/forms/SignupForm.js +3 -2
  4. package/dist/components/dashboard/navigation/DynamicNavigation.d.ts.map +1 -1
  5. package/dist/components/dashboard/navigation/DynamicNavigation.js +2 -1
  6. package/dist/components/devtools/TestCasesViewer.d.ts.map +1 -1
  7. package/dist/components/devtools/TestCasesViewer.js +30 -23
  8. package/dist/components/devtools/TestCoverageDashboard.d.ts +2 -0
  9. package/dist/components/devtools/TestCoverageDashboard.d.ts.map +1 -0
  10. package/dist/components/devtools/TestCoverageDashboard.js +234 -0
  11. package/dist/components/devtools/bdd/BDDTableOfContents.d.ts.map +1 -1
  12. package/dist/components/devtools/bdd/BDDTableOfContents.js +25 -1
  13. package/dist/components/devtools/bdd/BDDTestCard.d.ts.map +1 -1
  14. package/dist/components/devtools/bdd/BDDTestCard.js +75 -2
  15. package/dist/components/devtools/bdd/parser.d.ts.map +1 -1
  16. package/dist/components/devtools/bdd/parser.js +35 -2
  17. package/dist/components/devtools/bdd/types.d.ts +8 -1
  18. package/dist/components/devtools/bdd/types.d.ts.map +1 -1
  19. package/dist/components/devtools/index.d.ts +1 -0
  20. package/dist/components/devtools/index.d.ts.map +1 -1
  21. package/dist/components/devtools/index.js +3 -1
  22. package/dist/lib/test/core-selectors.d.ts +12 -0
  23. package/dist/lib/test/core-selectors.d.ts.map +1 -1
  24. package/dist/lib/test/core-selectors.js +15 -2
  25. package/dist/lib/test/selectors.d.ts +24 -0
  26. package/dist/lib/test/selectors.d.ts.map +1 -1
  27. package/dist/messages/de/devtools.json +22 -1
  28. package/dist/messages/de/index.d.ts +21 -0
  29. package/dist/messages/de/index.d.ts.map +1 -1
  30. package/dist/messages/en/devtools.json +22 -1
  31. package/dist/messages/en/index.d.ts +21 -0
  32. package/dist/messages/en/index.d.ts.map +1 -1
  33. package/dist/messages/es/devtools.json +22 -1
  34. package/dist/messages/es/index.d.ts +21 -0
  35. package/dist/messages/es/index.d.ts.map +1 -1
  36. package/dist/messages/fr/devtools.json +22 -1
  37. package/dist/messages/fr/index.d.ts +21 -0
  38. package/dist/messages/fr/index.d.ts.map +1 -1
  39. package/dist/messages/it/devtools.json +22 -1
  40. package/dist/messages/it/index.d.ts +21 -0
  41. package/dist/messages/it/index.d.ts.map +1 -1
  42. package/dist/messages/pt/devtools.json +22 -1
  43. package/dist/messages/pt/index.d.ts +21 -0
  44. package/dist/messages/pt/index.d.ts.map +1 -1
  45. package/dist/presets/theme/tests/cypress/src/session-helpers.ts +27 -10
  46. package/dist/presets/theme/tests/cypress.config.ts +17 -5
  47. package/dist/styles/classes.json +9 -2
  48. package/dist/styles/ui.css +1 -1
  49. package/dist/templates/app/(auth)/reset-password/page.tsx +9 -9
  50. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/auth.cy.ts +135 -24
  51. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/billing.cy.ts +182 -0
  52. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-mobile.cy.ts +137 -0
  53. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-navigation.cy.ts +70 -60
  54. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-sidebar.cy.ts +89 -0
  55. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-topnav.cy.ts +133 -0
  56. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/devtools.cy.ts +273 -0
  57. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/global-search.cy.ts +93 -0
  58. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/pages-editor.cy.ts +211 -0
  59. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/posts-editor.cy.ts +350 -0
  60. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-api-keys.cy.ts +233 -0
  61. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-billing.cy.ts +108 -0
  62. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-layout.cy.ts +123 -0
  63. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-password.cy.ts +74 -0
  64. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-profile.cy.ts +79 -0
  65. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-teams.cy.ts +90 -0
  66. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/superadmin.cy.ts +193 -0
  67. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/tasks.cy.ts +128 -102
  68. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/teams.cy.ts +151 -0
  69. package/dist/templates/contents/themes/starter/tests/cypress/src/core/DashboardEntityPOM.ts +2 -2
  70. package/dist/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +26 -8
  71. package/dist/templates/contents/themes/starter/tests/cypress/support/e2e.ts +2 -1
  72. package/dist/templates/contents/themes/starter/tests/cypress.config.ts +17 -6
  73. package/package.json +21 -18
  74. package/scripts/build/docs-registry.mjs +0 -0
  75. package/scripts/build/registry/generators/docs-registry.mjs +90 -0
  76. package/scripts/build/registry/generators/unified-registry.mjs +1 -0
  77. package/scripts/build/registry.mjs +2 -0
  78. package/scripts/create-theme.mjs +0 -0
  79. package/scripts/deploy/release-version.mjs +0 -0
  80. package/scripts/deploy/vercel-deploy.mjs +0 -0
  81. package/scripts/dev/watch-plugins.mjs +0 -0
  82. package/scripts/maintenance/update-core.mjs +0 -0
  83. package/scripts/setup/npm-postinstall.mjs +0 -0
  84. package/scripts/setup/setup-claude.mjs +0 -0
  85. package/scripts/test/cy.mjs +33 -8
  86. package/scripts/validation/check-imports.sh +0 -0
  87. package/templates/app/(auth)/reset-password/page.tsx +9 -9
  88. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/auth.cy.ts +135 -24
  89. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/billing.cy.ts +182 -0
  90. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-mobile.cy.ts +137 -0
  91. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-navigation.cy.ts +70 -60
  92. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-sidebar.cy.ts +89 -0
  93. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-topnav.cy.ts +133 -0
  94. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/devtools.cy.ts +273 -0
  95. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/global-search.cy.ts +93 -0
  96. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/pages-editor.cy.ts +211 -0
  97. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/posts-editor.cy.ts +350 -0
  98. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-api-keys.cy.ts +233 -0
  99. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-billing.cy.ts +108 -0
  100. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-layout.cy.ts +123 -0
  101. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-password.cy.ts +74 -0
  102. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-profile.cy.ts +79 -0
  103. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-teams.cy.ts +90 -0
  104. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/superadmin.cy.ts +193 -0
  105. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/tasks.cy.ts +128 -102
  106. package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/teams.cy.ts +151 -0
  107. package/templates/contents/themes/starter/tests/cypress/src/core/DashboardEntityPOM.ts +2 -2
  108. package/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +26 -8
  109. package/templates/contents/themes/starter/tests/cypress/support/e2e.ts +2 -1
  110. package/templates/contents/themes/starter/tests/cypress.config.ts +17 -6
  111. package/tests/cypress/support/e2e.ts +2 -1
  112. package/scripts/build/registry/generators/plugin-registry.mjs.bak +0 -219
@@ -198,7 +198,7 @@ function LoginForm() {
198
198
  }
199
199
  ),
200
200
  /* @__PURE__ */ jsxs(CardContent, { children: [
201
- fromInvite && /* @__PURE__ */ jsxs(Alert, { className: "mb-4", "data-cy": "login-invite-banner", children: [
201
+ fromInvite && /* @__PURE__ */ jsxs(Alert, { className: "mb-4", "data-cy": sel("auth.login.inviteBanner"), children: [
202
202
  /* @__PURE__ */ jsx(Users, { className: "h-4 w-4" }),
203
203
  /* @__PURE__ */ jsx(AlertDescription, { children: t("login.inviteBanner") })
204
204
  ] }),
@@ -1 +1 @@
1
- {"version":3,"file":"SignupForm.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/forms/SignupForm.tsx"],"names":[],"mappings":"AA4BA,wBAAgB,UAAU,4CAqgBzB"}
1
+ {"version":3,"file":"SignupForm.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/forms/SignupForm.tsx"],"names":[],"mappings":"AA4BA,wBAAgB,UAAU,4CAsgBzB"}
@@ -312,7 +312,7 @@ function SignupForm() {
312
312
  }
313
313
  ),
314
314
  /* @__PURE__ */ jsxs(CardContent, { children: [
315
- fromInvite && /* @__PURE__ */ jsxs(Alert, { className: "mb-4", "data-cy": "signup-invite-banner", children: [
315
+ fromInvite && /* @__PURE__ */ jsxs(Alert, { className: "mb-4", "data-cy": sel("auth.signup.inviteBanner"), children: [
316
316
  /* @__PURE__ */ jsx(Users, { className: "h-4 w-4" }),
317
317
  /* @__PURE__ */ jsx(AlertDescription, { children: t("signup.inviteBanner") })
318
318
  ] }),
@@ -407,7 +407,7 @@ function SignupForm() {
407
407
  ),
408
408
  errors.confirmPassword && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: errors.confirmPassword.message })
409
409
  ] }),
410
- error && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
410
+ error && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", "data-cy": sel("auth.signup.error"), children: [
411
411
  /* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
412
412
  /* @__PURE__ */ jsx(AlertDescription, { children: error })
413
413
  ] }),
@@ -460,6 +460,7 @@ function SignupForm() {
460
460
  onClick: handleGoogleSignUp,
461
461
  disabled: !!loadingProvider,
462
462
  className: "w-full",
463
+ "data-cy": sel("auth.signup.googleButton"),
463
464
  children: [
464
465
  loadingProvider === "google" ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxs("svg", { className: "mr-2 h-4 w-4", viewBox: "0 0 24 24", children: [
465
466
  /* @__PURE__ */ jsx("path", { fill: "#4285F4", d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" }),
@@ -1 +1 @@
1
- {"version":3,"file":"DynamicNavigation.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/navigation/DynamicNavigation.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAA;AA0BnF,UAAU,sBAAsB;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,QAAQ,EAAE,wBAAwB,EAAE,CAAA;CACrC;AAyGD,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,QAAgB,EAChB,WAAW,EACX,QAAQ,EACT,EAAE,sBAAsB,2CAoGxB;AAgDD,eAAe,iBAAiB,CAAA"}
1
+ {"version":3,"file":"DynamicNavigation.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/navigation/DynamicNavigation.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAA;AA0BnF,UAAU,sBAAsB;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,QAAQ,EAAE,wBAAwB,EAAE,CAAA;CACrC;AAyGD,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,QAAgB,EAChB,WAAW,EACX,QAAQ,EACT,EAAE,sBAAsB,2CAoGxB;AAoDD,eAAe,iBAAiB,CAAA"}
@@ -187,6 +187,7 @@ function NavigationLink({
187
187
  const isActive = pathname === item.href || pathname.startsWith(item.href + "/");
188
188
  const label = item.descriptionKey ? t(item.descriptionKey, { defaultValue: item.name }) : item.name;
189
189
  const cySlug = item.name.toLowerCase().replace(/\s+/g, "-");
190
+ const dataCyId = cySlug === "dashboard" ? createCyId("nav", "link-dashboard") : createCyId("nav", `link-entity-${cySlug}`);
190
191
  return /* @__PURE__ */ jsxs(
191
192
  Link,
192
193
  {
@@ -198,7 +199,7 @@ function NavigationLink({
198
199
  isMobile && "w-full"
199
200
  ),
200
201
  "aria-current": isActive ? "page" : void 0,
201
- "data-cy": createCyId("nav", `link-entity-${cySlug}`),
202
+ "data-cy": dataCyId,
202
203
  children: [
203
204
  /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
204
205
  /* @__PURE__ */ jsx("span", { className: "truncate", children: label })
@@ -1 +1 @@
1
- {"version":3,"file":"TestCasesViewer.d.ts","sourceRoot":"","sources":["../../../src/components/devtools/TestCasesViewer.tsx"],"names":[],"mappings":"AAyBA,UAAU,oBAAoB;IAC5B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAiBD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,2CAgOpE"}
1
+ {"version":3,"file":"TestCasesViewer.d.ts","sourceRoot":"","sources":["../../../src/components/devtools/TestCasesViewer.tsx"],"names":[],"mappings":"AA2BA,UAAU,oBAAoB;IAC5B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAiBD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,2CAkOpE"}
@@ -4,7 +4,9 @@ import { useState, useEffect, useMemo } from "react";
4
4
  import { FileTree } from "./FileTree.js";
5
5
  import { MarkdownViewer } from "./MarkdownViewer.js";
6
6
  import { BDDTestViewer } from "./bdd/index.js";
7
+ import { TestCoverageDashboard } from "./TestCoverageDashboard.js";
7
8
  import { cn } from "../../lib/utils.js";
9
+ import { sel } from "../../lib/test/index.js";
8
10
  import {
9
11
  Card,
10
12
  CardContent,
@@ -13,7 +15,7 @@ import {
13
15
  CardTitle
14
16
  } from "../ui/card.js";
15
17
  import { Button } from "../ui/button.js";
16
- import { Loader2, FileText, AlertCircle, ArrowLeft } from "lucide-react";
18
+ import { Loader2, FileText, AlertCircle, ArrowLeft, LayoutDashboard } from "lucide-react";
17
19
  import { useTranslations } from "next-intl";
18
20
  import { useTreeNavigation } from "../../hooks/useTreeNavigation.js";
19
21
  function pathExistsInTree(tree, path) {
@@ -104,16 +106,32 @@ function TestCasesViewer({ initialPath }) {
104
106
  ] }),
105
107
  /* @__PURE__ */ jsx(CardDescription, { children: t("fileTreeDescription") })
106
108
  ] }),
107
- /* @__PURE__ */ jsx(CardContent, { className: "overflow-y-auto h-[calc(100%-5rem)]", "data-cy": "devtools-tests-tree", children: tree.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("noTests") }) }) : /* @__PURE__ */ jsx(
108
- FileTree,
109
- {
110
- nodes: tree,
111
- selectedPath: selectedPath || void 0,
112
- expandedFolders,
113
- onSelectFile: navigateToFile,
114
- onToggleFolder: toggleFolder
115
- }
116
- ) })
109
+ /* @__PURE__ */ jsxs(CardContent, { className: "overflow-y-auto h-[calc(100%-5rem)]", "data-cy": "devtools-tests-tree", children: [
110
+ selectedPath && /* @__PURE__ */ jsxs(
111
+ Button,
112
+ {
113
+ variant: "ghost",
114
+ size: "sm",
115
+ onClick: clearSelection,
116
+ className: "w-full justify-start gap-2 mb-4",
117
+ "data-cy": sel("devtools.tests.dashboardButton"),
118
+ children: [
119
+ /* @__PURE__ */ jsx(LayoutDashboard, { className: "h-4 w-4" }),
120
+ t("dashboard.backToDashboard")
121
+ ]
122
+ }
123
+ ),
124
+ tree.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("noTests") }) }) : /* @__PURE__ */ jsx(
125
+ FileTree,
126
+ {
127
+ nodes: tree,
128
+ selectedPath: selectedPath || void 0,
129
+ expandedFolders,
130
+ onSelectFile: navigateToFile,
131
+ onToggleFolder: toggleFolder
132
+ }
133
+ )
134
+ ] })
117
135
  ] }) }),
118
136
  /* @__PURE__ */ jsx("div", { className: "lg:col-span-9", children: /* @__PURE__ */ jsx(Card, { className: "h-full", children: /* @__PURE__ */ jsxs(CardContent, { className: cn(
119
137
  "p-6 h-full",
@@ -145,18 +163,7 @@ function TestCasesViewer({ initialPath }) {
145
163
  ]
146
164
  }
147
165
  ),
148
- !selectedPath && !pathNotFound && /* @__PURE__ */ jsxs(
149
- "div",
150
- {
151
- className: "flex flex-col items-center justify-center h-full text-center",
152
- "data-cy": "devtools-tests-empty-state",
153
- children: [
154
- /* @__PURE__ */ jsx(FileText, { className: "h-16 w-16 text-muted-foreground/50 mb-4" }),
155
- /* @__PURE__ */ jsx("p", { className: "text-lg font-medium text-muted-foreground", children: t("selectFile") }),
156
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-2", children: t("selectFileDescription") })
157
- ]
158
- }
159
- ),
166
+ !selectedPath && !pathNotFound && /* @__PURE__ */ jsx(TestCoverageDashboard, {}),
160
167
  isLoadingFile && !pathNotFound && /* @__PURE__ */ jsx(
161
168
  "div",
162
169
  {
@@ -0,0 +1,2 @@
1
+ export declare function TestCoverageDashboard(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=TestCoverageDashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestCoverageDashboard.d.ts","sourceRoot":"","sources":["../../../src/components/devtools/TestCoverageDashboard.tsx"],"names":[],"mappings":"AA6GA,wBAAgB,qBAAqB,4CA+NpC"}
@@ -0,0 +1,234 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState, useEffect } from "react";
4
+ import { useTranslations } from "next-intl";
5
+ import { Card, CardContent, CardHeader, CardTitle } from "../ui/card.js";
6
+ import { Badge } from "../ui/badge.js";
7
+ import { Progress } from "../ui/progress.js";
8
+ import {
9
+ BarChart3,
10
+ FileText,
11
+ Tags,
12
+ Workflow,
13
+ AlertTriangle,
14
+ CheckCircle2,
15
+ Loader2
16
+ } from "lucide-react";
17
+ import { sel } from "../../lib/test/index.js";
18
+ function StatCard({ icon, label, value, percentage, dataCy, subtext }) {
19
+ return /* @__PURE__ */ jsx(Card, { "data-cy": dataCy, children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4", children: [
20
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
21
+ /* @__PURE__ */ jsx("div", { className: "p-2 rounded-lg bg-violet-100 dark:bg-violet-900/30", children: icon }),
22
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
23
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground truncate", children: label }),
24
+ /* @__PURE__ */ jsx("p", { className: "text-2xl font-bold", children: value }),
25
+ subtext && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: subtext })
26
+ ] })
27
+ ] }),
28
+ percentage !== void 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
29
+ /* @__PURE__ */ jsx(Progress, { value: percentage, className: "h-2" }),
30
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground mt-1 text-right", children: [
31
+ percentage,
32
+ "%"
33
+ ] })
34
+ ] })
35
+ ] }) });
36
+ }
37
+ const TAG_CATEGORY_MAP = {
38
+ layers: "Layers",
39
+ priorities: "Priorities",
40
+ features: "Features",
41
+ flows: "Flows",
42
+ blocks: "Blocks",
43
+ roles: "Roles",
44
+ operations: "Operations",
45
+ other: "Other"
46
+ };
47
+ function TestCoverageDashboard() {
48
+ const t = useTranslations("devtools.tests.dashboard");
49
+ const [data, setData] = useState(null);
50
+ const [loading, setLoading] = useState(true);
51
+ const [error, setError] = useState(null);
52
+ useEffect(() => {
53
+ async function fetchCoverage() {
54
+ try {
55
+ const response = await fetch("/api/v1/devtools/testing");
56
+ const json = await response.json();
57
+ if (!response.ok) throw new Error(json.error || "Failed to load coverage data");
58
+ setData(json);
59
+ } catch (err) {
60
+ setError(err instanceof Error ? err.message : "Failed to load");
61
+ } finally {
62
+ setLoading(false);
63
+ }
64
+ }
65
+ fetchCoverage();
66
+ }, []);
67
+ if (loading) {
68
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full", "data-cy": sel("devtools.tests.dashboard"), children: /* @__PURE__ */ jsx(Loader2, { className: "h-8 w-8 animate-spin text-violet-600 dark:text-violet-400" }) });
69
+ }
70
+ if (error) {
71
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full text-center", "data-cy": sel("devtools.tests.dashboard"), children: [
72
+ /* @__PURE__ */ jsx(AlertTriangle, { className: "h-12 w-12 text-amber-500 mb-4" }),
73
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium text-amber-600 dark:text-amber-400", children: error })
74
+ ] });
75
+ }
76
+ if (!(data == null ? void 0 : data.data)) return null;
77
+ const { summary, features = [], flows = [] } = data.data;
78
+ const featureCoverage = summary.features.total > 0 ? Math.round(summary.features.withTests / summary.features.total * 100) : 0;
79
+ const flowCoverage = summary.flows.total > 0 ? Math.round(summary.flows.withTests / summary.flows.total * 100) : 0;
80
+ const uncoveredFeatures = features.filter((f) => !f.testing.hasTests);
81
+ const uncoveredFlows = flows.filter((f) => !f.testing.hasTests);
82
+ const criticalUncoveredFlows = uncoveredFlows.filter((f) => f.criticalPath);
83
+ const hasGaps = uncoveredFeatures.length > 0 || uncoveredFlows.length > 0;
84
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6 h-full overflow-y-auto", "data-cy": sel("devtools.tests.dashboard"), children: [
85
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold text-violet-600 dark:text-violet-400", children: t("title") }) }),
86
+ /* @__PURE__ */ jsxs(
87
+ "div",
88
+ {
89
+ className: "grid grid-cols-2 lg:grid-cols-4 gap-4",
90
+ "data-cy": sel("devtools.tests.dashboardStats"),
91
+ children: [
92
+ /* @__PURE__ */ jsx(
93
+ StatCard,
94
+ {
95
+ icon: /* @__PURE__ */ jsx(BarChart3, { className: "h-5 w-5 text-violet-600 dark:text-violet-400" }),
96
+ label: t("features"),
97
+ value: `${summary.features.withTests}/${summary.features.total}`,
98
+ percentage: featureCoverage,
99
+ dataCy: sel("devtools.tests.dashboardStatFeatures"),
100
+ subtext: `${summary.features.withTests} ${t("withTests")}`
101
+ }
102
+ ),
103
+ /* @__PURE__ */ jsx(
104
+ StatCard,
105
+ {
106
+ icon: /* @__PURE__ */ jsx(Workflow, { className: "h-5 w-5 text-violet-600 dark:text-violet-400" }),
107
+ label: t("flows"),
108
+ value: `${summary.flows.withTests}/${summary.flows.total}`,
109
+ percentage: flowCoverage,
110
+ dataCy: sel("devtools.tests.dashboardStatFlows"),
111
+ subtext: `${summary.flows.withTests} ${t("withTests")}`
112
+ }
113
+ ),
114
+ /* @__PURE__ */ jsx(
115
+ StatCard,
116
+ {
117
+ icon: /* @__PURE__ */ jsx(FileText, { className: "h-5 w-5 text-violet-600 dark:text-violet-400" }),
118
+ label: t("testFiles"),
119
+ value: String(summary.testFiles),
120
+ dataCy: sel("devtools.tests.dashboardStatFiles")
121
+ }
122
+ ),
123
+ /* @__PURE__ */ jsx(
124
+ StatCard,
125
+ {
126
+ icon: /* @__PURE__ */ jsx(Tags, { className: "h-5 w-5 text-violet-600 dark:text-violet-400" }),
127
+ label: t("tags"),
128
+ value: String(summary.totalTags),
129
+ dataCy: sel("devtools.tests.dashboardStatTags")
130
+ }
131
+ )
132
+ ]
133
+ }
134
+ ),
135
+ /* @__PURE__ */ jsxs(Card, { "data-cy": sel("devtools.tests.dashboardGaps"), children: [
136
+ /* @__PURE__ */ jsx(CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsxs(CardTitle, { className: "text-lg flex items-center gap-2", children: [
137
+ hasGaps ? /* @__PURE__ */ jsx(AlertTriangle, { className: "h-5 w-5 text-amber-500" }) : /* @__PURE__ */ jsx(CheckCircle2, { className: "h-5 w-5 text-green-500" }),
138
+ t("gaps")
139
+ ] }) }),
140
+ /* @__PURE__ */ jsx(CardContent, { children: !hasGaps ? /* @__PURE__ */ jsxs("div", { className: "text-center py-4 text-muted-foreground", children: [
141
+ /* @__PURE__ */ jsx(CheckCircle2, { className: "h-8 w-8 text-green-500 mx-auto mb-2" }),
142
+ /* @__PURE__ */ jsx("p", { children: t("noGaps") })
143
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
144
+ criticalUncoveredFlows.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
145
+ /* @__PURE__ */ jsxs("h4", { className: "text-sm font-medium text-red-600 dark:text-red-400 mb-2 flex items-center gap-1", children: [
146
+ /* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4" }),
147
+ t("criticalPath"),
148
+ " (",
149
+ criticalUncoveredFlows.length,
150
+ ")"
151
+ ] }),
152
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: criticalUncoveredFlows.map((flow) => /* @__PURE__ */ jsx(
153
+ Badge,
154
+ {
155
+ variant: "destructive",
156
+ "data-cy": sel("devtools.tests.dashboardGapItem", { slug: flow.slug }),
157
+ children: flow.title
158
+ },
159
+ flow.slug
160
+ )) })
161
+ ] }),
162
+ uncoveredFeatures.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
163
+ /* @__PURE__ */ jsxs("h4", { className: "text-sm font-medium text-amber-600 dark:text-amber-400 mb-2", children: [
164
+ t("features"),
165
+ " ",
166
+ t("withoutTests"),
167
+ " (",
168
+ uncoveredFeatures.length,
169
+ ")"
170
+ ] }),
171
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
172
+ uncoveredFeatures.slice(0, 10).map((feature) => /* @__PURE__ */ jsx(
173
+ Badge,
174
+ {
175
+ variant: "outline",
176
+ className: "border-amber-500 text-amber-600 dark:text-amber-400",
177
+ "data-cy": sel("devtools.tests.dashboardGapItem", { slug: feature.slug }),
178
+ children: feature.title
179
+ },
180
+ feature.slug
181
+ )),
182
+ uncoveredFeatures.length > 10 && /* @__PURE__ */ jsxs(Badge, { variant: "secondary", children: [
183
+ "+",
184
+ uncoveredFeatures.length - 10
185
+ ] })
186
+ ] })
187
+ ] }),
188
+ uncoveredFlows.filter((f) => !f.criticalPath).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
189
+ /* @__PURE__ */ jsxs("h4", { className: "text-sm font-medium text-amber-600 dark:text-amber-400 mb-2", children: [
190
+ t("flows"),
191
+ " ",
192
+ t("withoutTests"),
193
+ " (",
194
+ uncoveredFlows.filter((f) => !f.criticalPath).length,
195
+ ")"
196
+ ] }),
197
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
198
+ uncoveredFlows.filter((f) => !f.criticalPath).slice(0, 10).map((flow) => /* @__PURE__ */ jsx(
199
+ Badge,
200
+ {
201
+ variant: "outline",
202
+ className: "border-amber-500 text-amber-600 dark:text-amber-400",
203
+ "data-cy": sel("devtools.tests.dashboardGapItem", { slug: flow.slug }),
204
+ children: flow.title
205
+ },
206
+ flow.slug
207
+ )),
208
+ uncoveredFlows.filter((f) => !f.criticalPath).length > 10 && /* @__PURE__ */ jsxs(Badge, { variant: "secondary", children: [
209
+ "+",
210
+ uncoveredFlows.filter((f) => !f.criticalPath).length - 10
211
+ ] })
212
+ ] })
213
+ ] })
214
+ ] }) })
215
+ ] }),
216
+ summary.byCategory && Object.keys(summary.byCategory).length > 0 && /* @__PURE__ */ jsxs(Card, { children: [
217
+ /* @__PURE__ */ jsx(CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsx(CardTitle, { className: "text-lg", children: t("coverage") }) }),
218
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-5 gap-4", children: Object.entries(summary.byCategory).map(([category, count]) => /* @__PURE__ */ jsxs(
219
+ "div",
220
+ {
221
+ className: "text-center p-3 rounded-lg bg-muted/50",
222
+ children: [
223
+ /* @__PURE__ */ jsx("p", { className: "text-2xl font-bold text-violet-600 dark:text-violet-400", children: count }),
224
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground capitalize", children: TAG_CATEGORY_MAP[category] || category })
225
+ ]
226
+ },
227
+ category
228
+ )) }) })
229
+ ] })
230
+ ] });
231
+ }
232
+ export {
233
+ TestCoverageDashboard
234
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"BDDTableOfContents.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/bdd/BDDTableOfContents.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,UAAU,uBAAuB;IAC/B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,YAAY,EACZ,YAAY,GACb,EAAE,uBAAuB,2CAiDzB"}
1
+ {"version":3,"file":"BDDTableOfContents.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/bdd/BDDTableOfContents.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,SAAS,CAAC;AAEvD,UAAU,uBAAuB;IAC/B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,YAAY,EACZ,YAAY,GACb,EAAE,uBAAuB,2CAwEzB"}
@@ -1,5 +1,12 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ CheckCircle2,
5
+ XCircle,
6
+ SkipForward,
7
+ Clock,
8
+ PlayCircle
9
+ } from "lucide-react";
3
10
  import { cn } from "../../../lib/utils.js";
4
11
  function BDDTableOfContents({
5
12
  tests,
@@ -18,6 +25,23 @@ function BDDTableOfContents({
18
25
  return "bg-slate-400";
19
26
  }
20
27
  };
28
+ const getStatusIcon = (status) => {
29
+ const iconClass = "h-3.5 w-3.5 shrink-0";
30
+ switch (status) {
31
+ case "passing":
32
+ return /* @__PURE__ */ jsx(CheckCircle2, { className: cn(iconClass, "text-green-500") });
33
+ case "failing":
34
+ return /* @__PURE__ */ jsx(XCircle, { className: cn(iconClass, "text-red-500") });
35
+ case "skipped":
36
+ return /* @__PURE__ */ jsx(SkipForward, { className: cn(iconClass, "text-amber-500") });
37
+ case "pending":
38
+ return /* @__PURE__ */ jsx(Clock, { className: cn(iconClass, "text-slate-400") });
39
+ case "active":
40
+ return /* @__PURE__ */ jsx(PlayCircle, { className: cn(iconClass, "text-blue-500") });
41
+ default:
42
+ return null;
43
+ }
44
+ };
21
45
  return /* @__PURE__ */ jsxs("div", { className: "space-y-2", "data-cy": "bdd-toc", children: [
22
46
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-muted-foreground uppercase tracking-wide px-2", children: "Test Cases" }),
23
47
  /* @__PURE__ */ jsx("nav", { className: "space-y-1", children: tests.map((test, index) => /* @__PURE__ */ jsxs(
@@ -32,7 +56,7 @@ function BDDTableOfContents({
32
56
  ),
33
57
  "data-cy": `bdd-toc-item-${test.id}`,
34
58
  children: [
35
- /* @__PURE__ */ jsx(
59
+ test.metadata.status ? getStatusIcon(test.metadata.status) : /* @__PURE__ */ jsx(
36
60
  "span",
37
61
  {
38
62
  className: cn(
@@ -1 +1 @@
1
- {"version":3,"file":"BDDTestCard.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/bdd/BDDTestCard.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAExD,UAAU,gBAAgB;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,WAAW,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CA2JxF"}
1
+ {"version":3,"file":"BDDTestCard.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/bdd/BDDTestCard.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAc,MAAM,SAAS,CAAC;AAEpE,UAAU,gBAAgB;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,WAAW,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CAmOxF"}
@@ -1,7 +1,21 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
- import { Check, Copy, ChevronDown, Tag, Zap, TestTube2 } from "lucide-react";
4
+ import {
5
+ Check,
6
+ Copy,
7
+ ChevronDown,
8
+ Tag,
9
+ Zap,
10
+ TestTube2,
11
+ Terminal,
12
+ CheckCircle2,
13
+ XCircle,
14
+ SkipForward,
15
+ Clock,
16
+ PlayCircle,
17
+ AlertTriangle
18
+ } from "lucide-react";
5
19
  import { cn } from "../../../lib/utils.js";
6
20
  import { Button } from "../../ui/button.js";
7
21
  import { Badge } from "../../ui/badge.js";
@@ -44,6 +58,44 @@ function BDDTestCard({ test, index, isOpen, onToggle, language }) {
44
58
  return null;
45
59
  }
46
60
  };
61
+ const getStatusColor = (status) => {
62
+ switch (status) {
63
+ case "passing":
64
+ return "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400";
65
+ case "failing":
66
+ return "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400";
67
+ case "skipped":
68
+ return "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400";
69
+ case "pending":
70
+ return "bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400";
71
+ case "active":
72
+ return "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400";
73
+ default:
74
+ return "bg-slate-100 text-slate-600 dark:bg-slate-800";
75
+ }
76
+ };
77
+ const getStatusIcon = (status) => {
78
+ switch (status) {
79
+ case "passing":
80
+ return /* @__PURE__ */ jsx(CheckCircle2, { className: "h-3 w-3" });
81
+ case "failing":
82
+ return /* @__PURE__ */ jsx(XCircle, { className: "h-3 w-3" });
83
+ case "skipped":
84
+ return /* @__PURE__ */ jsx(SkipForward, { className: "h-3 w-3" });
85
+ case "pending":
86
+ return /* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" });
87
+ case "active":
88
+ return /* @__PURE__ */ jsx(PlayCircle, { className: "h-3 w-3" });
89
+ default:
90
+ return null;
91
+ }
92
+ };
93
+ const copyGrepCommand = async (tag) => {
94
+ const command = `pnpm cy:tags "${tag}"`;
95
+ await navigator.clipboard.writeText(command);
96
+ setCopied(true);
97
+ setTimeout(() => setCopied(false), 2e3);
98
+ };
47
99
  return /* @__PURE__ */ jsx(Collapsible, { open: isOpen, onOpenChange: onToggle, children: /* @__PURE__ */ jsxs(
48
100
  "div",
49
101
  {
@@ -78,7 +130,11 @@ function BDDTestCard({ test, index, isOpen, onToggle, language }) {
78
130
  getTypeIcon(test.metadata.type),
79
131
  test.metadata.type
80
132
  ] }),
81
- test.metadata.priority && /* @__PURE__ */ jsx(Badge, { className: cn("text-xs", getPriorityColor(test.metadata.priority)), children: test.metadata.priority })
133
+ test.metadata.priority && /* @__PURE__ */ jsx(Badge, { className: cn("text-xs", getPriorityColor(test.metadata.priority)), children: test.metadata.priority }),
134
+ test.metadata.status && /* @__PURE__ */ jsxs(Badge, { className: cn("text-xs gap-1", getStatusColor(test.metadata.status)), children: [
135
+ getStatusIcon(test.metadata.status),
136
+ test.metadata.status
137
+ ] })
82
138
  ] })
83
139
  ]
84
140
  }
@@ -88,6 +144,23 @@ function BDDTestCard({ test, index, isOpen, onToggle, language }) {
88
144
  /* @__PURE__ */ jsx(Tag, { className: "h-3 w-3 text-muted-foreground" }),
89
145
  test.metadata.tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: tag }, tag))
90
146
  ] }),
147
+ test.metadata.grepTags && test.metadata.grepTags.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
148
+ /* @__PURE__ */ jsx(Terminal, { className: "h-3 w-3 text-emerald-500" }),
149
+ test.metadata.grepTags.map((tag) => /* @__PURE__ */ jsx(
150
+ Badge,
151
+ {
152
+ className: "text-xs bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400 cursor-pointer hover:bg-emerald-200 dark:hover:bg-emerald-900/50 transition-colors",
153
+ onClick: () => copyGrepCommand(tag),
154
+ title: `Click to copy: pnpm cy:tags "${tag}"`,
155
+ children: tag
156
+ },
157
+ tag
158
+ ))
159
+ ] }),
160
+ test.metadata.statusReason && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 text-sm text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 rounded-md px-3 py-2", children: [
161
+ /* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }),
162
+ /* @__PURE__ */ jsx("span", { children: test.metadata.statusReason })
163
+ ] }),
91
164
  /* @__PURE__ */ jsxs("div", { className: "relative", children: [
92
165
  /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 z-10", children: /* @__PURE__ */ jsx(
93
166
  Button,
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/bdd/parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAA0D,MAAM,SAAS,CAAC;AA4MnG;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAkB7D"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/bdd/parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAsE,MAAM,SAAS,CAAC;AAoP/G;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAkB7D"}
@@ -40,9 +40,14 @@ function parseTestMetadata(section) {
40
40
  if (priorityMatch) {
41
41
  metadata.priority = priorityMatch[1].toLowerCase();
42
42
  }
43
- const typeMatch = section.match(/\*\*Type:\*\*\s*(\w+)/i);
43
+ const typeMatch = section.match(/\*\*Type:\*\*\s*(.+?)(?:\n|$)/i);
44
44
  if (typeMatch) {
45
- metadata.type = typeMatch[1].toLowerCase();
45
+ const rawType = typeMatch[1].trim().toLowerCase();
46
+ if (rawType.includes("selector")) {
47
+ metadata.type = "selector";
48
+ } else {
49
+ metadata.type = rawType.split(/\s+/)[0];
50
+ }
46
51
  }
47
52
  const tagsMatch = section.match(/\*\*Tags:\*\*\s*(.+)/i);
48
53
  if (tagsMatch) {
@@ -50,6 +55,34 @@ function parseTestMetadata(section) {
50
55
  }
51
56
  const automatedMatch = section.match(/\*\*Automated:\*\*\s*(yes|true)/i);
52
57
  metadata.automated = !!automatedMatch;
58
+ const statusMatch = section.match(/\*\*Status:\*\*\s*(\w+)(?:\s*[-–]\s*(.+))?/i);
59
+ if (statusMatch) {
60
+ const [, status, reason] = statusMatch;
61
+ const normalizedStatus = status.toLowerCase();
62
+ if (normalizedStatus === "skip" || normalizedStatus === "skipped") {
63
+ metadata.status = "skipped";
64
+ } else if (normalizedStatus === "pass" || normalizedStatus === "passing" || normalizedStatus === "passed") {
65
+ metadata.status = "passing";
66
+ } else if (normalizedStatus === "fail" || normalizedStatus === "failing" || normalizedStatus === "failed") {
67
+ metadata.status = "failing";
68
+ } else if (normalizedStatus === "pending" || normalizedStatus === "todo") {
69
+ metadata.status = "pending";
70
+ } else if (normalizedStatus === "active") {
71
+ metadata.status = "active";
72
+ } else {
73
+ metadata.status = normalizedStatus;
74
+ }
75
+ if (reason) {
76
+ metadata.statusReason = reason.trim();
77
+ }
78
+ }
79
+ const grepMatch = section.match(/\*\*Grep:\*\*\s*(.+)/i);
80
+ if (grepMatch) {
81
+ const grepTags = grepMatch[1].match(/@[\w-]+/g);
82
+ if (grepTags && grepTags.length > 0) {
83
+ metadata.grepTags = grepTags;
84
+ }
85
+ }
53
86
  return metadata;
54
87
  }
55
88
  function extractGherkinScenarios(section) {
@@ -11,11 +11,18 @@ export interface BDDFeature {
11
11
  grepTags?: string[];
12
12
  coverage?: number;
13
13
  }
14
+ export type TestStatus = 'passing' | 'failing' | 'skipped' | 'pending' | 'active';
14
15
  export interface BDDTestMetadata {
15
16
  priority?: 'high' | 'medium' | 'low';
16
- type?: 'smoke' | 'regression' | 'integration' | 'e2e';
17
+ type?: 'smoke' | 'regression' | 'integration' | 'e2e' | 'selector';
17
18
  tags?: string[];
18
19
  automated?: boolean;
20
+ /** Test execution status */
21
+ status?: TestStatus;
22
+ /** Reason for status (e.g., "requires OWNER permission") */
23
+ statusReason?: string;
24
+ /** Grep tags for Cypress filtering (e.g., ["@ui-selectors", "@SEL_BILL_001"]) */
25
+ grepTags?: string[];
19
26
  }
20
27
  export type BDDLanguage = 'en' | 'es';
21
28
  export interface BDDScenarios {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/bdd/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,aAAa,GAAG,KAAK,CAAC;IACtD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtC,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,CAAC;IAC1B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,SAAS,EAAE,YAAY,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/bdd/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,aAAa,GAAG,KAAK,GAAG,UAAU,CAAC;IACnE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtC,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,CAAC;IAC1B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,SAAS,EAAE,YAAY,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB"}