1import * as Axiom from "@/Axiom";
2import * as Provider from "@/Provider";
3import * as Test from "@/Test/Alchemy";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7
8const { test } = Test.make({ providers: Axiom.providers() });
9
10const logLevel = Effect.provideService(
11 MinimumLogLevel,
12 process.env.DEBUG ? "Debug" : "Info",
13);
14
15// Axiom credentials are resolved via the AuthProvider (env method reads
16// AXIOM_TOKEN / AXIOM_API_KEY). When neither is present the suite can't talk
17// to the real API, so skipIf-gate the live list test. On an entitled run the
18// failure mode without creds is an `AuthError`:
19// "Axiom env credentials not found. Set AXIOM_TOKEN (or AXIOM_API_KEY)."
20const hasAxiomCreds = !!(process.env.AXIOM_TOKEN || process.env.AXIOM_API_KEY);
21
22// Deterministic names (no Date.now) so reruns target the same view/dataset and
23// the start/end destroy bookends keep the org clean. A view's APL query is
24// validated against existing datasets on create, so we stand up a backing
25// dataset in the same stack.
26const VIEW_NAME = "alchemy-list-test-view";
27const DATASET_NAME = "alchemy-list-test-view-dataset";
28
29test.provider.skipIf(!hasAxiomCreds)(
30 "list enumerates the deployed view",
31 (stack) =>
32 Effect.gen(function* () {
33 yield* stack.destroy();
34
35 const deployed = yield* stack.deploy(
36 Effect.gen(function* () {
37 const dataset = yield* Axiom.Dataset("ListViewDataset", {
38 name: DATASET_NAME,
39 });
40 return yield* Axiom.View("ListView", {
41 name: VIEW_NAME,
42 description: "alchemy list() lifecycle op test",
43 datasets: [dataset.name],
44 aplQuery: `['${DATASET_NAME}'] | take 1`,
45 });
46 }),
47 );
48
49 const provider = yield* Provider.findProvider(Axiom.View);
50 const all = yield* provider.list();
51
52 // `getViews` returns the full account-wide list in one shot; the freshly
53 // created view must be present, hydrated into the exact `read` Attributes
54 // shape (so `.id` / `.name` are directly usable by `delete`).
55 expect(all.some((v) => v.id === deployed.id)).toBe(true);
56
57 const row = all.find((v) => v.id === deployed.id)!;
58 expect(row.name).toEqual(VIEW_NAME);
59 expect(row.aplQuery).toEqual(deployed.aplQuery);
60
61 yield* stack.destroy();
62 }).pipe(logLevel),
63 {
64 tags: [
65 "provider:axiom",
66 "provider:axiom:dataset",
67 "provider:axiom:view",
68 "live",
69 ],
70 timeout: 120_000,
71 },
72);