Skip to content

Commit 1c3a1ff

Browse files
CCM-12875: Added more tests for coverage
1 parent 07cc3a5 commit 1c3a1ff

File tree

3 files changed

+220
-1
lines changed

3 files changed

+220
-1
lines changed

lambdas/pdm-mock-api/jest.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ const config: Config = {
2424
},
2525

2626
moduleNameMapper: {
27+
'^utils$': '<rootDir>/../../utils/utils',
2728
'^handlers$': '<rootDir>/src/handlers',
28-
'^utils$': '<rootDir>/src/utils',
2929
'^container$': '<rootDir>/src/container',
30+
'^config$': '<rootDir>/src/config',
3031
'^authenticator$': '<rootDir>/src/authenticator',
3132
},
3233
};
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import { ParameterStoreService, loadConfig } from 'config';
2+
3+
describe('Config', () => {
4+
const originalEnv = process.env;
5+
6+
beforeEach(() => {
7+
jest.resetModules();
8+
process.env = { ...originalEnv };
9+
});
10+
11+
afterAll(() => {
12+
process.env = originalEnv;
13+
});
14+
15+
describe('loadConfig', () => {
16+
it('should load config with default values', () => {
17+
delete process.env.MOCK_ACCESS_TOKEN;
18+
delete process.env.ACCESS_TOKEN_SSM_PATH;
19+
delete process.env.USE_NON_MOCK_TOKEN;
20+
delete process.env.LOG_LEVEL;
21+
22+
const config = loadConfig();
23+
24+
expect(config.mockAccessToken).toBe('mock-token-for-local-dev');
25+
expect(config.accessTokenSsmPath).toBe('/mock/access-token');
26+
expect(config.useNonMockToken).toBe(false);
27+
expect(config.logLevel).toBe('INFO');
28+
});
29+
30+
it('should load config from environment variables', () => {
31+
process.env.MOCK_ACCESS_TOKEN = 'custom-token';
32+
process.env.ACCESS_TOKEN_SSM_PATH = '/custom/path';
33+
process.env.USE_NON_MOCK_TOKEN = 'true';
34+
process.env.LOG_LEVEL = 'DEBUG';
35+
36+
const config = loadConfig();
37+
38+
expect(config.mockAccessToken).toBe('custom-token');
39+
expect(config.accessTokenSsmPath).toBe('/custom/path');
40+
expect(config.useNonMockToken).toBe(true);
41+
expect(config.logLevel).toBe('DEBUG');
42+
});
43+
44+
it('should parse boolean environment variables correctly', () => {
45+
process.env.USE_NON_MOCK_TOKEN = 'TRUE';
46+
let config = loadConfig();
47+
expect(config.useNonMockToken).toBe(true);
48+
49+
process.env.USE_NON_MOCK_TOKEN = 'false';
50+
config = loadConfig();
51+
expect(config.useNonMockToken).toBe(false);
52+
53+
process.env.USE_NON_MOCK_TOKEN = 'FALSE';
54+
config = loadConfig();
55+
expect(config.useNonMockToken).toBe(false);
56+
});
57+
58+
it('should throw error for missing required env var without default', () => {
59+
const config = loadConfig();
60+
expect(config).toBeDefined();
61+
});
62+
});
63+
64+
describe('ParameterStoreService', () => {
65+
let service: ParameterStoreService;
66+
67+
beforeEach(() => {
68+
service = new ParameterStoreService();
69+
});
70+
71+
it('should create an instance', () => {
72+
expect(service).toBeInstanceOf(ParameterStoreService);
73+
});
74+
75+
it('should cache parameter values', async () => {
76+
const mockParameter = 'test-value';
77+
const mockSend = jest.fn().mockResolvedValue({
78+
Parameter: { Value: mockParameter },
79+
});
80+
81+
(service as any).ssmClient = {
82+
send: mockSend,
83+
};
84+
85+
const result1 = await service.getParameter('/test/path');
86+
expect(result1).toBe(mockParameter);
87+
expect(mockSend).toHaveBeenCalledTimes(1);
88+
89+
const result2 = await service.getParameter('/test/path');
90+
expect(result2).toBe(mockParameter);
91+
expect(mockSend).toHaveBeenCalledTimes(1);
92+
});
93+
94+
it('should refresh cache after TTL expires', async () => {
95+
const mockParameter = 'test-value';
96+
const mockSend = jest.fn().mockResolvedValue({
97+
Parameter: { Value: mockParameter },
98+
});
99+
100+
(service as any).ssmClient = {
101+
send: mockSend,
102+
};
103+
104+
(service as any).cacheTtl = 10;
105+
106+
await service.getParameter('/test/path');
107+
expect(mockSend).toHaveBeenCalledTimes(1);
108+
109+
await new Promise((resolve) => {
110+
setTimeout(resolve, 20);
111+
});
112+
113+
await service.getParameter('/test/path');
114+
expect(mockSend).toHaveBeenCalledTimes(2);
115+
});
116+
117+
it('should throw error when parameter is not found', async () => {
118+
const mockSend = jest.fn().mockResolvedValue({
119+
Parameter: {},
120+
});
121+
122+
(service as any).ssmClient = {
123+
send: mockSend,
124+
};
125+
126+
await expect(service.getParameter('/missing/path')).rejects.toThrow(
127+
'Parameter /missing/path not found or has no value',
128+
);
129+
});
130+
131+
it('should handle SSM errors', async () => {
132+
const mockError = new Error('SSM error');
133+
const mockSend = jest.fn().mockRejectedValue(mockError);
134+
135+
(service as any).ssmClient = {
136+
send: mockSend,
137+
};
138+
139+
await expect(service.getParameter('/error/path')).rejects.toThrow(
140+
'SSM error',
141+
);
142+
});
143+
});
144+
});
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { createContainer } from 'container';
2+
3+
jest.mock('utils', () => ({
4+
logger: {
5+
debug: jest.fn(),
6+
info: jest.fn(),
7+
warn: jest.fn(),
8+
error: jest.fn(),
9+
child: jest.fn(),
10+
},
11+
}));
12+
13+
describe('Container', () => {
14+
let container: ReturnType<typeof createContainer>;
15+
16+
beforeEach(() => {
17+
jest.clearAllMocks();
18+
process.env.MOCK_ACCESS_TOKEN = 'test-token';
19+
process.env.ACCESS_TOKEN_SSM_PATH = '/test/path';
20+
process.env.USE_NON_MOCK_TOKEN = 'false';
21+
process.env.LOG_LEVEL = 'INFO';
22+
23+
container = createContainer();
24+
});
25+
26+
it('should create a container with all required dependencies', () => {
27+
expect(container).toBeDefined();
28+
expect(container.authenticator).toBeDefined();
29+
expect(container.getResourceHandler).toBeDefined();
30+
expect(container.createResourceHandler).toBeDefined();
31+
expect(container.logger).toBeDefined();
32+
});
33+
34+
it('should create an authenticator function', () => {
35+
expect(typeof container.authenticator).toBe('function');
36+
});
37+
38+
it('should create a getResourceHandler function', () => {
39+
expect(typeof container.getResourceHandler).toBe('function');
40+
});
41+
42+
it('should create a createResourceHandler function', () => {
43+
expect(typeof container.createResourceHandler).toBe('function');
44+
});
45+
46+
it('should provide a logger instance', () => {
47+
expect(container.logger).toBeDefined();
48+
expect(container.logger.info).toBeDefined();
49+
expect(container.logger.warn).toBeDefined();
50+
expect(container.logger.error).toBeDefined();
51+
expect(container.logger.debug).toBeDefined();
52+
});
53+
54+
it('should create handlers that can be called', async () => {
55+
const mockEvent = {
56+
pathParameters: { id: 'test-id' },
57+
requestContext: { requestId: 'test-request' },
58+
};
59+
60+
const result = await container.getResourceHandler(mockEvent as never);
61+
expect(result).toBeDefined();
62+
expect(result.statusCode).toBeDefined();
63+
});
64+
65+
it('should create authenticator that can be called', async () => {
66+
const mockEvent = {
67+
headers: { Authorization: 'Bearer test-token' },
68+
};
69+
70+
const result = await container.authenticator(mockEvent);
71+
expect(result).toBeDefined();
72+
expect(result.isValid).toBeDefined();
73+
});
74+
});

0 commit comments

Comments
 (0)