Skip to content

Commit 3778b3a

Browse files
committed
migrate webhook to vitest
1 parent db2d704 commit 3778b3a

File tree

8 files changed

+99
-68
lines changed

8 files changed

+99
-68
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import 'aws-sdk-client-mock-jest/vitest';

lambdas/functions/webhook/src/ConfigLoader.test.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { getParameter } from '@aws-github-runner/aws-ssm-util';
22
import { ConfigWebhook, ConfigWebhookEventBridge, ConfigDispatcher } from './ConfigLoader';
3-
import { mocked } from 'jest-mock';
3+
44
import { logger } from '@aws-github-runner/aws-powertools-util';
55
import { RunnerMatcherConfig } from './sqs';
6+
import { describe, it, expect, beforeEach, beforeAll, afterEach, afterAll, vi } from 'vitest';
7+
68

7-
jest.mock('@aws-github-runner/aws-ssm-util');
9+
vi.mock('@aws-github-runner/aws-ssm-util');
810

911
describe('ConfigLoader Tests', () => {
1012
beforeEach(() => {
11-
jest.clearAllMocks();
13+
vi.clearAllMocks();
1214
ConfigWebhook.reset();
1315
ConfigWebhookEventBridge.reset();
1416
ConfigDispatcher.reset();
@@ -35,7 +37,7 @@ describe('ConfigLoader Tests', () => {
3537
},
3638
},
3739
];
38-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
40+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
3941
if (paramPath === '/path/to/matcher/config') {
4042
return JSON.stringify(matcherConfig);
4143
}
@@ -75,7 +77,7 @@ describe('ConfigLoader Tests', () => {
7577

7678
it('should filter secrets from being logged', async () => {
7779
setupConfiguration();
78-
const spy = jest.spyOn(logger, 'debug');
80+
const spy = vi.spyOn(logger, 'debug');
7981

8082
await ConfigWebhook.load();
8183

@@ -105,7 +107,7 @@ describe('ConfigLoader Tests', () => {
105107
},
106108
},
107109
];
108-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
110+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
109111
if (paramPath === '/path/to/matcher/config') {
110112
return JSON.stringify(matcherConfig);
111113
}
@@ -135,7 +137,7 @@ describe('ConfigLoader Tests', () => {
135137
},
136138
},
137139
];
138-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
140+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
139141
if (paramPath === '/path/to/matcher/config') {
140142
return JSON.stringify(matcherConfig);
141143
}
@@ -156,7 +158,7 @@ describe('ConfigLoader Tests', () => {
156158
it('should throw error if config loading fails', async () => {
157159
process.env.PARAMETER_RUNNER_MATCHER_CONFIG_PATH = '/path/to/matcher/config';
158160

159-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
161+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
160162
if (paramPath === '/path/to/matcher/config') {
161163
throw new Error('Failed to load matcher config');
162164
}
@@ -175,7 +177,7 @@ describe('ConfigLoader Tests', () => {
175177
process.env.EVENT_BUS_NAME = 'event-bus';
176178
process.env.PARAMETER_GITHUB_APP_WEBHOOK_SECRET = '/path/to/webhook/secret';
177179

178-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
180+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
179181
if (paramPath === '/path/to/webhook/secret') {
180182
return 'secret';
181183
}
@@ -190,7 +192,7 @@ describe('ConfigLoader Tests', () => {
190192
});
191193

192194
it('should throw error if config loading fails', async () => {
193-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
195+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
194196
throw new Error(`Parameter ${paramPath} not found`);
195197
});
196198

@@ -215,7 +217,7 @@ describe('ConfigLoader Tests', () => {
215217
},
216218
},
217219
];
218-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
220+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
219221
if (paramPath === '/path/to/matcher/config') {
220222
return JSON.stringify(matcherConfig);
221223
}
@@ -229,7 +231,7 @@ describe('ConfigLoader Tests', () => {
229231
});
230232

231233
it('should throw error if config loading fails', async () => {
232-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
234+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
233235
throw new Error(`Parameter ${paramPath} not found`);
234236
});
235237

@@ -251,7 +253,7 @@ describe('ConfigLoader Tests', () => {
251253
},
252254
},
253255
];
254-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
256+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
255257
if (paramPath === '/path/to/matcher/config') {
256258
return JSON.stringify(matcherConfig);
257259
}
@@ -268,7 +270,7 @@ describe('ConfigLoader Tests', () => {
268270
process.env.REPOSITORY_ALLOW_LIST = '["repo1", "repo2"]';
269271
process.env.PARAMETER_RUNNER_MATCHER_CONFIG_PATH = '/path/to/matcher/config';
270272

271-
mocked(getParameter).mockImplementation(async (paramPath: string) => {
273+
vi.mocked(getParameter).mockImplementation(async (paramPath: string) => {
272274
if (paramPath === '/path/to/matcher/config') {
273275
return JSON.stringify('');
274276
}

lambdas/functions/webhook/src/eventbridge/index.test.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,22 @@ import { EventBridgeClient, PutEventsCommandOutput, PutEventsRequestEntry } from
22
import nock from 'nock';
33

44
import { publish } from '.';
5+
import { describe, it, expect, beforeEach, beforeAll, afterEach, afterAll, vi } from 'vitest';
56

6-
jest.mock('@aws-sdk/client-eventbridge');
7+
8+
vi.mock('@aws-sdk/client-eventbridge');
79

810
const cleanEnv = process.env;
911

1012
beforeEach(() => {
11-
jest.resetModules();
12-
jest.clearAllMocks();
13+
vi.resetModules();
14+
vi.clearAllMocks();
1315
process.env = { ...cleanEnv };
1416
nock.disableNetConnect();
1517
});
1618

1719
describe('Test EventBridge adapter', () => {
18-
test('Test publish without errors', async () => {
20+
it('Test publish without errors', async () => {
1921
// Arrange
2022
const output: PutEventsCommandOutput = {
2123
$metadata: {
@@ -25,7 +27,7 @@ describe('Test EventBridge adapter', () => {
2527
FailedEntryCount: 0,
2628
};
2729

28-
EventBridgeClient.prototype.send = jest.fn().mockResolvedValue(output);
30+
EventBridgeClient.prototype.send = vi.fn().mockResolvedValue(output);
2931

3032
// Act
3133
const result = await publish({
@@ -39,7 +41,7 @@ describe('Test EventBridge adapter', () => {
3941
expect(result).toBe(undefined);
4042
});
4143

42-
test('Test publish with errors', async () => {
44+
it('Test publish with errors', async () => {
4345
// Arrange
4446
const output: PutEventsCommandOutput = {
4547
$metadata: {
@@ -49,7 +51,7 @@ describe('Test EventBridge adapter', () => {
4951
FailedEntryCount: 1,
5052
};
5153

52-
EventBridgeClient.prototype.send = jest.fn().mockResolvedValue(output);
54+
EventBridgeClient.prototype.send = vi.fn().mockResolvedValue(output);
5355

5456
await expect(
5557
publish({
@@ -61,10 +63,10 @@ describe('Test EventBridge adapter', () => {
6163
).rejects.toThrowError('Event failed to send to EventBridge.');
6264
});
6365

64-
test('Test publish with exceptions', async () => {
66+
it('Test publish with exceptions', async () => {
6567
// Arrange
6668
const error = new Error('test');
67-
EventBridgeClient.prototype.send = jest.fn().mockRejectedValue(error);
69+
EventBridgeClient.prototype.send = vi.fn().mockRejectedValue(error);
6870

6971
await expect(
7072
publish({

lambdas/functions/webhook/src/lambda.test.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { logger } from '@aws-github-runner/aws-powertools-util';
22
import { APIGatewayEvent, Context } from 'aws-lambda';
3-
import { mocked } from 'jest-mock';
3+
44
import { WorkflowJobEvent } from '@octokit/webhooks-types';
55

66
import { dispatchToRunners, eventBridgeWebhook, directWebhook } from './lambda';
@@ -9,6 +9,8 @@ import ValidationError from './ValidationError';
99
import { getParameter } from '@aws-github-runner/aws-ssm-util';
1010
import { dispatch } from './runners/dispatch';
1111
import { EventWrapper } from './types';
12+
import { describe, it, expect, beforeEach, beforeAll, afterEach, afterAll, vi } from 'vitest';
13+
1214

1315
const event: APIGatewayEvent = {
1416
body: JSON.stringify(''),
@@ -76,22 +78,22 @@ const context: Context = {
7678
},
7779
};
7880

79-
jest.mock('./runners/dispatch');
80-
jest.mock('./webhook');
81-
jest.mock('@aws-github-runner/aws-ssm-util');
81+
vi.mock('./runners/dispatch');
82+
vi.mock('./webhook');
83+
vi.mock('@aws-github-runner/aws-ssm-util');
8284

8385
describe('Test webhook lambda wrapper.', () => {
8486
beforeEach(() => {
8587
// We mock all SSM request to resolve to a non empty array. Since we mock all implemeantions
8688
// relying on the config opbject that is enought to test the handlers.
87-
const mockedGet = mocked(getParameter);
89+
const mockedGet = vi.mocked(getParameter);
8890
mockedGet.mockResolvedValue('["abc"]');
89-
jest.clearAllMocks();
91+
vi.clearAllMocks();
9092
});
9193

9294
describe('Test webhook lambda wrapper.', () => {
9395
it('Happy flow, resolve.', async () => {
94-
const mock = mocked(publishForRunners);
96+
const mock = vi.mocked(publishForRunners);
9597
mock.mockImplementation(() => {
9698
return new Promise((resolve) => {
9799
resolve({ body: 'test', statusCode: 200 });
@@ -103,16 +105,16 @@ describe('Test webhook lambda wrapper.', () => {
103105
});
104106

105107
it('An expected error, resolve.', async () => {
106-
const mock = mocked(publishForRunners);
108+
const mock = vi.mocked(publishForRunners);
107109
mock.mockRejectedValue(new ValidationError(400, 'some error'));
108110

109111
const result = await directWebhook(event, context);
110112
expect(result).toMatchObject({ body: 'some error', statusCode: 400 });
111113
});
112114

113115
it('Errors are not thrown.', async () => {
114-
const mock = mocked(publishForRunners);
115-
const logSpy = jest.spyOn(logger, 'error');
116+
const mock = vi.mocked(publishForRunners);
117+
const logSpy = vi.spyOn(logger, 'error');
116118
mock.mockRejectedValue(new Error('some error'));
117119
const result = await directWebhook(event, context);
118120
expect(result).toMatchObject({ body: 'Check the Lambda logs for the error details.', statusCode: 500 });
@@ -126,7 +128,7 @@ describe('Test webhook lambda wrapper.', () => {
126128
});
127129

128130
it('Happy flow, resolve.', async () => {
129-
const mock = mocked(publishOnEventBridge);
131+
const mock = vi.mocked(publishOnEventBridge);
130132
mock.mockImplementation(() => {
131133
return new Promise((resolve) => {
132134
resolve({ body: 'test', statusCode: 200 });
@@ -138,7 +140,7 @@ describe('Test webhook lambda wrapper.', () => {
138140
});
139141

140142
it('Reject events .', async () => {
141-
const mock = mocked(publishOnEventBridge);
143+
const mock = vi.mocked(publishOnEventBridge);
142144
mock.mockRejectedValue(new Error('some error'));
143145

144146
mock.mockRejectedValue(new ValidationError(400, 'some error'));
@@ -148,8 +150,8 @@ describe('Test webhook lambda wrapper.', () => {
148150
});
149151

150152
it('Errors are not thrown.', async () => {
151-
const mock = mocked(publishOnEventBridge);
152-
const logSpy = jest.spyOn(logger, 'error');
153+
const mock = vi.mocked(publishOnEventBridge);
154+
const logSpy = vi.spyOn(logger, 'error');
153155
mock.mockRejectedValue(new Error('some error'));
154156
const result = await eventBridgeWebhook(event, context);
155157
expect(result).toMatchObject({ body: 'Check the Lambda logs for the error details.', statusCode: 500 });
@@ -159,7 +161,7 @@ describe('Test webhook lambda wrapper.', () => {
159161

160162
describe('Lambda dispatchToRunners.', () => {
161163
it('Happy flow, resolve.', async () => {
162-
const mock = mocked(dispatch);
164+
const mock = vi.mocked(dispatch);
163165
mock.mockImplementation(() => {
164166
return new Promise((resolve) => {
165167
resolve({ body: 'test', statusCode: 200 });
@@ -174,7 +176,7 @@ describe('Test webhook lambda wrapper.', () => {
174176
});
175177

176178
it('Rejects non workflow_job events.', async () => {
177-
const mock = mocked(dispatch);
179+
const mock = vi.mocked(dispatch);
178180
mock.mockImplementation(() => {
179181
return new Promise((resolve) => {
180182
resolve({ body: 'test', statusCode: 200 });
@@ -191,7 +193,7 @@ describe('Test webhook lambda wrapper.', () => {
191193
});
192194

193195
it('Rejects any event causing an error.', async () => {
194-
const mock = mocked(dispatch);
196+
const mock = vi.mocked(dispatch);
195197
mock.mockRejectedValue(new Error('some error'));
196198

197199
const testEvent = {

lambdas/functions/webhook/src/runners/dispatch.test.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getParameter } from '@aws-github-runner/aws-ssm-util';
2-
import { mocked } from 'jest-mock';
2+
33
import nock from 'nock';
44
import { WorkflowJobEvent } from '@octokit/webhooks-types';
55

@@ -10,9 +10,11 @@ import { RunnerConfig, sendActionRequest } from '../sqs';
1010
import { canRunJob, dispatch } from './dispatch';
1111
import { ConfigDispatcher } from '../ConfigLoader';
1212
import { logger } from '@aws-github-runner/aws-powertools-util';
13+
import { describe, it, expect, beforeEach, beforeAll, afterEach, afterAll, vi } from 'vitest';
14+
1315

14-
jest.mock('../sqs');
15-
jest.mock('@aws-github-runner/aws-ssm-util');
16+
vi.mock('../sqs');
17+
vi.mock('@aws-github-runner/aws-ssm-util');
1618

1719
const GITHUB_APP_WEBHOOK_SECRET = 'TEST_SECRET';
1820

@@ -28,9 +30,9 @@ describe('Dispatcher', () => {
2830

2931
nock.disableNetConnect();
3032
originalError = console.error;
31-
console.error = jest.fn();
32-
jest.clearAllMocks();
33-
jest.resetAllMocks();
33+
console.error = vi.fn();
34+
vi.clearAllMocks();
35+
vi.resetAllMocks();
3436

3537
mockSSMResponse();
3638
config = await createConfig(undefined, runnerConfig);
@@ -57,9 +59,9 @@ describe('Dispatcher', () => {
5759
expect(sendActionRequest).not.toHaveBeenCalled();
5860
});
5961

60-
it('should handle workflow_job events without installation id', async () => {
62+
it('should handle workflow_job events with a valid installation id', async () => {
6163
config = await createConfig(['github-aws-runners/terraform-aws-github-runner']);
62-
const event = { ...workFlowJobEvent, installation: null } as unknown as WorkflowJobEvent;
64+
const event = { ...workFlowJobEvent, installation: { id: 123 } } as unknown as WorkflowJobEvent;
6365
const resp = await dispatch(event, 'workflow_job', config);
6466
expect(resp.statusCode).toBe(201);
6567
expect(sendActionRequest).toHaveBeenCalled();
@@ -229,7 +231,7 @@ describe('Dispatcher', () => {
229231

230232
function mockSSMResponse(runnerConfigInput?: RunnerConfig) {
231233
process.env.PARAMETER_RUNNER_MATCHER_CONFIG_PATH = '/github-runner/runner-matcher-config';
232-
const mockedGet = mocked(getParameter);
234+
const mockedGet = vi.mocked(getParameter);
233235
mockedGet.mockImplementation((parameter_name) => {
234236
const value =
235237
parameter_name == '/github-runner/runner-matcher-config'

lambdas/functions/webhook/src/sqs/index.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { SendMessageCommandInput } from '@aws-sdk/client-sqs';
22
import { sendActionRequest } from '.';
3+
import { describe, it, expect, beforeEach, beforeAll, afterEach, afterAll, vi } from 'vitest';
4+
35

46
const mockSQS = {
5-
sendMessage: jest.fn(() => {
7+
sendMessage: vi.fn(() => {
68
return {};
79
}),
810
};
9-
jest.mock('@aws-sdk/client-sqs', () => ({
10-
SQS: jest.fn().mockImplementation(() => mockSQS),
11+
vi.mock('@aws-sdk/client-sqs', () => ({
12+
SQS: vi.fn().mockImplementation(() => mockSQS),
1113
}));
12-
jest.mock('@aws-github-runner/aws-ssm-util');
14+
vi.mock('@aws-github-runner/aws-ssm-util');
1315

1416
describe('Test sending message to SQS.', () => {
1517
const queueUrl = 'https://sqs.eu-west-1.amazonaws.com/123456789/queued-builds';
@@ -25,7 +27,7 @@ describe('Test sending message to SQS.', () => {
2527
};
2628

2729
afterEach(() => {
28-
jest.clearAllMocks();
30+
vi.clearAllMocks();
2931
});
3032

3133
it('no fifo queue', async () => {

0 commit comments

Comments
 (0)