Repository navigation
Expand file tree
/
Copy pathcheck-changesets.test.mjs
More file actions
116 lines (104 loc) · 3.28 KB
/
Copy pathcheck-changesets.test.mjs
File metadata and controls
116 lines (104 loc) · 3.28 KB
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) Meta Platforms, Inc. and affiliates.
/**
* @file check-changesets.test.mjs
* Unit tests for the changeset convention gate — specifically the 0.x semver
* coupling: a [breaking] change must bump the minor, every other category must
* bump the patch, and major is rejected while pre-1.0.
*/
import {describe, it, expect} from 'vitest';
import {validateChangeset} from './check-changesets.mjs';
const ctx = {
pre1: true,
pubNames: new Set(['@astryxdesign/core', '@astryxdesign/cli']),
allNames: new Set([
'@astryxdesign/core',
'@astryxdesign/cli',
'@astryxdesign/storybook',
]),
};
const cs = (frontmatter, body) => `---\n${frontmatter}\n---\n\n${body}\n`;
describe('validateChangeset — 0.x semver coupling', () => {
it('accepts [breaking] with a minor bump', () => {
const problems = validateChangeset(
'a.md',
cs(
"'@astryxdesign/core': minor",
'[breaking] Rename items to options (#1)\n@who',
),
ctx,
);
expect(problems).toEqual([]);
});
it('accepts a non-breaking category with a patch bump', () => {
for (const category of [
'feat',
'fix',
'component',
'perf',
'docs',
'chore',
]) {
const problems = validateChangeset(
'a.md',
cs("'@astryxdesign/core': patch", `[${category}] Something (#1)\n@who`),
ctx,
);
expect(problems, category).toEqual([]);
}
});
it('rejects [breaking] declared as patch', () => {
const problems = validateChangeset(
'a.md',
cs("'@astryxdesign/core': patch", '[breaking] Remove onHide (#1)\n@who'),
ctx,
);
expect(problems).toHaveLength(1);
expect(problems[0]).toMatch(/breaking.*declares "patch".*Use "minor"/);
});
it('rejects a non-breaking category declared as minor', () => {
const problems = validateChangeset(
'a.md',
cs(
"'@astryxdesign/core': minor",
'[feat] Add optional size prop (#1)\n@who',
),
ctx,
);
expect(problems).toHaveLength(1);
expect(problems[0]).toMatch(/declares "minor".*category is \[feat\]/);
});
it('rejects a major bump while 0.x', () => {
const problems = validateChangeset(
'a.md',
cs("'@astryxdesign/core': major", '[breaking] Total rewrite (#1)\n@who'),
ctx,
);
expect(problems).toHaveLength(1);
expect(problems[0]).toMatch(/declares "major".*no major bump.*1\.0\.0/);
});
it('does not enforce the coupling once past 1.0', () => {
const problems = validateChangeset(
'a.md',
cs("'@astryxdesign/core': minor", '[feat] Add prop (#1)\n@who'),
{...ctx, pre1: false},
);
expect(problems).toEqual([]);
});
it('still flags a missing category and missing contributor', () => {
const problems = validateChangeset(
'a.md',
cs("'@astryxdesign/core': patch", 'no category or handle here'),
ctx,
);
expect(problems.some(p => /\[category\] tag/.test(p))).toBe(true);
expect(problems.some(p => /contributor/.test(p))).toBe(true);
});
it('flags a private/ignored package', () => {
const problems = validateChangeset(
'a.md',
cs("'@astryxdesign/storybook': patch", '[fix] x (#1)\n@who'),
ctx,
);
expect(problems.some(p => /private\/ignored/.test(p))).toBe(true);
});
});