Skip to content

Commit 5f61141

Browse files
authored
test(region-provider): add extensive unit tests for region-provider (#1280)
1 parent d055da7 commit 5f61141

File tree

6 files changed

+360
-218
lines changed

6 files changed

+360
-218
lines changed
Lines changed: 50 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,72 @@
1-
import { defaultProvider } from "./defaultProvider";
2-
import { ProviderError } from "@aws-sdk/property-provider";
1+
import { fromEnv } from "./fromEnv";
2+
import { fromSharedConfigFiles } from "./fromSharedConfigFiles";
3+
import { chain, memoize } from "@aws-sdk/property-provider";
4+
import {
5+
defaultProvider,
6+
RegionProviderConfiguration
7+
} from "./defaultProvider";
38

4-
jest.mock("./fromEnv", () => {
5-
const envProvider = jest.fn();
6-
return {
7-
fromEnv: jest.fn().mockReturnValue(envProvider)
8-
};
9-
});
10-
import { fromEnv, EnvConfiguration } from "./fromEnv";
9+
jest.mock("./fromEnv", () => ({
10+
fromEnv: jest.fn()
11+
}));
1112

12-
jest.mock("./fromSharedConfigFiles", () => {
13-
const iniProvider = jest.fn();
14-
return {
15-
fromSharedConfigFiles: jest.fn().mockReturnValue(iniProvider)
16-
};
17-
});
18-
import {
19-
fromSharedConfigFiles,
20-
SharedConfigInit
21-
} from "./fromSharedConfigFiles";
13+
jest.mock("./fromSharedConfigFiles", () => ({
14+
fromSharedConfigFiles: jest.fn()
15+
}));
2216

23-
beforeEach(() => {
24-
(fromEnv() as any).mockClear();
25-
(fromSharedConfigFiles() as any).mockClear();
26-
(fromEnv as any).mockClear();
27-
(fromSharedConfigFiles as any).mockClear();
28-
});
17+
jest.mock("@aws-sdk/property-provider", () => ({
18+
chain: jest.fn(),
19+
memoize: jest.fn()
20+
}));
2921

3022
describe("defaultProvider", () => {
31-
it("should stop after the environmental provider if a region has been found", async () => {
32-
const region = "foo";
33-
(fromEnv() as any).mockImplementation(() => Promise.resolve(region));
23+
const configuration: RegionProviderConfiguration = {
24+
profile: "profile",
25+
environmentVariableName: "environmentVariableName"
26+
};
3427

35-
expect(await defaultProvider()()).toEqual(region);
36-
expect((fromEnv() as any).mock.calls.length).toBe(1);
37-
expect((fromSharedConfigFiles() as any).mock.calls.length).toBe(0);
28+
afterEach(() => {
29+
jest.clearAllMocks();
3830
});
3931

40-
it("should continue on to the ini provider if no environment variable region has been found", async () => {
41-
const region = "foo";
32+
it("passes fromEnv() and fromSharedConfigFiles() to chain", () => {
33+
const mockFromEnvReturn = "mockFromEnvReturn";
34+
(fromEnv as jest.Mock).mockReturnValueOnce(mockFromEnvReturn);
4235

43-
(fromEnv() as any).mockImplementation(() =>
44-
Promise.reject(new ProviderError("Nothing here!"))
36+
const mockFromSharedConfigFilesReturn = "mockFromSharedConfigFilesReturn";
37+
(fromSharedConfigFiles as jest.Mock).mockReturnValueOnce(
38+
mockFromSharedConfigFilesReturn
4539
);
46-
(fromSharedConfigFiles() as any).mockImplementation(() =>
47-
Promise.resolve(region)
48-
);
49-
50-
expect(await defaultProvider()()).toEqual(region);
51-
expect((fromEnv() as any).mock.calls.length).toBe(1);
52-
expect((fromSharedConfigFiles() as any).mock.calls.length).toBe(1);
53-
});
54-
55-
it("should pass configuration on to the env provider", async () => {
56-
const envConfig: EnvConfiguration = {
57-
environmentVariableName: "foo"
58-
};
59-
60-
(fromEnv() as any).mockImplementation(() => Promise.resolve("region"));
61-
(fromEnv as any).mockClear();
6240

63-
await expect(defaultProvider(envConfig)()).resolves;
64-
65-
expect((fromEnv as any).mock.calls.length).toBe(1);
66-
expect((fromEnv as any).mock.calls[0][0]).toBe(envConfig);
67-
});
41+
defaultProvider(configuration);
6842

69-
it("should pass configuration on to the ini provider", async () => {
70-
const iniConfig: SharedConfigInit = {
71-
profile: "foo",
72-
filepath: "/home/user/.secrets/credentials.ini",
73-
configFilepath: "/home/user/.secrets/credentials.ini"
74-
};
43+
expect(fromEnv).toHaveBeenCalledTimes(1);
44+
expect(fromEnv).toHaveBeenCalledWith(configuration);
45+
expect(fromSharedConfigFiles).toHaveBeenCalledTimes(1);
46+
expect(fromSharedConfigFiles).toHaveBeenCalledWith(configuration);
7547

76-
(fromEnv() as any).mockImplementation(() =>
77-
Promise.reject(new ProviderError("Keep moving!"))
48+
expect(chain).toHaveBeenCalledTimes(1);
49+
expect(chain).toHaveBeenCalledWith(
50+
mockFromEnvReturn,
51+
mockFromSharedConfigFilesReturn
7852
);
79-
(fromSharedConfigFiles() as any).mockImplementation(() =>
80-
Promise.resolve("region")
81-
);
82-
83-
(fromSharedConfigFiles as any).mockClear();
84-
85-
await expect(defaultProvider(iniConfig)()).resolves;
86-
87-
expect((fromSharedConfigFiles as any).mock.calls.length).toBe(1);
88-
expect((fromSharedConfigFiles as any).mock.calls[0][0]).toBe(iniConfig);
8953
});
9054

91-
it("should return the same promise across invocations", async () => {
92-
const region = "foo";
93-
(fromEnv() as any).mockImplementation(() => Promise.resolve(region));
55+
it("passes output of chain to memoize", () => {
56+
const mockChainReturn = "mockChainReturn";
57+
(chain as jest.Mock).mockReturnValueOnce(mockChainReturn);
9458

95-
const provider = defaultProvider();
59+
defaultProvider(configuration);
9660

97-
expect(await provider()).toEqual(region);
61+
expect(chain).toHaveBeenCalledTimes(1);
62+
expect(memoize).toHaveBeenCalledTimes(1);
63+
expect(memoize).toHaveBeenCalledWith(mockChainReturn);
64+
});
9865

99-
expect(provider()).toBe(provider());
66+
it("returns output memoize", () => {
67+
const mockMemoizeReturn = "mockMemoizeReturn";
68+
(memoize as jest.Mock).mockReturnValueOnce(mockMemoizeReturn);
10069

101-
expect(await provider()).toEqual(region);
102-
expect((fromEnv() as any).mock.calls.length).toBe(1);
70+
expect(defaultProvider(configuration)).toEqual(mockMemoizeReturn);
10371
});
10472
});

packages/region-provider/src/defaultProvider.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ import { Provider } from "@aws-sdk/types";
88

99
export type RegionProviderConfiguration = EnvConfiguration & SharedConfigInit;
1010

11-
export function defaultProvider(
11+
export const defaultProvider = (
1212
configuration: RegionProviderConfiguration = {}
13-
): Provider<string> {
14-
return memoize(
15-
chain(fromEnv(configuration), fromSharedConfigFiles(configuration))
16-
);
17-
}
13+
): Provider<string> =>
14+
memoize(chain(fromEnv(configuration), fromSharedConfigFiles(configuration)));

packages/region-provider/src/fromEnv.spec.ts

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,81 @@ import { ProviderError } from "@aws-sdk/property-provider";
44
describe("fromEnv", () => {
55
const ENV_CUSTOM = "AWS_DEFAULT_REGION";
66
const envRegion = process.env[ENV_REGION];
7-
const customEnv = process.env[ENV_CUSTOM];
7+
const envCustom = process.env[ENV_CUSTOM];
8+
const mockEnvRegion = "mockEnvRegion";
9+
const mockEnvCustom = "mockEnvCustom";
10+
11+
const getProviderError = (envVarName: string) =>
12+
new ProviderError(
13+
`No value defined for the ${envVarName} environment variable`
14+
);
815

916
beforeEach(() => {
1017
delete process.env[ENV_REGION];
1118
delete process.env[ENV_CUSTOM];
1219
});
1320

1421
afterAll(() => {
15-
process.env[ENV_CUSTOM] = customEnv;
22+
process.env[ENV_CUSTOM] = envCustom;
1623
process.env[ENV_REGION] = envRegion;
1724
});
1825

19-
it(`should read from the ${ENV_REGION} environment variable`, async () => {
20-
process.env[ENV_REGION] = "us-north-12";
21-
expect(await fromEnv()()).toBe(process.env[ENV_REGION]);
22-
});
26+
describe("when no value is passed", () => {
27+
it(`returns value in '${ENV_REGION}' env var when set`, () => {
28+
process.env[ENV_REGION] = mockEnvRegion;
29+
return expect(fromEnv()()).resolves.toBe(mockEnvRegion);
30+
});
2331

24-
it(`should reject the promise is ${ENV_REGION} is not set`, async () => {
25-
await expect(fromEnv()()).rejects.toMatchObject(
26-
new ProviderError(
27-
`No value defined for the AWS_REGION environment variable`
28-
)
29-
);
32+
it(`throws when '${ENV_REGION}' env var is not set`, () => {
33+
return expect(fromEnv()()).rejects.toMatchObject(
34+
getProviderError(ENV_REGION)
35+
);
36+
});
3037
});
3138

32-
it("should allow specifying custom environment variables", async () => {
33-
process.env[ENV_CUSTOM] = "eu-central-35";
34-
expect(process.env[ENV_REGION]).toBeUndefined();
35-
expect(await fromEnv({ environmentVariableName: ENV_CUSTOM })()).toBe(
36-
process.env[ENV_CUSTOM]
37-
);
39+
describe(`when custom env var '${ENV_CUSTOM}' is passed`, () => {
40+
describe(`returns value in '${ENV_CUSTOM}' env var when set`, () => {
41+
const environmentVariableName = ENV_CUSTOM;
42+
43+
beforeEach(() => {
44+
process.env[environmentVariableName] = mockEnvCustom;
45+
expect(process.env[ENV_REGION]).toBeUndefined();
46+
});
47+
48+
it(`when '${ENV_REGION}' is set`, () => {
49+
process.env[ENV_REGION] = mockEnvRegion;
50+
return expect(fromEnv({ environmentVariableName })()).resolves.toBe(
51+
mockEnvCustom
52+
);
53+
});
54+
55+
it(`when '${ENV_REGION}' is not set`, () => {
56+
return expect(fromEnv({ environmentVariableName })()).resolves.toBe(
57+
mockEnvCustom
58+
);
59+
});
60+
});
61+
62+
describe(`throws when '${ENV_CUSTOM}' env var is not set`, () => {
63+
const environmentVariableName = ENV_CUSTOM;
64+
65+
beforeEach(() => {
66+
delete process.env[environmentVariableName];
67+
expect(process.env[ENV_REGION]).toBeUndefined();
68+
});
69+
70+
it(`when '${ENV_REGION}' is set`, () => {
71+
process.env[ENV_REGION] = mockEnvRegion;
72+
return expect(
73+
fromEnv({ environmentVariableName })()
74+
).rejects.toMatchObject(getProviderError(environmentVariableName));
75+
});
76+
77+
it(`when '${ENV_REGION}' is not set`, () => {
78+
return expect(
79+
fromEnv({ environmentVariableName })()
80+
).rejects.toMatchObject(getProviderError(environmentVariableName));
81+
});
82+
});
3883
});
3984
});

packages/region-provider/src/fromEnv.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@ export interface EnvConfiguration {
77
environmentVariableName?: string;
88
}
99

10-
export function fromEnv({
10+
export const fromEnv = ({
1111
environmentVariableName = ENV_REGION
12-
}: EnvConfiguration = {}): Provider<string> {
13-
return async () => {
14-
const envRegion = process.env[environmentVariableName];
15-
if (envRegion) {
16-
return envRegion;
17-
}
12+
}: EnvConfiguration = {}): Provider<string> => async () => {
13+
const envRegion = process.env[environmentVariableName];
14+
if (envRegion) {
15+
return envRegion;
16+
}
1817

19-
throw new ProviderError(
20-
`No value defined for the ${environmentVariableName} environment variable`
21-
);
22-
};
23-
}
18+
throw new ProviderError(
19+
`No value defined for the ${environmentVariableName} environment variable`
20+
);
21+
};

0 commit comments

Comments
 (0)