@simplybusiness/services 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/cjs/index.js +10 -0
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/meta.json +4 -4
- package/dist/esm/index.js +10 -0
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/meta.json +4 -4
- package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/vitest.config.d.ts +2 -0
- package/package.json +7 -12
- package/src/address-lookup/index.test.ts +12 -23
- package/src/airbrake/index.test.ts +3 -10
- package/src/snowplow/event-definitions/qcp.ts +10 -0
- package/src/snowplow/index.test.ts +24 -24
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplybusiness/services",
|
|
3
3
|
"license": "UNLICENSED",
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.2",
|
|
5
5
|
"description": "Internal library for services",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"build:types": "tsc --emitDeclarationOnly --project tsconfig.build.json",
|
|
48
48
|
"lint": "eslint .",
|
|
49
49
|
"lint:fix": "eslint . --fix",
|
|
50
|
-
"test": "
|
|
51
|
-
"test:coverage": "
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"test:coverage": "vitest run --coverage",
|
|
52
52
|
"check-types": "tsc --noEmit --pretty"
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false,
|
|
@@ -62,16 +62,14 @@
|
|
|
62
62
|
"@eslint/js": "^9.39.2",
|
|
63
63
|
"@simplybusiness/build-scripts": "^2.0.1",
|
|
64
64
|
"@simplybusiness/eslint-config": "^2.0.1",
|
|
65
|
-
"@swc/core": "^1.12.5",
|
|
66
|
-
"@swc/jest": "^0.2.39",
|
|
67
65
|
"@testing-library/dom": "^10.4.1",
|
|
68
66
|
"@testing-library/jest-dom": "6.9.1",
|
|
69
67
|
"@testing-library/react": "^16.3.2",
|
|
70
|
-
"@types/jest": "^30.0.0",
|
|
71
68
|
"@types/react": "^19.2.11",
|
|
72
69
|
"@types/react-dom": "^19.2.3",
|
|
73
70
|
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
74
71
|
"@typescript-eslint/parser": "^8.54.0",
|
|
72
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
75
73
|
"eslint": "^9.39.2",
|
|
76
74
|
"eslint-config-prettier": "^10.1.8",
|
|
77
75
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
@@ -81,19 +79,16 @@
|
|
|
81
79
|
"eslint-plugin-prettier": "^5.5.5",
|
|
82
80
|
"eslint-plugin-react": "^7.37.5",
|
|
83
81
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
84
|
-
"identity-obj-proxy": "^3.0.0",
|
|
85
|
-
"jest": "^30.2.0",
|
|
86
|
-
"jest-config": "^30.2.0",
|
|
87
|
-
"jest-environment-jsdom": "^30.2.0",
|
|
88
82
|
"prettier": "^3.8.1",
|
|
89
83
|
"react": "^19.2.4",
|
|
90
84
|
"react-dom": "^19.2.4",
|
|
91
85
|
"tslib": "^2.8.1",
|
|
92
|
-
"typescript": "^5.9.3"
|
|
86
|
+
"typescript": "^5.9.3",
|
|
87
|
+
"vitest": "^4.0.18"
|
|
93
88
|
},
|
|
94
89
|
"dependencies": {
|
|
95
90
|
"@airbrake/browser": "^2.1.9",
|
|
96
|
-
"@simplybusiness/mobius": "^
|
|
91
|
+
"@simplybusiness/mobius": "^9.0.0",
|
|
97
92
|
"@snowplow/browser-tracker": "^3.24.6",
|
|
98
93
|
"classnames": "^2.5.1"
|
|
99
94
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Mock } from "vitest";
|
|
1
2
|
import { AddressLookup } from "./index";
|
|
2
3
|
import type { FindAddressResponse, RetrieveAddressResponse } from "./types";
|
|
3
4
|
|
|
@@ -11,11 +12,7 @@ describe("AddressLookup Service", () => {
|
|
|
11
12
|
apiKey: mockApiKey,
|
|
12
13
|
countries: mockCountries,
|
|
13
14
|
});
|
|
14
|
-
global.fetch =
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
afterEach(() => {
|
|
18
|
-
jest.resetAllMocks();
|
|
15
|
+
global.fetch = vi.fn();
|
|
19
16
|
});
|
|
20
17
|
|
|
21
18
|
describe("find", () => {
|
|
@@ -39,7 +36,7 @@ describe("AddressLookup Service", () => {
|
|
|
39
36
|
};
|
|
40
37
|
|
|
41
38
|
it("should fetch and format address search results, and set a callback for addresses whose type is not 'Address'", async () => {
|
|
42
|
-
(global.fetch as
|
|
39
|
+
(global.fetch as Mock).mockResolvedValueOnce({
|
|
43
40
|
json: () => Promise.resolve(mockFindResponse),
|
|
44
41
|
});
|
|
45
42
|
|
|
@@ -69,9 +66,7 @@ describe("AddressLookup Service", () => {
|
|
|
69
66
|
|
|
70
67
|
it("should reject with error when fetch fails", async () => {
|
|
71
68
|
const errorMessage = "Network error";
|
|
72
|
-
(global.fetch as
|
|
73
|
-
new Error(errorMessage),
|
|
74
|
-
);
|
|
69
|
+
(global.fetch as Mock).mockRejectedValueOnce(new Error(errorMessage));
|
|
75
70
|
|
|
76
71
|
await expect(addressLookup.find("123 Main")).rejects.toThrow(
|
|
77
72
|
errorMessage,
|
|
@@ -79,7 +74,7 @@ describe("AddressLookup Service", () => {
|
|
|
79
74
|
});
|
|
80
75
|
|
|
81
76
|
it("should throw error when no Items found", async () => {
|
|
82
|
-
(global.fetch as
|
|
77
|
+
(global.fetch as Mock).mockResolvedValueOnce({
|
|
83
78
|
json: () => Promise.resolve({ Items: null }),
|
|
84
79
|
});
|
|
85
80
|
|
|
@@ -100,7 +95,7 @@ describe("AddressLookup Service", () => {
|
|
|
100
95
|
],
|
|
101
96
|
};
|
|
102
97
|
|
|
103
|
-
(global.fetch as
|
|
98
|
+
(global.fetch as Mock).mockResolvedValueOnce({
|
|
104
99
|
json: () => Promise.resolve(errorResponse),
|
|
105
100
|
});
|
|
106
101
|
|
|
@@ -122,7 +117,7 @@ describe("AddressLookup Service", () => {
|
|
|
122
117
|
};
|
|
123
118
|
|
|
124
119
|
it("should fetch and format address results by container ID", async () => {
|
|
125
|
-
(global.fetch as
|
|
120
|
+
(global.fetch as Mock).mockResolvedValueOnce({
|
|
126
121
|
json: () => Promise.resolve(mockFindByIdResponse),
|
|
127
122
|
});
|
|
128
123
|
|
|
@@ -147,9 +142,7 @@ describe("AddressLookup Service", () => {
|
|
|
147
142
|
describe("findById error cases", () => {
|
|
148
143
|
it("should reject with error when fetch fails", async () => {
|
|
149
144
|
const errorMessage = "Network error";
|
|
150
|
-
(global.fetch as
|
|
151
|
-
new Error(errorMessage),
|
|
152
|
-
);
|
|
145
|
+
(global.fetch as Mock).mockRejectedValueOnce(new Error(errorMessage));
|
|
153
146
|
|
|
154
147
|
await expect(addressLookup.findById("container-123")).rejects.toThrow(
|
|
155
148
|
errorMessage,
|
|
@@ -173,7 +166,7 @@ describe("AddressLookup Service", () => {
|
|
|
173
166
|
};
|
|
174
167
|
|
|
175
168
|
it("should retrieve and format full address details", async () => {
|
|
176
|
-
(global.fetch as
|
|
169
|
+
(global.fetch as Mock).mockResolvedValueOnce({
|
|
177
170
|
json: () => Promise.resolve(mockRetrieveResponse),
|
|
178
171
|
});
|
|
179
172
|
|
|
@@ -196,9 +189,7 @@ describe("AddressLookup Service", () => {
|
|
|
196
189
|
describe("get error cases", () => {
|
|
197
190
|
it("should reject with error when fetch fails", async () => {
|
|
198
191
|
const errorMessage = "Network error";
|
|
199
|
-
(global.fetch as
|
|
200
|
-
new Error(errorMessage),
|
|
201
|
-
);
|
|
192
|
+
(global.fetch as Mock).mockRejectedValueOnce(new Error(errorMessage));
|
|
202
193
|
|
|
203
194
|
await expect(addressLookup.get("address-123")).rejects.toThrow(
|
|
204
195
|
errorMessage,
|
|
@@ -206,7 +197,7 @@ describe("AddressLookup Service", () => {
|
|
|
206
197
|
});
|
|
207
198
|
|
|
208
199
|
it("should throw error when response has no Items", async () => {
|
|
209
|
-
(global.fetch as
|
|
200
|
+
(global.fetch as Mock).mockResolvedValueOnce({
|
|
210
201
|
json: () => Promise.resolve({ Items: null }),
|
|
211
202
|
});
|
|
212
203
|
|
|
@@ -229,9 +220,7 @@ describe("AddressLookup Service", () => {
|
|
|
229
220
|
|
|
230
221
|
it("should reject with error when fetch fails", async () => {
|
|
231
222
|
const errorMessage = "Network error";
|
|
232
|
-
(global.fetch as
|
|
233
|
-
new Error(errorMessage),
|
|
234
|
-
);
|
|
223
|
+
(global.fetch as Mock).mockRejectedValueOnce(new Error(errorMessage));
|
|
235
224
|
|
|
236
225
|
await expect(addressLookup.find("123 Main")).rejects.toThrow(
|
|
237
226
|
errorMessage,
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import { Notifier } from "@airbrake/browser";
|
|
2
|
+
import { type MockedClass } from "vitest";
|
|
2
3
|
import { getAirbrake, getAirbrakeEnvironment } from "./index";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
vi.mock("@airbrake/browser");
|
|
5
6
|
|
|
6
|
-
const MockNotifier = Notifier as
|
|
7
|
+
const MockNotifier = Notifier as MockedClass<typeof Notifier>;
|
|
7
8
|
|
|
8
9
|
describe("getAirbrake", () => {
|
|
9
10
|
const originalEnv = process.env.AIRBRAKE_ENV;
|
|
10
11
|
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
jest.clearAllMocks();
|
|
13
|
-
// Clear the notifier instances cache between tests
|
|
14
|
-
// by creating new notifiers with different projectIds
|
|
15
|
-
});
|
|
16
|
-
|
|
17
12
|
afterEach(() => {
|
|
18
13
|
if (originalEnv === undefined) {
|
|
19
14
|
delete process.env.AIRBRAKE_ENV;
|
|
@@ -66,7 +61,6 @@ describe("getAirbrake", () => {
|
|
|
66
61
|
const result = getAirbrake({ projectId: 1003 });
|
|
67
62
|
|
|
68
63
|
expect(MockNotifier).not.toHaveBeenCalled();
|
|
69
|
-
// In test environment, notify is a jest.fn() to avoid console spam
|
|
70
64
|
expect(typeof result.notify).toBe("function");
|
|
71
65
|
expect(result).not.toBeInstanceOf(Notifier);
|
|
72
66
|
});
|
|
@@ -76,7 +70,6 @@ describe("getAirbrake", () => {
|
|
|
76
70
|
const result = getAirbrake({ projectId: 1004 });
|
|
77
71
|
|
|
78
72
|
expect(MockNotifier).not.toHaveBeenCalled();
|
|
79
|
-
// In test environment, notify is a jest.fn() to avoid console spam
|
|
80
73
|
expect(typeof result.notify).toBe("function");
|
|
81
74
|
expect(result).not.toBeInstanceOf(Notifier);
|
|
82
75
|
});
|
|
@@ -366,4 +366,14 @@ export const qcpEventDefinitions: EventDefinition[] = [
|
|
|
366
366
|
};
|
|
367
367
|
},
|
|
368
368
|
},
|
|
369
|
+
{
|
|
370
|
+
name: "cancelAnytimeBadgeClicked",
|
|
371
|
+
type: "structured",
|
|
372
|
+
makePayload: () => ({
|
|
373
|
+
category: "us-26-02-qcp-cancel-anytime-test",
|
|
374
|
+
action: "cancel_anytime_badge_clicked",
|
|
375
|
+
label: "cancel_anytime",
|
|
376
|
+
property: window.location.href,
|
|
377
|
+
}),
|
|
378
|
+
},
|
|
369
379
|
];
|
|
@@ -26,8 +26,8 @@ describe("Snowplow Analytics Class", () => {
|
|
|
26
26
|
beforeEach(() => {
|
|
27
27
|
testSnowplow = new Snowplow(snowplowProps as TrackingProps);
|
|
28
28
|
testSnowplow.setContexts(contexts);
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
vi.clearAllMocks();
|
|
30
|
+
vi.resetModules();
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
it("exports a Singleton instance with static properties", () => {
|
|
@@ -44,8 +44,8 @@ describe("Snowplow Analytics Class", () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
it("tracks page view event and adds contexts", async () => {
|
|
47
|
-
const trackViewSpy =
|
|
48
|
-
const innerSpy =
|
|
47
|
+
const trackViewSpy = vi.spyOn(testSnowplow, "trackView");
|
|
48
|
+
const innerSpy = vi
|
|
49
49
|
.spyOn(SnowplowLib, "trackPageView")
|
|
50
50
|
.mockImplementation(() => {});
|
|
51
51
|
|
|
@@ -69,8 +69,8 @@ describe("Snowplow Analytics Class", () => {
|
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
it("tracks structured event and adds contexts", () => {
|
|
72
|
-
const trackStructEventSpy =
|
|
73
|
-
const innerSpy =
|
|
72
|
+
const trackStructEventSpy = vi.spyOn(testSnowplow, "trackEvent");
|
|
73
|
+
const innerSpy = vi
|
|
74
74
|
.spyOn(SnowplowLib, "trackStructEvent")
|
|
75
75
|
.mockImplementation(() => {});
|
|
76
76
|
|
|
@@ -92,11 +92,11 @@ describe("Snowplow Analytics Class", () => {
|
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
it("tracks self-describing event and adds contexts", () => {
|
|
95
|
-
const trackUnstructEventSpy =
|
|
95
|
+
const trackUnstructEventSpy = vi.spyOn(
|
|
96
96
|
testSnowplow,
|
|
97
97
|
"trackUnstructEvent",
|
|
98
98
|
);
|
|
99
|
-
const innerSpy =
|
|
99
|
+
const innerSpy = vi
|
|
100
100
|
.spyOn(SnowplowLib, "trackSelfDescribingEvent")
|
|
101
101
|
.mockImplementation(() => {});
|
|
102
102
|
|
|
@@ -137,8 +137,8 @@ describe("Snowplow Analytics Class", () => {
|
|
|
137
137
|
it("triggers an added structured event", () => {
|
|
138
138
|
testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
|
|
139
139
|
|
|
140
|
-
const trackStructEventSpy =
|
|
141
|
-
const innerSpy =
|
|
140
|
+
const trackStructEventSpy = vi.spyOn(testSnowplow, "trackEvent");
|
|
141
|
+
const innerSpy = vi
|
|
142
142
|
.spyOn(SnowplowLib, "trackStructEvent")
|
|
143
143
|
.mockImplementation(() => {});
|
|
144
144
|
|
|
@@ -163,11 +163,11 @@ describe("Snowplow Analytics Class", () => {
|
|
|
163
163
|
it("triggers an added unstructured event", () => {
|
|
164
164
|
testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
|
|
165
165
|
|
|
166
|
-
const trackUnstructEventSpy =
|
|
166
|
+
const trackUnstructEventSpy = vi.spyOn(
|
|
167
167
|
testSnowplow,
|
|
168
168
|
"trackUnstructEvent",
|
|
169
169
|
);
|
|
170
|
-
const innerSpy =
|
|
170
|
+
const innerSpy = vi
|
|
171
171
|
.spyOn(SnowplowLib, "trackSelfDescribingEvent")
|
|
172
172
|
.mockImplementation(() => {});
|
|
173
173
|
|
|
@@ -210,11 +210,11 @@ describe("Snowplow Analytics Class", () => {
|
|
|
210
210
|
it("triggers an added unstructured event and readact the pii information and replace question name", () => {
|
|
211
211
|
testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
|
|
212
212
|
|
|
213
|
-
const trackUnstructEventSpy =
|
|
213
|
+
const trackUnstructEventSpy = vi.spyOn(
|
|
214
214
|
testSnowplow,
|
|
215
215
|
"trackUnstructEvent",
|
|
216
216
|
);
|
|
217
|
-
const innerSpy =
|
|
217
|
+
const innerSpy = vi
|
|
218
218
|
.spyOn(SnowplowLib, "trackSelfDescribingEvent")
|
|
219
219
|
.mockImplementation(() => {});
|
|
220
220
|
|
|
@@ -257,11 +257,11 @@ describe("Snowplow Analytics Class", () => {
|
|
|
257
257
|
it("triggers an added unstructured event and replace radio answer from questions", () => {
|
|
258
258
|
testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
|
|
259
259
|
|
|
260
|
-
const trackUnstructEventSpy =
|
|
260
|
+
const trackUnstructEventSpy = vi.spyOn(
|
|
261
261
|
testSnowplow,
|
|
262
262
|
"trackUnstructEvent",
|
|
263
263
|
);
|
|
264
|
-
const innerSpy =
|
|
264
|
+
const innerSpy = vi
|
|
265
265
|
.spyOn(SnowplowLib, "trackSelfDescribingEvent")
|
|
266
266
|
.mockImplementation(() => {});
|
|
267
267
|
|
|
@@ -304,11 +304,11 @@ describe("Snowplow Analytics Class", () => {
|
|
|
304
304
|
it("triggers an added unstructured event for address lookup type questions", () => {
|
|
305
305
|
testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
|
|
306
306
|
|
|
307
|
-
const trackUnstructEventSpy =
|
|
307
|
+
const trackUnstructEventSpy = vi.spyOn(
|
|
308
308
|
testSnowplow,
|
|
309
309
|
"trackUnstructEvent",
|
|
310
310
|
);
|
|
311
|
-
const innerSpy =
|
|
311
|
+
const innerSpy = vi
|
|
312
312
|
.spyOn(SnowplowLib, "trackSelfDescribingEvent")
|
|
313
313
|
.mockImplementation(() => {});
|
|
314
314
|
|
|
@@ -364,11 +364,11 @@ describe("Snowplow Analytics Class", () => {
|
|
|
364
364
|
(initialVertical, answer, vertical) => {
|
|
365
365
|
testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
|
|
366
366
|
|
|
367
|
-
const trackUnstructEventSpy =
|
|
367
|
+
const trackUnstructEventSpy = vi.spyOn(
|
|
368
368
|
testSnowplow,
|
|
369
369
|
"trackUnstructEvent",
|
|
370
370
|
);
|
|
371
|
-
const innerSpy =
|
|
371
|
+
const innerSpy = vi
|
|
372
372
|
.spyOn(SnowplowLib, "trackSelfDescribingEvent")
|
|
373
373
|
.mockImplementation(() => {});
|
|
374
374
|
|
|
@@ -403,11 +403,11 @@ describe("Snowplow Analytics Class", () => {
|
|
|
403
403
|
it("triggers an added unstructured help_text_opened event", () => {
|
|
404
404
|
testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
|
|
405
405
|
|
|
406
|
-
const trackUnstructEventSpy =
|
|
406
|
+
const trackUnstructEventSpy = vi.spyOn(
|
|
407
407
|
testSnowplow,
|
|
408
408
|
"trackUnstructEvent",
|
|
409
409
|
);
|
|
410
|
-
const innerSpy =
|
|
410
|
+
const innerSpy = vi
|
|
411
411
|
.spyOn(SnowplowLib, "trackSelfDescribingEvent")
|
|
412
412
|
.mockImplementation(() => {});
|
|
413
413
|
|
|
@@ -443,11 +443,11 @@ describe("Snowplow Analytics Class", () => {
|
|
|
443
443
|
it("uses server-supplied context in events", () => {
|
|
444
444
|
testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
|
|
445
445
|
|
|
446
|
-
const trackUnstructEventSpy =
|
|
446
|
+
const trackUnstructEventSpy = vi.spyOn(
|
|
447
447
|
testSnowplow,
|
|
448
448
|
"trackUnstructEvent",
|
|
449
449
|
);
|
|
450
|
-
const innerSpy =
|
|
450
|
+
const innerSpy = vi
|
|
451
451
|
.spyOn(SnowplowLib, "trackSelfDescribingEvent")
|
|
452
452
|
.mockImplementation(() => {});
|
|
453
453
|
|