1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as jobs from "@distilled.cloud/gcp/jobs_v4";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import * as Schedule from "effect/Schedule";
7import { logLevel, currentProject, runLifecycle } from "./common.ts";
8
9const { test } = Test.make({ providers: GCP.providers() });
10
11const waitUntilGone = (name: string) =>
12 jobs.getProjectsTenantsCompanies({ name }).pipe(
13 Effect.as("found" as const),
14 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
15 Effect.repeat({
16 schedule: Schedule.spaced("1 second"),
17 until: (status) => status === "gone",
18 times: 10,
19 }),
20 );
21
22test.provider.skipIf(!runLifecycle)(
23 "getProjectsTenantsCompanies on a missing company fails with a typed tag",
24 (stack) =>
25 Effect.gen(function* () {
26 const project = yield* currentProject;
27 yield* stack.destroy();
28
29 const error = yield* Effect.flip(
30 jobs.getProjectsTenantsCompanies({
31 name: `projects/${project}/tenants/alchemy-missing/companies/alchemy-missing`,
32 }),
33 );
34 expect(error._tag).toEqual("NotFound");
35
36 yield* stack.destroy();
37 }).pipe(logLevel),
38 { tags: ["provider:gcp", "provider:gcp:jobs", "live"], timeout: 90_000 },
39);
40
41test.provider.skipIf(runLifecycle)(
42 "createProjectsTenantsCompanies fails with TalentDataPermissionRequired until onboarded",
43 (stack) =>
44 Effect.gen(function* () {
45 const project = yield* currentProject;
46 yield* stack.destroy();
47
48 const error = yield* Effect.flip(
49 jobs.createProjectsTenantsCompanies({
50 parent: `projects/${project}/tenants/alchemy-missing`,
51 body: {
52 externalId: "alchemy-company-probe",
53 displayName: "Alchemy Probe",
54 },
55 }),
56 );
57 expect(error._tag).toEqual("TalentDataPermissionRequired");
58
59 yield* stack.destroy();
60 }).pipe(logLevel),
61 { tags: ["provider:gcp", "provider:gcp:jobs", "live"], timeout: 90_000 },
62);
63
64test.provider.skipIf(!runLifecycle)(
65 "create, update, and delete a company",
66 (stack) =>
67 Effect.gen(function* () {
68 yield* stack.destroy();
69
70 const created = yield* stack.deploy(
71 Effect.gen(function* () {
72 const tenant = yield* GCP.Jobs.Tenant("AcmeCo", {
73 externalId: "acme-company-tenant",
74 });
75 const company = yield* GCP.Jobs.TenantsCompany("Labs", {
76 parent: tenant.name,
77 externalId: "acme-labs",
78 displayName: "Acme Labs",
79 websiteUri: "https://www.example.com",
80 });
81 return { tenant, company };
82 }),
83 );
84
85 expect(created.company.name).toContain("/companies/");
86 expect(created.company.parent).toEqual(created.tenant.name);
87 expect(created.company.externalId).toEqual("acme-labs");
88 expect(created.company.displayName).toEqual("Acme Labs");
89 expect(created.company.websiteUri).toEqual("https://www.example.com");
90
91 const fetched = yield* jobs.getProjectsTenantsCompanies({
92 name: created.company.name,
93 });
94 expect(fetched.name).toEqual(created.company.name);
95 expect(fetched.displayName).toEqual("Acme Labs");
96 expect(fetched.websiteUri).toEqual("https://www.example.com");
97
98 const updated = yield* stack.deploy(
99 Effect.gen(function* () {
100 const tenant = yield* GCP.Jobs.Tenant("AcmeCo", {
101 tenantId: created.tenant.tenantId,
102 externalId: "acme-company-tenant",
103 });
104 const company = yield* GCP.Jobs.TenantsCompany("Labs", {
105 parent: tenant.name,
106 companyId: created.company.companyId,
107 externalId: "acme-labs",
108 displayName: "Acme Research",
109 websiteUri: "https://careers.example.com",
110 headquartersAddress: "Mountain View, CA",
111 });
112 return { tenant, company };
113 }),
114 );
115
116 expect(updated.company.name).toEqual(created.company.name);
117 expect(updated.company.displayName).toEqual("Acme Research");
118 expect(updated.company.websiteUri).toEqual("https://careers.example.com");
119 expect(updated.company.headquartersAddress).toEqual("Mountain View, CA");
120
121 yield* stack.destroy();
122
123 const gone = yield* waitUntilGone(created.company.name);
124 expect(gone).toEqual("gone");
125 }).pipe(logLevel),
126 { tags: ["provider:gcp", "provider:gcp:jobs", "live"], timeout: 90_000 },
127);