@prosopo/provider-mock 2.8.143 → 2.8.145
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/.turbo/turbo-build$colon$cjs.log +8 -6
- package/.turbo/turbo-build$colon$tsc.log +26 -26
- package/.turbo/turbo-build.log +9 -7
- package/CHANGELOG.md +52 -0
- package/Dockerfile +11 -0
- package/dist/api.d.ts +35 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +97 -67
- package/dist/api.js.map +1 -1
- package/dist/cjs/api.cjs +105 -66
- package/dist/cjs/db.cjs +16 -7
- package/dist/cjs/isMain.cjs +16 -0
- package/dist/cjs/start.cjs +59 -16
- package/dist/cjs/verify.cjs +39 -0
- package/dist/db.d.ts +8 -4
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +16 -7
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/isMain.d.ts +2 -0
- package/dist/isMain.d.ts.map +1 -0
- package/dist/isMain.js +16 -0
- package/dist/isMain.js.map +1 -0
- package/dist/start.d.ts +17 -0
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +54 -17
- package/dist/start.js.map +1 -1
- package/dist/tests/db.unit.test.d.ts +2 -0
- package/dist/tests/db.unit.test.d.ts.map +1 -0
- package/dist/tests/db.unit.test.js +184 -0
- package/dist/tests/db.unit.test.js.map +1 -0
- package/dist/tests/fixtures.d.ts +33 -0
- package/dist/tests/fixtures.d.ts.map +1 -0
- package/dist/tests/fixtures.js +55 -0
- package/dist/tests/fixtures.js.map +1 -0
- package/dist/tests/handlers.unit.test.d.ts +2 -0
- package/dist/tests/handlers.unit.test.d.ts.map +1 -0
- package/dist/tests/handlers.unit.test.js +204 -0
- package/dist/tests/handlers.unit.test.js.map +1 -0
- package/dist/tests/providerMock.test-d.d.ts +2 -0
- package/dist/tests/providerMock.test-d.d.ts.map +1 -0
- package/dist/tests/providerMock.test-d.js +88 -0
- package/dist/tests/providerMock.test-d.js.map +1 -0
- package/dist/tests/start.unit.test.d.ts +2 -0
- package/dist/tests/start.unit.test.d.ts.map +1 -0
- package/dist/tests/start.unit.test.js +205 -0
- package/dist/tests/start.unit.test.js.map +1 -0
- package/dist/tests/verify.unit.test.d.ts +2 -0
- package/dist/tests/verify.unit.test.d.ts.map +1 -0
- package/dist/tests/verify.unit.test.js +63 -0
- package/dist/tests/verify.unit.test.js.map +1 -0
- package/dist/tests/wiring.unit.test.d.ts +2 -0
- package/dist/tests/wiring.unit.test.d.ts.map +1 -0
- package/dist/tests/wiring.unit.test.js +181 -0
- package/dist/tests/wiring.unit.test.js.map +1 -0
- package/dist/verify.d.ts +13 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +34 -0
- package/dist/verify.js.map +1 -0
- package/package.json +20 -12
- package/src/api.ts +170 -79
- package/src/db.ts +39 -12
- package/src/index.ts +18 -0
- package/src/isMain.ts +37 -0
- package/src/start.ts +92 -18
- package/src/tests/db.unit.test.ts +287 -0
- package/src/tests/fixtures.ts +117 -0
- package/src/tests/handlers.unit.test.ts +325 -0
- package/src/tests/providerMock.test-d.ts +165 -0
- package/src/tests/start.unit.test.ts +291 -0
- package/src/tests/verify.unit.test.ts +143 -0
- package/src/tests/wiring.unit.test.ts +293 -0
- package/src/verify.ts +63 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vite.test.config.ts +32 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
import { ProsopoDBError } from "@prosopo/common";
|
|
16
|
+
import { MongoDatabase } from "@prosopo/database";
|
|
17
|
+
import type mongoose from "mongoose";
|
|
18
|
+
import {
|
|
19
|
+
type Mock,
|
|
20
|
+
afterEach,
|
|
21
|
+
beforeEach,
|
|
22
|
+
describe,
|
|
23
|
+
expect,
|
|
24
|
+
test,
|
|
25
|
+
vi,
|
|
26
|
+
} from "vitest";
|
|
27
|
+
import { type JA4Data, JA4Database } from "../db.js";
|
|
28
|
+
|
|
29
|
+
type ModelFn = (
|
|
30
|
+
name: string,
|
|
31
|
+
schema: mongoose.Schema,
|
|
32
|
+
) => ReturnType<mongoose.Connection["model"]>;
|
|
33
|
+
|
|
34
|
+
interface ConnectionMock {
|
|
35
|
+
model: Mock<ModelFn>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A connection whose model() hands back a stand-in the tests can drive.
|
|
40
|
+
*
|
|
41
|
+
* The real thing needs a running mongod, which CI does not have; only model()
|
|
42
|
+
* is reached by the code under test.
|
|
43
|
+
*/
|
|
44
|
+
const createConnectionMock = (table: TableMock): ConnectionMock => ({
|
|
45
|
+
model: vi.fn<ModelFn>(
|
|
46
|
+
() => table as unknown as ReturnType<mongoose.Connection["model"]>,
|
|
47
|
+
),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The subset of a mongoose model the code under test actually uses: the
|
|
52
|
+
* constructor, save(), find() and findOne(). Standing the whole Model interface
|
|
53
|
+
* up would mean a hundred stubs that no test ever calls.
|
|
54
|
+
*/
|
|
55
|
+
interface TableMock {
|
|
56
|
+
find: Mock<(filter: object) => Promise<unknown[]>>;
|
|
57
|
+
findOne: Mock<(filter: object) => Promise<RecordMock | null>>;
|
|
58
|
+
constructed: JA4Data[];
|
|
59
|
+
saved: Mock<() => Promise<unknown>>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface RecordMock {
|
|
63
|
+
observation_count?: number;
|
|
64
|
+
save: Mock<() => Promise<unknown>>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const createRecordMock = (observationCount?: number): RecordMock => ({
|
|
68
|
+
observation_count: observationCount,
|
|
69
|
+
save: vi.fn<() => Promise<unknown>>(async () => undefined),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const RECORD: JA4Data = {
|
|
73
|
+
ja4_fingerprint: "t13d1516h2_8daaf6152771_b0da82dd1658",
|
|
74
|
+
user_agent_string: "Mozilla/5.0",
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
let db: JA4Database;
|
|
78
|
+
let connectSpy: Mock<() => Promise<void>>;
|
|
79
|
+
let table: TableMock;
|
|
80
|
+
|
|
81
|
+
/** Attach a fake connection the way a successful super.connect() would. */
|
|
82
|
+
const stubSuperConnect = (connection: ConnectionMock | undefined): void => {
|
|
83
|
+
connectSpy = vi.fn<() => Promise<void>>(async () => {
|
|
84
|
+
db.connection = connection as unknown as mongoose.Connection;
|
|
85
|
+
});
|
|
86
|
+
vi.spyOn(MongoDatabase.prototype, "connect").mockImplementation(connectSpy);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
beforeEach(() => {
|
|
90
|
+
db = new JA4Database("mongodb://localhost:27017", "client", "admin");
|
|
91
|
+
const constructed: JA4Data[] = [];
|
|
92
|
+
const saved = vi.fn<() => Promise<unknown>>(async () => undefined);
|
|
93
|
+
function TableModel(this: JA4Data, doc: JA4Data): void {
|
|
94
|
+
constructed.push(doc);
|
|
95
|
+
}
|
|
96
|
+
TableModel.prototype.save = saved;
|
|
97
|
+
table = Object.assign(TableModel, {
|
|
98
|
+
find: vi.fn<(filter: object) => Promise<unknown[]>>(async () => []),
|
|
99
|
+
findOne: vi.fn<(filter: object) => Promise<RecordMock | null>>(
|
|
100
|
+
async () => null,
|
|
101
|
+
),
|
|
102
|
+
constructed,
|
|
103
|
+
saved,
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
afterEach(() => {
|
|
108
|
+
vi.restoreAllMocks();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe("the constructor", () => {
|
|
112
|
+
test("builds a url from the parts it is given", () => {
|
|
113
|
+
expect(db.url).toContain("mongodb://localhost:27017");
|
|
114
|
+
expect(db.url).toContain("authSource=admin");
|
|
115
|
+
expect(db.dbname).toBe("client");
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("registers no tables before connecting", () => {
|
|
119
|
+
expect(db.tables).toEqual({});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("works without a database name or auth source", () => {
|
|
123
|
+
const bare = new JA4Database("mongodb://localhost:27017");
|
|
124
|
+
expect(bare.url).toContain("localhost:27017");
|
|
125
|
+
expect(bare.tables).toEqual({});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("connect", () => {
|
|
130
|
+
test("registers the ja4 model on the open connection", async () => {
|
|
131
|
+
const connection = createConnectionMock(table);
|
|
132
|
+
stubSuperConnect(connection);
|
|
133
|
+
await db.connect();
|
|
134
|
+
expect(connection.model).toHaveBeenCalledOnce();
|
|
135
|
+
expect(connection.model.mock.calls[0]?.[0]).toBe("ja4");
|
|
136
|
+
expect(db.tables.ja4).toBeDefined();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("opens the connection before registering anything", async () => {
|
|
140
|
+
stubSuperConnect(createConnectionMock(table));
|
|
141
|
+
await db.connect();
|
|
142
|
+
expect(connectSpy).toHaveBeenCalledOnce();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("fails loudly when the base class left no connection", async () => {
|
|
146
|
+
// The models used to be read off an undefined connection, so this showed
|
|
147
|
+
// up much later as "cannot read properties of undefined".
|
|
148
|
+
stubSuperConnect(undefined);
|
|
149
|
+
await expect(db.connect()).rejects.toBeInstanceOf(ProsopoDBError);
|
|
150
|
+
expect(db.tables.ja4).toBeUndefined();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("propagates a failure to connect", async () => {
|
|
154
|
+
vi.spyOn(MongoDatabase.prototype, "connect").mockRejectedValue(
|
|
155
|
+
new Error("mongo is down"),
|
|
156
|
+
);
|
|
157
|
+
await expect(db.connect()).rejects.toThrow("mongo is down");
|
|
158
|
+
expect(db.tables.ja4).toBeUndefined();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("connecting twice is harmless", async () => {
|
|
162
|
+
stubSuperConnect(createConnectionMock(table));
|
|
163
|
+
await db.connect();
|
|
164
|
+
await db.connect();
|
|
165
|
+
expect(db.tables.ja4).toBeDefined();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe("getTables", () => {
|
|
170
|
+
test("throws when nothing has been registered yet", () => {
|
|
171
|
+
expect(() => db.getTables()).toThrow(ProsopoDBError);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("returns the models once connected", async () => {
|
|
175
|
+
stubSuperConnect(createConnectionMock(table));
|
|
176
|
+
await db.connect();
|
|
177
|
+
expect(db.getTables().ja4).toBeDefined();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("querying before connecting is a database error, not a TypeError", async () => {
|
|
181
|
+
await expect(db.getJA4Records()).rejects.toBeInstanceOf(ProsopoDBError);
|
|
182
|
+
await expect(
|
|
183
|
+
db.getJA4RecordByFingerprintAndUserAgent("a", "b"),
|
|
184
|
+
).rejects.toBeInstanceOf(ProsopoDBError);
|
|
185
|
+
await expect(db.addOrUpdateJA4Record(RECORD)).rejects.toBeInstanceOf(
|
|
186
|
+
ProsopoDBError,
|
|
187
|
+
);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe("queries", () => {
|
|
192
|
+
beforeEach(async () => {
|
|
193
|
+
stubSuperConnect(createConnectionMock(table));
|
|
194
|
+
await db.connect();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("getJA4Records asks for every record", async () => {
|
|
198
|
+
await db.getJA4Records();
|
|
199
|
+
expect(table.find).toHaveBeenCalledWith({});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test("getJA4Records passes an empty result through", async () => {
|
|
203
|
+
table.find.mockResolvedValue([]);
|
|
204
|
+
expect(await db.getJA4Records()).toEqual([]);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("a lookup matches on both the fingerprint and the user agent", async () => {
|
|
208
|
+
await db.getJA4RecordByFingerprintAndUserAgent("fp", "ua");
|
|
209
|
+
expect(table.findOne).toHaveBeenCalledWith({
|
|
210
|
+
ja4_fingerprint: "fp",
|
|
211
|
+
user_agent_string: "ua",
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test("a miss is null, not an error", async () => {
|
|
216
|
+
expect(
|
|
217
|
+
await db.getJA4RecordByFingerprintAndUserAgent("fp", "ua"),
|
|
218
|
+
).toBeNull();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test("a failed query is propagated", async () => {
|
|
222
|
+
table.find.mockRejectedValue(new Error("connection reset"));
|
|
223
|
+
await expect(db.getJA4Records()).rejects.toThrow("connection reset");
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
describe("addOrUpdateJA4Record", () => {
|
|
228
|
+
beforeEach(async () => {
|
|
229
|
+
stubSuperConnect(createConnectionMock(table));
|
|
230
|
+
await db.connect();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test("inserts when there is no matching record", async () => {
|
|
234
|
+
await db.addOrUpdateJA4Record(RECORD);
|
|
235
|
+
expect(table.constructed).toEqual([RECORD]);
|
|
236
|
+
expect(table.saved).toHaveBeenCalledOnce();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test("increments the count when there is one", async () => {
|
|
240
|
+
const existing = createRecordMock(4);
|
|
241
|
+
table.findOne.mockResolvedValue(existing);
|
|
242
|
+
const result = await db.addOrUpdateJA4Record(RECORD);
|
|
243
|
+
expect(existing.observation_count).toBe(5);
|
|
244
|
+
expect(existing.save).toHaveBeenCalledOnce();
|
|
245
|
+
expect(result).toBe(existing);
|
|
246
|
+
expect(table.constructed).toEqual([]);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test("a record with no count so far starts from one", async () => {
|
|
250
|
+
const existing = createRecordMock(undefined);
|
|
251
|
+
table.findOne.mockResolvedValue(existing);
|
|
252
|
+
await db.addOrUpdateJA4Record(RECORD);
|
|
253
|
+
expect(existing.observation_count).toBe(1);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test("a count of zero is incremented, not treated as missing", async () => {
|
|
257
|
+
const existing = createRecordMock(0);
|
|
258
|
+
table.findOne.mockResolvedValue(existing);
|
|
259
|
+
await db.addOrUpdateJA4Record(RECORD);
|
|
260
|
+
expect(existing.observation_count).toBe(1);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("looks up by the record's own fingerprint and user agent", async () => {
|
|
264
|
+
await db.addOrUpdateJA4Record(RECORD);
|
|
265
|
+
expect(table.findOne).toHaveBeenCalledWith({
|
|
266
|
+
ja4_fingerprint: RECORD.ja4_fingerprint,
|
|
267
|
+
user_agent_string: RECORD.user_agent_string,
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test("an empty user agent is looked up as the empty string", async () => {
|
|
272
|
+
await db.addOrUpdateJA4Record({ ...RECORD, user_agent_string: "" });
|
|
273
|
+
expect(table.findOne).toHaveBeenCalledWith({
|
|
274
|
+
ja4_fingerprint: RECORD.ja4_fingerprint,
|
|
275
|
+
user_agent_string: "",
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test("a failure to save is propagated", async () => {
|
|
280
|
+
const existing = createRecordMock(1);
|
|
281
|
+
existing.save.mockRejectedValue(new Error("duplicate key"));
|
|
282
|
+
table.findOne.mockResolvedValue(existing);
|
|
283
|
+
await expect(db.addOrUpdateJA4Record(RECORD)).rejects.toThrow(
|
|
284
|
+
"duplicate key",
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
import type { IncomingHttpHeaders } from "node:http";
|
|
16
|
+
import { getLogger } from "@prosopo/logger";
|
|
17
|
+
import type { ProcaptchaOutput } from "@prosopo/types";
|
|
18
|
+
import { type Mock, vi } from "vitest";
|
|
19
|
+
import type { ApiRequest, ApiResponse, RouterDeps } from "../api.js";
|
|
20
|
+
import type { JA4Record, JA4Store } from "../db.js";
|
|
21
|
+
import { TEST_ACCOUNT, TEST_DAPP } from "../verify.js";
|
|
22
|
+
|
|
23
|
+
/** A decoded token with the fields the mock inspects, and nothing else set. */
|
|
24
|
+
export const createOutput = (
|
|
25
|
+
overrides: Partial<ProcaptchaOutput> = {},
|
|
26
|
+
): ProcaptchaOutput => ({
|
|
27
|
+
user: TEST_ACCOUNT,
|
|
28
|
+
dapp: TEST_DAPP,
|
|
29
|
+
timestamp: "1717171717",
|
|
30
|
+
signature: {
|
|
31
|
+
provider: { challenge: undefined, requestHash: undefined },
|
|
32
|
+
user: { timestamp: undefined, requestHash: undefined },
|
|
33
|
+
},
|
|
34
|
+
...overrides,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/** A body that VerifySolutionBody accepts. */
|
|
38
|
+
export const createBody = (
|
|
39
|
+
overrides: Record<string, unknown> = {},
|
|
40
|
+
): Record<string, unknown> => ({
|
|
41
|
+
token: "0xdeadbeef",
|
|
42
|
+
dappSignature: "0xsignature",
|
|
43
|
+
...overrides,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export interface DatabaseMock extends JA4Store {
|
|
47
|
+
connect: Mock<() => Promise<void>>;
|
|
48
|
+
close: Mock<() => Promise<void>>;
|
|
49
|
+
addOrUpdateJA4Record: Mock<JA4Store["addOrUpdateJA4Record"]>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** A stand-in for the database, implementing the whole JA4Store interface. */
|
|
53
|
+
export const createDatabaseMock = (): DatabaseMock => ({
|
|
54
|
+
connect: vi.fn<() => Promise<void>>(async () => undefined),
|
|
55
|
+
close: vi.fn<() => Promise<void>>(async () => undefined),
|
|
56
|
+
addOrUpdateJA4Record: vi.fn<JA4Store["addOrUpdateJA4Record"]>(
|
|
57
|
+
async (): Promise<JA4Record | null> => null,
|
|
58
|
+
),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export interface DepsMock {
|
|
62
|
+
deps: RouterDeps;
|
|
63
|
+
database: DatabaseMock;
|
|
64
|
+
getJA4: Mock<
|
|
65
|
+
(headers: IncomingHttpHeaders) => Promise<{ ja4PlusFingerprint: string }>
|
|
66
|
+
>;
|
|
67
|
+
decodeToken: Mock<(token: string) => ProcaptchaOutput>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const createDeps = (overrides: Partial<RouterDeps> = {}): DepsMock => {
|
|
71
|
+
const database = createDatabaseMock();
|
|
72
|
+
const getJA4 = vi.fn<
|
|
73
|
+
(headers: IncomingHttpHeaders) => Promise<{ ja4PlusFingerprint: string }>
|
|
74
|
+
>(async () => ({
|
|
75
|
+
ja4PlusFingerprint: "t13d1516h2_8daaf6152771_b0da82dd1658",
|
|
76
|
+
}));
|
|
77
|
+
const decodeToken = vi.fn<(token: string) => ProcaptchaOutput>(() =>
|
|
78
|
+
createOutput(),
|
|
79
|
+
);
|
|
80
|
+
return {
|
|
81
|
+
database,
|
|
82
|
+
getJA4,
|
|
83
|
+
decodeToken,
|
|
84
|
+
deps: {
|
|
85
|
+
db: database,
|
|
86
|
+
getJA4,
|
|
87
|
+
decodeToken,
|
|
88
|
+
logger: getLogger("fatal", "provider-mock:test"),
|
|
89
|
+
...overrides,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export interface ResponseMock {
|
|
95
|
+
res: ApiResponse;
|
|
96
|
+
json: Mock<(body: object) => unknown>;
|
|
97
|
+
status: Mock<(code: number) => { send: (body: string) => unknown }>;
|
|
98
|
+
send: Mock<(body: string) => unknown>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const createResponse = (): ResponseMock => {
|
|
102
|
+
const json = vi.fn<(body: object) => unknown>(() => undefined);
|
|
103
|
+
const send = vi.fn<(body: string) => unknown>(() => undefined);
|
|
104
|
+
const status = vi.fn<(code: number) => { send: (body: string) => unknown }>(
|
|
105
|
+
() => ({ send }),
|
|
106
|
+
);
|
|
107
|
+
return { res: { json, status }, json, status, send };
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const createRequest = (
|
|
111
|
+
overrides: Partial<ApiRequest> = {},
|
|
112
|
+
): ApiRequest => ({
|
|
113
|
+
body: createBody(),
|
|
114
|
+
headers: { "user-agent": "Mozilla/5.0" },
|
|
115
|
+
t: (key: string): string => `translated:${key}`,
|
|
116
|
+
...overrides,
|
|
117
|
+
});
|