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