apify-test-tools 0.3.0 → 0.5.0
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 +9 -0
- package/dist/lib/consts.d.ts.map +1 -1
- package/dist/lib/consts.js +1 -0
- package/dist/lib/consts.js.map +1 -1
- package/dist/lib/extend-expect.d.ts.map +1 -1
- package/dist/lib/extend-expect.js +32 -12
- package/dist/lib/extend-expect.js.map +1 -1
- package/dist/lib/lib.d.ts +6 -6
- package/dist/lib/lib.d.ts.map +1 -1
- package/dist/lib/lib.js.map +1 -1
- package/dist/lib/types.d.ts +12 -1
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/lib/consts.ts +1 -0
- package/lib/extend-expect.ts +38 -12
- package/lib/lib.ts +6 -7
- package/lib/types.ts +14 -1
- package/package.json +1 -1
package/lib/consts.ts
CHANGED
package/lib/extend-expect.ts
CHANGED
|
@@ -117,6 +117,8 @@ export const extendExpect = (expect: ExpectStatic): ExpectStatic => {
|
|
|
117
117
|
...userOptions,
|
|
118
118
|
};
|
|
119
119
|
|
|
120
|
+
const failedAssertions: string[] = [];
|
|
121
|
+
|
|
120
122
|
const diffs: Diffs = {
|
|
121
123
|
pass: true,
|
|
122
124
|
actual: ['Run:'],
|
|
@@ -125,9 +127,13 @@ export const extendExpect = (expect: ExpectStatic): ExpectStatic => {
|
|
|
125
127
|
{
|
|
126
128
|
const expected = options?.status;
|
|
127
129
|
const actual = received.status;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
130
|
+
const statusTest = expected === actual;
|
|
131
|
+
if (statusTest === false) {
|
|
132
|
+
diffs.pass = false;
|
|
133
|
+
diffs.actual.push(`status=${actual}`);
|
|
134
|
+
diffs.expected.push(`status=${expected}`);
|
|
135
|
+
failedAssertions.push(`Failed status check, expected "${expected}", got "${actual}".`);
|
|
136
|
+
}
|
|
131
137
|
}
|
|
132
138
|
|
|
133
139
|
const {
|
|
@@ -135,12 +141,25 @@ export const extendExpect = (expect: ExpectStatic): ExpectStatic => {
|
|
|
135
141
|
stats: { durationMillis },
|
|
136
142
|
} = await received.getRunInfo();
|
|
137
143
|
const datasetItemCount = (await received.getDataset()).items.length;
|
|
138
|
-
const stats =
|
|
144
|
+
const stats = await received.getStatistics();
|
|
139
145
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
146
|
+
const checkInterval = (
|
|
147
|
+
value: number | undefined,
|
|
148
|
+
key: ['datasetItemCount', 'duration', 'failedRequests', 'requestsRetries', 'maxRetriesPerRequest'][number],
|
|
149
|
+
label: string,
|
|
150
|
+
) => {
|
|
151
|
+
const result = isWithinInterval(diffs, value, options, key);
|
|
152
|
+
if (result === false) {
|
|
153
|
+
failedAssertions.push(`Failed ${label} check, expected ${JSON.stringify(options[key])}, got ${value}.`);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
checkInterval(datasetItemCount, 'datasetItemCount', 'dataset item count');
|
|
158
|
+
checkInterval(durationMillis, 'duration', 'duration');
|
|
159
|
+
checkInterval(stats?.requestsFailed, 'failedRequests', 'failed requests');
|
|
160
|
+
checkInterval(stats?.requestsRetries, 'requestsRetries', 'requests retries');
|
|
161
|
+
const maxRetriesObserved = (stats?.requestRetryHistogram ?? [0]).length - 1;
|
|
162
|
+
checkInterval(maxRetriesObserved, 'maxRetriesPerRequest', 'max retries per request');
|
|
144
163
|
|
|
145
164
|
const ppeDiffs: Diffs = {
|
|
146
165
|
pass: true,
|
|
@@ -175,9 +194,12 @@ export const extendExpect = (expect: ExpectStatic): ExpectStatic => {
|
|
|
175
194
|
isWithinInterval(ppeDiffs, actual[ppeEvent], expected, ppeEvent as PpeEvent);
|
|
176
195
|
}
|
|
177
196
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
197
|
+
if (ppeDiffs.pass === false) {
|
|
198
|
+
diffs.pass = ppeDiffs.pass;
|
|
199
|
+
diffs.actual.push(ppeDiffs.actual.join('\n '));
|
|
200
|
+
diffs.expected.push(ppeDiffs.expected.join('\n '));
|
|
201
|
+
failedAssertions.push(`Failed PPE event counts check, expected ${JSON.stringify(options.chargedEventCounts)}, got ${JSON.stringify(chargedEventCounts)}.`);
|
|
202
|
+
}
|
|
181
203
|
}
|
|
182
204
|
|
|
183
205
|
{
|
|
@@ -193,12 +215,13 @@ export const extendExpect = (expect: ExpectStatic): ExpectStatic => {
|
|
|
193
215
|
diffs.pass = false;
|
|
194
216
|
diffs.actual.push(` logs=[${occuredLogs.join(', ')}]`);
|
|
195
217
|
diffs.expected.push(` logs=[]`);
|
|
218
|
+
failedAssertions.push(`Failed forbidden logs check, expected [] but got [${occuredLogs.join(', ')}].`);
|
|
196
219
|
}
|
|
197
220
|
}
|
|
198
221
|
|
|
199
222
|
return {
|
|
200
223
|
pass: diffs.pass,
|
|
201
|
-
message: () => `Run
|
|
224
|
+
message: () => `Run did not finish as expected. Failed assertions: ${failedAssertions.join(' ',)}`,
|
|
202
225
|
actual: diffs.actual.join('\n '),
|
|
203
226
|
expected: diffs.expected.join('\n '),
|
|
204
227
|
};
|
|
@@ -256,6 +279,7 @@ const isWithinInterval = <T extends string>(
|
|
|
256
279
|
diffs.pass = false;
|
|
257
280
|
diffs.actual.push(`${intervalOption}=${actual}`);
|
|
258
281
|
diffs.expected.push(`${intervalOption}=${expected}`);
|
|
282
|
+
return false
|
|
259
283
|
}
|
|
260
284
|
} else if (typeof expected === 'object') {
|
|
261
285
|
const { min, max } = expected;
|
|
@@ -263,6 +287,8 @@ const isWithinInterval = <T extends string>(
|
|
|
263
287
|
diffs.pass = false;
|
|
264
288
|
diffs.actual.push(`${intervalOption}=${actual}`);
|
|
265
289
|
diffs.expected.push(`${intervalOption}=<${min ?? ''},${max ?? ''}>`);
|
|
290
|
+
return false
|
|
266
291
|
}
|
|
267
292
|
}
|
|
293
|
+
return
|
|
268
294
|
};
|
package/lib/lib.ts
CHANGED
|
@@ -5,10 +5,9 @@ import {
|
|
|
5
5
|
TestFunction,
|
|
6
6
|
test as vitestTest,
|
|
7
7
|
SuiteFactory,
|
|
8
|
-
TestOptions,
|
|
9
8
|
TestContext,
|
|
10
9
|
} from 'vitest';
|
|
11
|
-
import type { ActorBuild, RunOptions } from './types';
|
|
10
|
+
import type { ActorBuild, ActorTestOptions, RunOptions } from './types';
|
|
12
11
|
import { RunTestResult } from './run-test-result.js';
|
|
13
12
|
import { extendExpect } from './extend-expect.js';
|
|
14
13
|
import { getActorPrefilledInput, sleep } from './utils.js';
|
|
@@ -38,7 +37,7 @@ export { ExpectStatic };
|
|
|
38
37
|
const { TESTER_APIFY_TOKEN, RUN_PLATFORM_TESTS, RUN_ALL_PLATFORM_TESTS } = process.env;
|
|
39
38
|
const apifyClient = new ApifyClient({ token: TESTER_APIFY_TOKEN });
|
|
40
39
|
|
|
41
|
-
const DEFAULT_TEST_OPTIONS:
|
|
40
|
+
const DEFAULT_TEST_OPTIONS: ActorTestOptions = {
|
|
42
41
|
// we want to run tests concurrently
|
|
43
42
|
concurrent: true,
|
|
44
43
|
// test should finish within 1 hour
|
|
@@ -48,12 +47,12 @@ const DEFAULT_TEST_OPTIONS: TestOptions = {
|
|
|
48
47
|
export const describe = (
|
|
49
48
|
name: string,
|
|
50
49
|
fn?: SuiteFactory<object>,
|
|
51
|
-
options:
|
|
50
|
+
options: ActorTestOptions = DEFAULT_TEST_OPTIONS,
|
|
52
51
|
) => {
|
|
53
52
|
vitestDescribe.runIf(!!RUN_PLATFORM_TESTS || !!RUN_ALL_PLATFORM_TESTS)(name, options, fn);
|
|
54
53
|
};
|
|
55
54
|
|
|
56
|
-
const DEFAULT_TEST_ACTOR_OPTIONS:
|
|
55
|
+
const DEFAULT_TEST_ACTOR_OPTIONS: ActorTestOptions = {
|
|
57
56
|
retry: 1,
|
|
58
57
|
};
|
|
59
58
|
|
|
@@ -61,7 +60,7 @@ export const testActor = <T>(
|
|
|
61
60
|
actorName: string,
|
|
62
61
|
testName: string,
|
|
63
62
|
fn: TestFunction<{ run: ReturnType<typeof createStartRunFn<T>> }>,
|
|
64
|
-
testOptions?:
|
|
63
|
+
testOptions?: ActorTestOptions,
|
|
65
64
|
) => {
|
|
66
65
|
const options = {
|
|
67
66
|
...DEFAULT_TEST_ACTOR_OPTIONS,
|
|
@@ -90,7 +89,7 @@ export const testStandbyActor = <I = any, O = any>(
|
|
|
90
89
|
actorName: string,
|
|
91
90
|
testName: string,
|
|
92
91
|
fn: TestFunction<{ callStandby: ReturnType<typeof createStartStandbyFn<I, O>> }>,
|
|
93
|
-
testOptions?:
|
|
92
|
+
testOptions?: ActorTestOptions,
|
|
94
93
|
) => {
|
|
95
94
|
const options = {
|
|
96
95
|
...DEFAULT_TEST_ACTOR_OPTIONS,
|
package/lib/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ActorCallOptions } from 'apify-client';
|
|
2
|
-
import { Assertion } from 'vitest';
|
|
2
|
+
import { Assertion, TestOptions } from 'vitest';
|
|
3
3
|
|
|
4
4
|
export type ActorBuild = {
|
|
5
5
|
buildId: string;
|
|
@@ -46,6 +46,7 @@ export type ToFinishWithOptionsWithDefaults = {
|
|
|
46
46
|
failedRequests: Interval | null
|
|
47
47
|
requestsRetries: Interval | null
|
|
48
48
|
forbiddenLogs: string[]
|
|
49
|
+
maxRetriesPerRequest: number | null
|
|
49
50
|
}
|
|
50
51
|
export type IntervalOption<PpeEvent extends string> = keyof Pick<
|
|
51
52
|
ToFinishWithOptions<PpeEvent>,
|
|
@@ -123,6 +124,7 @@ export interface ActorMatchers<R = unknown> {
|
|
|
123
124
|
* - `failedRequests` (default: `0`)
|
|
124
125
|
* - `requestsRetries` (default: `{ max: 3 }`)
|
|
125
126
|
* - `forbiddenLogs` (default: `['ReferenceError', 'TypeError']`)
|
|
127
|
+
* - `maxRetriesPerRequest` (not checked by default)
|
|
126
128
|
* - `datasetItemCount` (required)
|
|
127
129
|
* - `chargedEventCounts`
|
|
128
130
|
*/
|
|
@@ -131,6 +133,17 @@ export interface ActorMatchers<R = unknown> {
|
|
|
131
133
|
hard: <T>(actual: T, message?: string) => Assertion
|
|
132
134
|
}
|
|
133
135
|
|
|
136
|
+
export type ActorTestOptions = Omit<TestOptions, 'retry'> & {
|
|
137
|
+
/**
|
|
138
|
+
* Times to retry the test if fails. Useful for making flaky tests more stable.
|
|
139
|
+
* When retries is up, the last test error will be thrown.
|
|
140
|
+
*
|
|
141
|
+
* @default 1
|
|
142
|
+
*/
|
|
143
|
+
// we are just extending the docs here to replace the default value, otherwise it's the exact same
|
|
144
|
+
retry?: TestOptions['retry'];
|
|
145
|
+
};
|
|
146
|
+
|
|
134
147
|
declare module 'vitest' {
|
|
135
148
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
136
149
|
interface Assertion<T = any> extends ActorMatchers<T> { }
|