apify-test-tools 0.9.0-beta.1 → 0.9.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 +13 -0
- package/bin/actor-filtering.ts +21 -0
- package/bin/git.ts +5 -1
- package/bin/main.ts +65 -61
- package/bin/slack.ts +4 -4
- package/bin/types.ts +2 -0
- package/bin/utils.ts +3 -2
- package/dist/bin/actor-filtering.d.ts +13 -0
- package/dist/bin/actor-filtering.d.ts.map +1 -0
- package/dist/bin/actor-filtering.js +19 -0
- package/dist/bin/actor-filtering.js.map +1 -0
- package/dist/bin/git.d.ts +1 -1
- package/dist/bin/git.d.ts.map +1 -1
- package/dist/bin/git.js +1 -1
- package/dist/bin/git.js.map +1 -1
- package/dist/bin/main.d.ts +20 -1
- package/dist/bin/main.d.ts.map +1 -1
- package/dist/bin/main.js +56 -37
- package/dist/bin/main.js.map +1 -1
- package/dist/bin/slack.js +4 -4
- package/dist/bin/slack.js.map +1 -1
- package/dist/bin/types.d.ts +2 -0
- package/dist/bin/types.d.ts.map +1 -1
- package/dist/bin/utils.d.ts +4 -1
- package/dist/bin/utils.d.ts.map +1 -1
- package/dist/bin/utils.js +3 -2
- package/dist/bin/utils.js.map +1 -1
- package/dist/lib/consts.d.ts +6 -0
- package/dist/lib/consts.d.ts.map +1 -1
- package/dist/lib/consts.js +6 -0
- package/dist/lib/consts.js.map +1 -1
- package/dist/lib/lib.js +3 -3
- package/dist/lib/lib.js.map +1 -1
- package/dist/test/unit/bin/actor-filtering.test.d.ts +2 -0
- package/dist/test/unit/bin/actor-filtering.test.d.ts.map +1 -0
- package/dist/test/unit/bin/actor-filtering.test.js +41 -0
- package/dist/test/unit/bin/actor-filtering.test.js.map +1 -0
- package/dist/test/unit/bin/utils.test.js +52 -24
- package/dist/test/unit/bin/utils.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/lib/consts.ts +7 -0
- package/lib/lib.ts +3 -3
- package/package.json +62 -62
- package/test/unit/bin/actor-filtering.test.ts +52 -0
- package/test/unit/bin/utils.test.ts +62 -24
package/lib/consts.ts
CHANGED
|
@@ -16,3 +16,10 @@ export const TO_FINISH_WITH_OPTIONS: ToFinishWithOptionsWithDefaults = {
|
|
|
16
16
|
* Both the test runs and the vitest test specs should finish in this time - 1 hour
|
|
17
17
|
*/
|
|
18
18
|
export const DEFAULT_TEST_RUN_DURATION_MS = 60 * 60 * 1000; // 1 hour
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Delay before checking the dataset and statistics after a run finishes to resolve eventual consistency.
|
|
22
|
+
* - This value should ensure that the dataset and statistics are fully updated before any assertions are made.
|
|
23
|
+
* - Super rarely the platform is still not synced even after 10s, so 20s should be sufficient practically always.
|
|
24
|
+
*/
|
|
25
|
+
export const DATASET_SYNC_DELAY_MS = 20 * 1000; // 20 seconds
|
package/lib/lib.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { ApifyClient } from 'apify-client';
|
|
|
3
3
|
import type { SuiteFactory, TestContext, TestFunction } from 'vitest';
|
|
4
4
|
import { describe as vitestDescribe, ExpectStatic, test as vitestTest } from 'vitest';
|
|
5
5
|
|
|
6
|
-
import { DEFAULT_TEST_RUN_DURATION_MS } from './consts.js';
|
|
6
|
+
import { DATASET_SYNC_DELAY_MS, DEFAULT_TEST_RUN_DURATION_MS } from './consts.js';
|
|
7
7
|
import { extendExpect } from './extend-expect.js';
|
|
8
8
|
import { RunTestResult } from './run-test-result.js';
|
|
9
9
|
import type { ActorBuild, ActorTestOptions, RunOptions } from './types.js';
|
|
@@ -286,8 +286,8 @@ const createStartRunFn = <T>(actorId: string, testContext: TestContext) => {
|
|
|
286
286
|
actorId: actorConfig?.actorFullName ?? actorId,
|
|
287
287
|
};
|
|
288
288
|
|
|
289
|
-
// waiting for
|
|
290
|
-
await sleep(
|
|
289
|
+
// waiting for dataset and statistics to sync, the Apify platform is only eventually consistent.
|
|
290
|
+
await sleep(DATASET_SYNC_DELAY_MS);
|
|
291
291
|
|
|
292
292
|
return new RunTestResult(apifyClient, run);
|
|
293
293
|
};
|
package/package.json
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
2
|
+
"name": "apify-test-tools",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "TBD",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/apify/apify-test-tools.git"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18.0.0"
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"apify-test-tools": "dist/bin/main.js"
|
|
15
|
+
},
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"main": "./dist/lib/lib.js",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@apify/consts": "^2.43.0",
|
|
20
|
+
"@slack/web-api": "^7.9.2",
|
|
21
|
+
"apify-client": "^2.22.2",
|
|
22
|
+
"ignore": "^7.0.5",
|
|
23
|
+
"yargs": "^18.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@apify/eslint-config": "^1.0.0",
|
|
27
|
+
"@apify/tsconfig": "^0.1.1",
|
|
28
|
+
"@types/node": "^24.0.0",
|
|
29
|
+
"@types/yargs": "^17.0.33",
|
|
30
|
+
"eslint": "^9.29.0",
|
|
31
|
+
"eslint-config-prettier": "^10.1.5",
|
|
32
|
+
"globals": "^17.0.0",
|
|
33
|
+
"husky": "^9.0.11",
|
|
34
|
+
"knip": "^5.65.0",
|
|
35
|
+
"lint-staged": "^15.2.2",
|
|
36
|
+
"prettier": "^3.5.3",
|
|
37
|
+
"tsx": "^4.20.3",
|
|
38
|
+
"typescript": "^5.9.3",
|
|
39
|
+
"typescript-eslint": "^8.34.1",
|
|
40
|
+
"vitest": "^3.2.4"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"vitest": ">=3.2.4"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"start": "npm run dist/bin/main.js",
|
|
47
|
+
"start:dev": "GITHUB_WORKSPACE=local-clone tsx bin/main.ts",
|
|
48
|
+
"build": "tsc && chmod +x ./dist/bin/main.js",
|
|
49
|
+
"lint": "eslint",
|
|
50
|
+
"lint:fix": "eslint --fix",
|
|
51
|
+
"format": "prettier --write .",
|
|
52
|
+
"format:check": "prettier --check .",
|
|
53
|
+
"type-check": "tsc --noEmit",
|
|
54
|
+
"test": "vitest run",
|
|
55
|
+
"check-unused": "npx knip",
|
|
56
|
+
"prepare": "husky .husky || true"
|
|
57
|
+
},
|
|
58
|
+
"lint-staged": {
|
|
59
|
+
"*.js": "eslint",
|
|
60
|
+
"*.ts": "eslint"
|
|
61
|
+
},
|
|
62
|
+
"author": "oklinov",
|
|
63
|
+
"license": "ISC"
|
|
64
64
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { selectActors } from '../../../bin/actor-filtering.js';
|
|
4
|
+
import type { ActorConfig } from '../../../bin/types.js';
|
|
5
|
+
|
|
6
|
+
const actor = (actorFullName: string): ActorConfig => ({
|
|
7
|
+
actorFullName,
|
|
8
|
+
folder: actorFullName.split('/')[1],
|
|
9
|
+
tokenEnvVar: 'TOKEN',
|
|
10
|
+
dockerContextDir: '.',
|
|
11
|
+
contextPaths: [],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const configs = [actor('owner/a'), actor('owner/b'), actor('owner/c')];
|
|
15
|
+
const names = (result: ActorConfig[]) => result.map((c) => c.actorFullName);
|
|
16
|
+
|
|
17
|
+
describe('selectActors', () => {
|
|
18
|
+
it('returns all actors when neither filter is set', () => {
|
|
19
|
+
expect(names(selectActors({ actors: [], ignore: [] }, configs))).toStrictEqual([
|
|
20
|
+
'owner/a',
|
|
21
|
+
'owner/b',
|
|
22
|
+
'owner/c',
|
|
23
|
+
]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('keeps only the actors listed in --actors', () => {
|
|
27
|
+
expect(names(selectActors({ actors: ['owner/a', 'owner/c'], ignore: [] }, configs))).toStrictEqual([
|
|
28
|
+
'owner/a',
|
|
29
|
+
'owner/c',
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('drops the actors listed in --ignore', () => {
|
|
34
|
+
expect(names(selectActors({ actors: [], ignore: ['owner/b'] }, configs))).toStrictEqual(['owner/a', 'owner/c']);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('applies --actors first, then removes --ignore from that subset', () => {
|
|
38
|
+
expect(names(selectActors({ actors: ['owner/a', 'owner/b'], ignore: ['owner/b'] }, configs))).toStrictEqual([
|
|
39
|
+
'owner/a',
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('can select down to nothing when --actors and --ignore overlap fully', () => {
|
|
44
|
+
expect(selectActors({ actors: ['owner/a'], ignore: ['owner/a'] }, configs)).toStrictEqual([]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('throws listing every unknown name across both filters', () => {
|
|
48
|
+
expect(() => selectActors({ actors: ['owner/x'], ignore: ['owner/y'] }, configs)).toThrow(
|
|
49
|
+
'The following actors from the filter config do not exist: owner/x, owner/y',
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -12,6 +12,8 @@ vi.mock('node:fs/promises', () => ({ default: fsMock }));
|
|
|
12
12
|
|
|
13
13
|
afterEach(() => vi.restoreAllMocks());
|
|
14
14
|
|
|
15
|
+
const emptyActorSelection = { actors: [], ignore: [] };
|
|
16
|
+
|
|
15
17
|
const validConfig = (actors: object[]) => JSON.stringify({ actors });
|
|
16
18
|
const actorJson = (fields: Record<string, unknown> = {}) => JSON.stringify(fields);
|
|
17
19
|
|
|
@@ -39,7 +41,7 @@ describe('readConfigFile', () => {
|
|
|
39
41
|
'actors/shopify/.actor/actor.json': actorJson({ dockerContextDir: '../../..' }),
|
|
40
42
|
});
|
|
41
43
|
|
|
42
|
-
const result = await readConfigFile();
|
|
44
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
43
45
|
expectFileRead('actors/shopify/.actor/actor.json');
|
|
44
46
|
expect(result).toEqual([
|
|
45
47
|
{
|
|
@@ -60,7 +62,7 @@ describe('readConfigFile', () => {
|
|
|
60
62
|
'.actor/actor.json': actorJson({}),
|
|
61
63
|
});
|
|
62
64
|
|
|
63
|
-
const result = await readConfigFile();
|
|
65
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
64
66
|
expect(result[0].folder).toBe('');
|
|
65
67
|
expectFileRead('.actor/actor.json');
|
|
66
68
|
});
|
|
@@ -73,7 +75,7 @@ describe('readConfigFile', () => {
|
|
|
73
75
|
'actors/web-scraper/.actor/actor.json': actorJson({}),
|
|
74
76
|
});
|
|
75
77
|
|
|
76
|
-
const result = await readConfigFile();
|
|
78
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
77
79
|
expect(result[0].dockerContextDir).toBe('actors/web-scraper');
|
|
78
80
|
expect(result[0].contextPaths).toEqual(['actors/web-scraper']);
|
|
79
81
|
});
|
|
@@ -86,7 +88,7 @@ describe('readConfigFile', () => {
|
|
|
86
88
|
'actors/shopify/.actor/actor.json': actorJson({ dockerContextDir: '../../..' }),
|
|
87
89
|
});
|
|
88
90
|
|
|
89
|
-
const result = await readConfigFile();
|
|
91
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
90
92
|
expect(result[0].dockerContextDir).toBe('');
|
|
91
93
|
});
|
|
92
94
|
|
|
@@ -103,7 +105,7 @@ describe('readConfigFile', () => {
|
|
|
103
105
|
'actors/shopify/.actor/actor.json': actorJson({ dockerContextDir: '../../..' }),
|
|
104
106
|
});
|
|
105
107
|
|
|
106
|
-
const result = await readConfigFile();
|
|
108
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
107
109
|
expect(result[0].contextPaths).toEqual(['actors/shopify', 'packages']);
|
|
108
110
|
});
|
|
109
111
|
|
|
@@ -121,7 +123,7 @@ describe('readConfigFile', () => {
|
|
|
121
123
|
'actors/email-sender/.actor/actor.json': actorJson({}),
|
|
122
124
|
});
|
|
123
125
|
|
|
124
|
-
const result = await readConfigFile();
|
|
126
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
125
127
|
expect(result).toHaveLength(2);
|
|
126
128
|
expect(result[0].actorFullName).toBe('apify/web-scraper');
|
|
127
129
|
expect(result[1].actorFullName).toBe('other-team/email-sender');
|
|
@@ -129,17 +131,17 @@ describe('readConfigFile', () => {
|
|
|
129
131
|
|
|
130
132
|
it('throws when config file is missing', async () => {
|
|
131
133
|
fsMock.readFile.mockRejectedValue(new Error('ENOENT'));
|
|
132
|
-
await expect(readConfigFile()).rejects.toThrow('not found');
|
|
134
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('not found');
|
|
133
135
|
});
|
|
134
136
|
|
|
135
137
|
it('throws when config file contains invalid JSON', async () => {
|
|
136
138
|
fsMock.readFile.mockResolvedValue('{bad json');
|
|
137
|
-
await expect(readConfigFile()).rejects.toThrow('invalid JSON');
|
|
139
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('invalid JSON');
|
|
138
140
|
});
|
|
139
141
|
|
|
140
142
|
it('throws when actors array is missing', async () => {
|
|
141
143
|
fsMock.readFile.mockResolvedValue(JSON.stringify({ notActors: [] }));
|
|
142
|
-
await expect(readConfigFile()).rejects.toThrow('"actors" array');
|
|
144
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('"actors" array');
|
|
143
145
|
});
|
|
144
146
|
|
|
145
147
|
it('throws on duplicate folders', async () => {
|
|
@@ -151,7 +153,7 @@ describe('readConfigFile', () => {
|
|
|
151
153
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
152
154
|
});
|
|
153
155
|
|
|
154
|
-
await expect(readConfigFile()).rejects.toThrow('Duplicate folder');
|
|
156
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('Duplicate folder');
|
|
155
157
|
});
|
|
156
158
|
|
|
157
159
|
it('throws on duplicate folders after normalization ("." and "")', async () => {
|
|
@@ -163,7 +165,7 @@ describe('readConfigFile', () => {
|
|
|
163
165
|
'.actor/actor.json': actorJson({}),
|
|
164
166
|
});
|
|
165
167
|
|
|
166
|
-
await expect(readConfigFile()).rejects.toThrow('Duplicate folder');
|
|
168
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('Duplicate folder');
|
|
167
169
|
});
|
|
168
170
|
|
|
169
171
|
it('throws when actor.json is missing', async () => {
|
|
@@ -173,7 +175,7 @@ describe('readConfigFile', () => {
|
|
|
173
175
|
]),
|
|
174
176
|
});
|
|
175
177
|
|
|
176
|
-
await expect(readConfigFile()).rejects.toThrow('Cannot read');
|
|
178
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('Cannot read');
|
|
177
179
|
});
|
|
178
180
|
|
|
179
181
|
it('throws when folder is missing', async () => {
|
|
@@ -181,7 +183,7 @@ describe('readConfigFile', () => {
|
|
|
181
183
|
[CONFIG_FILE_NAME]: validConfig([{ actorFullName: 'apify/shopify', tokenEnvVar: 'APIFY_TOKEN_APIFY' }]),
|
|
182
184
|
});
|
|
183
185
|
|
|
184
|
-
await expect(readConfigFile()).rejects.toThrow(/Invalid "folder"/);
|
|
186
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow(/Invalid "folder"/);
|
|
185
187
|
});
|
|
186
188
|
|
|
187
189
|
it('throws when folder is not a string', async () => {
|
|
@@ -191,7 +193,7 @@ describe('readConfigFile', () => {
|
|
|
191
193
|
]),
|
|
192
194
|
});
|
|
193
195
|
|
|
194
|
-
await expect(readConfigFile()).rejects.toThrow(/Invalid "folder"/);
|
|
196
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow(/Invalid "folder"/);
|
|
195
197
|
});
|
|
196
198
|
|
|
197
199
|
it('throws when actorFullName is missing', async () => {
|
|
@@ -200,7 +202,7 @@ describe('readConfigFile', () => {
|
|
|
200
202
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
201
203
|
});
|
|
202
204
|
|
|
203
|
-
await expect(readConfigFile()).rejects.toThrow('Invalid "actorFullName"');
|
|
205
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('Invalid "actorFullName"');
|
|
204
206
|
});
|
|
205
207
|
|
|
206
208
|
it('throws when actorFullName has no slash', async () => {
|
|
@@ -211,7 +213,7 @@ describe('readConfigFile', () => {
|
|
|
211
213
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
212
214
|
});
|
|
213
215
|
|
|
214
|
-
await expect(readConfigFile()).rejects.toThrow('Invalid "actorFullName"');
|
|
216
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('Invalid "actorFullName"');
|
|
215
217
|
});
|
|
216
218
|
|
|
217
219
|
it('throws when actorFullName has empty parts', async () => {
|
|
@@ -222,7 +224,7 @@ describe('readConfigFile', () => {
|
|
|
222
224
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
223
225
|
});
|
|
224
226
|
|
|
225
|
-
await expect(readConfigFile()).rejects.toThrow('Invalid "actorFullName"');
|
|
227
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('Invalid "actorFullName"');
|
|
226
228
|
});
|
|
227
229
|
|
|
228
230
|
it('throws when overrideActorContext is not an array', async () => {
|
|
@@ -238,7 +240,7 @@ describe('readConfigFile', () => {
|
|
|
238
240
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
239
241
|
});
|
|
240
242
|
|
|
241
|
-
await expect(readConfigFile()).rejects.toThrow('Invalid "overrideActorContext"');
|
|
243
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('Invalid "overrideActorContext"');
|
|
242
244
|
});
|
|
243
245
|
|
|
244
246
|
it('throws when overrideActorContext contains non-strings', async () => {
|
|
@@ -254,7 +256,7 @@ describe('readConfigFile', () => {
|
|
|
254
256
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
255
257
|
});
|
|
256
258
|
|
|
257
|
-
await expect(readConfigFile()).rejects.toThrow('Invalid "overrideActorContext"');
|
|
259
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow('Invalid "overrideActorContext"');
|
|
258
260
|
});
|
|
259
261
|
|
|
260
262
|
it('throws when overrideActorContext entries overlap (one is a prefix of another)', async () => {
|
|
@@ -270,7 +272,7 @@ describe('readConfigFile', () => {
|
|
|
270
272
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
271
273
|
});
|
|
272
274
|
|
|
273
|
-
await expect(readConfigFile()).rejects.toThrow(/overlap/);
|
|
275
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow(/overlap/);
|
|
274
276
|
});
|
|
275
277
|
|
|
276
278
|
it('throws when overrideActorContext contains the repo root alongside another entry', async () => {
|
|
@@ -286,7 +288,7 @@ describe('readConfigFile', () => {
|
|
|
286
288
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
287
289
|
});
|
|
288
290
|
|
|
289
|
-
await expect(readConfigFile()).rejects.toThrow(/overlap/);
|
|
291
|
+
await expect(readConfigFile(emptyActorSelection)).rejects.toThrow(/overlap/);
|
|
290
292
|
});
|
|
291
293
|
|
|
292
294
|
it('adds the actor own folder automatically when overrideActorContext does not cover it', async () => {
|
|
@@ -302,7 +304,7 @@ describe('readConfigFile', () => {
|
|
|
302
304
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
303
305
|
});
|
|
304
306
|
|
|
305
|
-
const result = await readConfigFile();
|
|
307
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
306
308
|
expect(result[0].contextPaths).toEqual(['code', 'shared', 'actors/shopify']);
|
|
307
309
|
});
|
|
308
310
|
|
|
@@ -319,7 +321,7 @@ describe('readConfigFile', () => {
|
|
|
319
321
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
320
322
|
});
|
|
321
323
|
|
|
322
|
-
const result = await readConfigFile();
|
|
324
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
323
325
|
expect(result[0].folder).toBe('actors/shopify');
|
|
324
326
|
expect(result[0].contextPaths).toEqual(['actors/shopify', 'packages']);
|
|
325
327
|
});
|
|
@@ -337,7 +339,43 @@ describe('readConfigFile', () => {
|
|
|
337
339
|
'actors/shopify/.actor/actor.json': actorJson({}),
|
|
338
340
|
});
|
|
339
341
|
|
|
340
|
-
const result = await readConfigFile();
|
|
342
|
+
const result = await readConfigFile(emptyActorSelection);
|
|
341
343
|
expect(result[0].contextPaths).toEqual(['actors/shopify', 'code', 'shared']);
|
|
342
344
|
});
|
|
345
|
+
|
|
346
|
+
describe('actor selection', () => {
|
|
347
|
+
const twoActors = () =>
|
|
348
|
+
mockFiles({
|
|
349
|
+
[CONFIG_FILE_NAME]: validConfig([
|
|
350
|
+
{ folder: 'actors/a', actorFullName: 'team/a', tokenEnvVar: 'TOKEN' },
|
|
351
|
+
{ folder: 'actors/b', actorFullName: 'team/b', tokenEnvVar: 'TOKEN' },
|
|
352
|
+
]),
|
|
353
|
+
'actors/a/.actor/actor.json': actorJson({}),
|
|
354
|
+
'actors/b/.actor/actor.json': actorJson({}),
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
const fullNames = (result: { actorFullName: string }[]) => result.map((c) => c.actorFullName);
|
|
358
|
+
|
|
359
|
+
it('returns all actors when the selection is empty', async () => {
|
|
360
|
+
twoActors();
|
|
361
|
+
expect(fullNames(await readConfigFile(emptyActorSelection))).toEqual(['team/a', 'team/b']);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('keeps only the selected actors', async () => {
|
|
365
|
+
twoActors();
|
|
366
|
+
expect(fullNames(await readConfigFile({ actors: ['team/a'], ignore: [] }))).toEqual(['team/a']);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('drops ignored actors', async () => {
|
|
370
|
+
twoActors();
|
|
371
|
+
expect(fullNames(await readConfigFile({ actors: [], ignore: ['team/a'] }))).toEqual(['team/b']);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('throws on an unknown actor name', async () => {
|
|
375
|
+
twoActors();
|
|
376
|
+
await expect(readConfigFile({ actors: ['team/nope'], ignore: [] })).rejects.toThrow(
|
|
377
|
+
'do not exist: team/nope',
|
|
378
|
+
);
|
|
379
|
+
});
|
|
380
|
+
});
|
|
343
381
|
});
|