1import {
2 applyEnvRegionOverride,
3 parseAwsSsoLoginOutput,
4} from "@/AWS/AuthProvider.ts";
5import { loadConfigProvider } from "@/Util/ConfigProvider.ts";
6import { PlatformServices } from "@/Util/PlatformServices.ts";
7import { describe, expect, it } from "alchemy-test";
8import * as ConfigProvider from "effect/ConfigProvider";
9import * as Effect from "effect/Effect";
10import * as FileSystem from "effect/FileSystem";
11import * as Option from "effect/Option";
12import * as Path from "effect/Path";
13
14const withEnv = (env: Record<string, string>) =>
15 Effect.provide(ConfigProvider.layer(ConfigProvider.fromEnv({ env })));
16
17// Simulates credentials resolved from an SSO profile whose ~/.aws/config
18// region differs from the region the user explicitly set in the environment.
19const profileCreds = { accountId: "123456789012", region: "us-west-2" };
20
21describe(
22 "parseAwsSsoLoginOutput",
23 { tags: ["unit", "provider:aws", "local"] },
24 () => {
25 it("reads browser authorization JSON", () => {
26 expect(
27 parseAwsSsoLoginOutput(
28 JSON.stringify({
29 authorizationUrl: "https://oidc.example.com/authorize?state=abc",
30 }),
31 ),
32 ).toEqual({
33 url: "https://oidc.example.com/authorize?state=abc",
34 code: undefined,
35 });
36 });
37
38 it("reads the text AWS emits despite --output json", () => {
39 expect(
40 parseAwsSsoLoginOutput(`Browser will not be automatically opened.
41Please visit the following URL:
42
43https://example.awsapps.com/start/#/device
44
45Then enter the code:
46
47CRKF-LVXR`),
48 ).toEqual({
49 url: "https://example.awsapps.com/start/#/device",
50 code: "CRKF-LVXR",
51 });
52 });
53 },
54);
55
56describe(
57 "applyEnvRegionOverride",
58 { tags: ["unit", "provider:aws", "local"] },
59 () => {
60 it.effect("AWS_REGION overrides the profile region", () =>
61 Effect.gen(function* () {
62 const creds = yield* applyEnvRegionOverride(profileCreds);
63 expect(creds.region).toBe("us-east-2");
64 expect(creds.accountId).toBe("123456789012");
65 }).pipe(withEnv({ AWS_REGION: "us-east-2" })),
66 );
67
68 // AWS_DEFAULT_REGION is a default, not an override — the profile's region
69 // is explicit configuration and must win over it.
70 it.effect("AWS_DEFAULT_REGION does NOT override the profile region", () =>
71 Effect.gen(function* () {
72 const creds = yield* applyEnvRegionOverride(profileCreds);
73 expect(creds.region).toBe("us-west-2");
74 }).pipe(withEnv({ AWS_DEFAULT_REGION: "eu-west-1" })),
75 );
76
77 it.effect("falls back to the profile region when no env is set", () =>
78 Effect.gen(function* () {
79 const creds = yield* applyEnvRegionOverride(profileCreds);
80 expect(creds.region).toBe("us-west-2");
81 }).pipe(withEnv({})),
82 );
83
84 it.effect(
85 "process environment overrides the default dotenv region",
86 () =>
87 Effect.scoped(
88 Effect.gen(function* () {
89 const fs = yield* FileSystem.FileSystem;
90 const path = yield* Path.Path;
91 const tempDir = yield* fs.makeTempDirectoryScoped({
92 prefix: "alchemy-config-provider-",
93 });
94 yield* fs.writeFileString(
95 path.join(tempDir, ".env"),
96 "AWS_REGION=ap-south-1\n",
97 );
98
99 const originalCwd = process.cwd();
100 const originalRegion = process.env.AWS_REGION;
101 yield* Effect.gen(function* () {
102 yield* Effect.sync(() => {
103 process.chdir(tempDir);
104 process.env.AWS_REGION = "us-east-1";
105 });
106
107 const configProvider = yield* loadConfigProvider(Option.none());
108 const creds = yield* applyEnvRegionOverride({
109 accountId: "654654387918",
110 region: "us-west-2",
111 }).pipe(Effect.provide(ConfigProvider.layer(configProvider)));
112 expect(creds.region).toBe("us-east-1");
113 expect(creds.accountId).toBe("654654387918");
114 }).pipe(
115 Effect.ensuring(
116 Effect.sync(() => {
117 process.chdir(originalCwd);
118 if (originalRegion === undefined) {
119 delete process.env.AWS_REGION;
120 } else {
121 process.env.AWS_REGION = originalRegion;
122 }
123 }),
124 ),
125 );
126 }),
127 ).pipe(Effect.provide(PlatformServices)),
128 { exclusive: true },
129 );
130 },
131);