@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.
- package/dist/components/auth/forms/LoginForm.js +1 -1
- package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
- package/dist/components/auth/forms/SignupForm.js +3 -2
- package/dist/components/dashboard/navigation/DynamicNavigation.d.ts.map +1 -1
- package/dist/components/dashboard/navigation/DynamicNavigation.js +2 -1
- package/dist/components/devtools/TestCasesViewer.d.ts.map +1 -1
- package/dist/components/devtools/TestCasesViewer.js +30 -23
- package/dist/components/devtools/TestCoverageDashboard.d.ts +2 -0
- package/dist/components/devtools/TestCoverageDashboard.d.ts.map +1 -0
- package/dist/components/devtools/TestCoverageDashboard.js +234 -0
- package/dist/components/devtools/bdd/BDDTableOfContents.d.ts.map +1 -1
- package/dist/components/devtools/bdd/BDDTableOfContents.js +25 -1
- package/dist/components/devtools/bdd/BDDTestCard.d.ts.map +1 -1
- package/dist/components/devtools/bdd/BDDTestCard.js +75 -2
- package/dist/components/devtools/bdd/parser.d.ts.map +1 -1
- package/dist/components/devtools/bdd/parser.js +35 -2
- package/dist/components/devtools/bdd/types.d.ts +8 -1
- package/dist/components/devtools/bdd/types.d.ts.map +1 -1
- package/dist/components/devtools/index.d.ts +1 -0
- package/dist/components/devtools/index.d.ts.map +1 -1
- package/dist/components/devtools/index.js +3 -1
- package/dist/lib/test/core-selectors.d.ts +12 -0
- package/dist/lib/test/core-selectors.d.ts.map +1 -1
- package/dist/lib/test/core-selectors.js +15 -2
- package/dist/lib/test/selectors.d.ts +24 -0
- package/dist/lib/test/selectors.d.ts.map +1 -1
- package/dist/messages/de/devtools.json +22 -1
- package/dist/messages/de/index.d.ts +21 -0
- package/dist/messages/de/index.d.ts.map +1 -1
- package/dist/messages/en/devtools.json +22 -1
- package/dist/messages/en/index.d.ts +21 -0
- package/dist/messages/en/index.d.ts.map +1 -1
- package/dist/messages/es/devtools.json +22 -1
- package/dist/messages/es/index.d.ts +21 -0
- package/dist/messages/es/index.d.ts.map +1 -1
- package/dist/messages/fr/devtools.json +22 -1
- package/dist/messages/fr/index.d.ts +21 -0
- package/dist/messages/fr/index.d.ts.map +1 -1
- package/dist/messages/it/devtools.json +22 -1
- package/dist/messages/it/index.d.ts +21 -0
- package/dist/messages/it/index.d.ts.map +1 -1
- package/dist/messages/pt/devtools.json +22 -1
- package/dist/messages/pt/index.d.ts +21 -0
- package/dist/messages/pt/index.d.ts.map +1 -1
- package/dist/presets/theme/tests/cypress/src/session-helpers.ts +27 -10
- package/dist/presets/theme/tests/cypress.config.ts +17 -5
- package/dist/styles/classes.json +9 -2
- package/dist/styles/ui.css +1 -1
- package/dist/templates/app/(auth)/reset-password/page.tsx +9 -9
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/auth.cy.ts +135 -24
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/billing.cy.ts +182 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-mobile.cy.ts +137 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-navigation.cy.ts +70 -60
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-sidebar.cy.ts +89 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-topnav.cy.ts +133 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/devtools.cy.ts +273 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/global-search.cy.ts +93 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/pages-editor.cy.ts +211 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/posts-editor.cy.ts +350 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-api-keys.cy.ts +233 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-billing.cy.ts +108 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-layout.cy.ts +123 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-password.cy.ts +74 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-profile.cy.ts +79 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-teams.cy.ts +90 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/superadmin.cy.ts +193 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/tasks.cy.ts +128 -102
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_selectors/teams.cy.ts +151 -0
- package/dist/templates/contents/themes/starter/tests/cypress/src/core/DashboardEntityPOM.ts +2 -2
- package/dist/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +26 -8
- package/dist/templates/contents/themes/starter/tests/cypress/support/e2e.ts +2 -1
- package/dist/templates/contents/themes/starter/tests/cypress.config.ts +17 -6
- package/package.json +21 -18
- package/scripts/build/docs-registry.mjs +0 -0
- package/scripts/build/registry/generators/docs-registry.mjs +90 -0
- package/scripts/build/registry/generators/unified-registry.mjs +1 -0
- package/scripts/build/registry.mjs +2 -0
- package/scripts/create-theme.mjs +0 -0
- package/scripts/deploy/release-version.mjs +0 -0
- package/scripts/deploy/vercel-deploy.mjs +0 -0
- package/scripts/dev/watch-plugins.mjs +0 -0
- package/scripts/maintenance/update-core.mjs +0 -0
- package/scripts/setup/npm-postinstall.mjs +0 -0
- package/scripts/setup/setup-claude.mjs +0 -0
- package/scripts/test/cy.mjs +33 -8
- package/scripts/validation/check-imports.sh +0 -0
- package/templates/app/(auth)/reset-password/page.tsx +9 -9
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/auth.cy.ts +135 -24
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/billing.cy.ts +182 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-mobile.cy.ts +137 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-navigation.cy.ts +70 -60
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-sidebar.cy.ts +89 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/dashboard-topnav.cy.ts +133 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/devtools.cy.ts +273 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/global-search.cy.ts +93 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/pages-editor.cy.ts +211 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/posts-editor.cy.ts +350 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-api-keys.cy.ts +233 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-billing.cy.ts +108 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-layout.cy.ts +123 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-password.cy.ts +74 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-profile.cy.ts +79 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/settings-teams.cy.ts +90 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/superadmin.cy.ts +193 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/tasks.cy.ts +128 -102
- package/templates/contents/themes/starter/tests/cypress/e2e/_selectors/teams.cy.ts +151 -0
- package/templates/contents/themes/starter/tests/cypress/src/core/DashboardEntityPOM.ts +2 -2
- package/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +26 -8
- package/templates/contents/themes/starter/tests/cypress/support/e2e.ts +2 -1
- package/templates/contents/themes/starter/tests/cypress.config.ts +17 -6
- package/tests/cypress/support/e2e.ts +2 -1
- 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
|
|
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,
|
|
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
|
|
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;
|
|
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":
|
|
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":"
|
|
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__ */
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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__ */
|
|
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 @@
|
|
|
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":"
|
|
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":"
|
|
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 {
|
|
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,
|
|
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*(
|
|
43
|
+
const typeMatch = section.match(/\*\*Type:\*\*\s*(.+?)(?:\n|$)/i);
|
|
44
44
|
if (typeMatch) {
|
|
45
|
-
|
|
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;
|
|
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"}
|