feat(apollo-vertex): add Solution Tests data layer (collection-backed hooks)#790
Draft
frankkluijtmans wants to merge 1 commit into
Draft
feat(apollo-vertex): add Solution Tests data layer (collection-backed hooks)#790frankkluijtmans wants to merge 1 commit into
frankkluijtmans wants to merge 1 commit into
Conversation
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Dependency License Review
License distribution
Excluded packages
|
frankkluijtmans
added a commit
that referenced
this pull request
Jun 8, 2026
The UI + registry wiring for the Solution Tests component. Stacked on the data layer PR (#790) — the view consumes the adapter/context/config/hooks from there. - SolutionTestsView + KPI bar, tabs, expandable rows, run-details dialog, evaluator results, JSON viewer, delete confirm, user-message popover - index.ts barrel; registry.json entry (installable as @uipath/solution-tests); tsconfig path alias - SolutionTestsTemplate demo (in-memory mock) + Templates docs page and nav Merge after #790. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Introduces the initial data-layer foundation for the Solution Tests registry item in Apollo Vertex (adapter contract, DataFabric-backed default adapter, context/config wiring, and TanStack Query hook), plus supporting types/utilities and new English i18n keys needed by the upcoming UI.
Changes:
- Added
SolutionTestsAdaptercontract and a default DataFabric/Orchestrator-backed adapter factory (createDataFabricAdapter). - Added provider/context + resolved presentation config, and a TanStack Query-based hook for reads/mutations with polling support.
- Added shared view-model types, status-to-badge maps, user-message parsing helpers, and new
en.jsontranslation keys.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/apollo-vertex/registry/solution-tests/adapter.ts | Defines the adapter interface + mutation/attachment types used by the Solution Tests view. |
| apps/apollo-vertex/registry/solution-tests/config.ts | Defines per-vertical presentation configuration and default resolution. |
| apps/apollo-vertex/registry/solution-tests/context.tsx | Provides adapter/config via React context for deep component access. |
| apps/apollo-vertex/registry/solution-tests/data-fabric-adapter.ts | Implements a default adapter over a minimal “data port” for DataFabric queries + triggers/functions. |
| apps/apollo-vertex/registry/solution-tests/hooks.ts | Documents a future vs-core collection-backed hook API (stubbed, not wired). |
| apps/apollo-vertex/registry/solution-tests/status-maps.ts | Maps numeric statuses to badge variants / classes for display. |
| apps/apollo-vertex/registry/solution-tests/types.ts | Declares domain-neutral Solution Tests view model types + default label maps. |
| apps/apollo-vertex/registry/solution-tests/use-solution-tests-data.ts | Adds TanStack Query reads/mutations and run polling behavior for the view. |
| apps/apollo-vertex/registry/solution-tests/user-messages.ts | Adds parsing + severity helpers for user-messages payloads. |
| apps/apollo-vertex/registry/solution-tests/utils.ts | Adds formatting helpers and small run/result utilities. |
| apps/apollo-vertex/locales/en.json | Adds new English translation keys required by the Solution Tests feature. |
Comment on lines
+30
to
+48
| const { data, isLoading, error } = useQuery({ | ||
| queryKey: QUERY_KEY, | ||
| queryFn: () => fetchData(adapter), | ||
| }); | ||
|
|
||
| const tests = data?.tests ?? []; | ||
| const batchRuns = data?.batchRuns ?? []; | ||
|
|
||
| const hasActiveRuns = batchRuns.some( | ||
| (r) => r.Status === RunStatus.Pending || r.Status === RunStatus.Running, | ||
| ); | ||
|
|
||
| // Poll while runs are active (syncing with an external timer). | ||
| useQuery({ | ||
| queryKey: [...QUERY_KEY, "polling"], | ||
| queryFn: () => fetchData(adapter), | ||
| refetchInterval: config.pollIntervalMs, | ||
| enabled: hasActiveRuns, | ||
| }); |
Comment on lines
+77
to
+85
| const runAllMutation = useMutation({ | ||
| mutationFn: () => adapter.runTests(), | ||
| onSuccess: (result) => { | ||
| assertOk(result, t("failed_to_run_tests")); | ||
| toast.success(t("all_tests_triggered")); | ||
| invalidate(); | ||
| }, | ||
| onError: onMutationError(), | ||
| }); |
Comment on lines
+87
to
+95
| const runTestMutation = useMutation({ | ||
| mutationFn: (testId: string) => adapter.runTests([testId]), | ||
| onSuccess: (result) => { | ||
| assertOk(result, t("failed_to_run_test")); | ||
| toast.success(t("test_triggered")); | ||
| invalidate(); | ||
| }, | ||
| onError: onMutationError(), | ||
| }); |
Comment on lines
+107
to
+115
| const forceStopBatchMutation = useMutation({ | ||
| mutationFn: (batchId: string) => adapter.forceStopBatch(batchId), | ||
| onSuccess: (result) => { | ||
| assertOk(result, t("failed_to_force_stop_batch")); | ||
| toast.success(t("force_stop_initiated")); | ||
| invalidate(); | ||
| }, | ||
| onError: onMutationError(), | ||
| }); |
Comment on lines
+117
to
+126
| const deleteMutation = useMutation({ | ||
| mutationFn: (testId: string) => adapter.deleteTest(testId), | ||
| onSuccess: (result) => { | ||
| assertOk(result, t("failed_to_delete_test")); | ||
| toast.success(t("test_deleted")); | ||
| invalidate(); | ||
| }, | ||
| onError: onMutationError(), | ||
| onSettled: () => setDeleteConfirmId(null), | ||
| }); |
Comment on lines
+13
to
+16
| export function formatJson(data: unknown): string { | ||
| if (data == null) return "No data available"; | ||
| if (typeof data === "string") return data; | ||
| return JSON.stringify(data, null, 2); |
Comment on lines
+3
to
+6
| export function formatDate(value?: string): string { | ||
| if (!value) return "-"; | ||
| return new Date(value).toLocaleString(); | ||
| } |
1258a4c to
e3b6b1c
Compare
frankkluijtmans
added a commit
that referenced
this pull request
Jun 8, 2026
The UI + registry wiring for the Solution Tests component. Stacked on the data layer PR (#790) — the view consumes the adapter/context/config/hooks from there. - SolutionTestsView + KPI bar, tabs, expandable rows, run-details dialog, evaluator results, JSON viewer, delete confirm, user-message popover - index.ts barrel; registry.json entry (installable as @uipath/solution-tests); tsconfig path alias - SolutionTestsTemplate demo (in-memory mock) + Templates docs page and nav Merge after #790. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
e3b6b1c to
b9d2ae2
Compare
frankkluijtmans
added a commit
that referenced
this pull request
Jun 8, 2026
The UI + registry wiring for the Solution Tests component. Stacked on the data layer PR (#790) — the view consumes the adapter/context/config/hooks from there. - SolutionTestsView + KPI bar, tabs, expandable rows, run-details dialog, evaluator results, JSON viewer, delete confirm, user-message popover - index.ts barrel; registry.json entry (installable as @uipath/solution-tests); tsconfig path alias - SolutionTestsTemplate demo (in-memory mock) + Templates docs page and nav Merge after #790. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment on lines
+30
to
+48
| const { data, isLoading, error } = useQuery({ | ||
| queryKey: QUERY_KEY, | ||
| queryFn: () => fetchData(adapter), | ||
| }); | ||
|
|
||
| const tests = data?.tests ?? []; | ||
| const batchRuns = data?.batchRuns ?? []; | ||
|
|
||
| const hasActiveRuns = batchRuns.some( | ||
| (r) => r.Status === RunStatus.Pending || r.Status === RunStatus.Running, | ||
| ); | ||
|
|
||
| // Poll while runs are active (syncing with an external timer). | ||
| useQuery({ | ||
| queryKey: [...QUERY_KEY, "polling"], | ||
| queryFn: () => fetchData(adapter), | ||
| refetchInterval: config.pollIntervalMs, | ||
| enabled: hasActiveRuns, | ||
| }); |
Comment on lines
+3
to
+6
| export function formatDate(value?: string): string { | ||
| if (!value) return "-"; | ||
| return new Date(value).toLocaleString(); | ||
| } |
Comment on lines
+32
to
+33
| if (typeof parsed !== "object" || parsed === null) return false; | ||
| return "auto_pass" in parsed; |
Comment on lines
+21
to
+24
| [RunResultStatus.Passed]: "success", | ||
| [RunResultStatus.Failed]: "error", | ||
| [RunResultStatus.Error]: "warning", | ||
| [RunResultStatus.NoBaseline]: "info", |
Comment on lines
+137
to
+139
| togglingTestId: toggleActiveMutation.isPending | ||
| ? (toggleActiveMutation.variables as { testId: string }).testId | ||
| : null, |
b9d2ae2 to
cf96c5b
Compare
frankkluijtmans
added a commit
that referenced
this pull request
Jun 8, 2026
The UI + registry wiring for the Solution Tests component, stacked on the data layer PR (#790). The view is presentational (dumb): data + handlers arrive via props/render-props from a smart container that calls the collection hooks. The demo renders the dumb view with in-memory mock data (no vs-core), mirroring the GroupMembershipGuard demo.
cf96c5b to
7992e7f
Compare
frankkluijtmans
added a commit
that referenced
this pull request
Jun 10, 2026
The UI + registry wiring for the Solution Tests component, stacked on the data layer PR (#790). The view is presentational (dumb): data + handlers arrive via props/render-props from a smart container that calls the collection hooks. The demo renders the dumb view with in-memory mock data (no vs-core), mirroring the GroupMembershipGuard demo.
Comment on lines
+7
to
+23
| function isUserMessageItem(value: unknown): value is UserMessageItem { | ||
| if (typeof value !== "object" || value === null) return false; | ||
| return ( | ||
| "key" in value && | ||
| typeof value.key === "string" && | ||
| "category" in value && | ||
| typeof value.category === "string" && | ||
| MESSAGE_CATEGORIES.has(value.category) && | ||
| "message" in value && | ||
| typeof value.message === "string" && | ||
| "timestamp" in value && | ||
| typeof value.timestamp === "string" && | ||
| "details" in value && | ||
| typeof value.details === "object" && | ||
| value.details !== null | ||
| ); | ||
| } |
| export function useSolutionTests(): UseSolutionTestsResult { | ||
| const solution = useSolution(); | ||
| const { data, isLoading } = useLiveQuery<SolutionTest>((q) => | ||
| q.from({ tests: solution?.api.collections.solutionTests[ENTITY.tests] }), |
| export function useSolutionTestRuns(): UseSolutionTestRunsResult { | ||
| const solution = useSolution(); | ||
| const { data, isLoading } = useLiveQuery<SolutionTestRun>((q) => | ||
| q.from({ runs: solution?.api.collections.solutionTests[ENTITY.runs] }), |
| const solution = useSolution(); | ||
| const { data, isLoading } = useLiveQuery<SolutionTestBatchRun>((q) => | ||
| q.from({ | ||
| batchRuns: solution?.api.collections.solutionTests[ENTITY.batchRuns], |
| const solution = useSolution(); | ||
| const { data, isLoading } = useLiveQuery<SolutionTestRunResult>((q) => | ||
| q.from({ | ||
| runResults: solution?.api.collections.solutionTests[ENTITY.runResults], |
| export function useBaselineJobs(testId: string): UseBaselineJobsResult { | ||
| const solution = useSolution(); | ||
| const { data, isLoading } = useLiveQuery<SolutionTestJob>((q) => | ||
| q.from({ jobs: solution?.api.collections.solutionTests[ENTITY.jobs] }), |
Comment on lines
+137
to
+143
| } catch { | ||
| // Network/timeout — the job was likely started; treat as fire-and-forget. | ||
| return { | ||
| success: true, | ||
| message: "Request sent (response timed out — job may still be running)", | ||
| }; | ||
| } |
7992e7f to
fde61bb
Compare
frankkluijtmans
added a commit
that referenced
this pull request
Jun 11, 2026
The UI + registry wiring for the Solution Tests component, stacked on the data layer PR (#790). The view is presentational (dumb): data + handlers arrive via props/render-props from a smart container that calls the collection hooks. The demo renders the dumb view with in-memory mock data (no vs-core), mirroring the GroupMembershipGuard demo.
fde61bb to
d9b3be3
Compare
frankkluijtmans
added a commit
that referenced
this pull request
Jun 11, 2026
The UI + registry wiring for the Solution Tests component, stacked on the data layer PR (#790). The view is presentational (dumb): data + handlers arrive via props/render-props from a smart container that calls the collection hooks. The demo renders the dumb view with in-memory mock data (no vs-core), mirroring the GroupMembershipGuard demo.
Comment on lines
+137
to
+143
| } catch { | ||
| // Network/timeout — the job was likely started; treat as fire-and-forget. | ||
| return { | ||
| success: true, | ||
| message: "Request sent (response timed out — job may still be running)", | ||
| }; | ||
| } |
Comment on lines
+52
to
+56
| return { | ||
| mutate: (testId: string, isActive: boolean) => | ||
| actions.toggleTestActive(testId, isActive), | ||
| isPending: false, | ||
| }; |
Comment on lines
+55
to
+60
| export function useJobExpectedOutput(): AttachmentFetcher<[jobId: string]> { | ||
| const actions = useSolutionTestsActions(); | ||
| return { | ||
| fetch: (jobId: string) => actions.getJobExpectedOutput(jobId), | ||
| }; | ||
| } |
Comment on lines
+85
to
+89
| const actions = useSolutionTestsActions(); | ||
| return { | ||
| fetch: (resultId: string, field: ResultAttachmentField) => | ||
| actions.getResultAttachment(resultId, field), | ||
| }; |
Comment on lines
+19
to
+21
| "details" in value && | ||
| typeof value.details === "object" && | ||
| value.details !== null |
Comment on lines
+1
to
+5
| /** | ||
| * Collection-backed data layer for the Solution Tests view — one module per | ||
| * query entity, each owning its live read plus the writes that act on it: | ||
| * - `use-solution-tests` — tests list + run / toggle-active / delete | ||
| * - `use-solution-test-batch-runs` — batch-run list |
Comment on lines
+20
to
+27
| export const runResultStatusBadgeMap: Record<number, BadgeStatus> = { | ||
| [RunResultStatus.Passed]: "success", | ||
| [RunResultStatus.Failed]: "error", | ||
| [RunResultStatus.Error]: "warning", | ||
| [RunResultStatus.NoBaseline]: "info", | ||
| [RunResultStatus.Pending]: "info", | ||
| [RunResultStatus.Aborted]: "warning", | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The data layer for the Solution Tests component, split out of #782 so it can land and be reviewed ahead of the UI. The view components depend on this, so the components PR is stacked on this branch and merges after it.
Contents (all under
registry/solution-tests/, plus theen.jsonkeys):adapter.ts—SolutionTestsAdapterinterface +MutationResult/ResultAttachmentFielddata-fabric-adapter.ts—createDataFabricAdapter(entity/trigger-name-driven, genericUiPathST*defaults) over a smallSolutionTestsDataPortcontext.tsx—SolutionTestsProvider+ context hooks;config.ts(subjectColumns, subjectNoun, statusLabels, thresholds)use-solution-tests-data.ts— TanStack Query reads/mutations + active-run pollinghooks.ts— stub of the planned vs-core collection-backed hook API (not wired; documents the future swap)types.ts,status-maps.ts,utils.ts,user-messages.ts, and theen.jsontranslation keysNot included here: the rendered components, the
registry.jsonentry, and the demo/docs — those are in the stacked components PR (solution-testsonly becomes an installable registry item once both land).Testing
pnpm typecheckandpnpm lintpass.🤖 Generated with Claude Code