Skip to content

Commit 120a622

Browse files
committed
Add functional tests
This commit adds tests which run the script within a separate shell instance and verifies that the script makes the appropriate changes to the repo. I've tried to make these functional tests as readable as possible. In order to do that, I created a small framework which replicates the environment in which the script will run and then allows that environment to be modified per-test to suit the assertions being made.
1 parent 603d122 commit 120a622

18 files changed

+1347
-91
lines changed

src/fs.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import util from 'util';
44
import rimraf from 'rimraf';
55
import { when } from 'jest-when';
66
import * as actionUtils from '@metamask/action-utils';
7-
import { withSandbox } from '../tests/unit/helpers';
7+
import { withSandbox } from '../tests/helpers';
88
import {
99
readFile,
1010
writeFile,

src/functional.test.ts

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
import { withMonorepoProjectEnvironment } from '../tests/functional/helpers/with';
2+
import { buildChangelog } from '../tests/functional/helpers/utils';
3+
4+
describe('create-release-branch (functional)', () => {
5+
describe('against a monorepo with independent versions', () => {
6+
it('updates the version of the root package to be the current date along with the versions of the specified packages', async () => {
7+
await withMonorepoProjectEnvironment(
8+
{
9+
packages: {
10+
$root$: {
11+
name: '@scope/monorepo',
12+
version: '2022.1.1',
13+
directoryPath: '.',
14+
},
15+
a: {
16+
name: '@scope/a',
17+
version: '0.1.2',
18+
directoryPath: 'packages/a',
19+
},
20+
b: {
21+
name: '@scope/b',
22+
version: '1.1.4',
23+
directoryPath: 'packages/b',
24+
},
25+
c: {
26+
name: '@scope/c',
27+
version: '2.0.13',
28+
directoryPath: 'packages/c',
29+
},
30+
d: {
31+
name: '@scope/d',
32+
version: '1.2.3',
33+
directoryPath: 'packages/d',
34+
},
35+
e: {
36+
name: '@scope/e',
37+
version: '0.0.3',
38+
directoryPath: 'packages/e',
39+
},
40+
},
41+
workspaces: {
42+
'.': ['packages/*'],
43+
},
44+
today: new Date('2022-06-24'),
45+
},
46+
async (environment) => {
47+
await environment.runTool({
48+
releaseSpecification: {
49+
packages: {
50+
a: 'major',
51+
b: 'minor',
52+
c: 'patch',
53+
d: '1.2.4',
54+
},
55+
},
56+
});
57+
58+
expect(await environment.readJsonFile('package.json')).toMatchObject({
59+
version: '2022.6.24',
60+
});
61+
expect(
62+
await environment.readJsonFileWithinPackage('a', 'package.json'),
63+
).toMatchObject({
64+
version: '1.0.0',
65+
});
66+
expect(
67+
await environment.readJsonFileWithinPackage('b', 'package.json'),
68+
).toMatchObject({
69+
version: '1.2.0',
70+
});
71+
expect(
72+
await environment.readJsonFileWithinPackage('c', 'package.json'),
73+
).toMatchObject({
74+
version: '2.0.14',
75+
});
76+
expect(
77+
await environment.readJsonFileWithinPackage('d', 'package.json'),
78+
).toMatchObject({
79+
version: '1.2.4',
80+
});
81+
expect(
82+
await environment.readJsonFileWithinPackage('e', 'package.json'),
83+
).toMatchObject({
84+
version: '0.0.3',
85+
});
86+
},
87+
);
88+
});
89+
90+
it("updates each of the specified package's changelog by adding a new section which lists all commits concerning the package over the entire history of the repo", async () => {
91+
await withMonorepoProjectEnvironment(
92+
{
93+
packages: {
94+
$root$: {
95+
name: '@scope/monorepo',
96+
version: '1.0.0',
97+
directoryPath: '.',
98+
},
99+
a: {
100+
name: '@scope/a',
101+
version: '1.0.0',
102+
directoryPath: 'packages/a',
103+
},
104+
b: {
105+
name: '@scope/b',
106+
version: '1.0.0',
107+
directoryPath: 'packages/b',
108+
},
109+
},
110+
workspaces: {
111+
'.': ['packages/*'],
112+
},
113+
createInitialCommit: false,
114+
},
115+
async (environment) => {
116+
// Create an initial commit
117+
await environment.writeFileWithinPackage(
118+
'a',
119+
'CHANGELOG.md',
120+
buildChangelog(`
121+
## [Unreleased]
122+
123+
[Unreleased]: https://github.com/example-org/example-repo
124+
`),
125+
);
126+
await environment.writeFileWithinPackage(
127+
'b',
128+
'CHANGELOG.md',
129+
buildChangelog(`
130+
## [Unreleased]
131+
132+
[Unreleased]: https://github.com/example-org/example-repo
133+
`),
134+
);
135+
await environment.createCommit('Initial commit');
136+
137+
// Create another commit that only changes "a"
138+
await environment.writeFileWithinPackage(
139+
'a',
140+
'dummy.txt',
141+
'Some content',
142+
);
143+
await environment.createCommit('Update "a"');
144+
145+
// Run the tool
146+
await environment.runTool({
147+
releaseSpecification: {
148+
packages: {
149+
a: 'major',
150+
b: 'major',
151+
},
152+
},
153+
});
154+
155+
// Both changelogs should get updated, with an additional
156+
// commit listed for "a"
157+
expect(
158+
await environment.readFileWithinPackage('a', 'CHANGELOG.md'),
159+
).toStrictEqual(
160+
buildChangelog(`
161+
## [Unreleased]
162+
163+
## [2.0.0]
164+
### Uncategorized
165+
- Update "a"
166+
- Initial commit
167+
168+
[Unreleased]: https://github.com/example-org/example-repo/compare/v2.0.0...HEAD
169+
[2.0.0]: https://github.com/example-org/example-repo/releases/tag/v2.0.0
170+
`),
171+
);
172+
expect(
173+
await environment.readFileWithinPackage('b', 'CHANGELOG.md'),
174+
).toStrictEqual(
175+
buildChangelog(`
176+
## [Unreleased]
177+
178+
## [2.0.0]
179+
### Uncategorized
180+
- Initial commit
181+
182+
[Unreleased]: https://github.com/example-org/example-repo/compare/v2.0.0...HEAD
183+
[2.0.0]: https://github.com/example-org/example-repo/releases/tag/v2.0.0
184+
`),
185+
);
186+
},
187+
);
188+
});
189+
190+
it('commits the updates and saves the new commit to a new branch, then switches to that branch', async () => {
191+
await withMonorepoProjectEnvironment(
192+
{
193+
packages: {
194+
$root$: {
195+
name: '@scope/monorepo',
196+
version: '1.0.0',
197+
directoryPath: '.',
198+
},
199+
a: {
200+
name: '@scope/a',
201+
version: '1.0.0',
202+
directoryPath: 'packages/a',
203+
},
204+
},
205+
workspaces: {
206+
'.': ['packages/*'],
207+
},
208+
today: new Date('2022-06-24'),
209+
},
210+
async (environment) => {
211+
await environment.runTool({
212+
releaseSpecification: {
213+
packages: {
214+
a: 'major',
215+
},
216+
},
217+
});
218+
219+
// The most recent commit should be called the right thing, and
220+
// should be the current one, and should also be called
221+
// `release/YYYY-MM-DD`
222+
const mostRecentCommitInfo = (
223+
await environment.runCommand('git', [
224+
'log',
225+
'--pretty=%D%x09%s%x09%H',
226+
'--date-order',
227+
'--max-count=1',
228+
])
229+
).stdout
230+
.trim()
231+
.split('\x09');
232+
expect(mostRecentCommitInfo.slice(0, -1)).toStrictEqual([
233+
'HEAD -> release/2022-06-24',
234+
'Release 2022-06-24',
235+
]);
236+
// The most recent branch should point to the most recent commit
237+
const commitIdOfMostRecentBranch = (
238+
await environment.runCommand('git', [
239+
'rev-list',
240+
'--branches',
241+
'--date-order',
242+
'--max-count=1',
243+
])
244+
).stdout.trim();
245+
expect(mostRecentCommitInfo[2]).toStrictEqual(
246+
commitIdOfMostRecentBranch,
247+
);
248+
},
249+
);
250+
});
251+
});
252+
});

src/monorepo-workflow-operations.test.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import fs from 'fs';
22
import path from 'path';
33
import { SemVer } from 'semver';
4-
import {
5-
withSandbox,
6-
buildMockPackage,
7-
buildMockProject,
8-
} from '../tests/unit/helpers';
4+
import { withSandbox } from '../tests/helpers';
5+
import { buildMockPackage, buildMockProject } from '../tests/unit/helpers';
96
import { followMonorepoWorkflow } from './monorepo-workflow-operations';
107
import * as editorModule from './editor';
118
import * as envModule from './env';

src/package-manifest.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fs from 'fs';
22
import path from 'path';
33
import { SemVer } from 'semver';
4-
import { withSandbox } from '../tests/unit/helpers';
4+
import { withSandbox } from '../tests/helpers';
55
import { readPackageManifest } from './package-manifest';
66

77
describe('package-manifest', () => {

src/package.test.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@ import fs from 'fs';
22
import path from 'path';
33
import { when } from 'jest-when';
44
import * as autoChangelog from '@metamask/auto-changelog';
5-
import {
6-
buildMockProject,
7-
buildMockManifest,
8-
withSandbox,
9-
} from '../tests/unit/helpers';
10-
import { readPackage, updatePackage } from './package';
5+
import { withSandbox } from '../tests/helpers';
6+
import { buildMockProject, buildMockManifest } from '../tests/unit/helpers';
117
import * as fsModule from './fs';
8+
import { readPackage, updatePackage } from './package';
129
import * as packageManifestModule from './package-manifest';
1310

1411
jest.mock('@metamask/auto-changelog');

src/project.test.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import fs from 'fs';
22
import path from 'path';
33
import { when } from 'jest-when';
4-
import {
5-
buildMockManifest,
6-
buildMockPackage,
7-
withSandbox,
8-
} from '../tests/unit/helpers';
4+
import { withSandbox } from '../tests/helpers';
5+
import { buildMockManifest, buildMockPackage } from '../tests/unit/helpers';
96
import { readProject } from './project';
107
import * as packageModule from './package';
118
import * as repoModule from './repo';

src/release-specification.test.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ import { when } from 'jest-when';
44
import { MockWritable } from 'stdio-mock';
55
import YAML from 'yaml';
66
import { SemVer } from 'semver';
7-
import {
8-
withSandbox,
9-
buildMockProject,
10-
buildMockPackage,
11-
} from '../tests/unit/helpers';
7+
import { withSandbox } from '../tests/helpers';
8+
import { buildMockProject, buildMockPackage } from '../tests/unit/helpers';
129
import {
1310
generateReleaseSpecificationTemplateForMonorepo,
1411
waitForUserToEditReleaseSpecification,

tests/functional/helpers/constants.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import path from 'path';
2+
3+
export const ROOT_DIR = path.resolve(__dirname, '../../..');
4+
export const TOOL_EXECUTABLE_PATH = path.join(ROOT_DIR, 'src', 'cli.ts');
5+
export const TS_NODE_PATH = path.join(
6+
ROOT_DIR,
7+
'node_modules',
8+
'.bin',
9+
'ts-node',
10+
);

0 commit comments

Comments
 (0)