1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as cw from "@distilled.cloud/gcp/contentwarehouse_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8import { GcpEnvironment } from "@/GCP/Environment";
9
10const { test } = Test.make({ providers: GCP.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17// Document AI Warehouse is disabled on the testing project: calls fail with
18// ServiceDisabled "Document AI Warehouse API has not been used in project ...
19// before or it is disabled" (the service also needs per-project
20// provisioning). Set GCP_TEST_CONTENTWAREHOUSE=1 on a provisioned project.
21const runLifecycle =
22 !process.env.FAST && !!process.env.GCP_TEST_CONTENTWAREHOUSE;
23
24const location = "us";
25
26const waitUntilGone = (name: string) =>
27 cw.getProjectsLocationsDocuments({ name }).pipe(
28 Effect.as("found" as const),
29 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
30 Effect.repeat({
31 schedule: Schedule.spaced("1 second"),
32 until: (status) => status === "gone",
33 times: 10,
34 }),
35 );
36
37test.provider.skipIf(runLifecycle)(
38 "getProjectsLocationsDocuments without Document AI Warehouse enabled fails with ServiceDisabled",
39 (stack) =>
40 Effect.gen(function* () {
41 const { project } = yield* GcpEnvironment.current;
42 const parent = `projects/${project}/locations/${location}`;
43 yield* stack.destroy();
44
45 const error = yield* Effect.flip(
46 cw.getProjectsLocationsDocuments({
47 name: `${parent}/documents/alchemy-missing-document`,
48 }),
49 );
50 expect(error._tag).toEqual("ServiceDisabled");
51
52 yield* stack.destroy();
53 }).pipe(logLevel),
54 {
55 tags: ["provider:gcp", "provider:gcp:contentwarehouse", "live"],
56 timeout: 90_000,
57 },
58);
59
60test.provider.skipIf(!runLifecycle)(
61 "create, update, and delete a document",
62 (stack) =>
63 Effect.gen(function* () {
64 const { project } = yield* GcpEnvironment.current;
65 const parent = `projects/${project}/locations/${location}`;
66 yield* stack.destroy();
67
68 const created = yield* stack.deploy(
69 Effect.gen(function* () {
70 const schema = yield* GCP.ContentWarehouse.DocumentSchema("Note", {
71 location,
72 displayName: "note",
73 propertyDefinitions: [
74 {
75 name: "title",
76 isSearchable: true,
77 textTypeOptions: {},
78 },
79 ],
80 });
81 const document = yield* GCP.ContentWarehouse.Document("Welcome", {
82 location,
83 documentSchemaName: schema.name,
84 displayName: "welcome",
85 title: "welcome",
86 plainText: "hello warehouse",
87 });
88 return { schema, document };
89 }),
90 );
91
92 expect(created.document.name).toContain("/documents/");
93 expect(created.document.documentId).toEqual(expect.any(String));
94 expect(created.document.displayName).toEqual("welcome");
95 expect(created.document.plainText).toEqual("hello warehouse");
96 expect(created.document.documentSchemaName).toEqual(created.schema.name);
97
98 const fetched = yield* cw.getProjectsLocationsDocuments({
99 name: created.document.name,
100 });
101 expect(fetched.name).toEqual(created.document.name);
102 expect(fetched.displayName).toEqual(created.document.displayName);
103 expect(fetched.plainText).toEqual("hello warehouse");
104
105 const updated = yield* stack.deploy(
106 Effect.gen(function* () {
107 const schema = yield* GCP.ContentWarehouse.DocumentSchema("Note", {
108 documentSchemaId: created.schema.documentSchemaId,
109 location,
110 displayName: "note",
111 propertyDefinitions: [
112 {
113 name: "title",
114 isSearchable: true,
115 textTypeOptions: {},
116 },
117 ],
118 });
119 const document = yield* GCP.ContentWarehouse.Document("Welcome", {
120 documentId: created.document.documentId,
121 referenceId: created.document.referenceId,
122 location,
123 documentSchemaName: schema.name,
124 displayName: "welcome-v2",
125 title: "welcome v2",
126 plainText: "hello again",
127 });
128 return { schema, document };
129 }),
130 );
131
132 expect(updated.document.name).toEqual(created.document.name);
133 expect(updated.document.displayName).toEqual("welcome-v2");
134 expect(updated.document.plainText).toEqual("hello again");
135
136 yield* stack.destroy();
137 const gone = yield* waitUntilGone(created.document.name);
138 expect(gone).toEqual("gone");
139 }).pipe(logLevel),
140 {
141 tags: ["provider:gcp", "provider:gcp:contentwarehouse", "live"],
142 timeout: 90_000,
143 },
144);