1import * as GCP from "@/GCP";
2import * as Output from "@/Output";
3import * as Test from "@/Test/Alchemy";
4import * as cloudchannel from "@distilled.cloud/gcp/cloudchannel_v1";
5import { expect } from "alchemy-test";
6import * as Effect from "effect/Effect";
7import {
8 logLevel,
9 probeAccountName,
10 runLifecycle,
11 waitUntilCustomerRepricingGone,
12} from "./common.ts";
13
14const { test } = Test.make({ providers: GCP.providers() });
15
16const probeParent = `${probeAccountName}/customers/alchemy-missing`;
17const probeMonth = { year: 2099, month: 1, day: 0 };
18
19test.provider(
20 "getAccountsCustomersCustomerRepricingConfigs on a missing config fails with a typed tag",
21 (stack) =>
22 Effect.gen(function* () {
23 yield* stack.destroy();
24
25 const error = yield* Effect.flip(
26 cloudchannel.getAccountsCustomersCustomerRepricingConfigs({
27 name: `${probeParent}/customerRepricingConfigs/alchemy-missing`,
28 }),
29 );
30 expect(error._tag).toEqual("Forbidden");
31
32 yield* stack.destroy();
33 }).pipe(logLevel),
34 {
35 tags: ["provider:gcp", "provider:gcp:cloudchannel", "live"],
36 timeout: 90_000,
37 },
38);
39
40test.provider.skipIf(runLifecycle)(
41 "createAccountsCustomersCustomerRepricingConfigs without Cloud Channel access fails with a typed entitlement error",
42 (stack) =>
43 Effect.gen(function* () {
44 yield* stack.destroy();
45
46 const error = yield* Effect.flip(
47 cloudchannel.createAccountsCustomersCustomerRepricingConfigs({
48 parent: probeParent,
49 body: {
50 repricingConfig: {
51 effectiveInvoiceMonth: probeMonth,
52 rebillingBasis: "COST_AT_LIST",
53 adjustment: {
54 percentageAdjustment: { percentage: { value: "0.00" } },
55 },
56 entitlementGranularity: {
57 entitlement: `${probeParent}/entitlements/alchemy-missing`,
58 },
59 },
60 },
61 }),
62 );
63 expect(error._tag).toEqual("Forbidden");
64
65 yield* stack.destroy();
66 }).pipe(logLevel),
67 {
68 tags: ["provider:gcp", "provider:gcp:cloudchannel", "live"],
69 timeout: 90_000,
70 },
71);
72
73test.provider.skipIf(!runLifecycle)(
74 "create, update, and delete a customer repricing config",
75 (stack) =>
76 Effect.gen(function* () {
77 yield* stack.destroy();
78
79 const entitlement = process.env.GCP_CLOUDCHANNEL_ENTITLEMENT?.trim();
80
81 const created = yield* stack.deploy(
82 Effect.gen(function* () {
83 const customer = yield* GCP.CloudChannel.Customer("AcmeBill", {
84 parent: probeAccountName,
85 orgDisplayName: "Acme Billing",
86 });
87 const config =
88 yield* GCP.CloudChannel.CustomersCustomerRepricingConfig(
89 "AcmeRule",
90 {
91 parent: customer.name,
92 effectiveInvoiceMonth: probeMonth,
93 adjustmentPercentage: "0.00",
94 entitlement:
95 entitlement ??
96 Output.interpolate`${customer.name}/entitlements/alchemy`,
97 },
98 );
99 return { customer, config };
100 }),
101 );
102
103 expect(created.config.name).toContain("/customerRepricingConfigs/");
104 expect(created.config.parent).toEqual(created.customer.name);
105
106 const fetched =
107 yield* cloudchannel.getAccountsCustomersCustomerRepricingConfigs({
108 name: created.config.name,
109 });
110 expect(fetched.name).toEqual(created.config.name);
111
112 const updated = yield* stack.deploy(
113 Effect.gen(function* () {
114 const customer = yield* GCP.CloudChannel.Customer("AcmeBill", {
115 parent: probeAccountName,
116 customerId: created.customer.customerId,
117 orgDisplayName: "Acme Billing",
118 domain: created.customer.domain,
119 });
120 const config =
121 yield* GCP.CloudChannel.CustomersCustomerRepricingConfig(
122 "AcmeRule",
123 {
124 parent: customer.name,
125 configId: created.config.configId,
126 effectiveInvoiceMonth: probeMonth,
127 adjustmentPercentage: "1.00",
128 entitlement:
129 entitlement ??
130 Output.interpolate`${customer.name}/entitlements/alchemy`,
131 },
132 );
133 return { customer, config };
134 }),
135 );
136
137 expect(updated.config.name).toEqual(created.config.name);
138
139 yield* stack.destroy();
140
141 const gone = yield* waitUntilCustomerRepricingGone(created.config.name);
142 expect(gone).toEqual("gone");
143 }).pipe(logLevel),
144 {
145 tags: ["provider:gcp", "provider:gcp:cloudchannel", "live"],
146 timeout: 90_000,
147 },
148);