apify-test-tools 0.10.2-beta.1 → 0.10.2-beta.11

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.
Files changed (189) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/actionlint.yaml +11 -0
  3. package/.github/actions/checkout-restore-dependencies/action.yaml +64 -28
  4. package/.github/cli/apify-test-tools.mjs +360 -0
  5. package/.github/scripts/mask-config-secrets.sh +17 -0
  6. package/.github/scripts/run-with-apify-tokens.mjs +37 -12
  7. package/.github/workflows/_check_code.yaml +25 -16
  8. package/.github/workflows/_move_major_tag.yaml +5 -83
  9. package/.github/workflows/_tests.yaml +34 -0
  10. package/.github/workflows/_update_release_metadata.yaml +0 -12
  11. package/.github/workflows/manual_move_major_tag.yaml +3 -3
  12. package/.github/workflows/manual_release_stable.yaml +3 -13
  13. package/.github/workflows/on_master.yaml +9 -5
  14. package/.github/workflows/on_pull_request.yaml +3 -48
  15. package/.github/workflows/public_platform-tests-claude-investigate-and-fix.yaml +16 -3
  16. package/.github/workflows/public_platform-tests.yaml +27 -3
  17. package/.github/workflows/public_pr-build-test.yaml +67 -29
  18. package/.github/workflows/public_push-build-latest.yaml +44 -10
  19. package/.github/workflows/public_review.yaml +5 -4
  20. package/.husky/pre-commit +5 -0
  21. package/.prettierignore +3 -0
  22. package/CHANGELOG.md +17 -0
  23. package/CONTRIBUTING.md +112 -24
  24. package/README.md +218 -600
  25. package/bin/affected-actors.ts +198 -0
  26. package/bin/build-from-local.ts +65 -13
  27. package/bin/build.ts +123 -41
  28. package/bin/diff-changes.ts +32 -23
  29. package/bin/diff-json-schema.ts +5 -6
  30. package/bin/git.ts +69 -99
  31. package/bin/main.ts +96 -135
  32. package/bin/slack.ts +43 -10
  33. package/bin/stdin-input.ts +65 -0
  34. package/bin/test-report.ts +6 -9
  35. package/bin/types.ts +15 -0
  36. package/dist/bin/affected-actors.d.ts +46 -0
  37. package/dist/bin/affected-actors.d.ts.map +1 -0
  38. package/dist/bin/affected-actors.js +135 -0
  39. package/dist/bin/affected-actors.js.map +1 -0
  40. package/dist/bin/build-from-local.d.ts +12 -3
  41. package/dist/bin/build-from-local.d.ts.map +1 -1
  42. package/dist/bin/build-from-local.js +34 -12
  43. package/dist/bin/build-from-local.js.map +1 -1
  44. package/dist/bin/build.d.ts +30 -7
  45. package/dist/bin/build.d.ts.map +1 -1
  46. package/dist/bin/build.js +85 -26
  47. package/dist/bin/build.js.map +1 -1
  48. package/dist/bin/diff-changes.d.ts +11 -4
  49. package/dist/bin/diff-changes.d.ts.map +1 -1
  50. package/dist/bin/diff-changes.js +19 -19
  51. package/dist/bin/diff-changes.js.map +1 -1
  52. package/dist/bin/diff-json-schema.d.ts +2 -2
  53. package/dist/bin/diff-json-schema.d.ts.map +1 -1
  54. package/dist/bin/diff-json-schema.js +1 -4
  55. package/dist/bin/diff-json-schema.js.map +1 -1
  56. package/dist/bin/git.d.ts +23 -21
  57. package/dist/bin/git.d.ts.map +1 -1
  58. package/dist/bin/git.js +60 -83
  59. package/dist/bin/git.js.map +1 -1
  60. package/dist/bin/main.js +82 -105
  61. package/dist/bin/main.js.map +1 -1
  62. package/dist/bin/slack.d.ts +14 -4
  63. package/dist/bin/slack.d.ts.map +1 -1
  64. package/dist/bin/slack.js +39 -6
  65. package/dist/bin/slack.js.map +1 -1
  66. package/dist/bin/stdin-input.d.ts +17 -0
  67. package/dist/bin/stdin-input.d.ts.map +1 -0
  68. package/dist/bin/stdin-input.js +54 -0
  69. package/dist/bin/stdin-input.js.map +1 -0
  70. package/dist/bin/test-report.d.ts.map +1 -1
  71. package/dist/bin/test-report.js +6 -8
  72. package/dist/bin/test-report.js.map +1 -1
  73. package/dist/bin/types.d.ts +13 -0
  74. package/dist/bin/types.d.ts.map +1 -1
  75. package/dist/lib/extend-expect.d.ts.map +1 -1
  76. package/dist/lib/extend-expect.js +37 -218
  77. package/dist/lib/extend-expect.js.map +1 -1
  78. package/dist/lib/lib.d.ts +1 -2
  79. package/dist/lib/lib.d.ts.map +1 -1
  80. package/dist/lib/lib.js +15 -22
  81. package/dist/lib/lib.js.map +1 -1
  82. package/dist/lib/run-checks.d.ts +14 -0
  83. package/dist/lib/run-checks.d.ts.map +1 -0
  84. package/dist/lib/run-checks.js +82 -0
  85. package/dist/lib/run-checks.js.map +1 -0
  86. package/dist/lib/run-test-result.d.ts +3 -6
  87. package/dist/lib/run-test-result.d.ts.map +1 -1
  88. package/dist/lib/run-test-result.js +41 -54
  89. package/dist/lib/run-test-result.js.map +1 -1
  90. package/dist/test/bundle/cli-bundle.test.d.ts +2 -0
  91. package/dist/test/bundle/cli-bundle.test.d.ts.map +1 -0
  92. package/dist/test/bundle/cli-bundle.test.js +190 -0
  93. package/dist/test/bundle/cli-bundle.test.js.map +1 -0
  94. package/dist/test/e2e/cli-bundle.e2e.test.d.ts +2 -0
  95. package/dist/test/e2e/cli-bundle.e2e.test.d.ts.map +1 -0
  96. package/dist/test/e2e/cli-bundle.e2e.test.js +138 -0
  97. package/dist/test/e2e/cli-bundle.e2e.test.js.map +1 -0
  98. package/dist/test/e2e/git-build-release.e2e.test.d.ts +2 -0
  99. package/dist/test/e2e/git-build-release.e2e.test.d.ts.map +1 -0
  100. package/dist/test/e2e/git-build-release.e2e.test.js +87 -0
  101. package/dist/test/e2e/git-build-release.e2e.test.js.map +1 -0
  102. package/dist/test/e2e/helpers.d.ts +37 -0
  103. package/dist/test/e2e/helpers.d.ts.map +1 -0
  104. package/dist/test/e2e/helpers.js +57 -0
  105. package/dist/test/e2e/helpers.js.map +1 -0
  106. package/dist/test/unit/bin/affected-actors-cli.test.d.ts +2 -0
  107. package/dist/test/unit/bin/affected-actors-cli.test.d.ts.map +1 -0
  108. package/dist/test/unit/bin/affected-actors-cli.test.js +167 -0
  109. package/dist/test/unit/bin/affected-actors-cli.test.js.map +1 -0
  110. package/dist/test/unit/bin/affected-actors.test.d.ts +2 -0
  111. package/dist/test/unit/bin/affected-actors.test.d.ts.map +1 -0
  112. package/dist/test/unit/bin/affected-actors.test.js +141 -0
  113. package/dist/test/unit/bin/affected-actors.test.js.map +1 -0
  114. package/dist/test/unit/bin/build-cli.test.d.ts +2 -0
  115. package/dist/test/unit/bin/build-cli.test.d.ts.map +1 -0
  116. package/dist/test/unit/bin/build-cli.test.js +44 -0
  117. package/dist/test/unit/bin/build-cli.test.js.map +1 -0
  118. package/dist/test/unit/bin/build-from-local.test.js +65 -1
  119. package/dist/test/unit/bin/build-from-local.test.js.map +1 -1
  120. package/dist/test/unit/bin/build.test.js +223 -3
  121. package/dist/test/unit/bin/build.test.js.map +1 -1
  122. package/dist/test/unit/bin/compiled-cli.d.ts +6 -0
  123. package/dist/test/unit/bin/compiled-cli.d.ts.map +1 -0
  124. package/dist/test/unit/bin/compiled-cli.js +16 -0
  125. package/dist/test/unit/bin/compiled-cli.js.map +1 -0
  126. package/dist/test/unit/bin/diff-changes.test.js +130 -101
  127. package/dist/test/unit/bin/diff-changes.test.js.map +1 -1
  128. package/dist/test/unit/bin/diff.test.js +25 -28
  129. package/dist/test/unit/bin/diff.test.js.map +1 -1
  130. package/dist/test/unit/bin/git.test.js +69 -152
  131. package/dist/test/unit/bin/git.test.js.map +1 -1
  132. package/dist/test/unit/bin/slack.test.d.ts +2 -0
  133. package/dist/test/unit/bin/slack.test.d.ts.map +1 -0
  134. package/dist/test/unit/bin/slack.test.js +71 -0
  135. package/dist/test/unit/bin/slack.test.js.map +1 -0
  136. package/dist/test/unit/bin/stdin-input.test.d.ts +2 -0
  137. package/dist/test/unit/bin/stdin-input.test.d.ts.map +1 -0
  138. package/dist/test/unit/bin/stdin-input.test.js +50 -0
  139. package/dist/test/unit/bin/stdin-input.test.js.map +1 -0
  140. package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts +2 -0
  141. package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts.map +1 -0
  142. package/dist/test/unit/github-scripts/mask-config-secrets.test.js +50 -0
  143. package/dist/test/unit/github-scripts/mask-config-secrets.test.js.map +1 -0
  144. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts +2 -0
  145. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts.map +1 -0
  146. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js +102 -0
  147. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js.map +1 -0
  148. package/dist/test/unit/run-checks.test.d.ts +2 -0
  149. package/dist/test/unit/run-checks.test.d.ts.map +1 -0
  150. package/dist/test/unit/run-checks.test.js +62 -0
  151. package/dist/test/unit/run-checks.test.js.map +1 -0
  152. package/dist/test/unit/run-test-result.test.d.ts +2 -0
  153. package/dist/test/unit/run-test-result.test.d.ts.map +1 -0
  154. package/dist/test/unit/run-test-result.test.js +34 -0
  155. package/dist/test/unit/run-test-result.test.js.map +1 -0
  156. package/dist/test/unit/should-built-and-test.test.js +41 -38
  157. package/dist/test/unit/should-built-and-test.test.js.map +1 -1
  158. package/dist/tsconfig.tsbuildinfo +1 -1
  159. package/docs/cli.md +373 -0
  160. package/docs/lib.md +271 -0
  161. package/docs/workflows.md +370 -0
  162. package/lib/extend-expect.ts +48 -258
  163. package/lib/lib.ts +24 -28
  164. package/lib/run-checks.ts +101 -0
  165. package/lib/run-test-result.ts +45 -55
  166. package/package.json +13 -3
  167. package/test/bundle/cli-bundle.test.ts +235 -0
  168. package/test/e2e/cli-bundle.e2e.test.ts +207 -0
  169. package/test/e2e/git-build-release.e2e.test.ts +113 -0
  170. package/test/e2e/helpers.ts +82 -0
  171. package/test/unit/bin/affected-actors-cli.test.ts +201 -0
  172. package/test/unit/bin/affected-actors.test.ts +182 -0
  173. package/test/unit/bin/build-cli.test.ts +55 -0
  174. package/test/unit/bin/build-from-local.test.ts +71 -0
  175. package/test/unit/bin/build.test.ts +279 -3
  176. package/test/unit/bin/compiled-cli.ts +17 -0
  177. package/test/unit/bin/diff-changes.test.ts +139 -101
  178. package/test/unit/bin/diff.test.ts +25 -28
  179. package/test/unit/bin/git.test.ts +85 -176
  180. package/test/unit/bin/slack.test.ts +84 -0
  181. package/test/unit/bin/stdin-input.test.ts +61 -0
  182. package/test/unit/github-scripts/mask-config-secrets.test.ts +61 -0
  183. package/test/unit/github-scripts/run-with-apify-tokens.test.ts +115 -0
  184. package/test/unit/run-checks.test.ts +76 -0
  185. package/test/unit/run-test-result.test.ts +44 -0
  186. package/test/unit/should-built-and-test.test.ts +46 -39
  187. package/.github/scripts/check-major-tag-refs.mjs +0 -72
  188. package/.github/scripts/check-package-version-bump.mjs +0 -74
  189. package/.github/workflows-package-version +0 -1
@@ -39,91 +39,97 @@ const amazonActor = actorConfig('junglee/amazon-crawler', 'actors/junglee_Amazon
39
39
  'code',
40
40
  'shared',
41
41
  ]);
42
- const commits = [{ sha: 'Commit1', author: '', date: '', message: '' }];
42
+ const range = { fromRef: 'Commit0', toRef: 'Commit1' };
43
+ // What a PR (functional changes only) or a release (isLatest, all changes) builds, in config order
44
+ const changedActorsFor = async ({ isLatest = false, ...options }) => {
45
+ const { functional, cosmetic } = await getChangedActors(options);
46
+ const changed = isLatest ? [...functional, ...cosmetic] : functional;
47
+ return options.actorConfigs.filter((config) => changed.includes(config));
48
+ };
43
49
  describe('getChangedActors', () => {
44
50
  beforeEach(() => {
45
51
  vi.restoreAllMocks();
46
52
  vi.spyOn(DiffJsonSchema, 'isCosmeticOnlyJsonSchemaChange').mockResolvedValue(false);
47
53
  });
48
54
  it('returns empty array when no files changed', async () => {
49
- expect(await getChangedActors({ filepathsChanged: [], actorConfigs, commits })).toEqual([]);
55
+ expect(await changedActorsFor({ filepathsChanged: [], actorConfigs, range })).toEqual([]);
50
56
  });
51
57
  it('returns empty array when only ignored top-level files changed', async () => {
52
- const result = await getChangedActors({
58
+ const result = await changedActorsFor({
53
59
  filepathsChanged: ['.gitignore', 'README.md', '.husky/pre-commit', '.vscode/settings.json'],
54
60
  actorConfigs,
55
- commits,
61
+ range,
56
62
  });
57
63
  expect(result).toEqual([]);
58
64
  });
59
65
  it('does not ignore source files whose names contain an ignored file name', async () => {
60
- const result = await getChangedActors({
66
+ const result = await changedActorsFor({
61
67
  filepathsChanged: ['actors/foo_bar/src/.gitignore-helper.ts'],
62
68
  actorConfigs,
63
- commits,
69
+ range,
64
70
  });
65
71
  expect(result).toEqual([miniActor]);
66
72
  });
67
73
  it('returns the actor when a functional file in its folder changes', async () => {
68
- const result = await getChangedActors({
74
+ const result = await changedActorsFor({
69
75
  filepathsChanged: ['actors/foo_bar/src/main.ts'],
70
76
  actorConfigs,
71
- commits,
77
+ range,
72
78
  });
73
79
  expect(result).toEqual([miniActor]);
74
80
  });
75
81
  it('returns actor when isLatest and README in actor folder changed (cosmetic)', async () => {
76
- const result = await getChangedActors({
82
+ const result = await changedActorsFor({
77
83
  filepathsChanged: ['actors/foo_bar/README.md'],
78
84
  actorConfigs,
79
- commits,
85
+ range,
80
86
  isLatest: true,
81
87
  });
82
88
  expect(result).toEqual([miniActor]);
83
89
  });
84
90
  it('does not return actor when not isLatest and only README changed (cosmetic)', async () => {
85
- const result = await getChangedActors({
91
+ const result = await changedActorsFor({
86
92
  filepathsChanged: ['actors/foo_bar/README.md'],
87
93
  actorConfigs,
88
- commits,
94
+ range,
89
95
  isLatest: false,
90
96
  });
91
97
  expect(result).toEqual([]);
92
98
  });
93
99
  it('returns actor when isLatest and JSON file has only cosmetic changes', async () => {
94
100
  vi.spyOn(DiffJsonSchema, 'isCosmeticOnlyJsonSchemaChange').mockResolvedValue(true);
95
- const result = await getChangedActors({
101
+ const result = await changedActorsFor({
96
102
  filepathsChanged: ['actors/foo_bar/.actor/actor.json'],
97
103
  actorConfigs,
98
- commits,
104
+ range,
99
105
  isLatest: true,
100
106
  });
101
107
  expect(result).toEqual([miniActor]);
102
108
  });
103
109
  it('does not return actor when not isLatest and JSON file has only cosmetic changes', async () => {
104
110
  vi.spyOn(DiffJsonSchema, 'isCosmeticOnlyJsonSchemaChange').mockResolvedValue(true);
105
- const result = await getChangedActors({
111
+ const result = await changedActorsFor({
106
112
  filepathsChanged: ['actors/foo_bar/.actor/actor.json'],
107
113
  actorConfigs,
108
- commits,
114
+ range,
109
115
  isLatest: false,
110
116
  });
111
117
  expect(result).toEqual([]);
112
118
  });
113
119
  it('returns actor when JSON file has functional changes', async () => {
114
- const result = await getChangedActors({
120
+ const result = await changedActorsFor({
115
121
  filepathsChanged: ['actors/foo_bar/.actor/actor.json'],
116
122
  actorConfigs,
117
- commits,
123
+ range,
118
124
  });
119
125
  expect(result).toEqual([miniActor]);
120
126
  });
121
127
  it('JSON file in actor folder but outside .actor/ is functional, not checked for cosmetic', async () => {
122
128
  vi.spyOn(DiffJsonSchema, 'isCosmeticOnlyJsonSchemaChange').mockResolvedValue(true);
123
- const result = await getChangedActors({
129
+ const result = await changedActorsFor({
124
130
  filepathsChanged: ['actors/foo_bar/package.json'],
125
131
  actorConfigs,
126
- commits,
132
+ range,
127
133
  isLatest: false,
128
134
  });
129
135
  expect(result).toEqual([miniActor]);
@@ -131,48 +137,48 @@ describe('getChangedActors', () => {
131
137
  });
132
138
  it('JSON file under .actor/ inside actor folder is checked for cosmetic changes', async () => {
133
139
  vi.spyOn(DiffJsonSchema, 'isCosmeticOnlyJsonSchemaChange').mockResolvedValue(true);
134
- const result = await getChangedActors({
140
+ const result = await changedActorsFor({
135
141
  filepathsChanged: ['actors/foo_bar/.actor/input_schema.json'],
136
142
  actorConfigs,
137
- commits,
143
+ range,
138
144
  isLatest: false,
139
145
  });
140
146
  expect(result).toEqual([]);
141
- expect(DiffJsonSchema.isCosmeticOnlyJsonSchemaChange).toHaveBeenCalledWith(commits, 'actors/foo_bar/.actor/input_schema.json');
147
+ expect(DiffJsonSchema.isCosmeticOnlyJsonSchemaChange).toHaveBeenCalledWith(range, 'actors/foo_bar/.actor/input_schema.json');
142
148
  });
143
149
  it('does not trigger narrow-context actor when shared file changes', async () => {
144
- const result = await getChangedActors({
150
+ const result = await changedActorsFor({
145
151
  filepathsChanged: ['shared/utils.ts'],
146
152
  actorConfigs,
147
- commits,
153
+ range,
148
154
  });
149
155
  expect(result).toContainEqual(miniActor);
150
156
  expect(result).not.toContainEqual(standaloneActor);
151
157
  });
152
158
  it('root-level changelog outside any actor folder is cosmetic for every actor when isLatest', async () => {
153
- const result = await getChangedActors({
159
+ const result = await changedActorsFor({
154
160
  filepathsChanged: ['CHANGELOG.md'],
155
161
  actorConfigs,
156
- commits,
162
+ range,
157
163
  isLatest: true,
158
164
  });
159
165
  expect(result).toEqual(expect.arrayContaining([miniActor, standaloneActor]));
160
166
  expect(result).toHaveLength(2);
161
167
  });
162
168
  it('root-level changelog is not cosmetic-triggered when not isLatest', async () => {
163
- const result = await getChangedActors({
169
+ const result = await changedActorsFor({
164
170
  filepathsChanged: ['CHANGELOG.md'],
165
171
  actorConfigs,
166
- commits,
172
+ range,
167
173
  isLatest: false,
168
174
  });
169
175
  expect(result).toEqual([]);
170
176
  });
171
177
  it('treats any changelog filename as cosmetic regardless of configured paths', async () => {
172
- const result = await getChangedActors({
178
+ const result = await changedActorsFor({
173
179
  filepathsChanged: ['docs/CHANGELOG.md'],
174
180
  actorConfigs: [miniActor, standaloneActor],
175
- commits,
181
+ range,
176
182
  isLatest: true,
177
183
  });
178
184
  expect(result).toEqual([miniActor, standaloneActor]);
@@ -182,63 +188,63 @@ describe('getChangedActors', () => {
182
188
  ...standaloneActor,
183
189
  actorJson: { ...standaloneActor.actorJson, readme: new RelativeFile('docs/guide.md') },
184
190
  };
185
- const result = await getChangedActors({
191
+ const result = await changedActorsFor({
186
192
  filepathsChanged: ['docs/guide.md'],
187
193
  actorConfigs: [configuredActor],
188
- commits,
194
+ range,
189
195
  isLatest: true,
190
196
  });
191
197
  expect(result).toEqual([]);
192
198
  });
193
199
  it('triggers narrow-context actor when its own folder changes', async () => {
194
- const result = await getChangedActors({
200
+ const result = await changedActorsFor({
195
201
  filepathsChanged: ['standalone-actors/standalone/src/main.ts'],
196
202
  actorConfigs,
197
- commits,
203
+ range,
198
204
  });
199
205
  expect(result).toContainEqual(standaloneActor);
200
206
  });
201
207
  it('deduplicates actors when multiple files in same actor folder change', async () => {
202
- const result = await getChangedActors({
208
+ const result = await changedActorsFor({
203
209
  filepathsChanged: ['actors/foo_bar/src/main.ts', 'actors/foo_bar/package.json'],
204
210
  actorConfigs,
205
- commits,
211
+ range,
206
212
  });
207
213
  expect(result).toHaveLength(1);
208
214
  expect(result).toContainEqual(miniActor);
209
215
  });
210
216
  it('handles mixed changes: returns both broad and narrow-context actors', async () => {
211
- const result = await getChangedActors({
217
+ const result = await changedActorsFor({
212
218
  filepathsChanged: ['actors/foo_bar/src/main.ts', 'standalone-actors/standalone/Dockerfile'],
213
219
  actorConfigs,
214
- commits,
220
+ range,
215
221
  });
216
222
  expect(result).toContainEqual(miniActor);
217
223
  expect(result).toContainEqual(standaloneActor);
218
224
  });
219
225
  it('matches folder where folder name differs from actor name', async () => {
220
226
  const ownerlessActor = actorConfig('myteam/shopify-scraper', 'actors/shopify', 'APIFY_TOKEN_MYTEAM', '', ['']);
221
- const result = await getChangedActors({
227
+ const result = await changedActorsFor({
222
228
  filepathsChanged: ['actors/shopify/src/main.ts'],
223
229
  actorConfigs: [ownerlessActor],
224
- commits,
230
+ range,
225
231
  });
226
232
  expect(result).toEqual([ownerlessActor]);
227
233
  });
228
234
  it('in single-actor repo, .actor/ changes trigger builds', async () => {
229
235
  const rootActor = actorConfig('myteam/my-actor', '', 'BUILDER_APIFY_TOKEN', '', ['']);
230
- const result = await getChangedActors({
236
+ const result = await changedActorsFor({
231
237
  filepathsChanged: ['.actor/actor.json'],
232
238
  actorConfigs: [rootActor],
233
- commits,
239
+ range,
234
240
  });
235
241
  expect(result).toEqual([rootActor]);
236
242
  });
237
243
  it('in multi-actor repo, .actor/ changes only trigger broad-context actors', async () => {
238
- const result = await getChangedActors({
244
+ const result = await changedActorsFor({
239
245
  filepathsChanged: ['.actor/actor.json'],
240
246
  actorConfigs,
241
- commits,
247
+ range,
242
248
  });
243
249
  expect(result).toEqual([miniActor]);
244
250
  });
@@ -246,38 +252,38 @@ describe('getChangedActors', () => {
246
252
  const narrowActor = actorConfig('foo/bar', 'actors/foo_bar', 'APIFY_TOKEN_FOO', 'actors/foo_bar', [
247
253
  'actors/foo_bar',
248
254
  ]);
249
- const result = await getChangedActors({
255
+ const result = await changedActorsFor({
250
256
  filepathsChanged: ['Actors/FOO_BAR/Main.ts'],
251
257
  actorConfigs: [narrowActor],
252
- commits,
258
+ range,
253
259
  });
254
260
  expect(result).toEqual([]);
255
261
  });
256
262
  it('triggers actor with contextPaths override when file matches an override path', async () => {
257
263
  const overrideActor = actorConfig('team/override-actor', 'actors/override', 'APIFY_TOKEN_TEAM', 'actors/override', ['actors/override', 'packages']);
258
- const result = await getChangedActors({
264
+ const result = await changedActorsFor({
259
265
  filepathsChanged: ['packages/shared/utils.ts'],
260
266
  actorConfigs: [overrideActor],
261
- commits,
267
+ range,
262
268
  });
263
269
  expect(result).toEqual([overrideActor]);
264
270
  });
265
271
  it('does not trigger actor with contextPaths override when file is outside all override paths', async () => {
266
272
  const overrideActor = actorConfig('team/override-actor', 'actors/override', 'APIFY_TOKEN_TEAM', 'actors/override', ['actors/override', 'packages']);
267
- const result = await getChangedActors({
273
+ const result = await changedActorsFor({
268
274
  filepathsChanged: ['other-dir/file.ts'],
269
275
  actorConfigs: [overrideActor],
270
- commits,
276
+ range,
271
277
  });
272
278
  expect(result).toEqual([]);
273
279
  });
274
280
  it('broad-context actor skips files in sibling actor folders', async () => {
275
281
  const actorA = actorConfig('team/actor-a', 'actors/a', 'APIFY_TOKEN_TEAM', '', ['']);
276
282
  const actorB = actorConfig('team/actor-b', 'actors/b', 'APIFY_TOKEN_TEAM', '', ['']);
277
- const result = await getChangedActors({
283
+ const result = await changedActorsFor({
278
284
  filepathsChanged: ['actors/b/src/main.ts'],
279
285
  actorConfigs: [actorA, actorB],
280
- commits,
286
+ range,
281
287
  });
282
288
  expect(result).toEqual([actorB]);
283
289
  });
@@ -286,10 +292,10 @@ describe('getChangedActors', () => {
286
292
  const childActor = actorConfig('team/child', 'actors/child', 'APIFY_TOKEN_TEAM', 'actors/child', [
287
293
  'actors/child',
288
294
  ]);
289
- const result = await getChangedActors({
295
+ const result = await changedActorsFor({
290
296
  filepathsChanged: ['actors/child/src/main.ts'],
291
297
  actorConfigs: [rootActor, childActor],
292
- commits,
298
+ range,
293
299
  });
294
300
  expect(result).not.toContainEqual(rootActor);
295
301
  expect(result).toContainEqual(childActor);
@@ -299,73 +305,73 @@ describe('getChangedActors', () => {
299
305
  const childActor = actorConfig('team/child', 'actors/child', 'APIFY_TOKEN_TEAM', 'actors/child', [
300
306
  'actors/child',
301
307
  ]);
302
- const result = await getChangedActors({
308
+ const result = await changedActorsFor({
303
309
  filepathsChanged: ['lib/shared-utils.ts'],
304
310
  actorConfigs: [rootActor, childActor],
305
- commits,
311
+ range,
306
312
  });
307
313
  expect(result).toContainEqual(rootActor);
308
314
  expect(result).not.toContainEqual(childActor);
309
315
  });
310
316
  it('file matched by .dockerignore is treated as ignored', async () => {
311
317
  vi.spyOn(Dockerignore, 'loadDockerIgnore').mockReturnValue((filePath) => filePath === 'actors/foo_bar/node_modules/foo.js');
312
- const result = await getChangedActors({
318
+ const result = await changedActorsFor({
313
319
  filepathsChanged: ['actors/foo_bar/node_modules/foo.js'],
314
320
  actorConfigs: [miniActor],
315
- commits,
321
+ range,
316
322
  });
317
323
  expect(result).toEqual([]);
318
324
  });
319
325
  it('file not matched by .dockerignore is classified normally', async () => {
320
326
  vi.spyOn(Dockerignore, 'loadDockerIgnore').mockReturnValue((filePath) => filePath.includes('node_modules'));
321
- const result = await getChangedActors({
327
+ const result = await changedActorsFor({
322
328
  filepathsChanged: ['actors/foo_bar/src/main.ts'],
323
329
  actorConfigs: [miniActor],
324
- commits,
330
+ range,
325
331
  });
326
332
  expect(result).toEqual([miniActor]);
327
333
  });
328
334
  it('test file listed in .dockerignore triggers a build when it matches the test files glob', async () => {
329
335
  vi.spyOn(Dockerignore, 'loadDockerIgnore').mockReturnValue((filePath) => filePath.startsWith('test/'));
330
- const result = await getChangedActors({
336
+ const result = await changedActorsFor({
331
337
  filepathsChanged: ['test/platform/daily/foo.test.ts'],
332
338
  actorConfigs: [miniActor],
333
- commits,
339
+ range,
334
340
  testFilesGlob: 'test/platform/**',
335
341
  });
336
342
  expect(result).toEqual([miniActor]);
337
343
  });
338
344
  it('test file listed in .dockerignore stays ignored without a test files glob', async () => {
339
345
  vi.spyOn(Dockerignore, 'loadDockerIgnore').mockReturnValue((filePath) => filePath.startsWith('test/'));
340
- const result = await getChangedActors({
346
+ const result = await changedActorsFor({
341
347
  filepathsChanged: ['test/platform/daily/foo.test.ts'],
342
348
  actorConfigs: [miniActor],
343
- commits,
349
+ range,
344
350
  });
345
351
  expect(result).toEqual([]);
346
352
  });
347
353
  it('test files glob matches case-insensitively and does not bypass .dockerignore for other files', async () => {
348
354
  vi.spyOn(Dockerignore, 'loadDockerIgnore').mockReturnValue(() => true);
349
- const result = await getChangedActors({
355
+ const result = await changedActorsFor({
350
356
  filepathsChanged: ['Test/Platform/Foo.test.ts'],
351
357
  actorConfigs: [miniActor],
352
- commits,
358
+ range,
353
359
  testFilesGlob: 'test/platform/**',
354
360
  });
355
361
  expect(result).toEqual([miniActor]);
356
- expect(await getChangedActors({
362
+ expect(await changedActorsFor({
357
363
  filepathsChanged: ['actors/foo_bar/node_modules/foo.js'],
358
364
  actorConfigs: [miniActor],
359
- commits,
365
+ range,
360
366
  testFilesGlob: 'test/platform/**',
361
367
  })).toEqual([]);
362
368
  });
363
369
  it('test file outside an actor context still does not trigger it', async () => {
364
370
  vi.spyOn(Dockerignore, 'loadDockerIgnore').mockReturnValue(() => true);
365
- const result = await getChangedActors({
371
+ const result = await changedActorsFor({
366
372
  filepathsChanged: ['test/platform/daily/foo.test.ts'],
367
373
  actorConfigs: [standaloneActor],
368
- commits,
374
+ range,
369
375
  testFilesGlob: 'test/platform/**',
370
376
  });
371
377
  expect(result).toEqual([]);
@@ -376,77 +382,77 @@ describe('getChangedActors', () => {
376
382
  ...standaloneActor,
377
383
  contextPaths: [...standaloneActor.contextPaths, new RelativeDir('test')],
378
384
  };
379
- const result = await getChangedActors({
385
+ const result = await changedActorsFor({
380
386
  filepathsChanged: ['test/platform/standalone.test.ts'],
381
387
  actorConfigs: [actorWithTests],
382
- commits,
388
+ range,
383
389
  testFilesGlob: 'test/platform/**',
384
390
  });
385
391
  expect(result).toEqual([actorWithTests]);
386
392
  });
387
393
  it('JSON file in context but outside actor folder is functional (not checked for cosmetic)', async () => {
388
- const result = await getChangedActors({
394
+ const result = await changedActorsFor({
389
395
  filepathsChanged: ['lib/config.json'],
390
396
  actorConfigs: [miniActor],
391
- commits,
397
+ range,
392
398
  });
393
399
  expect(result).toEqual([miniActor]);
394
400
  });
395
401
  it('README outside actor folder but inside context is ignored (not cosmetic)', async () => {
396
- const result = await getChangedActors({
402
+ const result = await changedActorsFor({
397
403
  filepathsChanged: ['docs/README.md'],
398
404
  actorConfigs: [miniActor],
399
- commits,
405
+ range,
400
406
  isLatest: true,
401
407
  });
402
408
  expect(result).toEqual([]);
403
409
  });
404
410
  it('README inside actor folder is cosmetic', async () => {
405
- const result = await getChangedActors({
411
+ const result = await changedActorsFor({
406
412
  filepathsChanged: ['actors/foo_bar/README.md'],
407
413
  actorConfigs: [miniActor],
408
- commits,
414
+ range,
409
415
  isLatest: true,
410
416
  });
411
417
  expect(result).toEqual([miniActor]);
412
418
  });
413
419
  it('ignores a standalone actor top-level dev file relative to its context', async () => {
414
- const result = await getChangedActors({
420
+ const result = await changedActorsFor({
415
421
  filepathsChanged: ['standalone-actors/standalone/.eslintrc'],
416
422
  actorConfigs,
417
- commits,
423
+ range,
418
424
  });
419
425
  expect(result).toEqual([]);
420
426
  });
421
427
  it('does not special-case code/ and shared/ prefixes anymore — must be declared via overrideActorContext', async () => {
422
- const result = await getChangedActors({
428
+ const result = await changedActorsFor({
423
429
  filepathsChanged: ['code/some/code.ts'],
424
430
  actorConfigs: [miniActor],
425
- commits,
431
+ range,
426
432
  });
427
433
  expect(result).toEqual([miniActor]);
428
434
  });
429
435
  it('ignores code/.eslintrc when "code" is declared via overrideActorContext', async () => {
430
- const result = await getChangedActors({
436
+ const result = await changedActorsFor({
431
437
  filepathsChanged: ['code/.eslintrc'],
432
438
  actorConfigs: [amazonActor],
433
- commits,
439
+ range,
434
440
  });
435
441
  expect(result).toEqual([]);
436
442
  });
437
443
  it('shared/Dockerfile declared via overrideActorContext is functional', async () => {
438
- const result = await getChangedActors({
444
+ const result = await changedActorsFor({
439
445
  filepathsChanged: ['shared/Dockerfile'],
440
446
  actorConfigs: [amazonActor],
441
- commits,
447
+ range,
442
448
  });
443
449
  expect(result).toEqual([amazonActor]);
444
450
  });
445
451
  it('code/README.md declared via overrideActorContext is ignored (outside actor folder)', async () => {
446
- const result = await getChangedActors({
452
+ const result = await changedActorsFor({
447
453
  filepathsChanged: ['code/README.md'],
448
454
  actorConfigs: [amazonActor],
449
- commits,
455
+ range,
450
456
  isLatest: true,
451
457
  });
452
458
  expect(result).toEqual([]);
@@ -462,10 +468,11 @@ describe('getChangedActors logging', () => {
462
468
  await getChangedActors({
463
469
  filepathsChanged: ['actors/foo_bar/src/main.ts'],
464
470
  actorConfigs: [miniActor],
465
- commits,
471
+ range,
466
472
  });
467
473
  expect(logger.info).toHaveBeenCalledWith('[DIFF]: Changes specific to actor foo/bar: actors/foo_bar/src/main.ts');
468
- expect(logger.info).toHaveBeenCalledWith('[DIFF]: Actors to be built and tested: foo/bar');
474
+ expect(logger.info).toHaveBeenCalledWith('[DIFF]: Actors with functional changes: foo/bar');
475
+ expect(logger.info).toHaveBeenCalledWith('[DIFF]: Actors with only cosmetic changes: none');
469
476
  });
470
477
  it('logs a single "shared" group when two actors are triggered by the exact same file', async () => {
471
478
  const actorA = actorConfig('team/actor-a', 'actors/a', 'APIFY_TOKEN_TEAM', '', ['', 'shared']);
@@ -473,11 +480,11 @@ describe('getChangedActors logging', () => {
473
480
  await getChangedActors({
474
481
  filepathsChanged: ['shared/shared.ts'],
475
482
  actorConfigs: [actorA, actorB],
476
- commits,
483
+ range,
477
484
  });
478
485
  expect(logger.info).toHaveBeenCalledWith('[DIFF]: Shared changes for actors team/actor-a, team/actor-b: shared/shared.ts');
479
486
  expect(logger.info).not.toHaveBeenCalledWith(expect.stringContaining('Changes specific to actor'));
480
- expect(logger.info).toHaveBeenCalledWith('[DIFF]: Actors to be built and tested: team/actor-a, team/actor-b');
487
+ expect(logger.info).toHaveBeenCalledWith('[DIFF]: Actors with functional changes: team/actor-a, team/actor-b');
481
488
  });
482
489
  it('logs shared and specific groups in descending-size order for partial overlap across actors', async () => {
483
490
  const actorA = actorConfig('team/actor-a', 'actors/a', 'APIFY_TOKEN_TEAM', '', ['']);
@@ -485,14 +492,15 @@ describe('getChangedActors logging', () => {
485
492
  await getChangedActors({
486
493
  filepathsChanged: ['shared.ts', 'actors/a/a-only.ts', 'actors/b/b-only.ts'],
487
494
  actorConfigs: [actorA, actorB],
488
- commits,
495
+ range,
489
496
  });
490
497
  const errorCalls = vi.mocked(logger.info).mock.calls.map((call) => call[0]);
491
498
  expect(errorCalls).toEqual([
492
499
  '[DIFF]: Shared changes for actors team/actor-a, team/actor-b: shared.ts',
493
500
  '[DIFF]: Changes specific to actor team/actor-a: actors/a/a-only.ts',
494
501
  '[DIFF]: Changes specific to actor team/actor-b: actors/b/b-only.ts',
495
- '[DIFF]: Actors to be built and tested: team/actor-a, team/actor-b',
502
+ '[DIFF]: Actors with functional changes: team/actor-a, team/actor-b',
503
+ '[DIFF]: Actors with only cosmetic changes: none',
496
504
  ]);
497
505
  });
498
506
  const outsideContextWarning = (testFile) => `[DIFF]: Test file ${testFile} is outside every Actor's context, so changing only it builds and tests nothing. ` +
@@ -501,16 +509,16 @@ describe('getChangedActors logging', () => {
501
509
  await getChangedActors({
502
510
  filepathsChanged: ['test/platform/standalone.test.ts'],
503
511
  actorConfigs: [standaloneActor],
504
- commits,
512
+ range,
505
513
  testFilesGlob: 'test/platform/**',
506
514
  });
507
515
  expect(logger.warn).toHaveBeenCalledWith(outsideContextWarning('test/platform/standalone.test.ts'));
508
516
  });
509
517
  it('still warns when the same push also rebuilds an Actor', async () => {
510
- const result = await getChangedActors({
518
+ const result = await changedActorsFor({
511
519
  filepathsChanged: ['test/platform/standalone.test.ts', 'standalone-actors/standalone/src/main.ts'],
512
520
  actorConfigs: [standaloneActor],
513
- commits,
521
+ range,
514
522
  testFilesGlob: 'test/platform/**',
515
523
  });
516
524
  expect(result).toEqual([standaloneActor]);
@@ -520,7 +528,7 @@ describe('getChangedActors logging', () => {
520
528
  await getChangedActors({
521
529
  filepathsChanged: ['test/platform/foo.test.ts', 'test/platform/README.md', 'test/platform/CHANGELOG.md'],
522
530
  actorConfigs: [miniActor],
523
- commits,
531
+ range,
524
532
  testFilesGlob: 'test/platform/**',
525
533
  });
526
534
  expect(logger.warn).not.toHaveBeenCalled();
@@ -529,11 +537,32 @@ describe('getChangedActors logging', () => {
529
537
  await getChangedActors({
530
538
  filepathsChanged: ['.gitignore', '.prettierrc'],
531
539
  actorConfigs,
532
- commits,
540
+ range,
533
541
  });
534
542
  expect(logger.info).not.toHaveBeenCalledWith(expect.stringContaining('Shared changes'));
535
543
  expect(logger.info).not.toHaveBeenCalledWith(expect.stringContaining('Changes specific to'));
536
- expect(logger.info).toHaveBeenCalledWith('[DIFF]: No relevant files changed, skipping builds and tests');
544
+ expect(logger.info).toHaveBeenCalledWith('[DIFF]: Actors with functional changes: none');
545
+ expect(logger.info).toHaveBeenCalledWith('[DIFF]: Actors with only cosmetic changes: none');
546
+ });
547
+ });
548
+ describe('getChangedActors split by impact', () => {
549
+ beforeEach(() => {
550
+ vi.spyOn(DiffJsonSchema, 'isCosmeticOnlyJsonSchemaChange').mockResolvedValue(false);
551
+ });
552
+ it('lists an Actor as functional when it has any functional change, and as cosmetic only otherwise', async () => {
553
+ const result = await getChangedActors({
554
+ filepathsChanged: [
555
+ 'actors/foo_bar/README.md',
556
+ 'standalone-actors/standalone/README.md',
557
+ 'actors/foo_bar/src/main.ts',
558
+ ],
559
+ actorConfigs,
560
+ range,
561
+ });
562
+ expect(result).toStrictEqual({ functional: [miniActor], cosmetic: [standaloneActor] });
563
+ });
564
+ it('returns empty lists when nothing relevant changed', async () => {
565
+ expect(await getChangedActors({ filepathsChanged: ['.vscode/settings.json'], actorConfigs, range })).toStrictEqual({ functional: [], cosmetic: [] });
537
566
  });
538
567
  });
539
568
  //# sourceMappingURL=diff-changes.test.js.map