apify-test-tools 0.10.2-beta.2 → 0.10.2-beta.3
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/.github/cli/apify-test-tools.mjs +124 -125
- package/CHANGELOG.md +1 -0
- package/README.md +55 -0
- package/bin/affected-actors.ts +166 -0
- package/bin/diff-changes.ts +25 -17
- package/bin/git.ts +52 -41
- package/bin/main.ts +43 -73
- package/dist/bin/affected-actors.d.ts +50 -0
- package/dist/bin/affected-actors.d.ts.map +1 -0
- package/dist/bin/affected-actors.js +89 -0
- package/dist/bin/affected-actors.js.map +1 -0
- package/dist/bin/diff-changes.d.ts +8 -2
- package/dist/bin/diff-changes.d.ts.map +1 -1
- package/dist/bin/diff-changes.js +16 -16
- package/dist/bin/diff-changes.js.map +1 -1
- package/dist/bin/git.d.ts +23 -13
- package/dist/bin/git.d.ts.map +1 -1
- package/dist/bin/git.js +44 -32
- package/dist/bin/git.js.map +1 -1
- package/dist/bin/main.js +39 -53
- package/dist/bin/main.js.map +1 -1
- package/dist/test/bundle/cli-bundle.test.js +9 -2
- package/dist/test/bundle/cli-bundle.test.js.map +1 -1
- package/dist/test/unit/bin/affected-actors.test.d.ts +2 -0
- package/dist/test/unit/bin/affected-actors.test.d.ts.map +1 -0
- package/dist/test/unit/bin/affected-actors.test.js +160 -0
- package/dist/test/unit/bin/affected-actors.test.js.map +1 -0
- package/dist/test/unit/bin/diff-changes.test.js +78 -49
- package/dist/test/unit/bin/diff-changes.test.js.map +1 -1
- package/dist/test/unit/bin/git.test.js +50 -53
- package/dist/test/unit/bin/git.test.js.map +1 -1
- package/dist/test/unit/should-built-and-test.test.js +23 -17
- package/dist/test/unit/should-built-and-test.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/test/bundle/cli-bundle.test.ts +9 -2
- package/test/unit/bin/affected-actors.test.ts +190 -0
- package/test/unit/bin/diff-changes.test.ts +87 -49
- package/test/unit/bin/git.test.ts +56 -53
- package/test/unit/should-built-and-test.test.ts +27 -17
package/package.json
CHANGED
|
@@ -130,9 +130,16 @@ describe('CLI bundle', () => {
|
|
|
130
130
|
});
|
|
131
131
|
|
|
132
132
|
it('get-affected-actors returns only the Actor whose files changed', () => {
|
|
133
|
-
|
|
133
|
+
// `feature` is checked out, and the range always ends at HEAD
|
|
134
|
+
const { status, stdout, stderr } = runCli('get-affected-actors', '--base', 'main');
|
|
134
135
|
expect(status, stderr).toBe(0);
|
|
135
|
-
expect(JSON.parse(stdout)).toMatchObject(
|
|
136
|
+
expect(JSON.parse(stdout)).toMatchObject({
|
|
137
|
+
version: 1,
|
|
138
|
+
head: headSha,
|
|
139
|
+
functionallyChangedActors: [{ actorFullName: 'tester/foo' }],
|
|
140
|
+
// The root README isn't in tester/bar's folder, so it doesn't count for it
|
|
141
|
+
cosmeticallyChangedActors: [],
|
|
142
|
+
});
|
|
136
143
|
});
|
|
137
144
|
|
|
138
145
|
it('build --dry-run with nothing to build needs no token', () => {
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import type { MockInstance } from 'vitest';
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { getAffectedActors, toAffectedActorsDocument } from '../../../bin/affected-actors.js';
|
|
5
|
+
import * as DiffChanges from '../../../bin/diff-changes.js';
|
|
6
|
+
import * as Git from '../../../bin/git.js';
|
|
7
|
+
import type { ActorConfig, Commit } from '../../../bin/types.js';
|
|
8
|
+
import * as LoadConfig from '../../../bin/utils/config/load-config.js';
|
|
9
|
+
|
|
10
|
+
// Everything that reads the configs is mocked, so only the identity and name of an Actor matter here
|
|
11
|
+
const actorA = { actorFullName: 'owner/a' } as ActorConfig;
|
|
12
|
+
const actorB = { actorFullName: 'owner/b' } as ActorConfig;
|
|
13
|
+
|
|
14
|
+
const headSha = 'f'.repeat(40);
|
|
15
|
+
const sinceSha = '5'.repeat(40);
|
|
16
|
+
const commit = (sha: string): Commit => ({ sha, author: 'Dev<dev@example.com>', date: 'Date', message: 'msg' });
|
|
17
|
+
const commits = [commit('1'.repeat(40)), commit('2'.repeat(40))];
|
|
18
|
+
const changedFiles = ['src/main.ts', 'CHANGELOG.md'];
|
|
19
|
+
|
|
20
|
+
const selection = { actors: [], ignore: [] };
|
|
21
|
+
|
|
22
|
+
describe('getAffectedActors', () => {
|
|
23
|
+
let changedActorsSpy: MockInstance;
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
vi.spyOn(LoadConfig, 'readConfigFile').mockResolvedValue([actorA, actorB]);
|
|
27
|
+
changedActorsSpy = vi
|
|
28
|
+
.spyOn(DiffChanges, 'getChangedActors')
|
|
29
|
+
.mockResolvedValue({ functional: [actorA], cosmetic: [actorB] });
|
|
30
|
+
vi.spyOn(Git, 'resolveCommitSha').mockResolvedValue(headSha);
|
|
31
|
+
vi.spyOn(Git, 'resolveBranchName').mockResolvedValue('feature');
|
|
32
|
+
vi.spyOn(Git, 'getChangedFilesBetween').mockResolvedValue(changedFiles);
|
|
33
|
+
vi.spyOn(Git, 'getChangelogAdditions').mockResolvedValue('- Added foo');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('requires --base or --since', async () => {
|
|
37
|
+
const options = { head: 'HEAD', ...selection };
|
|
38
|
+
await expect(getAffectedActors(options)).rejects.toThrow('Pass --base, --since, or both');
|
|
39
|
+
// An empty --since (e.g. from an empty cache file) counts as not passed
|
|
40
|
+
await expect(getAffectedActors({ ...options, since: '' })).rejects.toThrow('Pass --base, --since, or both');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('with --base', () => {
|
|
44
|
+
let getCommitsSpy: MockInstance;
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
vi.spyOn(Git, 'hasMergeFromTarget').mockResolvedValue(false);
|
|
48
|
+
getCommitsSpy = vi.spyOn(Git, 'getCommits').mockResolvedValue(commits);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('inspects the branch commits after --since', async () => {
|
|
52
|
+
const result = await getAffectedActors({
|
|
53
|
+
head: 'origin/feature',
|
|
54
|
+
base: 'origin/master',
|
|
55
|
+
since: sinceSha,
|
|
56
|
+
...selection,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(result).toStrictEqual({
|
|
60
|
+
headSha,
|
|
61
|
+
ref: 'feature',
|
|
62
|
+
commits,
|
|
63
|
+
changedFiles,
|
|
64
|
+
changelog: '- Added foo',
|
|
65
|
+
functionallyChangedActors: [actorA],
|
|
66
|
+
cosmeticallyChangedActors: [actorB],
|
|
67
|
+
});
|
|
68
|
+
expect(getCommitsSpy).toHaveBeenCalledWith({
|
|
69
|
+
sourceBranch: 'origin/feature',
|
|
70
|
+
targetBranch: 'origin/master',
|
|
71
|
+
baseCommit: sinceSha,
|
|
72
|
+
});
|
|
73
|
+
// From the parent of the oldest commit to the newest one, for the files and the changelog alike
|
|
74
|
+
expect(Git.getChangedFilesBetween).toHaveBeenCalledWith(`${commits[0].sha}~`, commits[1].sha);
|
|
75
|
+
expect(Git.getChangelogAdditions).toHaveBeenCalledWith(`${commits[0].sha}~`, commits[1].sha, changedFiles);
|
|
76
|
+
expect(changedActorsSpy).toHaveBeenCalledWith({
|
|
77
|
+
filepathsChanged: changedFiles,
|
|
78
|
+
actorConfigs: [actorA, actorB],
|
|
79
|
+
commits,
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('when the branch merged --base in', () => {
|
|
84
|
+
beforeEach(() => {
|
|
85
|
+
vi.spyOn(Git, 'hasMergeFromTarget').mockResolvedValue(true);
|
|
86
|
+
vi.spyOn(Git, 'getBranchOnlyChangedFiles').mockResolvedValue(['own-file']);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const getWithOwnChanges = async (own: DiffChanges.ChangedActors) => {
|
|
90
|
+
changedActorsSpy.mockImplementation(async ({ filepathsChanged }) =>
|
|
91
|
+
filepathsChanged[0] === 'own-file' ? own : { functional: [actorA], cosmetic: [actorB] },
|
|
92
|
+
);
|
|
93
|
+
return getAffectedActors({ head: 'feature', base: 'master', since: sinceSha, ...selection });
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
it("classifies the branch's own files against the whole branch, ignoring --since", async () => {
|
|
97
|
+
await getWithOwnChanges({ functional: [actorA], cosmetic: [] });
|
|
98
|
+
expect(changedActorsSpy).toHaveBeenCalledWith({
|
|
99
|
+
filepathsChanged: ['own-file'],
|
|
100
|
+
actorConfigs: [actorA, actorB],
|
|
101
|
+
commits,
|
|
102
|
+
});
|
|
103
|
+
expect(getCommitsSpy).toHaveBeenCalledWith({ sourceBranch: 'feature', targetBranch: 'master' });
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('reports everything when the branch has functional changes of its own', async () => {
|
|
107
|
+
const result = await getWithOwnChanges({ functional: [actorA], cosmetic: [] });
|
|
108
|
+
expect(result.functionallyChangedActors).toStrictEqual([actorA]);
|
|
109
|
+
expect(result.cosmeticallyChangedActors).toStrictEqual([actorB]);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('reports only cosmetic Actors when its own changes are only cosmetic', async () => {
|
|
113
|
+
const result = await getWithOwnChanges({ functional: [], cosmetic: [actorB] });
|
|
114
|
+
expect(result.functionallyChangedActors).toStrictEqual([]);
|
|
115
|
+
expect(result.cosmeticallyChangedActors).toStrictEqual([actorB]);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('reports nothing when it has no changes of its own', async () => {
|
|
119
|
+
const result = await getWithOwnChanges({ functional: [], cosmetic: [] });
|
|
120
|
+
expect(result.functionallyChangedActors).toStrictEqual([]);
|
|
121
|
+
expect(result.cosmeticallyChangedActors).toStrictEqual([]);
|
|
122
|
+
// The range is still reported
|
|
123
|
+
expect(result.commits).toStrictEqual(commits);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('with --since only', () => {
|
|
129
|
+
let resolveBaseSpy: MockInstance;
|
|
130
|
+
let commitsBetweenSpy: MockInstance;
|
|
131
|
+
|
|
132
|
+
beforeEach(() => {
|
|
133
|
+
resolveBaseSpy = vi.spyOn(Git, 'resolveReleaseBaseCommit').mockResolvedValue(sinceSha);
|
|
134
|
+
commitsBetweenSpy = vi.spyOn(Git, 'getCommitsBetween').mockResolvedValue(commits);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('inspects everything after --since up to --head', async () => {
|
|
138
|
+
const result = await getAffectedActors({ head: 'release', since: 'HEAD~2', ...selection });
|
|
139
|
+
|
|
140
|
+
expect(result).toStrictEqual({
|
|
141
|
+
headSha,
|
|
142
|
+
ref: 'feature',
|
|
143
|
+
commits,
|
|
144
|
+
changedFiles,
|
|
145
|
+
changelog: '- Added foo',
|
|
146
|
+
functionallyChangedActors: [actorA],
|
|
147
|
+
cosmeticallyChangedActors: [actorB],
|
|
148
|
+
});
|
|
149
|
+
expect(resolveBaseSpy).toHaveBeenCalledWith('HEAD~2', 'release');
|
|
150
|
+
expect(commitsBetweenSpy).toHaveBeenCalledWith(sinceSha, headSha);
|
|
151
|
+
expect(Git.getChangedFilesBetween).toHaveBeenCalledWith(sinceSha, headSha);
|
|
152
|
+
expect(Git.getChangelogAdditions).toHaveBeenCalledWith(sinceSha, headSha, changedFiles);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('has no commits when head is the --since commit', async () => {
|
|
156
|
+
resolveBaseSpy.mockResolvedValue(headSha);
|
|
157
|
+
|
|
158
|
+
const result = await getAffectedActors({ head: 'HEAD', since: headSha, ...selection });
|
|
159
|
+
|
|
160
|
+
expect(result.commits).toStrictEqual([]);
|
|
161
|
+
// Empty `git log x..x` output doesn't parse as a commit, so it's never run
|
|
162
|
+
expect(commitsBetweenSpy).not.toHaveBeenCalled();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('toAffectedActorsDocument', () => {
|
|
168
|
+
it('keeps only the Actor names, the config file stays the source of truth for the rest', () => {
|
|
169
|
+
expect(
|
|
170
|
+
toAffectedActorsDocument({
|
|
171
|
+
headSha,
|
|
172
|
+
ref: null,
|
|
173
|
+
commits,
|
|
174
|
+
changedFiles: ['src/main.ts'],
|
|
175
|
+
changelog: null,
|
|
176
|
+
functionallyChangedActors: [actorA],
|
|
177
|
+
cosmeticallyChangedActors: [actorB],
|
|
178
|
+
}),
|
|
179
|
+
).toStrictEqual({
|
|
180
|
+
version: 1,
|
|
181
|
+
ref: null,
|
|
182
|
+
head: headSha,
|
|
183
|
+
commits,
|
|
184
|
+
changedFiles: ['src/main.ts'],
|
|
185
|
+
changelog: null,
|
|
186
|
+
functionallyChangedActors: [{ actorFullName: 'owner/a' }],
|
|
187
|
+
cosmeticallyChangedActors: [{ actorFullName: 'owner/b' }],
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
});
|