@mui/internal-code-infra 0.0.4-canary.73 → 0.0.4-canary.75
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/package.json +7 -5
- package/src/brokenLinksChecker/crawlWorker.mjs +23 -0
- package/src/cli/cmdPublish.mjs +32 -3
- package/src/brokenLinksChecker/__fixtures__/static-site/broken-links.html +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/broken-targets.html +0 -22
- package/src/brokenLinksChecker/__fixtures__/static-site/example.md +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/external-links.html +0 -21
- package/src/brokenLinksChecker/__fixtures__/static-site/ignored-page.html +0 -17
- package/src/brokenLinksChecker/__fixtures__/static-site/index.html +0 -29
- package/src/brokenLinksChecker/__fixtures__/static-site/invalid-html.html +0 -15
- package/src/brokenLinksChecker/__fixtures__/static-site/known-targets.json +0 -5
- package/src/brokenLinksChecker/__fixtures__/static-site/nested/page.html +0 -21
- package/src/brokenLinksChecker/__fixtures__/static-site/orphaned-page.html +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/page-with-api-links.html +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/page-with-custom-targets.html +0 -24
- package/src/brokenLinksChecker/__fixtures__/static-site/page-with-ignored-content.html +0 -28
- package/src/brokenLinksChecker/__fixtures__/static-site/page-with-known-target-links.html +0 -19
- package/src/brokenLinksChecker/__fixtures__/static-site/unclosed-tags.html +0 -1
- package/src/brokenLinksChecker/__fixtures__/static-site/valid.html +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/with-anchors.html +0 -31
- package/src/brokenLinksChecker/index.test.ts +0 -301
- package/src/changelog/categorizeCommits.test.ts +0 -319
- package/src/changelog/filterCommits.test.ts +0 -363
- package/src/changelog/parseCommitLabels.test.ts +0 -509
- package/src/changelog/renderChangelog.test.ts +0 -378
- package/src/changelog/sortSections.test.ts +0 -199
- package/src/cli/cmdVale.test.mjs +0 -644
- package/src/eslint/mui/rules/add-undef-to-optional.test.mjs +0 -361
- package/src/eslint/mui/rules/consistent-production-guard.test.mjs +0 -162
- package/src/eslint/mui/rules/disallow-active-elements-as-key-event-target.test.mjs +0 -66
- package/src/eslint/mui/rules/disallow-react-api-in-server-components.test.mjs +0 -305
- package/src/eslint/mui/rules/docgen-ignore-before-comment.test.mjs +0 -52
- package/src/eslint/mui/rules/flatten-parentheses.test.mjs +0 -245
- package/src/eslint/mui/rules/mui-name-matches-component-name.test.mjs +0 -247
- package/src/eslint/mui/rules/no-empty-box.test.mjs +0 -40
- package/src/eslint/mui/rules/no-floating-cleanup.test.mjs +0 -141
- package/src/eslint/mui/rules/no-guarded-throw.test.mjs +0 -206
- package/src/eslint/mui/rules/no-presentation-role.test.mjs +0 -33
- package/src/eslint/mui/rules/no-styled-box.test.mjs +0 -73
- package/src/eslint/mui/rules/require-dev-wrapper.test.mjs +0 -265
- package/src/eslint/mui/rules/rules-of-use-theme-variants.test.mjs +0 -149
- package/src/eslint/mui/rules/straight-quotes.test.mjs +0 -67
- package/src/remark/firstBlockHeading.test.mjs +0 -107
- package/src/remark/gitDiff.test.mjs +0 -45
- package/src/remark/noSpaceInLinks.test.mjs +0 -22
- package/src/remark/straightQuotes.test.mjs +0 -25
- package/src/remark/tableAlignment.test.mjs +0 -28
- package/src/remark/terminalLanguage.test.mjs +0 -17
- package/src/utils/build.test.mjs +0 -1263
- package/src/utils/pnpm.test.mjs +0 -731
- package/src/utils/template.test.mjs +0 -133
- package/src/utils/typescript.test.mjs +0 -341
package/src/utils/pnpm.test.mjs
DELETED
|
@@ -1,731 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs/promises';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { describe, it, expect } from 'vitest';
|
|
4
|
-
|
|
5
|
-
import { makeTempDir } from './testUtils.mjs';
|
|
6
|
-
import {
|
|
7
|
-
checkPublishDependencies,
|
|
8
|
-
readPackageJson,
|
|
9
|
-
writePackageJson,
|
|
10
|
-
writeOverridesToWorkspace,
|
|
11
|
-
} from './pnpm.mjs';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Write a package.json file to a temp subdirectory and return the directory path.
|
|
15
|
-
* @param {string} root - Root temp directory
|
|
16
|
-
* @param {string} name - Package subdirectory name
|
|
17
|
-
* @param {object} pkgJson - package.json contents
|
|
18
|
-
* @returns {Promise<string>} Path to the package directory
|
|
19
|
-
*/
|
|
20
|
-
async function writePackage(root, name, pkgJson) {
|
|
21
|
-
const pkgDir = path.join(root, name);
|
|
22
|
-
await fs.mkdir(pkgDir, { recursive: true });
|
|
23
|
-
await fs.writeFile(path.join(pkgDir, 'package.json'), JSON.stringify(pkgJson, null, 2));
|
|
24
|
-
return pkgDir;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {string} name
|
|
29
|
-
* @param {string} pkgPath
|
|
30
|
-
* @returns {import('./pnpm.mjs').PublicPackage}
|
|
31
|
-
*/
|
|
32
|
-
function publicPkg(name, pkgPath) {
|
|
33
|
-
return { name, version: '1.0.0', path: pkgPath, isPrivate: false };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @param {string} name
|
|
38
|
-
* @param {string} pkgPath
|
|
39
|
-
* @returns {import('./pnpm.mjs').PrivatePackage}
|
|
40
|
-
*/
|
|
41
|
-
function privatePkg(name, pkgPath) {
|
|
42
|
-
return { name, version: '1.0.0', path: pkgPath, isPrivate: true };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Build the workspace maps expected by checkPublishDependencies.
|
|
47
|
-
* @param {(import('./pnpm.mjs').PublicPackage | import('./pnpm.mjs').PrivatePackage)[]} allPkgs
|
|
48
|
-
*/
|
|
49
|
-
function workspaceMaps(allPkgs) {
|
|
50
|
-
/** @type {Map<string, import('./pnpm.mjs').PublicPackage | import('./pnpm.mjs').PrivatePackage>} */
|
|
51
|
-
const byName = new Map(allPkgs.flatMap((p) => (p.name ? [[p.name, p]] : [])));
|
|
52
|
-
const pathByName = new Map(allPkgs.flatMap((p) => (p.name ? [[p.name, p.path]] : [])));
|
|
53
|
-
return { byName, pathByName };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
describe('checkPublishDependencies', () => {
|
|
57
|
-
describe('workspace: protocol in dependencies', () => {
|
|
58
|
-
it('returns no issues when all workspace: dependencies are included in the publish set', async () => {
|
|
59
|
-
const root = await makeTempDir();
|
|
60
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
61
|
-
name: '@scope/pkg-a',
|
|
62
|
-
dependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
63
|
-
});
|
|
64
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
65
|
-
|
|
66
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
67
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
68
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
69
|
-
|
|
70
|
-
const { issues } = await checkPublishDependencies([pkgA, pkgB], byName, pathByName);
|
|
71
|
-
expect(issues).toEqual([]);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('reports an issue when a workspace: dependency is missing from the publish set', async () => {
|
|
75
|
-
const root = await makeTempDir();
|
|
76
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
77
|
-
name: '@scope/pkg-a',
|
|
78
|
-
dependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
79
|
-
});
|
|
80
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
81
|
-
|
|
82
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
83
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
84
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
85
|
-
|
|
86
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
87
|
-
expect(issues).toHaveLength(1);
|
|
88
|
-
expect(issues[0]).toContain('@scope/pkg-b');
|
|
89
|
-
expect(issues[0]).toContain('Add them to the --filter list');
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('reports an issue when a workspace: dependency is private', async () => {
|
|
93
|
-
const root = await makeTempDir();
|
|
94
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
95
|
-
name: '@scope/pkg-a',
|
|
96
|
-
dependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
97
|
-
});
|
|
98
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b', private: true });
|
|
99
|
-
|
|
100
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
101
|
-
const pkgB = privatePkg('@scope/pkg-b', bDir);
|
|
102
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
103
|
-
|
|
104
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
105
|
-
expect(issues).toHaveLength(1);
|
|
106
|
-
expect(issues[0]).toContain('@scope/pkg-b');
|
|
107
|
-
expect(issues[0]).toContain('private');
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('resolves transitive workspace: dependencies', async () => {
|
|
111
|
-
const root = await makeTempDir();
|
|
112
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
113
|
-
name: '@scope/pkg-a',
|
|
114
|
-
dependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
115
|
-
});
|
|
116
|
-
const bDir = await writePackage(root, 'pkg-b', {
|
|
117
|
-
name: '@scope/pkg-b',
|
|
118
|
-
dependencies: { '@scope/pkg-c': 'workspace:*' },
|
|
119
|
-
});
|
|
120
|
-
const cDir = await writePackage(root, 'pkg-c', { name: '@scope/pkg-c' });
|
|
121
|
-
|
|
122
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
123
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
124
|
-
const pkgC = publicPkg('@scope/pkg-c', cDir);
|
|
125
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB, pkgC]);
|
|
126
|
-
|
|
127
|
-
// publishing only A and B — C is missing but transitively required
|
|
128
|
-
const { issues } = await checkPublishDependencies([pkgA, pkgB], byName, pathByName);
|
|
129
|
-
expect(issues).toHaveLength(1);
|
|
130
|
-
expect(issues[0]).toContain('@scope/pkg-c');
|
|
131
|
-
|
|
132
|
-
// publishing all three — no issues
|
|
133
|
-
const { issues: noIssues } = await checkPublishDependencies(
|
|
134
|
-
[pkgA, pkgB, pkgC],
|
|
135
|
-
byName,
|
|
136
|
-
pathByName,
|
|
137
|
-
);
|
|
138
|
-
expect(noIssues).toEqual([]);
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
describe('peerDependencies are never hard requirements', () => {
|
|
143
|
-
it('does not require a peer dependency even when using workspace: protocol', async () => {
|
|
144
|
-
const root = await makeTempDir();
|
|
145
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
146
|
-
name: '@scope/pkg-a',
|
|
147
|
-
peerDependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
148
|
-
});
|
|
149
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
150
|
-
|
|
151
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
152
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
153
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
154
|
-
|
|
155
|
-
// publishing only A — B is a workspace: peer dep but must NOT be required
|
|
156
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
157
|
-
expect(issues).toEqual([]);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it('does not require a peer dependency with a pinned version', async () => {
|
|
161
|
-
const root = await makeTempDir();
|
|
162
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
163
|
-
name: '@scope/pkg-a',
|
|
164
|
-
peerDependencies: { '@scope/pkg-b': '^1.0.0' },
|
|
165
|
-
});
|
|
166
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
167
|
-
|
|
168
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
169
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
170
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
171
|
-
|
|
172
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
173
|
-
expect(issues).toEqual([]);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('does not require a private peer dependency', async () => {
|
|
177
|
-
const root = await makeTempDir();
|
|
178
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
179
|
-
name: '@scope/pkg-a',
|
|
180
|
-
peerDependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
181
|
-
});
|
|
182
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b', private: true });
|
|
183
|
-
|
|
184
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
185
|
-
const pkgB = privatePkg('@scope/pkg-b', bDir);
|
|
186
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
187
|
-
|
|
188
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
189
|
-
expect(issues).toEqual([]);
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
describe('workspace:^ protocol in dependencies', () => {
|
|
194
|
-
it('requires a workspace:^ dependency that is missing from the publish set', async () => {
|
|
195
|
-
const root = await makeTempDir();
|
|
196
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
197
|
-
name: '@scope/pkg-a',
|
|
198
|
-
dependencies: { '@scope/pkg-b': 'workspace:^' },
|
|
199
|
-
});
|
|
200
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
201
|
-
|
|
202
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
203
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
204
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
205
|
-
|
|
206
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
207
|
-
expect(issues).toHaveLength(1);
|
|
208
|
-
expect(issues[0]).toContain('@scope/pkg-b');
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it('returns no issues when a workspace:^ dependency is included in the publish set', async () => {
|
|
212
|
-
const root = await makeTempDir();
|
|
213
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
214
|
-
name: '@scope/pkg-a',
|
|
215
|
-
dependencies: { '@scope/pkg-b': 'workspace:^' },
|
|
216
|
-
});
|
|
217
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
218
|
-
|
|
219
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
220
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
221
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
222
|
-
|
|
223
|
-
const { issues } = await checkPublishDependencies([pkgA, pkgB], byName, pathByName);
|
|
224
|
-
expect(issues).toEqual([]);
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
describe('devDependencies are never hard requirements', () => {
|
|
229
|
-
it('does not require a workspace: devDependency missing from the publish set', async () => {
|
|
230
|
-
const root = await makeTempDir();
|
|
231
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
232
|
-
name: '@scope/pkg-a',
|
|
233
|
-
devDependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
234
|
-
});
|
|
235
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
236
|
-
|
|
237
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
238
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
239
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
240
|
-
|
|
241
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
242
|
-
expect(issues).toEqual([]);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it('does not require a workspace:^ devDependency missing from the publish set', async () => {
|
|
246
|
-
const root = await makeTempDir();
|
|
247
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
248
|
-
name: '@scope/pkg-a',
|
|
249
|
-
devDependencies: { '@scope/pkg-b': 'workspace:^' },
|
|
250
|
-
});
|
|
251
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
252
|
-
|
|
253
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
254
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
255
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
256
|
-
|
|
257
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
258
|
-
expect(issues).toEqual([]);
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it('does not require a private workspace: devDependency', async () => {
|
|
262
|
-
const root = await makeTempDir();
|
|
263
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
264
|
-
name: '@scope/pkg-a',
|
|
265
|
-
devDependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
266
|
-
});
|
|
267
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b', private: true });
|
|
268
|
-
|
|
269
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
270
|
-
const pkgB = privatePkg('@scope/pkg-b', bDir);
|
|
271
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
272
|
-
|
|
273
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
274
|
-
expect(issues).toEqual([]);
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
describe('pinned versions in dependencies are not hard requirements', () => {
|
|
279
|
-
it('does not require a workspace package referenced with a pinned version in dependencies', async () => {
|
|
280
|
-
const root = await makeTempDir();
|
|
281
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
282
|
-
name: '@scope/pkg-a',
|
|
283
|
-
dependencies: { '@scope/pkg-b': '^1.0.0' },
|
|
284
|
-
});
|
|
285
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
286
|
-
|
|
287
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
288
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
289
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB]);
|
|
290
|
-
|
|
291
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
292
|
-
expect(issues).toEqual([]);
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
describe('mixed dependency types', () => {
|
|
297
|
-
it('requires workspace: dependencies but not workspace: peers from the same package', async () => {
|
|
298
|
-
const root = await makeTempDir();
|
|
299
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
300
|
-
name: '@scope/pkg-a',
|
|
301
|
-
dependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
302
|
-
peerDependencies: { '@scope/pkg-c': 'workspace:*' },
|
|
303
|
-
});
|
|
304
|
-
const bDir = await writePackage(root, 'pkg-b', { name: '@scope/pkg-b' });
|
|
305
|
-
const cDir = await writePackage(root, 'pkg-c', { name: '@scope/pkg-c' });
|
|
306
|
-
|
|
307
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
308
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
309
|
-
const pkgC = publicPkg('@scope/pkg-c', cDir);
|
|
310
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB, pkgC]);
|
|
311
|
-
|
|
312
|
-
// B is required (workspace: dep), C is not (workspace: peer)
|
|
313
|
-
const { issues } = await checkPublishDependencies([pkgA, pkgB], byName, pathByName);
|
|
314
|
-
expect(issues).toEqual([]);
|
|
315
|
-
|
|
316
|
-
// Omitting B should flag it
|
|
317
|
-
const { issues: missingB } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
318
|
-
expect(missingB).toHaveLength(1);
|
|
319
|
-
expect(missingB[0]).toContain('@scope/pkg-b');
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
it('does not traverse peer deps when resolving transitive requirements', async () => {
|
|
323
|
-
const root = await makeTempDir();
|
|
324
|
-
// A depends on B (workspace:), B has C as a peer (workspace:)
|
|
325
|
-
// C should NOT be required just because B peers it
|
|
326
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
327
|
-
name: '@scope/pkg-a',
|
|
328
|
-
dependencies: { '@scope/pkg-b': 'workspace:*' },
|
|
329
|
-
});
|
|
330
|
-
const bDir = await writePackage(root, 'pkg-b', {
|
|
331
|
-
name: '@scope/pkg-b',
|
|
332
|
-
peerDependencies: { '@scope/pkg-c': 'workspace:*' },
|
|
333
|
-
});
|
|
334
|
-
const cDir = await writePackage(root, 'pkg-c', { name: '@scope/pkg-c' });
|
|
335
|
-
|
|
336
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
337
|
-
const pkgB = publicPkg('@scope/pkg-b', bDir);
|
|
338
|
-
const pkgC = publicPkg('@scope/pkg-c', cDir);
|
|
339
|
-
const { byName, pathByName } = workspaceMaps([pkgA, pkgB, pkgC]);
|
|
340
|
-
|
|
341
|
-
const { issues } = await checkPublishDependencies([pkgA, pkgB], byName, pathByName);
|
|
342
|
-
expect(issues).toEqual([]);
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
describe('material-ui packages-internal workspace simulation', () => {
|
|
347
|
-
/**
|
|
348
|
-
* Mirrors the real package structure from material-ui packages-internal/* plus the
|
|
349
|
-
* packages/* that appear as workspace deps.
|
|
350
|
-
*
|
|
351
|
-
* Public packages-internal:
|
|
352
|
-
* @mui/internal-core-docs – deps: @mui/internal-markdown (workspace:^)
|
|
353
|
-
* – devDeps: @mui-internal/api-docs-builder (workspace:*),
|
|
354
|
-
* @mui/icons-material (workspace:*), @mui/material (workspace:*)
|
|
355
|
-
* – peers: @mui/material, @mui/icons-material, @mui/system, … (pinned ranges)
|
|
356
|
-
* @mui/internal-docs-utils – no workspace deps
|
|
357
|
-
* @mui/internal-markdown – no workspace deps
|
|
358
|
-
* @mui/internal-scripts – deps: @mui/internal-docs-utils (workspace:^)
|
|
359
|
-
*
|
|
360
|
-
* Private packages-internal:
|
|
361
|
-
* @mui-internal/api-docs-builder – deps: @mui/internal-docs-utils (workspace:^),
|
|
362
|
-
* @mui/internal-markdown (workspace:^)
|
|
363
|
-
* @mui-internal/api-docs-builder-core – deps: @mui-internal/api-docs-builder (workspace:^),
|
|
364
|
-
* @mui/internal-markdown (workspace:^)
|
|
365
|
-
* @mui/internal-waterfall – no workspace deps
|
|
366
|
-
*
|
|
367
|
-
* Public packages/* (not in the --filter set, resolve from registry):
|
|
368
|
-
* @mui/material, @mui/icons-material, @mui/system, @mui/utils, @mui/material-nextjs,
|
|
369
|
-
* @mui/stylis-plugin-rtl, @mui/core-downloads-tracker, @mui/types,
|
|
370
|
-
* @mui/material-pigment-css, @mui/private-theming, @mui/styled-engine
|
|
371
|
-
*/
|
|
372
|
-
/** @param {string} root */
|
|
373
|
-
async function buildMaterialUiWorkspace(root) {
|
|
374
|
-
// packages-internal — public
|
|
375
|
-
const coreDocs = await writePackage(root, 'packages-internal/core-docs', {
|
|
376
|
-
name: '@mui/internal-core-docs',
|
|
377
|
-
version: '9.0.0-beta.1',
|
|
378
|
-
dependencies: {
|
|
379
|
-
'@babel/runtime': '^7.29.2',
|
|
380
|
-
'@mui/internal-markdown': 'workspace:^',
|
|
381
|
-
'clipboard-copy': '^4.0.1',
|
|
382
|
-
clsx: '^2.1.1',
|
|
383
|
-
},
|
|
384
|
-
devDependencies: {
|
|
385
|
-
'@mui-internal/api-docs-builder': 'workspace:*',
|
|
386
|
-
'@mui/icons-material': 'workspace:*',
|
|
387
|
-
'@mui/material': 'workspace:*',
|
|
388
|
-
},
|
|
389
|
-
peerDependencies: {
|
|
390
|
-
'@mui/base': '^5.0.0 || ^7.0.0',
|
|
391
|
-
'@mui/icons-material': '^5.0.0 || ^6.0.0 || ^7.0.0 || ^9.0.0',
|
|
392
|
-
'@mui/material': '^5.0.0 || ^6.0.0 || ^7.0.0 || ^9.0.0',
|
|
393
|
-
'@mui/material-nextjs': '^5.0.0 || ^6.0.0 || ^7.0.0 || ^9.0.0',
|
|
394
|
-
'@mui/stylis-plugin-rtl': '^5.0.0 || ^6.0.0 || ^7.0.0 || ^9.0.0',
|
|
395
|
-
'@mui/system': '^5.0.0 || ^6.0.0 || ^7.0.0 || ^9.0.0',
|
|
396
|
-
'@mui/utils': '^5.0.0 || ^6.0.0 || ^7.0.0 || ^9.0.0',
|
|
397
|
-
react: '^17.0.0 || ^18.0.0 || ^19.0.0',
|
|
398
|
-
},
|
|
399
|
-
});
|
|
400
|
-
const docsUtils = await writePackage(root, 'packages-internal/docs-utils', {
|
|
401
|
-
name: '@mui/internal-docs-utils',
|
|
402
|
-
version: '3.0.2',
|
|
403
|
-
dependencies: { rimraf: '^6.1.3', typescript: '^5.9.3' },
|
|
404
|
-
});
|
|
405
|
-
const markdown = await writePackage(root, 'packages-internal/markdown', {
|
|
406
|
-
name: '@mui/internal-markdown',
|
|
407
|
-
version: '3.0.6',
|
|
408
|
-
dependencies: { '@babel/runtime': '^7.29.2', marked: '^17.0.5', prismjs: '^1.30.0' },
|
|
409
|
-
});
|
|
410
|
-
const scripts = await writePackage(root, 'packages-internal/scripts', {
|
|
411
|
-
name: '@mui/internal-scripts',
|
|
412
|
-
version: '3.0.5',
|
|
413
|
-
dependencies: {
|
|
414
|
-
'@mui/internal-docs-utils': 'workspace:^',
|
|
415
|
-
'@babel/core': '^7.29.0',
|
|
416
|
-
doctrine: '^3.0.0',
|
|
417
|
-
},
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
// packages-internal — private
|
|
421
|
-
const apiDocsBuilder = await writePackage(root, 'packages-internal/api-docs-builder', {
|
|
422
|
-
name: '@mui-internal/api-docs-builder',
|
|
423
|
-
version: '1.0.0',
|
|
424
|
-
private: true,
|
|
425
|
-
dependencies: {
|
|
426
|
-
'@mui/internal-docs-utils': 'workspace:^',
|
|
427
|
-
'@mui/internal-markdown': 'workspace:^',
|
|
428
|
-
'@babel/core': '^7.29.0',
|
|
429
|
-
},
|
|
430
|
-
});
|
|
431
|
-
const apiDocsBuilderCore = await writePackage(
|
|
432
|
-
root,
|
|
433
|
-
'packages-internal/api-docs-builder-core',
|
|
434
|
-
{
|
|
435
|
-
name: '@mui-internal/api-docs-builder-core',
|
|
436
|
-
version: '1.0.0',
|
|
437
|
-
private: true,
|
|
438
|
-
dependencies: {
|
|
439
|
-
'@mui-internal/api-docs-builder': 'workspace:^',
|
|
440
|
-
'@mui/internal-markdown': 'workspace:^',
|
|
441
|
-
},
|
|
442
|
-
},
|
|
443
|
-
);
|
|
444
|
-
const waterfall = await writePackage(root, 'packages-internal/waterfall', {
|
|
445
|
-
name: '@mui/internal-waterfall',
|
|
446
|
-
version: '1.0.0',
|
|
447
|
-
private: true,
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
// packages/* — public, resolve from registry (not in the --filter set)
|
|
451
|
-
const material = await writePackage(root, 'packages/material', {
|
|
452
|
-
name: '@mui/material',
|
|
453
|
-
version: '9.0.0-beta.1',
|
|
454
|
-
});
|
|
455
|
-
const iconsM = await writePackage(root, 'packages/icons-material', {
|
|
456
|
-
name: '@mui/icons-material',
|
|
457
|
-
version: '9.0.0-beta.1',
|
|
458
|
-
});
|
|
459
|
-
const muiSystem = await writePackage(root, 'packages/system', {
|
|
460
|
-
name: '@mui/system',
|
|
461
|
-
version: '9.0.0-beta.1',
|
|
462
|
-
});
|
|
463
|
-
const muiUtils = await writePackage(root, 'packages/utils', {
|
|
464
|
-
name: '@mui/utils',
|
|
465
|
-
version: '9.0.0-beta.1',
|
|
466
|
-
});
|
|
467
|
-
const materialNextjs = await writePackage(root, 'packages/material-nextjs', {
|
|
468
|
-
name: '@mui/material-nextjs',
|
|
469
|
-
version: '9.0.0-beta.0',
|
|
470
|
-
});
|
|
471
|
-
const stylisPluginRtl = await writePackage(root, 'packages/stylis-plugin-rtl', {
|
|
472
|
-
name: '@mui/stylis-plugin-rtl',
|
|
473
|
-
version: '9.0.0-beta.0',
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
const publicInternalPkgs = [
|
|
477
|
-
publicPkg('@mui/internal-core-docs', coreDocs),
|
|
478
|
-
publicPkg('@mui/internal-docs-utils', docsUtils),
|
|
479
|
-
publicPkg('@mui/internal-markdown', markdown),
|
|
480
|
-
publicPkg('@mui/internal-scripts', scripts),
|
|
481
|
-
];
|
|
482
|
-
const privateInternalPkgs = [
|
|
483
|
-
privatePkg('@mui-internal/api-docs-builder', apiDocsBuilder),
|
|
484
|
-
privatePkg('@mui-internal/api-docs-builder-core', apiDocsBuilderCore),
|
|
485
|
-
privatePkg('@mui/internal-waterfall', waterfall),
|
|
486
|
-
];
|
|
487
|
-
const publicMainPkgs = [
|
|
488
|
-
publicPkg('@mui/material', material),
|
|
489
|
-
publicPkg('@mui/icons-material', iconsM),
|
|
490
|
-
publicPkg('@mui/system', muiSystem),
|
|
491
|
-
publicPkg('@mui/utils', muiUtils),
|
|
492
|
-
publicPkg('@mui/material-nextjs', materialNextjs),
|
|
493
|
-
publicPkg('@mui/stylis-plugin-rtl', stylisPluginRtl),
|
|
494
|
-
];
|
|
495
|
-
|
|
496
|
-
const allPkgs = [...publicInternalPkgs, ...privateInternalPkgs, ...publicMainPkgs];
|
|
497
|
-
return { publicInternalPkgs, privateInternalPkgs, publicMainPkgs, allPkgs };
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
it('passes with no issues when publishing all public packages-internal packages', async () => {
|
|
501
|
-
const root = await makeTempDir();
|
|
502
|
-
const { publicInternalPkgs, allPkgs } = await buildMaterialUiWorkspace(root);
|
|
503
|
-
const { byName, pathByName } = workspaceMaps(allPkgs);
|
|
504
|
-
|
|
505
|
-
const { issues } = await checkPublishDependencies(publicInternalPkgs, byName, pathByName);
|
|
506
|
-
expect(issues).toEqual([]);
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
it('passes when @mui/material and other pinned-range peers of core-docs are not in the publish set', async () => {
|
|
510
|
-
const root = await makeTempDir();
|
|
511
|
-
const { publicInternalPkgs, privateInternalPkgs } = await buildMaterialUiWorkspace(root);
|
|
512
|
-
// workspace without the packages/* — simulates --filter "./packages-internal/*"
|
|
513
|
-
const filteredWorkspace = [...publicInternalPkgs, ...privateInternalPkgs];
|
|
514
|
-
const { byName, pathByName } = workspaceMaps(filteredWorkspace);
|
|
515
|
-
|
|
516
|
-
const { issues } = await checkPublishDependencies(publicInternalPkgs, byName, pathByName);
|
|
517
|
-
expect(issues).toEqual([]);
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
it('passes when workspace:* devDependencies of core-docs are not in the publish set', async () => {
|
|
521
|
-
// core-docs has @mui-internal/api-docs-builder and @mui/icons-material as workspace:*
|
|
522
|
-
// devDependencies. They must NOT be required — devDeps are not installed on consumer devices.
|
|
523
|
-
const root = await makeTempDir();
|
|
524
|
-
const { publicInternalPkgs, allPkgs } = await buildMaterialUiWorkspace(root);
|
|
525
|
-
const { byName, pathByName } = workspaceMaps(allPkgs);
|
|
526
|
-
|
|
527
|
-
const { issues } = await checkPublishDependencies(publicInternalPkgs, byName, pathByName);
|
|
528
|
-
expect(issues).toEqual([]);
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
it('flags @mui/internal-markdown as missing when core-docs is published without it', async () => {
|
|
532
|
-
const root = await makeTempDir();
|
|
533
|
-
const { publicInternalPkgs, allPkgs } = await buildMaterialUiWorkspace(root);
|
|
534
|
-
const { byName, pathByName } = workspaceMaps(allPkgs);
|
|
535
|
-
|
|
536
|
-
const withoutMarkdown = publicInternalPkgs.filter((p) => p.name !== '@mui/internal-markdown');
|
|
537
|
-
const { issues } = await checkPublishDependencies(withoutMarkdown, byName, pathByName);
|
|
538
|
-
expect(issues).toHaveLength(1);
|
|
539
|
-
expect(issues[0]).toContain('@mui/internal-markdown');
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
it('flags @mui/internal-docs-utils as missing when scripts is published without it', async () => {
|
|
543
|
-
const root = await makeTempDir();
|
|
544
|
-
const { publicInternalPkgs, allPkgs } = await buildMaterialUiWorkspace(root);
|
|
545
|
-
const { byName, pathByName } = workspaceMaps(allPkgs);
|
|
546
|
-
|
|
547
|
-
const withoutDocsUtils = publicInternalPkgs.filter(
|
|
548
|
-
(p) => p.name !== '@mui/internal-docs-utils',
|
|
549
|
-
);
|
|
550
|
-
const { issues } = await checkPublishDependencies(withoutDocsUtils, byName, pathByName);
|
|
551
|
-
expect(issues).toHaveLength(1);
|
|
552
|
-
expect(issues[0]).toContain('@mui/internal-docs-utils');
|
|
553
|
-
});
|
|
554
|
-
|
|
555
|
-
it('flags both missing workspace: deps when core-docs and scripts lack their deps', async () => {
|
|
556
|
-
const root = await makeTempDir();
|
|
557
|
-
const { publicInternalPkgs, allPkgs } = await buildMaterialUiWorkspace(root);
|
|
558
|
-
const { byName, pathByName } = workspaceMaps(allPkgs);
|
|
559
|
-
|
|
560
|
-
const onlyCoreDocs = publicInternalPkgs.filter(
|
|
561
|
-
(p) => p.name !== '@mui/internal-markdown' && p.name !== '@mui/internal-docs-utils',
|
|
562
|
-
);
|
|
563
|
-
const { issues } = await checkPublishDependencies(onlyCoreDocs, byName, pathByName);
|
|
564
|
-
expect(issues).toHaveLength(1); // single issue listing both missing packages
|
|
565
|
-
expect(issues[0]).toContain('@mui/internal-markdown');
|
|
566
|
-
expect(issues[0]).toContain('@mui/internal-docs-utils');
|
|
567
|
-
});
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
describe('packages not in the workspace', () => {
|
|
571
|
-
it('ignores dependencies that are not workspace packages', async () => {
|
|
572
|
-
const root = await makeTempDir();
|
|
573
|
-
const aDir = await writePackage(root, 'pkg-a', {
|
|
574
|
-
name: '@scope/pkg-a',
|
|
575
|
-
dependencies: { react: '^18.0.0', lodash: '^4.0.0' },
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
const pkgA = publicPkg('@scope/pkg-a', aDir);
|
|
579
|
-
const { byName, pathByName } = workspaceMaps([pkgA]);
|
|
580
|
-
|
|
581
|
-
const { issues } = await checkPublishDependencies([pkgA], byName, pathByName);
|
|
582
|
-
expect(issues).toEqual([]);
|
|
583
|
-
});
|
|
584
|
-
});
|
|
585
|
-
});
|
|
586
|
-
|
|
587
|
-
/**
|
|
588
|
-
* Set up a temp workspace with a package.json and optional pnpm-workspace.yaml.
|
|
589
|
-
* @param {object} packageJson - package.json contents
|
|
590
|
-
* @param {string} [workspaceYaml] - pnpm-workspace.yaml contents, omitted to skip the file
|
|
591
|
-
* @returns {Promise<string>} The workspace directory
|
|
592
|
-
*/
|
|
593
|
-
async function makeWorkspace(packageJson, workspaceYaml) {
|
|
594
|
-
const cwd = await makeTempDir();
|
|
595
|
-
const writes = [writePackageJson(cwd, packageJson)];
|
|
596
|
-
if (workspaceYaml !== undefined) {
|
|
597
|
-
writes.push(fs.writeFile(path.join(cwd, 'pnpm-workspace.yaml'), workspaceYaml));
|
|
598
|
-
}
|
|
599
|
-
await Promise.all(writes);
|
|
600
|
-
return cwd;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/**
|
|
604
|
-
* @param {string} cwd
|
|
605
|
-
* @returns {Promise<string>}
|
|
606
|
-
*/
|
|
607
|
-
function readWorkspaceYaml(cwd) {
|
|
608
|
-
return fs.readFile(path.join(cwd, 'pnpm-workspace.yaml'), 'utf8');
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
describe('writeOverridesToWorkspace', () => {
|
|
612
|
-
describe('writing to pnpm-workspace.yaml', () => {
|
|
613
|
-
it('creates the file with an overrides block when none exists', async () => {
|
|
614
|
-
const cwd = await makeWorkspace({ name: 'root' });
|
|
615
|
-
|
|
616
|
-
await writeOverridesToWorkspace(cwd, { foo: '1.2.3' });
|
|
617
|
-
|
|
618
|
-
expect(await readWorkspaceYaml(cwd)).toMatchInlineSnapshot(`
|
|
619
|
-
"overrides:
|
|
620
|
-
foo: 1.2.3
|
|
621
|
-
"
|
|
622
|
-
`);
|
|
623
|
-
});
|
|
624
|
-
|
|
625
|
-
it('merges into an existing block, preserving comments and quoting scoped names', async () => {
|
|
626
|
-
const cwd = await makeWorkspace(
|
|
627
|
-
{ name: 'root' },
|
|
628
|
-
[
|
|
629
|
-
'packages:',
|
|
630
|
-
" - 'packages/*'",
|
|
631
|
-
'overrides:',
|
|
632
|
-
' # keep this pin',
|
|
633
|
-
" bar: '2.0.0'",
|
|
634
|
-
'',
|
|
635
|
-
].join('\n'),
|
|
636
|
-
);
|
|
637
|
-
|
|
638
|
-
await writeOverridesToWorkspace(cwd, { playwright: '1.49.1', '@playwright/test': '1.49.1' });
|
|
639
|
-
|
|
640
|
-
expect(await readWorkspaceYaml(cwd)).toMatchInlineSnapshot(`
|
|
641
|
-
"packages:
|
|
642
|
-
- 'packages/*'
|
|
643
|
-
overrides:
|
|
644
|
-
# keep this pin
|
|
645
|
-
bar: '2.0.0'
|
|
646
|
-
playwright: 1.49.1
|
|
647
|
-
"@playwright/test": 1.49.1
|
|
648
|
-
"
|
|
649
|
-
`);
|
|
650
|
-
// The package.json is left untouched.
|
|
651
|
-
expect(await readPackageJson(cwd)).toEqual({ name: 'root' });
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
it('overwrites a same-named override, keeping its quote style', async () => {
|
|
655
|
-
const cwd = await makeWorkspace(
|
|
656
|
-
{ name: 'root' },
|
|
657
|
-
['overrides:', " foo: '1.0.0'", ''].join('\n'),
|
|
658
|
-
);
|
|
659
|
-
|
|
660
|
-
await writeOverridesToWorkspace(cwd, { foo: '2.0.0' });
|
|
661
|
-
|
|
662
|
-
expect(await readWorkspaceYaml(cwd)).toMatchInlineSnapshot(`
|
|
663
|
-
"overrides:
|
|
664
|
-
foo: '2.0.0'
|
|
665
|
-
"
|
|
666
|
-
`);
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
it('prefers the workspace file when both manifests define overrides', async () => {
|
|
670
|
-
const cwd = await makeWorkspace(
|
|
671
|
-
{ name: 'root', pnpm: { overrides: { baz: '3.0.0' } } },
|
|
672
|
-
['overrides:', " bar: '2.0.0'", ''].join('\n'),
|
|
673
|
-
);
|
|
674
|
-
|
|
675
|
-
await writeOverridesToWorkspace(cwd, { foo: '1.2.3' });
|
|
676
|
-
|
|
677
|
-
expect(await readWorkspaceYaml(cwd)).toContain('foo: 1.2.3');
|
|
678
|
-
// package.json overrides are left where they were.
|
|
679
|
-
expect(await readPackageJson(cwd)).toEqual({
|
|
680
|
-
name: 'root',
|
|
681
|
-
pnpm: { overrides: { baz: '3.0.0' } },
|
|
682
|
-
});
|
|
683
|
-
});
|
|
684
|
-
});
|
|
685
|
-
|
|
686
|
-
describe('writing to package.json', () => {
|
|
687
|
-
it('honors the package.json location when no workspace overrides exist', async () => {
|
|
688
|
-
const cwd = await makeWorkspace({
|
|
689
|
-
name: 'root',
|
|
690
|
-
pnpm: { overrides: { foo: '1.0.0' }, packageExtensions: { thing: {} } },
|
|
691
|
-
});
|
|
692
|
-
|
|
693
|
-
await writeOverridesToWorkspace(cwd, { bar: '2.0.0' });
|
|
694
|
-
|
|
695
|
-
expect(await readPackageJson(cwd)).toEqual({
|
|
696
|
-
name: 'root',
|
|
697
|
-
pnpm: { overrides: { foo: '1.0.0', bar: '2.0.0' }, packageExtensions: { thing: {} } },
|
|
698
|
-
});
|
|
699
|
-
// No workspace file is created.
|
|
700
|
-
await expect(fs.access(path.join(cwd, 'pnpm-workspace.yaml'))).rejects.toThrow();
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
it('lets computed overrides win over an existing package.json override', async () => {
|
|
704
|
-
const cwd = await makeWorkspace({ name: 'root', pnpm: { overrides: { foo: '1.0.0' } } });
|
|
705
|
-
|
|
706
|
-
await writeOverridesToWorkspace(cwd, { foo: '2.0.0' });
|
|
707
|
-
|
|
708
|
-
expect(await readPackageJson(cwd)).toEqual({
|
|
709
|
-
name: 'root',
|
|
710
|
-
pnpm: { overrides: { foo: '2.0.0' } },
|
|
711
|
-
});
|
|
712
|
-
});
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
describe('rejecting resolutions', () => {
|
|
716
|
-
it('throws and writes nothing when package.json has a resolutions field', async () => {
|
|
717
|
-
const cwd = await makeWorkspace({ name: 'root', resolutions: { foo: '1.0.0' } });
|
|
718
|
-
|
|
719
|
-
await expect(writeOverridesToWorkspace(cwd, { bar: '2.0.0' })).rejects.toThrow(/resolutions/);
|
|
720
|
-
await expect(fs.access(path.join(cwd, 'pnpm-workspace.yaml'))).rejects.toThrow();
|
|
721
|
-
});
|
|
722
|
-
|
|
723
|
-
it('ignores an empty resolutions field', async () => {
|
|
724
|
-
const cwd = await makeWorkspace({ name: 'root', resolutions: {} });
|
|
725
|
-
|
|
726
|
-
await writeOverridesToWorkspace(cwd, { foo: '1.2.3' });
|
|
727
|
-
|
|
728
|
-
expect(await readWorkspaceYaml(cwd)).toContain('foo: 1.2.3');
|
|
729
|
-
});
|
|
730
|
-
});
|
|
731
|
-
});
|