Skip to content

Commit 02c28e4

Browse files
committed
fix test mocking
1 parent 022a25d commit 02c28e4

File tree

7 files changed

+150
-148
lines changed

7 files changed

+150
-148
lines changed

ab-testing/config/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"validate": "node scripts/validation/index.ts",
1313
"deploy": "node scripts/deploy/index.ts --mvts=dist/mvts.json --ab-tests=dist/ab-tests.json",
1414
"build": "node scripts/build/index.ts --mvts=dist/mvts.json --ab-tests=dist/ab-tests.json",
15-
"test": "node --test --test-reporter spec ./**/*.test.ts",
15+
"test": "node --test --test-reporter spec './**/*.test.ts'",
1616
"lint": "eslint .",
1717
"prettier:check": "prettier . --check --cache",
1818
"prettier:fix": "prettier . --write --cache",

ab-testing/deploy-lambda/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"type": "module",
77
"scripts": {
88
"build": "rollup -c rollup.config.js",
9-
"test": "node --test --experimental-test-module-mocks --test-reporter spec ./**/*.test.ts",
9+
"test": "node --test --experimental-test-module-mocks --test-reporter spec './**/*.test.ts'",
1010
"lint": "eslint .",
1111
"prettier:check": "prettier . --check --cache",
1212
"prettier:fix": "prettier . --write --cache"

ab-testing/deploy-lambda/src/index.test.ts

Lines changed: 30 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,27 @@ describe("index", () => {
1919
succeed: () => {},
2020
};
2121

22+
const createCustomResourceEvent = (
23+
overrides?: Partial<CloudFormationCustomResourceEvent>,
24+
) => {
25+
return {
26+
RequestType: "Create",
27+
ServiceToken:
28+
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
29+
ResponseURL: "https://example.com/response",
30+
StackId:
31+
"arn:aws:cloudformation:eu-west-1:123456789012:stack/test-stack/test-id",
32+
RequestId: "test-request-id",
33+
LogicalResourceId: "TestResource",
34+
ResourceType: "Custom::DictionaryDeployer",
35+
ResourceProperties: {
36+
ServiceToken:
37+
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
38+
},
39+
...overrides,
40+
} as CloudFormationCustomResourceEvent;
41+
};
42+
2243
afterEach(() => {
2344
mock.restoreAll();
2445
});
@@ -90,22 +111,10 @@ describe("index", () => {
90111
});
91112

92113
await it("should send SUCCESS for Delete events without deploying", async () => {
93-
const deleteEvent: CloudFormationCustomResourceEvent = {
94-
RequestType: "Delete",
95-
ServiceToken:
96-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
97-
ResponseURL: "https://example.com/response",
98-
StackId:
99-
"arn:aws:cloudformation:eu-west-1:123456789012:stack/test-stack/test-id",
100-
RequestId: "test-request-id",
101-
LogicalResourceId: "TestResource",
102-
ResourceType: "Custom::DictionaryDeployer",
103-
PhysicalResourceId: "test-physical-id",
104-
ResourceProperties: {
105-
ServiceToken:
106-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
107-
},
108-
};
114+
const deleteEvent: CloudFormationCustomResourceEvent =
115+
createCustomResourceEvent({
116+
RequestType: "Delete",
117+
});
109118

110119
const { handler } = await import("./index.ts");
111120

@@ -124,21 +133,7 @@ describe("index", () => {
124133
await it("should deploy dictionaries for Create events", async () => {
125134
process.env.STAGE = "TEST";
126135

127-
const createEvent: CloudFormationCustomResourceEvent = {
128-
RequestType: "Create",
129-
ServiceToken:
130-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
131-
ResponseURL: "https://example.com/response",
132-
StackId:
133-
"arn:aws:cloudformation:eu-west-1:123456789012:stack/test-stack/test-id",
134-
RequestId: "test-request-id",
135-
LogicalResourceId: "TestResource",
136-
ResourceType: "Custom::DictionaryDeployer",
137-
ResourceProperties: {
138-
ServiceToken:
139-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
140-
},
141-
};
136+
const createEvent = createCustomResourceEvent();
142137

143138
const { handler } = await import("./index.ts");
144139

@@ -156,26 +151,13 @@ describe("index", () => {
156151
await it("should deploy dictionaries for update events", async () => {
157152
process.env.STAGE = "TEST";
158153

159-
const updateEvent: CloudFormationCustomResourceEvent = {
154+
const updateEvent = createCustomResourceEvent({
160155
RequestType: "Update",
161-
ServiceToken:
162-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
163-
ResponseURL: "https://example.com/response",
164-
StackId:
165-
"arn:aws:cloudformation:eu-west-1:123456789012:stack/test-stack/test-id",
166-
RequestId: "test-request-id",
167-
LogicalResourceId: "TestResource",
168-
PhysicalResourceId: "test-physical-id",
169-
ResourceType: "Custom::DictionaryDeployer",
170-
ResourceProperties: {
171-
ServiceToken:
172-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
173-
},
174156
OldResourceProperties: {
175157
ServiceToken:
176158
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
177159
},
178-
};
160+
});
179161

180162
const { handler } = await import("./index.ts");
181163

@@ -197,21 +179,7 @@ describe("index", () => {
197179
throw new Error("Deployment failed");
198180
});
199181

200-
const createEvent: CloudFormationCustomResourceEvent = {
201-
RequestType: "Create",
202-
ServiceToken:
203-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
204-
ResponseURL: "https://example.com/response",
205-
StackId:
206-
"arn:aws:cloudformation:eu-west-1:123456789012:stack/test-stack/test-id",
207-
RequestId: "test-request-id",
208-
LogicalResourceId: "TestResource",
209-
ResourceType: "Custom::DictionaryDeployer",
210-
ResourceProperties: {
211-
ServiceToken:
212-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
213-
},
214-
};
182+
const createEvent = createCustomResourceEvent();
215183

216184
const { handler } = await import("./index.ts");
217185

@@ -233,21 +201,7 @@ describe("index", () => {
233201
throw new Error("Fastly API token expired");
234202
});
235203

236-
const createEvent: CloudFormationCustomResourceEvent = {
237-
RequestType: "Create",
238-
ServiceToken:
239-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
240-
ResponseURL: "https://example.com/response",
241-
StackId:
242-
"arn:aws:cloudformation:eu-west-1:123456789012:stack/test-stack/test-id",
243-
RequestId: "test-request-id",
244-
LogicalResourceId: "TestResource",
245-
ResourceType: "Custom::DictionaryDeployer",
246-
ResourceProperties: {
247-
ServiceToken:
248-
"arn:aws:lambda:eu-west-1:123456789012:function:test-function",
249-
},
250-
};
204+
const createEvent = createCustomResourceEvent();
251205

252206
const { handler } = await import("./index.ts");
253207

ab-testing/deploy-lambda/src/lib/deploy.test.ts

Lines changed: 64 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,51 @@
11
import assert from "node:assert";
2-
import type { Mock } from "node:test";
3-
import { beforeEach, describe, it, mock } from "node:test";
4-
import * as deployDictionary from "./deploy-dictionary.ts";
5-
import { fetchAndDeployArtifacts } from "./deploy.ts";
6-
import * as fetchArtifact from "./fetch-artifact.ts";
2+
import { before, beforeEach, describe, it, mock } from "node:test";
73

84
describe("deploy", () => {
9-
const setupMocks = ({
10-
deployDictionaryMock,
11-
fetchArtifactMock,
12-
}: {
13-
deployDictionaryMock: Mock<() => Promise<unknown>>;
14-
fetchArtifactMock: Mock<() => Promise<unknown>>;
15-
}) => ({
16-
deployDictionaryMock: mock.method(
17-
deployDictionary,
18-
"deployDictionary",
19-
mock.fn(async () => deployDictionaryMock),
20-
),
21-
fetchArtifactMock: mock.method(
22-
fetchArtifact,
23-
"fetchDictionaryArtifact",
24-
mock.fn(async () => fetchArtifactMock),
25-
),
26-
});
5+
describe("fetchAndDeployArtifacts", () => {
6+
const deployDictionaryMock = mock.fn<() => Promise<unknown>>();
7+
const fetchArtifactMock = mock.fn<() => Promise<unknown>>();
8+
9+
const mockDeployDictionary = (
10+
impl: (...args: unknown[]) => Promise<unknown>,
11+
) => {
12+
deployDictionaryMock.mock.mockImplementation(impl);
13+
};
14+
15+
const mockFetchArtifact = (
16+
impl: (...args: unknown[]) => Promise<unknown>,
17+
) => {
18+
fetchArtifactMock.mock.mockImplementation(impl);
19+
};
20+
21+
before(() => {
22+
mock.module("./fetch-artifact.ts", {
23+
namedExports: {
24+
fetchDictionaryArtifact: fetchArtifactMock,
25+
},
26+
});
2727

28-
beforeEach(() => {
29-
// Set required environment variables for tests
30-
process.env.ARTIFACT_BUCKET_NAME = "test-bucket";
31-
process.env.STAGE = "TEST";
32-
});
28+
mock.module("./deploy-dictionary.ts", {
29+
namedExports: {
30+
deployDictionary: deployDictionaryMock,
31+
},
32+
});
33+
});
34+
35+
beforeEach(() => {
36+
// Set required environment variables for tests
37+
process.env.ARTIFACT_BUCKET_NAME = "test-bucket";
38+
process.env.STAGE = "TEST";
39+
40+
deployDictionaryMock.mock.resetCalls();
41+
fetchArtifactMock.mock.resetCalls();
42+
});
3343

34-
describe("fetchAndDeployArtifacts", () => {
3544
it("should fetch and deploy artifacts in parallel", async () => {
36-
const { deployDictionaryMock, fetchArtifactMock } = setupMocks({
37-
fetchArtifactMock: mock.fn(async () => [
38-
{ item_key: "test1", item_value: "value1" },
39-
]),
40-
deployDictionaryMock: mock.fn(async () => {}),
41-
});
45+
const mockKeyValues = [{ item_key: "test1", item_value: "value1" }];
46+
47+
mockDeployDictionary(mock.fn(async () => {}));
48+
mockFetchArtifact(mock.fn(async () => mockKeyValues));
4249

4350
const mockDictionary1 = {
4451
name: "ab-tests-dictionary",
@@ -47,6 +54,8 @@ describe("deploy", () => {
4754
name: "mvt-dictionary",
4855
};
4956

57+
const { fetchAndDeployArtifacts } = await import("./deploy.ts");
58+
5059
await fetchAndDeployArtifacts([
5160
{
5261
artifact: "ab-tests.json",
@@ -68,15 +77,15 @@ describe("deploy", () => {
6877
it("should use correct S3 paths for artifacts", async () => {
6978
const mockKeyValues = [{ item_key: "test1", item_value: "value1" }];
7079

71-
const { fetchArtifactMock } = setupMocks({
72-
fetchArtifactMock: mock.fn(async () => mockKeyValues),
73-
deployDictionaryMock: mock.fn(async () => {}),
74-
});
80+
mockFetchArtifact(mock.fn(async () => mockKeyValues));
81+
mockDeployDictionary(mock.fn(async () => {}));
7582

7683
const mockDictionary = {
7784
name: "test-dictionary",
7885
};
7986

87+
const { fetchAndDeployArtifacts } = await import("./deploy.ts");
88+
8089
await fetchAndDeployArtifacts([
8190
{
8291
artifact: "ab-tests.json",
@@ -89,17 +98,19 @@ describe("deploy", () => {
8998
});
9099

91100
it("should throw error when artifact fetch fails", async () => {
92-
setupMocks({
93-
fetchArtifactMock: mock.fn(async () => {
101+
mockFetchArtifact(
102+
mock.fn(async () => {
94103
throw new Error("S3 fetch failed");
95104
}),
96-
deployDictionaryMock: mock.fn(async () => {}),
97-
});
105+
);
106+
mockDeployDictionary(mock.fn(async () => {}));
98107

99108
const mockDictionary = {
100109
name: "test-dictionary",
101110
};
102111

112+
const { fetchAndDeployArtifacts } = await import("./deploy.ts");
113+
103114
await assert.rejects(
104115
async () => {
105116
await fetchAndDeployArtifacts([
@@ -119,17 +130,19 @@ describe("deploy", () => {
119130
it("should throw error when deployment fails", async () => {
120131
const mockKeyValues = [{ item_key: "test1", item_value: "value1" }];
121132

122-
setupMocks({
123-
fetchArtifactMock: mock.fn(async () => mockKeyValues),
124-
deployDictionaryMock: mock.fn(async () => {
133+
mockFetchArtifact(mock.fn(async () => mockKeyValues));
134+
mockDeployDictionary(
135+
mock.fn(async () => {
125136
throw new Error("Deployment failed");
126137
}),
127-
});
138+
);
128139

129140
const mockDictionary = {
130141
name: "test-dictionary",
131142
};
132143

144+
const { fetchAndDeployArtifacts } = await import("./deploy.ts");
145+
133146
await assert.rejects(
134147
async () => {
135148
await fetchAndDeployArtifacts([
@@ -147,10 +160,10 @@ describe("deploy", () => {
147160
});
148161

149162
it("should handle empty deployments array", async () => {
150-
const { deployDictionaryMock, fetchArtifactMock } = setupMocks({
151-
fetchArtifactMock: mock.fn(async () => []),
152-
deployDictionaryMock: mock.fn(async () => {}),
153-
});
163+
mockFetchArtifact(mock.fn(async () => []));
164+
mockDeployDictionary(mock.fn(async () => {}));
165+
166+
const { fetchAndDeployArtifacts } = await import("./deploy.ts");
154167

155168
await fetchAndDeployArtifacts([]);
156169

ab-testing/deploy-lambda/src/lib/fastly-config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";
22
import { configStruct } from "@guardian/ab-testing-config/lib/config.ts";
33
import { assert } from "superstruct";
4-
import { REGION } from "./constants";
4+
import { REGION } from "./constants.ts";
55

66
const getSecureString = async (name: string) => {
77
const ssmClient = new SSMClient({ region: REGION });

0 commit comments

Comments
 (0)