Skip to content

Commit b57982c

Browse files
feat(apollo-vertex): add Solution Tests view + template
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.
1 parent 06a9a2a commit b57982c

24 files changed

Lines changed: 3362 additions & 0 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export default {
22
"list-page": "List page",
33
settings: "Settings",
4+
"solution-tests": "Solution tests",
45
};
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import { SolutionTestsTemplate } from '@/templates/SolutionTestsTemplate';
2+
import { PreviewFullScreen } from '@/app/_components/preview-full-screen';
3+
4+
# Solution tests
5+
6+
A full-page composition for managing UiPath Solution Tests — test cases,
7+
batch runs, a KPI score trend, run-result baselines, and adopt / update /
8+
remove actions. The view is domain-neutral: it reads the generic `UiPathST*`
9+
Solution Test entity collections from your vs-core solution and is
10+
parameterized for the subject entity (loans, claims, invoices, …) through
11+
`SolutionTestsConfig`. Intended to render inside an
12+
[`ApolloShell`](/patterns/shell).
13+
14+
<PreviewFullScreen title="Solution tests preview">
15+
<SolutionTestsTemplate />
16+
</PreviewFullScreen>
17+
18+
## Composition
19+
20+
In production, render the smart `SolutionTests` container inside a
21+
`SolutionTestsProvider`; it reads the `UiPathST*` collections from your vs-core
22+
solution through the collection-backed hooks. The preview above is instead a
23+
presentational demo — it renders the dumb `SolutionTestsView` (and the dumb
24+
expanded views) with in-memory mock data and no-op handlers, so it never
25+
touches the hooks or vs-core. From top to bottom the view stacks:
26+
27+
- **`PageHeader`** — title and the "Run all" action.
28+
- **KPI bar** — cards plus a `recharts` score-trend chart across recent runs.
29+
- **Tabs**`Test cases` (list, enable/disable, run, delete) and
30+
`Test runs` (batch runs backed by live queries, per-run results, force-stop).
31+
- **Dialogs** — run details, JSON viewer, and delete confirmation, plus the
32+
expected-vs-actual baseline adopt / update / remove flows.
33+
34+
Source: [`templates/SolutionTestsTemplate.tsx`](https://github.com/UiPath/apollo-ui/blob/main/apps/apollo-vertex/templates/SolutionTestsTemplate.tsx)
35+
36+
## Consumer interface
37+
38+
The smart container has four inputs, all on `SolutionTestsProvider` (three
39+
required, plus an optional `config`). Reads are implicit (the `UiPathST*`
40+
collections on your vs-core solution); writes and presentation are explicit
41+
props:
42+
43+
```tsx
44+
interface SolutionTestsProviderProps {
45+
/**
46+
* Required. Base URL that write-action slugs are appended to (no trailing
47+
* slash): `{base}/{org}/{tenant}/orchestrator_/t/{folderKey}`.
48+
*/
49+
triggerBaseUrl: string;
50+
/** Required. Resolves the caller's current bearer token (refreshed near expiry). */
51+
getToken: () => Promise<string | null> | string | null;
52+
/**
53+
* Required. Resolves a Solution Test entity name to its DataFabric id (GUID),
54+
* for attachment reads. e.g. `(name) => entities[name]?.id` from vss codegen.
55+
*/
56+
getEntityId: (name: string) => string | undefined;
57+
/** Optional per-vertical presentation config. */
58+
config?: SolutionTestsConfig;
59+
children: ReactNode;
60+
}
61+
62+
interface SolutionTestsConfig {
63+
/** Columns inserted between Test Name and Version. Usually the only customization. */
64+
subjectColumns?: ColumnDef<SolutionTest>[];
65+
/** Turns the test name into a link to its subject. */
66+
getSubjectHref?: (test: SolutionTest) => string | undefined;
67+
/** Subject noun for labels, e.g. `{ singular: "Loan", plural: "Loans" }`. */
68+
subjectNoun?: { singular: string; plural: string };
69+
/** Score at/above which a result passes (drives pass color + KPI trend line). Defaults to 0.9. */
70+
passThreshold?: number;
71+
}
72+
```
73+
74+
So a consumer is responsible for exactly three things:
75+
76+
1. **Reads** — ensure the name-keyed `UiPathST*` collections exist on your
77+
vs-core solution (`solution.api.collections.solutionTests`); the list reads
78+
query them reactively with no wiring. Attachment reads (expected/actual
79+
output, evaluator results) additionally need `getEntityId` to resolve each
80+
entity's DataFabric id, since vs-core doesn't expose entity ids on the
81+
solution. Pass `(name) => entities[name]?.id` from your vss codegen.
82+
2. **Writes** — pass `triggerBaseUrl` + `getToken`. The provider builds the
83+
whole write surface (run, delete, force-stop, adopt / update / remove
84+
baseline) from them. Toggle-active isn't a trigger. It goes through the
85+
collection's optimistic update and needs no extra wiring.
86+
3. **Presentation** — pass `config.subjectColumns` (and optionally
87+
`getSubjectHref` / `subjectNoun`) to flavor the table for your vertical.
88+
89+
Everything else (evaluator labels, status labels, the poll interval) is
90+
hard-coded in `constants.ts`. Edit there to retarget a deployment. The pass
91+
threshold defaults to `0.9` in `constants.ts` but is overridable per vertical
92+
via `config.passThreshold`. Consumers who want to supply their own data plumbing can instead
93+
render the dumb `SolutionTestsView`, which takes all data and callbacks via
94+
props (this is what the preview above does).
95+
96+
## Installation
97+
98+
```bash
99+
npx shadcn@latest add @uipath/solution-tests
100+
```
101+
102+
> **Requires [`@uipath/vs-core`](https://www.npmjs.com/package/@uipath/vs-core)
103+
> `^2.0.4`.** The container reads the Solution Test collections from the
104+
> dedicated, name-keyed `solution.api.collections.solutionTests` namespace
105+
> introduced in vs-core 2.x. Install vs-core per its README — it brings its own
106+
> peers (`@tanstack/db`, `@tanstack/query-db-collection`,
107+
> `@tanstack/react-query`, `@uipath/uipath-typescript`). The component itself
108+
> pulls `@tanstack/react-db` (for `useLiveQuery`), `@tanstack/react-table`,
109+
> `@tanstack/react-router`, `recharts`, `sonner`, and `react-i18next`.
110+
111+
The Solution Test entities (`UiPathST*`) are generic across verticals, so the
112+
only per-vertical customization most consumers need is their vertical's
113+
**`subjectColumns`**. The smart `SolutionTests` container reads its data from
114+
your vs-core Solution Test collections — the name-keyed
115+
`solution.api.collections.solutionTests` set (`UiPathSTTests`,
116+
`UiPathSTBatchRuns`, `UiPathSTRuns`, `UiPathSTJobs`, `UiPathSTRunResults`) — via
117+
the collection-backed hooks, so your only data responsibility is to make sure
118+
those collections exist on your solution. Wrap `<SolutionTests />` in a
119+
`<SolutionTestsProvider>` with your presentation `config`.
120+
121+
Reads are live the moment the collections exist. **Writes** (run, delete,
122+
force-stop, adopt/update/remove baseline) POST an action slug to your Solution
123+
Test trigger base URL — pass `triggerBaseUrl` and `getToken` to the provider and
124+
it builds the whole write surface for you, so you don't reimplement the
125+
trigger/auth plumbing. (Toggle-active and attachment reads aren't triggers — they
126+
go through the vs-core collections/sdk.)
127+
128+
```tsx
129+
"use client";
130+
131+
import {
132+
SolutionTests,
133+
SolutionTestsProvider,
134+
type SolutionTestsConfig,
135+
} from "@/components/ui/solution-tests";
136+
import { entities } from "@/vss.gen"; // vss codegen: entity name -> { id }
137+
138+
const config: SolutionTestsConfig = {
139+
subjectColumns, // the only per-vertical customization
140+
subjectNoun: { singular: "Loan", plural: "Loans" },
141+
};
142+
143+
export default function SolutionTestsPage() {
144+
// List reads come from the vs-core solution's `collections.solutionTests` in
145+
// context (provided higher up by your shell). No read wiring required.
146+
return (
147+
<SolutionTestsProvider
148+
config={config}
149+
// `{base}/{org}/{tenant}/orchestrator_/t/{folderKey}` (no trailing slash)
150+
triggerBaseUrl={`/${env.UIPATH_ORG_NAME}/${env.UIPATH_TENANT_NAME}/orchestrator_/t/${env.UIPATH_SOLUTION_FOLDER_KEY}`}
151+
getToken={() => tokenService.getCurrentToken()}
152+
getEntityId={(name) => entities[name]?.id}
153+
>
154+
<SolutionTests />
155+
</SolutionTestsProvider>
156+
);
157+
}
158+
```
159+
160+
The exported dumb `SolutionTestsView` takes all data + callbacks via props if
161+
you prefer to supply your own data plumbing or render the view against a mock
162+
(as the preview does).
163+
164+
## Customizing
165+
166+
- **Subject columns**`config.subjectColumns` injects your vertical's columns
167+
between Test Name and Version; `config.getSubjectHref` turns the test name
168+
into a link to the subject. This is normally the only required config.
169+
- **Data source** — the smart `SolutionTests` container reads the `UiPathST*`
170+
collections from `solution.api.collections.solutionTests` (vs-core 2.x) via
171+
the collection-backed hooks in `hooks.ts`; just ensure those collections exist
172+
on your solution. Reads are reactive (live queries); writes POST to the
173+
provider's `triggerBaseUrl` (see Installation).
174+
- **Subject noun**`config.subjectNoun` (a `singular` / `plural` pair) drives
175+
the subject-flavored KPI card (e.g. "Loans passing"), the runs "passed"
176+
column, and the run-results dialog title; omit it for generic "Tests"
177+
wording.
178+
- **Fixed setup** — evaluator labels, status labels, and the poll interval are
179+
hard-coded in `constants.ts`; edit there to retarget a deployment. The pass
180+
threshold defaults to `0.9` but is overridable via `config.passThreshold`.
181+
- **i18n** — framework strings use `react-i18next`; wrap your app in
182+
`ApolloShell` (which initializes i18n via `LocaleProvider`) or provide your
183+
own `I18nextProvider`.

apps/apollo-vertex/locales/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"analytics": "Analytics",
2323
"apollo_vertex": "Apollo Vertex",
2424
"apollo_vertex_description": "- UiPath Apollo Vertex",
25+
"are_you_sure": "Are you sure?",
2526
"asc": "Asc",
2627
"ask_ai": "Ask AI",
2728
"assistant": "Assistant",
@@ -52,6 +53,7 @@
5253
"compliance_pass_rates": "Compliance Pass Rates",
5354
"confirm_delete_test": "Delete this test?",
5455
"confirm_delete_test_description": "This permanently removes the test and its baselines. This action cannot be undone.",
56+
"confirm_run_tests_description": "Running solution tests re-processes each case, which can modify data in connected systems. Make sure you understand the impact before continuing.",
5557
"copied": "Copied!",
5658
"copy": "Copy",
5759
"copy_code": "Copy code",
@@ -92,6 +94,7 @@
9294
"failed_to_remove_agent_baseline": "Failed to remove agent from expected results",
9395
"failed_to_run_test": "Failed to run test",
9496
"failed_to_run_tests": "Failed to run tests",
97+
"failed_to_toggle_test": "Failed to update test status",
9598
"failed_to_update_baseline": "Failed to update expected result",
9699
"feedback_comment_placeholder": "What could the AI have done better?",
97100
"feedback_demo_default_label": "Default — buttons only",

0 commit comments

Comments
 (0)