1import * as Provider from "@/Provider";
2import * as Stripe from "@/Stripe";
3import * as Test from "@/Test/Alchemy";
4import {
5 GetTaxRegistration,
6 GetTaxSettings,
7 CreateTaxSettings,
8} from "@distilled.cloud/stripe/stripe";
9import { expect } from "alchemy-test";
10import * as Effect from "effect/Effect";
11import { MinimumLogLevel } from "effect/References";
12import * as Schedule from "effect/Schedule";
13import { isMissingStripeResource } from "@/Stripe/missing.ts";
14
15const { test } = Test.make({ providers: Stripe.providers() });
16
17const logLevel = Effect.provideService(
18 MinimumLogLevel,
19 process.env.DEBUG ? "Debug" : "Info",
20);
21
22const isMissing = isMissingStripeResource;
23
24const FAR_FUTURE = 1_893_456_000; // 2030-01-01T00:00:00Z
25
26const ensureHeadOffice = Effect.gen(function* () {
27 const settings = yield* GetTaxSettings({});
28 if (settings.head_office != null) return;
29 yield* CreateTaxSettings({
30 head_office: {
31 address: {
32 country: "US",
33 line1: "123 Market St",
34 city: "San Francisco",
35 state: "CA",
36 postal_code: "94105",
37 },
38 },
39 });
40});
41
42const waitUntilExpired = (id: string) =>
43 GetTaxRegistration({ id }).pipe(
44 Effect.map((registration) =>
45 registration.status === "expired"
46 ? ("expired" as const)
47 : ("active" as const),
48 ),
49 Effect.catchIf(isMissing, () => Effect.succeed("expired" as const)),
50 Effect.repeat({
51 schedule: Schedule.spaced("1 second"),
52 until: (status) => status === "expired",
53 times: 10,
54 }),
55 );
56
57test.provider(
58 "create, update, and expire a tax registration",
59 (stack) =>
60 Effect.gen(function* () {
61 yield* stack.destroy();
62 yield* ensureHeadOffice;
63
64 const created = yield* stack.deploy(
65 Effect.gen(function* () {
66 return yield* Stripe.TaxRegistration("LifecycleReg", {
67 country: "TJ",
68 countryOptions: { tj: { type: "simplified" } },
69 });
70 }),
71 );
72
73 expect(created.id).toMatch(/^taxreg_/);
74 expect(created.country).toEqual("TJ");
75 expect(created.countryOptions.tj?.type).toEqual("simplified");
76 expect(created.status).toEqual("active");
77 expect(created.expiresAt).toBeUndefined();
78 expect(created.activeFrom).toEqual(expect.any(Number));
79 expect(created.created).toEqual(expect.any(Number));
80 expect(created.livemode).toEqual(false);
81
82 const fetched = yield* GetTaxRegistration({ id: created.id });
83 expect(fetched.id).toEqual(created.id);
84 expect(fetched.country).toEqual("TJ");
85 expect(fetched.country_options.tj?.type).toEqual("simplified");
86 expect(fetched.status).toEqual("active");
87 expect(fetched.expires_at).toBeNull();
88
89 const updated = yield* stack.deploy(
90 Effect.gen(function* () {
91 return yield* Stripe.TaxRegistration("LifecycleReg", {
92 country: "TJ",
93 countryOptions: { tj: { type: "simplified" } },
94 expiresAt: FAR_FUTURE,
95 });
96 }),
97 );
98
99 expect(updated.id).toEqual(created.id);
100 expect(updated.country).toEqual("TJ");
101 expect(updated.expiresAt).toEqual(FAR_FUTURE);
102 expect(updated.status).toEqual("active");
103
104 const refetched = yield* GetTaxRegistration({ id: updated.id });
105 expect(refetched.id).toEqual(updated.id);
106 expect(refetched.expires_at).toEqual(FAR_FUTURE);
107 expect(refetched.status).toEqual("active");
108
109 yield* stack.destroy();
110
111 const expired = yield* waitUntilExpired(created.id);
112 expect(expired).toEqual("expired");
113 const deactivated = yield* GetTaxRegistration({ id: created.id });
114 expect(deactivated.status).toEqual("expired");
115 }).pipe(logLevel),
116 {
117 tags: [
118 "provider:stripe",
119 "provider:stripe:taxregistration",
120 "provider:stripe:taxsettings",
121 "live",
122 ],
123 timeout: 120_000,
124 },
125);
126
127test.provider(
128 "list enumerates the deployed tax registration",
129 (stack) =>
130 Effect.gen(function* () {
131 yield* stack.destroy();
132 yield* ensureHeadOffice;
133
134 const deployed = yield* stack.deploy(
135 Effect.gen(function* () {
136 return yield* Stripe.TaxRegistration("ListReg", {
137 country: "ZM",
138 countryOptions: { zm: { type: "simplified" } },
139 });
140 }),
141 );
142
143 const provider = yield* Provider.findProvider(Stripe.TaxRegistration);
144 const all = yield* provider.list();
145 const found = all.find((registration) => registration.id === deployed.id);
146 expect(found).toBeDefined();
147 expect(found?.country).toEqual("ZM");
148 expect(found?.countryOptions.zm?.type).toEqual("simplified");
149 expect(found?.status).toEqual("active");
150
151 yield* stack.destroy();
152
153 const expired = yield* waitUntilExpired(deployed.id);
154 expect(expired).toEqual("expired");
155 }).pipe(logLevel),
156 {
157 tags: [
158 "provider:stripe",
159 "provider:stripe:taxregistration",
160 "provider:stripe:taxsettings",
161 "live",
162 ],
163 timeout: 120_000,
164 },
165);
166
167test.provider(
168 "replace when country changes",
169 (stack) =>
170 Effect.gen(function* () {
171 yield* stack.destroy();
172 yield* ensureHeadOffice;
173
174 const created = yield* stack.deploy(
175 Effect.gen(function* () {
176 return yield* Stripe.TaxRegistration("ReplaceReg", {
177 country: "SR",
178 countryOptions: { sr: { type: "standard" } },
179 });
180 }),
181 );
182
183 expect(created.country).toEqual("SR");
184
185 const replaced = yield* stack.deploy(
186 Effect.gen(function* () {
187 return yield* Stripe.TaxRegistration("ReplaceReg", {
188 country: "UZ",
189 countryOptions: { uz: { type: "simplified" } },
190 });
191 }),
192 );
193
194 expect(replaced.id).not.toEqual(created.id);
195 expect(replaced.country).toEqual("UZ");
196 expect(replaced.countryOptions.uz?.type).toEqual("simplified");
197
198 const fetched = yield* GetTaxRegistration({ id: replaced.id });
199 expect(fetched.id).toEqual(replaced.id);
200 expect(fetched.country).toEqual("UZ");
201
202 const oldExpired = yield* waitUntilExpired(created.id);
203 expect(oldExpired).toEqual("expired");
204
205 yield* stack.destroy();
206
207 const gone = yield* waitUntilExpired(replaced.id);
208 expect(gone).toEqual("expired");
209 }).pipe(logLevel),
210 {
211 tags: [
212 "provider:stripe",
213 "provider:stripe:taxregistration",
214 "provider:stripe:taxsettings",
215 "live",
216 ],
217 timeout: 120_000,
218 },
219);