pm-dedup-core 2.1.0
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/LICENSE +21 -0
- package/README.md +105 -0
- package/dist/buildIdentifiedFixesMap.js +6 -0
- package/dist/buildIdentifiedFixesMap.js.map +1 -0
- package/dist/buildLockstepClusters.js +119 -0
- package/dist/buildLockstepClusters.js.map +1 -0
- package/dist/buildLockstepClusters.test.js +71 -0
- package/dist/buildLockstepClusters.test.js.map +1 -0
- package/dist/clusterLabel.js +59 -0
- package/dist/clusterLabel.js.map +1 -0
- package/dist/clusterLabel.test.js +56 -0
- package/dist/clusterLabel.test.js.map +1 -0
- package/dist/compareCandidateVersions.js +18 -0
- package/dist/compareCandidateVersions.js.map +1 -0
- package/dist/compareCandidateVersions.test.js +32 -0
- package/dist/compareCandidateVersions.test.js.map +1 -0
- package/dist/createPackageFilter.js +81 -0
- package/dist/createPackageFilter.js.map +1 -0
- package/dist/createPackageFilter.test.js +115 -0
- package/dist/createPackageFilter.test.js.map +1 -0
- package/dist/definitions/buildIdentifiedFixesMap.d.ts +4 -0
- package/dist/definitions/buildIdentifiedFixesMap.d.ts.map +1 -0
- package/dist/definitions/buildLockstepClusters.d.ts +8 -0
- package/dist/definitions/buildLockstepClusters.d.ts.map +1 -0
- package/dist/definitions/buildLockstepClusters.test.d.ts +2 -0
- package/dist/definitions/buildLockstepClusters.test.d.ts.map +1 -0
- package/dist/definitions/clusterLabel.d.ts +8 -0
- package/dist/definitions/clusterLabel.d.ts.map +1 -0
- package/dist/definitions/clusterLabel.test.d.ts +2 -0
- package/dist/definitions/clusterLabel.test.d.ts.map +1 -0
- package/dist/definitions/compareCandidateVersions.d.ts +10 -0
- package/dist/definitions/compareCandidateVersions.d.ts.map +1 -0
- package/dist/definitions/compareCandidateVersions.test.d.ts +2 -0
- package/dist/definitions/compareCandidateVersions.test.d.ts.map +1 -0
- package/dist/definitions/createPackageFilter.d.ts +45 -0
- package/dist/definitions/createPackageFilter.d.ts.map +1 -0
- package/dist/definitions/createPackageFilter.test.d.ts +2 -0
- package/dist/definitions/createPackageFilter.test.d.ts.map +1 -0
- package/dist/definitions/duplicateSnapshot.d.ts +8 -0
- package/dist/definitions/duplicateSnapshot.d.ts.map +1 -0
- package/dist/definitions/fileSnapshot.d.ts +7 -0
- package/dist/definitions/fileSnapshot.d.ts.map +1 -0
- package/dist/definitions/findProjectRoot.d.ts +27 -0
- package/dist/definitions/findProjectRoot.d.ts.map +1 -0
- package/dist/definitions/findProjectRoot.test.d.ts +2 -0
- package/dist/definitions/findProjectRoot.test.d.ts.map +1 -0
- package/dist/definitions/identifyLockstepClusterFixes.d.ts +89 -0
- package/dist/definitions/identifyLockstepClusterFixes.d.ts.map +1 -0
- package/dist/definitions/identifyLockstepClusterFixes.test.d.ts +2 -0
- package/dist/definitions/identifyLockstepClusterFixes.test.d.ts.map +1 -0
- package/dist/definitions/identifyResolutionFixes.d.ts +28 -0
- package/dist/definitions/identifyResolutionFixes.d.ts.map +1 -0
- package/dist/definitions/identifyResolutionFixes.test.d.ts +2 -0
- package/dist/definitions/identifyResolutionFixes.test.d.ts.map +1 -0
- package/dist/definitions/index.d.ts +44 -0
- package/dist/definitions/index.d.ts.map +1 -0
- package/dist/definitions/packageDependenciesUtils.d.ts +47 -0
- package/dist/definitions/packageDependenciesUtils.d.ts.map +1 -0
- package/dist/definitions/packageDependenciesUtils.test.d.ts +2 -0
- package/dist/definitions/packageDependenciesUtils.test.d.ts.map +1 -0
- package/dist/definitions/packageFilterArgs.d.ts +74 -0
- package/dist/definitions/packageFilterArgs.d.ts.map +1 -0
- package/dist/definitions/packageFilterArgs.test.d.ts +2 -0
- package/dist/definitions/packageFilterArgs.test.d.ts.map +1 -0
- package/dist/definitions/packageStyles.d.ts +14 -0
- package/dist/definitions/packageStyles.d.ts.map +1 -0
- package/dist/definitions/packageStyles.test.d.ts +2 -0
- package/dist/definitions/packageStyles.test.d.ts.map +1 -0
- package/dist/definitions/parseBinArgs.d.ts +14 -0
- package/dist/definitions/parseBinArgs.d.ts.map +1 -0
- package/dist/definitions/parseBinArgs.test.d.ts +2 -0
- package/dist/definitions/parseBinArgs.test.d.ts.map +1 -0
- package/dist/definitions/planClusterApply.d.ts +39 -0
- package/dist/definitions/planClusterApply.d.ts.map +1 -0
- package/dist/definitions/planClusterApply.test.d.ts +2 -0
- package/dist/definitions/planClusterApply.test.d.ts.map +1 -0
- package/dist/definitions/renderApplyPlan.d.ts +22 -0
- package/dist/definitions/renderApplyPlan.d.ts.map +1 -0
- package/dist/definitions/renderApplyPlan.test.d.ts +2 -0
- package/dist/definitions/renderApplyPlan.test.d.ts.map +1 -0
- package/dist/definitions/renderDedupeSummary.d.ts +22 -0
- package/dist/definitions/renderDedupeSummary.d.ts.map +1 -0
- package/dist/definitions/renderDedupeSummary.test.d.ts +2 -0
- package/dist/definitions/renderDedupeSummary.test.d.ts.map +1 -0
- package/dist/definitions/renderDuplicatesReport.d.ts +39 -0
- package/dist/definitions/renderDuplicatesReport.d.ts.map +1 -0
- package/dist/definitions/renderDuplicatesReport.test.d.ts +2 -0
- package/dist/definitions/renderDuplicatesReport.test.d.ts.map +1 -0
- package/dist/definitions/reportColors.d.ts +25 -0
- package/dist/definitions/reportColors.d.ts.map +1 -0
- package/dist/definitions/reportColors.test.d.ts +2 -0
- package/dist/definitions/reportColors.test.d.ts.map +1 -0
- package/dist/definitions/reportText.d.ts +29 -0
- package/dist/definitions/reportText.d.ts.map +1 -0
- package/dist/definitions/selectExplainedPackages.d.ts +22 -0
- package/dist/definitions/selectExplainedPackages.d.ts.map +1 -0
- package/dist/definitions/selectExplainedPackages.test.d.ts +2 -0
- package/dist/definitions/selectExplainedPackages.test.d.ts.map +1 -0
- package/dist/definitions/unconditionalOverrides.d.ts +24 -0
- package/dist/definitions/unconditionalOverrides.d.ts.map +1 -0
- package/dist/definitions/unconditionalOverrides.test.d.ts +2 -0
- package/dist/definitions/unconditionalOverrides.test.d.ts.map +1 -0
- package/dist/definitions/versionsSnapshot.d.ts +40 -0
- package/dist/definitions/versionsSnapshot.d.ts.map +1 -0
- package/dist/definitions/versionsSnapshot.test.d.ts +2 -0
- package/dist/definitions/versionsSnapshot.test.d.ts.map +1 -0
- package/dist/definitions/workspaceManifest.d.ts +21 -0
- package/dist/definitions/workspaceManifest.d.ts.map +1 -0
- package/dist/definitions/workspaceManifest.test.d.ts +2 -0
- package/dist/definitions/workspaceManifest.test.d.ts.map +1 -0
- package/dist/duplicateSnapshot.js +10 -0
- package/dist/duplicateSnapshot.js.map +1 -0
- package/dist/fileSnapshot.js +21 -0
- package/dist/fileSnapshot.js.map +1 -0
- package/dist/findProjectRoot.js +48 -0
- package/dist/findProjectRoot.js.map +1 -0
- package/dist/findProjectRoot.test.js +53 -0
- package/dist/findProjectRoot.test.js.map +1 -0
- package/dist/identifyLockstepClusterFixes.js +352 -0
- package/dist/identifyLockstepClusterFixes.js.map +1 -0
- package/dist/identifyLockstepClusterFixes.test.js +372 -0
- package/dist/identifyLockstepClusterFixes.test.js.map +1 -0
- package/dist/identifyResolutionFixes.js +102 -0
- package/dist/identifyResolutionFixes.js.map +1 -0
- package/dist/identifyResolutionFixes.test.js +70 -0
- package/dist/identifyResolutionFixes.test.js.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/packageDependenciesUtils.js +91 -0
- package/dist/packageDependenciesUtils.js.map +1 -0
- package/dist/packageDependenciesUtils.test.js +539 -0
- package/dist/packageDependenciesUtils.test.js.map +1 -0
- package/dist/packageFilterArgs.js +65 -0
- package/dist/packageFilterArgs.js.map +1 -0
- package/dist/packageFilterArgs.test.js +93 -0
- package/dist/packageFilterArgs.test.js.map +1 -0
- package/dist/packageStyles.js +33 -0
- package/dist/packageStyles.js.map +1 -0
- package/dist/packageStyles.test.js +58 -0
- package/dist/packageStyles.test.js.map +1 -0
- package/dist/parseBinArgs.js +28 -0
- package/dist/parseBinArgs.js.map +1 -0
- package/dist/parseBinArgs.test.js +62 -0
- package/dist/parseBinArgs.test.js.map +1 -0
- package/dist/planClusterApply.js +69 -0
- package/dist/planClusterApply.js.map +1 -0
- package/dist/planClusterApply.test.js +152 -0
- package/dist/planClusterApply.test.js.map +1 -0
- package/dist/renderApplyPlan.js +51 -0
- package/dist/renderApplyPlan.js.map +1 -0
- package/dist/renderApplyPlan.test.js +106 -0
- package/dist/renderApplyPlan.test.js.map +1 -0
- package/dist/renderDedupeSummary.js +38 -0
- package/dist/renderDedupeSummary.js.map +1 -0
- package/dist/renderDedupeSummary.test.js +91 -0
- package/dist/renderDedupeSummary.test.js.map +1 -0
- package/dist/renderDuplicatesReport.js +375 -0
- package/dist/renderDuplicatesReport.js.map +1 -0
- package/dist/renderDuplicatesReport.test.js +598 -0
- package/dist/renderDuplicatesReport.test.js.map +1 -0
- package/dist/reportColors.js +51 -0
- package/dist/reportColors.js.map +1 -0
- package/dist/reportColors.test.js +49 -0
- package/dist/reportColors.test.js.map +1 -0
- package/dist/reportText.js +29 -0
- package/dist/reportText.js.map +1 -0
- package/dist/selectExplainedPackages.js +42 -0
- package/dist/selectExplainedPackages.js.map +1 -0
- package/dist/selectExplainedPackages.test.js +55 -0
- package/dist/selectExplainedPackages.test.js.map +1 -0
- package/dist/unconditionalOverrides.js +36 -0
- package/dist/unconditionalOverrides.js.map +1 -0
- package/dist/unconditionalOverrides.test.js +71 -0
- package/dist/unconditionalOverrides.test.js.map +1 -0
- package/dist/versionsSnapshot.js +49 -0
- package/dist/versionsSnapshot.js.map +1 -0
- package/dist/versionsSnapshot.test.js +79 -0
- package/dist/versionsSnapshot.test.js.map +1 -0
- package/dist/workspaceManifest.js +63 -0
- package/dist/workspaceManifest.js.map +1 -0
- package/dist/workspaceManifest.test.js +159 -0
- package/dist/workspaceManifest.test.js.map +1 -0
- package/package.json +68 -0
- package/src/buildIdentifiedFixesMap.ts +22 -0
- package/src/buildLockstepClusters.test.ts +90 -0
- package/src/buildLockstepClusters.ts +155 -0
- package/src/clusterLabel.test.ts +79 -0
- package/src/clusterLabel.ts +75 -0
- package/src/compareCandidateVersions.test.ts +39 -0
- package/src/compareCandidateVersions.ts +23 -0
- package/src/createPackageFilter.test.ts +156 -0
- package/src/createPackageFilter.ts +142 -0
- package/src/duplicateSnapshot.ts +24 -0
- package/src/fileSnapshot.ts +28 -0
- package/src/findProjectRoot.test.ts +66 -0
- package/src/findProjectRoot.ts +61 -0
- package/src/identifyLockstepClusterFixes.test.ts +462 -0
- package/src/identifyLockstepClusterFixes.ts +602 -0
- package/src/identifyResolutionFixes.test.ts +133 -0
- package/src/identifyResolutionFixes.ts +183 -0
- package/src/index.ts +123 -0
- package/src/packageDependenciesUtils.test.ts +593 -0
- package/src/packageDependenciesUtils.ts +156 -0
- package/src/packageFilterArgs.test.ts +116 -0
- package/src/packageFilterArgs.ts +98 -0
- package/src/packageStyles.test.ts +77 -0
- package/src/packageStyles.ts +42 -0
- package/src/parseBinArgs.test.ts +73 -0
- package/src/parseBinArgs.ts +33 -0
- package/src/planClusterApply.test.ts +163 -0
- package/src/planClusterApply.ts +105 -0
- package/src/renderApplyPlan.test.ts +136 -0
- package/src/renderApplyPlan.ts +95 -0
- package/src/renderDedupeSummary.test.ts +121 -0
- package/src/renderDedupeSummary.ts +78 -0
- package/src/renderDuplicatesReport.test.ts +724 -0
- package/src/renderDuplicatesReport.ts +645 -0
- package/src/reportColors.test.ts +57 -0
- package/src/reportColors.ts +78 -0
- package/src/reportText.ts +58 -0
- package/src/selectExplainedPackages.test.ts +67 -0
- package/src/selectExplainedPackages.ts +79 -0
- package/src/unconditionalOverrides.test.ts +99 -0
- package/src/unconditionalOverrides.ts +60 -0
- package/src/versionsSnapshot.test.ts +146 -0
- package/src/versionsSnapshot.ts +93 -0
- package/src/workspaceManifest.test.ts +220 -0
- package/src/workspaceManifest.ts +100 -0
|
@@ -0,0 +1,724 @@
|
|
|
1
|
+
import { describe, it } from "bun:test";
|
|
2
|
+
import { ok, strictEqual } from "node:assert/strict";
|
|
3
|
+
import type { ClusterFix } from "./identifyLockstepClusterFixes.ts";
|
|
4
|
+
import { renderDuplicatesReport } from "./renderDuplicatesReport.ts";
|
|
5
|
+
import type {
|
|
6
|
+
DuplicatePackageView,
|
|
7
|
+
DuplicatesReportOptions,
|
|
8
|
+
} from "./renderDuplicatesReport.ts";
|
|
9
|
+
|
|
10
|
+
const escapeStart = "\u001B[";
|
|
11
|
+
// eslint-disable-next-line no-control-regex
|
|
12
|
+
const escapePattern = /\u001B\[[\d;]+m/gu;
|
|
13
|
+
|
|
14
|
+
const metroPin = {
|
|
15
|
+
requester: "package.json in devDependencies",
|
|
16
|
+
requesterName: undefined,
|
|
17
|
+
packageName: "metro",
|
|
18
|
+
range: "0.84.5",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const clusterFix = (overrides: Partial<ClusterFix> = {}): ClusterFix => ({
|
|
22
|
+
members: ["metro", "metro-config"],
|
|
23
|
+
duplicatedMembers: ["metro", "metro-config"],
|
|
24
|
+
memberVersions: {
|
|
25
|
+
metro: { versions: ["0.84.5", "0.87.0"], nonNpmCount: 0 },
|
|
26
|
+
"metro-config": { versions: ["0.84.5", "0.87.0"], nonNpmCount: 0 },
|
|
27
|
+
},
|
|
28
|
+
target: "0.87.0",
|
|
29
|
+
direction: "up",
|
|
30
|
+
convergentMembers: ["metro", "metro-config"],
|
|
31
|
+
driverMembers: ["metro"],
|
|
32
|
+
excludedMembers: [],
|
|
33
|
+
anchor: null,
|
|
34
|
+
reuseFixes: [],
|
|
35
|
+
floatingMembers: [],
|
|
36
|
+
workspaceChanges: [],
|
|
37
|
+
reResolutionSet: ["metro"],
|
|
38
|
+
externalConstraints: [metroPin],
|
|
39
|
+
needsRoundTrip: true,
|
|
40
|
+
applicable: true,
|
|
41
|
+
...overrides,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const metroPackage = (
|
|
45
|
+
overrides: Partial<DuplicatePackageView> = {},
|
|
46
|
+
): DuplicatePackageView => ({
|
|
47
|
+
packageName: "metro",
|
|
48
|
+
resolutions: [
|
|
49
|
+
{
|
|
50
|
+
resolution: "metro@0.84.5",
|
|
51
|
+
version: "0.84.5",
|
|
52
|
+
installations: ["metro@0.84.5"],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
resolution: "metro@0.87.0",
|
|
56
|
+
version: "0.87.0",
|
|
57
|
+
installations: ["metro@0.87.0"],
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
dependents: [
|
|
61
|
+
{
|
|
62
|
+
requester: "package.json in devDependencies",
|
|
63
|
+
range: "0.84.5",
|
|
64
|
+
resolvedVersion: "0.84.5",
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
dedupe: [],
|
|
68
|
+
...overrides,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// the tree is what the cluster sections live in; the one-line form has its own
|
|
72
|
+
// helper below
|
|
73
|
+
const render = (overrides: Partial<DuplicatesReportOptions> = {}): string => {
|
|
74
|
+
let buffer = "";
|
|
75
|
+
renderDuplicatesReport({
|
|
76
|
+
title: "duplicates",
|
|
77
|
+
packages: [metroPackage()],
|
|
78
|
+
totalDependencies: 120,
|
|
79
|
+
dedupeCommand: "pnpm-dedupe",
|
|
80
|
+
whyCommand: "pnpm-why-duplicate",
|
|
81
|
+
details: true,
|
|
82
|
+
color: false,
|
|
83
|
+
log: (message = "") => {
|
|
84
|
+
buffer += `${message}\n`;
|
|
85
|
+
},
|
|
86
|
+
...overrides,
|
|
87
|
+
});
|
|
88
|
+
return buffer;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const renderSummary = (
|
|
92
|
+
overrides: Partial<DuplicatesReportOptions> = {},
|
|
93
|
+
): string => render({ details: false, ...overrides });
|
|
94
|
+
|
|
95
|
+
const lastLine = (output: string): string =>
|
|
96
|
+
output.trimEnd().split("\n").at(-1)!;
|
|
97
|
+
|
|
98
|
+
describe("renderDuplicatesReport", () => {
|
|
99
|
+
it("groups every dependent under the version it resolved to", () => {
|
|
100
|
+
const output = render();
|
|
101
|
+
ok(output.startsWith("Found 1 duplicate:\n"));
|
|
102
|
+
ok(output.includes("metro — 2 versions"));
|
|
103
|
+
// highest first, so the version a merge usually targets leads
|
|
104
|
+
ok(output.indexOf(" 0.87.0") < output.indexOf(" 0.84.5"));
|
|
105
|
+
ok(
|
|
106
|
+
output.includes(
|
|
107
|
+
' - package.json in devDependencies requires "0.84.5"',
|
|
108
|
+
),
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("says when nothing declares a version through a comparable range", () => {
|
|
113
|
+
ok(render().includes(" (no semver range recorded for it)"));
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("files a dependent under the versionless resolution it names", () => {
|
|
117
|
+
const output = render({
|
|
118
|
+
packages: [
|
|
119
|
+
metroPackage({
|
|
120
|
+
resolutions: [
|
|
121
|
+
{
|
|
122
|
+
resolution: "metro@0.87.0",
|
|
123
|
+
version: "0.87.0",
|
|
124
|
+
installations: ["metro@0.87.0"],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
resolution: "metro@patch:metro@npm%3A0.87.0#./p.patch",
|
|
128
|
+
installations: ["metro@patch:metro@npm%3A0.87.0#./p.patch"],
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
dependents: [
|
|
132
|
+
{
|
|
133
|
+
requester: "package.json in devDependencies",
|
|
134
|
+
range: "^0.87.0",
|
|
135
|
+
resolvedVersion: "0.87.0",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
requester: "needs-patch@1.0.0",
|
|
139
|
+
range: "patch:metro@npm%3A0.87.0#./p.patch",
|
|
140
|
+
resolvedResolution: "metro@patch:metro@npm%3A0.87.0#./p.patch",
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
}),
|
|
144
|
+
],
|
|
145
|
+
});
|
|
146
|
+
ok(!output.includes("(no semver range recorded for it)"));
|
|
147
|
+
ok(!output.includes("(resolved version unknown)"));
|
|
148
|
+
ok(
|
|
149
|
+
output.indexOf(" metro@patch:metro@npm%3A0.87.0#./p.patch") <
|
|
150
|
+
output.indexOf("- needs-patch@1.0.0"),
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// a resolution the report does not carry cannot be guessed at as the sole
|
|
155
|
+
// version: whoever declared it is not holding that copy
|
|
156
|
+
it("leaves a dependent naming an unknown resolution unattributed", () => {
|
|
157
|
+
const output = render({
|
|
158
|
+
packages: [
|
|
159
|
+
metroPackage({
|
|
160
|
+
resolutions: [
|
|
161
|
+
{
|
|
162
|
+
resolution: "metro@0.84.5",
|
|
163
|
+
version: "0.84.5",
|
|
164
|
+
installations: ["metro@0.84.5"],
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
dependents: [
|
|
168
|
+
{
|
|
169
|
+
requester: "needs-patch@1.0.0",
|
|
170
|
+
range: "patch:metro@npm%3A0.87.0#./p.patch",
|
|
171
|
+
resolvedResolution: "metro@patch:metro@npm%3A0.87.0#./p.patch",
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
}),
|
|
175
|
+
],
|
|
176
|
+
});
|
|
177
|
+
ok(output.includes(" (resolved version unknown)"));
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("lists a dependent whose resolved version is unknown rather than dropping it", () => {
|
|
181
|
+
const output = render({
|
|
182
|
+
packages: [
|
|
183
|
+
metroPackage({
|
|
184
|
+
dependents: [{ requester: "mini-deep@2.0.0", range: "^0.84.0" }],
|
|
185
|
+
}),
|
|
186
|
+
],
|
|
187
|
+
});
|
|
188
|
+
ok(output.includes(" (resolved version unknown)"));
|
|
189
|
+
ok(output.includes(' - mini-deep@2.0.0 requires "^0.84.0"'));
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("attributes an unresolved dependent to the sole version", () => {
|
|
193
|
+
const output = render({
|
|
194
|
+
packages: [
|
|
195
|
+
metroPackage({
|
|
196
|
+
resolutions: [
|
|
197
|
+
{
|
|
198
|
+
resolution: "metro@0.84.5",
|
|
199
|
+
version: "0.84.5",
|
|
200
|
+
installations: ["metro@0.84.5"],
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
dependents: [
|
|
204
|
+
{
|
|
205
|
+
requester: "package.json in devDependencies",
|
|
206
|
+
range: "0.84.5",
|
|
207
|
+
resolvedVersion: "0.84.5",
|
|
208
|
+
},
|
|
209
|
+
// a peer range carries no resolved version of its own, and one
|
|
210
|
+
// version in the lockfile leaves nothing to attribute
|
|
211
|
+
{ requester: "mini-deep@2.0.0", range: "^0.84.0", peer: true },
|
|
212
|
+
// not even when the sole version does not satisfy it: an unmet peer
|
|
213
|
+
// is a warning, not a second copy
|
|
214
|
+
{ requester: "old-deep@1.0.0", range: "^0.74.0", peer: true },
|
|
215
|
+
],
|
|
216
|
+
}),
|
|
217
|
+
],
|
|
218
|
+
});
|
|
219
|
+
ok(!output.includes("(resolved version unknown)"));
|
|
220
|
+
ok(output.indexOf(" 0.84.5") < output.indexOf("- mini-deep@2.0.0"));
|
|
221
|
+
ok(
|
|
222
|
+
output.includes(
|
|
223
|
+
' - mini-deep@2.0.0 requires "^0.84.0" (peer)',
|
|
224
|
+
),
|
|
225
|
+
);
|
|
226
|
+
ok(
|
|
227
|
+
output.includes(
|
|
228
|
+
' - old-deep@1.0.0 requires "^0.74.0" (peer)',
|
|
229
|
+
),
|
|
230
|
+
);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it("lists the installation contexts of a shared resolution", () => {
|
|
234
|
+
const output = render({
|
|
235
|
+
packages: [
|
|
236
|
+
metroPackage({
|
|
237
|
+
resolutions: [
|
|
238
|
+
{
|
|
239
|
+
resolution: "metro@0.84.5",
|
|
240
|
+
version: "0.84.5",
|
|
241
|
+
installations: ["metro@0.84.5", "metro@0.84.5(react@19)"],
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
}),
|
|
245
|
+
],
|
|
246
|
+
});
|
|
247
|
+
ok(
|
|
248
|
+
output.includes(" installed at: metro@0.84.5, metro@0.84.5(react@19)"),
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("states how a duplicate would collapse", () => {
|
|
253
|
+
const output = render({
|
|
254
|
+
packages: [
|
|
255
|
+
metroPackage({
|
|
256
|
+
dedupe: [{ from: ["0.84.5"], to: "0.87.0", direction: "up" }],
|
|
257
|
+
}),
|
|
258
|
+
],
|
|
259
|
+
});
|
|
260
|
+
ok(
|
|
261
|
+
output.includes("metro — 2 versions, can be deduped to 0.87.0 (upgrade)"),
|
|
262
|
+
);
|
|
263
|
+
ok(output.includes(" 0.84.5 can be deduped to 0.87.0 (upgrade)"));
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("counts the versions left when only some of them merge", () => {
|
|
267
|
+
const output = render({
|
|
268
|
+
packages: [
|
|
269
|
+
metroPackage({
|
|
270
|
+
resolutions: [
|
|
271
|
+
{
|
|
272
|
+
resolution: "metro@0.87.0",
|
|
273
|
+
version: "0.87.0",
|
|
274
|
+
installations: ["metro@0.87.0"],
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
resolution: "metro@0.84.5",
|
|
278
|
+
version: "0.84.5",
|
|
279
|
+
installations: ["metro@0.84.5"],
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
resolution: "metro@0.74.1",
|
|
283
|
+
version: "0.74.1",
|
|
284
|
+
installations: ["metro@0.74.1"],
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
dedupe: [{ from: ["0.84.5"], to: "0.87.0", direction: "up" }],
|
|
288
|
+
}),
|
|
289
|
+
],
|
|
290
|
+
});
|
|
291
|
+
// three resolved, one merges away: two remain — never "one merged"
|
|
292
|
+
ok(output.includes("metro — 3 versions, can be deduped to 2 versions"));
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("reports no duplicates for an empty list", () => {
|
|
296
|
+
const output = render({ packages: [] });
|
|
297
|
+
ok(output.startsWith("No duplicates found\n"));
|
|
298
|
+
strictEqual(
|
|
299
|
+
lastLine(output),
|
|
300
|
+
"Found 120 dependencies, 0 duplicates, 0 dedupable.",
|
|
301
|
+
);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("leads with the notice instead of a count that would read as no report", () => {
|
|
305
|
+
const output = render({
|
|
306
|
+
title: "matches",
|
|
307
|
+
notice: "lodash is not duplicated. Showing its dependents:",
|
|
308
|
+
packages: [
|
|
309
|
+
metroPackage({
|
|
310
|
+
packageName: "lodash",
|
|
311
|
+
resolutions: [
|
|
312
|
+
{
|
|
313
|
+
resolution: "lodash@4.17.21",
|
|
314
|
+
version: "4.17.21",
|
|
315
|
+
installations: ["lodash@4.17.21"],
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
dependents: [
|
|
319
|
+
{
|
|
320
|
+
requester: "eslint@9.0.0",
|
|
321
|
+
range: "^4.17.0",
|
|
322
|
+
resolvedVersion: "4.17.21",
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
}),
|
|
326
|
+
],
|
|
327
|
+
});
|
|
328
|
+
ok(
|
|
329
|
+
output.startsWith("lodash is not duplicated. Showing its dependents:\n"),
|
|
330
|
+
);
|
|
331
|
+
ok(!output.includes("No duplicates found"));
|
|
332
|
+
ok(output.includes(' - eslint@9.0.0 requires "^4.17.0"'));
|
|
333
|
+
strictEqual(
|
|
334
|
+
lastLine(output),
|
|
335
|
+
"Found 120 dependencies, 1 match, 0 dedupable.",
|
|
336
|
+
);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it("omits the command when nothing is dedupable", () => {
|
|
340
|
+
ok(!render().includes("pnpm-dedupe"));
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it("credits a cluster for a package its own resolutions cannot fix", () => {
|
|
344
|
+
const output = render({ clusterFixes: [clusterFix()] });
|
|
345
|
+
ok(
|
|
346
|
+
output.includes("metro — 2 versions, can be deduped to 0.87.0 (upgrade)"),
|
|
347
|
+
);
|
|
348
|
+
strictEqual(
|
|
349
|
+
lastLine(output),
|
|
350
|
+
"Found 120 dependencies, 1 duplicate, at least 1 dedupable (deduping may remove more). Run `pnpm-dedupe` to apply.",
|
|
351
|
+
);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it("counts a package that is both its own fix and a cluster member once", () => {
|
|
355
|
+
const output = render({
|
|
356
|
+
packages: [
|
|
357
|
+
metroPackage({ dedupe: [{ from: ["0.84.5"], to: "0.87.0" }] }),
|
|
358
|
+
],
|
|
359
|
+
clusterFixes: [clusterFix()],
|
|
360
|
+
});
|
|
361
|
+
ok(lastLine(output).includes("at least 1 dedupable"));
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// A merged package drags its own dependency edges along, so the count is a
|
|
365
|
+
// floor and has to read like one.
|
|
366
|
+
it("words the dedupable count as a floor", () => {
|
|
367
|
+
ok(
|
|
368
|
+
render({ clusterFixes: [clusterFix()] }).includes(
|
|
369
|
+
"at least 1 dedupable (deduping may remove more)",
|
|
370
|
+
),
|
|
371
|
+
);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it("explains what a cluster is, once", () => {
|
|
375
|
+
const output = render({ clusterFixes: [clusterFix(), clusterFix()] });
|
|
376
|
+
ok(output.includes("Lockstep clusters:"));
|
|
377
|
+
strictEqual(
|
|
378
|
+
output.split("A lockstep cluster is a family of packages").length - 1,
|
|
379
|
+
1,
|
|
380
|
+
);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it("cross-references a member to its cluster", () => {
|
|
384
|
+
const output = render({ clusterFixes: [clusterFix()] });
|
|
385
|
+
ok(output.includes("(cluster 1)"));
|
|
386
|
+
ok(
|
|
387
|
+
output.includes(
|
|
388
|
+
"cluster 1 — metro* [2 packages, 2 duplicated, 2 fixable]:",
|
|
389
|
+
),
|
|
390
|
+
);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it("lists every member with its installed versions", () => {
|
|
394
|
+
const output = render({
|
|
395
|
+
clusterFixes: [
|
|
396
|
+
clusterFix({
|
|
397
|
+
members: ["metro", "metro-config-with-a-long-name"],
|
|
398
|
+
memberVersions: {
|
|
399
|
+
metro: { versions: ["0.84.5", "0.87.0"], nonNpmCount: 0 },
|
|
400
|
+
"metro-config-with-a-long-name": {
|
|
401
|
+
versions: ["0.87.0"],
|
|
402
|
+
nonNpmCount: 0,
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
}),
|
|
406
|
+
],
|
|
407
|
+
});
|
|
408
|
+
ok(output.includes(" Members:"));
|
|
409
|
+
// aligned on the longest member name
|
|
410
|
+
ok(output.includes(" - metro 0.84.5, 0.87.0"));
|
|
411
|
+
ok(output.includes(" - metro-config-with-a-long-name 0.87.0"));
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it("says when a member also has non-npm resolutions", () => {
|
|
415
|
+
const output = render({
|
|
416
|
+
clusterFixes: [
|
|
417
|
+
clusterFix({
|
|
418
|
+
memberVersions: {
|
|
419
|
+
metro: { versions: ["0.84.5"], nonNpmCount: 1 },
|
|
420
|
+
"metro-config": { versions: ["0.84.5", "0.87.0"], nonNpmCount: 0 },
|
|
421
|
+
},
|
|
422
|
+
}),
|
|
423
|
+
],
|
|
424
|
+
});
|
|
425
|
+
ok(output.includes("0.84.5 (+1 non-npm)"));
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it("renders the target, the drivers and the members that follow", () => {
|
|
429
|
+
const output = render({
|
|
430
|
+
clusterFixes: [
|
|
431
|
+
clusterFix({
|
|
432
|
+
members: ["metro", "metro-config", "metro-core"],
|
|
433
|
+
convergentMembers: ["metro", "metro-config", "metro-core"],
|
|
434
|
+
driverMembers: ["metro"],
|
|
435
|
+
}),
|
|
436
|
+
],
|
|
437
|
+
});
|
|
438
|
+
ok(output.includes(" Dedupe: 0.87.0 (upgrade)"));
|
|
439
|
+
ok(output.includes(" Driven by: metro (2 members follow)"));
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it("uses the singular when one member follows", () => {
|
|
443
|
+
ok(render({ clusterFixes: [clusterFix()] }).includes("(1 member follows)"));
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it("names the members whose version the resolver picks", () => {
|
|
447
|
+
const output = render({
|
|
448
|
+
clusterFixes: [clusterFix({ floatingMembers: ["metro-config"] })],
|
|
449
|
+
});
|
|
450
|
+
ok(output.includes(" Resolver picks: metro-config"));
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
it("has no Dedupe section for an unfixable cluster", () => {
|
|
454
|
+
const output = render({
|
|
455
|
+
clusterFixes: [
|
|
456
|
+
clusterFix({
|
|
457
|
+
target: null,
|
|
458
|
+
direction: "none",
|
|
459
|
+
applicable: false,
|
|
460
|
+
convergentMembers: [],
|
|
461
|
+
driverMembers: [],
|
|
462
|
+
reResolutionSet: [],
|
|
463
|
+
}),
|
|
464
|
+
],
|
|
465
|
+
});
|
|
466
|
+
ok(output.includes("[2 packages, 2 duplicated, 0 fixable]:"));
|
|
467
|
+
ok(!output.includes("Dedupe:"));
|
|
468
|
+
ok(lastLine(output).includes("0 dedupable"));
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
it("renders the duplicates an excluded member keeps", () => {
|
|
472
|
+
const output = render({
|
|
473
|
+
clusterFixes: [
|
|
474
|
+
clusterFix({
|
|
475
|
+
convergentMembers: ["metro"],
|
|
476
|
+
excludedMembers: [
|
|
477
|
+
{
|
|
478
|
+
packageName: "metro-config",
|
|
479
|
+
blockedBy: [
|
|
480
|
+
{
|
|
481
|
+
requester: "react-native-web@0.21.2",
|
|
482
|
+
requesterName: "react-native-web",
|
|
483
|
+
packageName: "metro-config",
|
|
484
|
+
range: "^0.74.1",
|
|
485
|
+
},
|
|
486
|
+
],
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
}),
|
|
490
|
+
],
|
|
491
|
+
});
|
|
492
|
+
ok(output.includes(" Remaining duplicates:"));
|
|
493
|
+
ok(
|
|
494
|
+
output.includes(
|
|
495
|
+
' - metro-config: react-native-web requires "^0.74.1"',
|
|
496
|
+
),
|
|
497
|
+
);
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it("renders open ranges that did not reuse the anchored version", () => {
|
|
501
|
+
const output = render({
|
|
502
|
+
clusterFixes: [
|
|
503
|
+
clusterFix({
|
|
504
|
+
anchor: "0.84.5",
|
|
505
|
+
reuseFixes: [
|
|
506
|
+
{
|
|
507
|
+
requester: "mini-deep@2.0.0",
|
|
508
|
+
requesterName: "mini-deep",
|
|
509
|
+
packageName: "metro-config",
|
|
510
|
+
range: "*",
|
|
511
|
+
from: "0.87.0",
|
|
512
|
+
to: "0.84.5",
|
|
513
|
+
},
|
|
514
|
+
],
|
|
515
|
+
}),
|
|
516
|
+
],
|
|
517
|
+
});
|
|
518
|
+
ok(output.includes(" Open ranges not reusing the pinned 0.84.5:"));
|
|
519
|
+
ok(
|
|
520
|
+
output.includes(
|
|
521
|
+
' - mini-deep requires metro-config "*", resolved 0.87.0 -> would pin 0.84.5',
|
|
522
|
+
),
|
|
523
|
+
);
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
it("renders open ranges even when the cluster cannot be fixed", () => {
|
|
527
|
+
const output = render({
|
|
528
|
+
clusterFixes: [
|
|
529
|
+
clusterFix({
|
|
530
|
+
applicable: false,
|
|
531
|
+
target: null,
|
|
532
|
+
convergentMembers: [],
|
|
533
|
+
anchor: "0.84.5",
|
|
534
|
+
reuseFixes: [
|
|
535
|
+
{
|
|
536
|
+
requester: "mini-deep@2.0.0",
|
|
537
|
+
requesterName: "mini-deep",
|
|
538
|
+
packageName: "metro-config",
|
|
539
|
+
range: "*",
|
|
540
|
+
from: "0.87.0",
|
|
541
|
+
to: "0.84.5",
|
|
542
|
+
},
|
|
543
|
+
],
|
|
544
|
+
}),
|
|
545
|
+
],
|
|
546
|
+
});
|
|
547
|
+
ok(output.includes("Open ranges not reusing the pinned 0.84.5:"));
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it("files an external range under the version it resolved to", () => {
|
|
551
|
+
const output = render({
|
|
552
|
+
clusterFixes: [
|
|
553
|
+
clusterFix({
|
|
554
|
+
externalConstraints: [
|
|
555
|
+
{ ...metroPin, resolvedVersion: "0.84.5" },
|
|
556
|
+
{
|
|
557
|
+
requester: "react-native-web@0.21.2",
|
|
558
|
+
requesterName: "react-native-web",
|
|
559
|
+
packageName: "metro-config",
|
|
560
|
+
range: "^0.74.1",
|
|
561
|
+
},
|
|
562
|
+
],
|
|
563
|
+
}),
|
|
564
|
+
],
|
|
565
|
+
});
|
|
566
|
+
ok(output.includes(" Resolutions (external):"));
|
|
567
|
+
ok(output.includes(" 0.84.5"));
|
|
568
|
+
ok(output.includes(' - workspace requires metro "0.84.5"'));
|
|
569
|
+
// nothing records what this one got, and it is not dropped for it
|
|
570
|
+
ok(output.includes(" (resolved version unknown)"));
|
|
571
|
+
ok(
|
|
572
|
+
output.includes(
|
|
573
|
+
' - react-native-web requires metro-config "^0.74.1"',
|
|
574
|
+
),
|
|
575
|
+
);
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
it("attributes a workspace constraint to the workspace", () => {
|
|
579
|
+
const output = render({ clusterFixes: [clusterFix()] });
|
|
580
|
+
ok(output.includes(" Resolutions (external):"));
|
|
581
|
+
ok(output.includes('- workspace requires metro "0.84.5"'));
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
it("skips a cluster with no duplicated member", () => {
|
|
585
|
+
const output = render({
|
|
586
|
+
clusterFixes: [clusterFix({ duplicatedMembers: [] })],
|
|
587
|
+
});
|
|
588
|
+
ok(!output.includes("Lockstep clusters:"));
|
|
589
|
+
ok(!output.includes("(cluster 1)"));
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it("titles the report for a match listing", () => {
|
|
593
|
+
ok(render({ title: "matches" }).startsWith("Found 1 match:\n"));
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
it("gives each package one line, with its census and its verdict", () => {
|
|
597
|
+
const output = renderSummary({
|
|
598
|
+
packages: [
|
|
599
|
+
metroPackage({
|
|
600
|
+
dedupe: [{ from: ["0.84.5"], to: "0.87.0", direction: "up" }],
|
|
601
|
+
}),
|
|
602
|
+
],
|
|
603
|
+
});
|
|
604
|
+
ok(
|
|
605
|
+
output.includes(
|
|
606
|
+
"- metro resolved to 2 versions (0.87.0, 0.84.5), can be deduped to 0.87.0 (upgrade)",
|
|
607
|
+
),
|
|
608
|
+
);
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it("leaves the verdict off a package nothing can collapse", () => {
|
|
612
|
+
const output = renderSummary();
|
|
613
|
+
ok(output.includes("- metro resolved to 2 versions (0.87.0, 0.84.5)"));
|
|
614
|
+
ok(!output.includes("can be deduped"));
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
it("keeps no tree and no cluster section", () => {
|
|
618
|
+
const output = renderSummary({ clusterFixes: [clusterFix()] });
|
|
619
|
+
ok(!output.includes("Lockstep clusters:"));
|
|
620
|
+
ok(!output.includes('requires "0.84.5"'));
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
it("points at the tree", () => {
|
|
624
|
+
ok(
|
|
625
|
+
renderSummary().includes(
|
|
626
|
+
"Run `pnpm-why-duplicate --details` to see every dependent.",
|
|
627
|
+
),
|
|
628
|
+
);
|
|
629
|
+
ok(!render().includes("--details"));
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
// one version installed several times is a duplicate the census cannot show
|
|
633
|
+
it("names the install paths of a package resolved once", () => {
|
|
634
|
+
const output = renderSummary({
|
|
635
|
+
packages: [
|
|
636
|
+
metroPackage({
|
|
637
|
+
resolutions: [
|
|
638
|
+
{
|
|
639
|
+
resolution: "metro@0.84.5",
|
|
640
|
+
version: "0.84.5",
|
|
641
|
+
installations: ["metro@0.84.5", "metro@0.84.5(react@19)"],
|
|
642
|
+
},
|
|
643
|
+
],
|
|
644
|
+
}),
|
|
645
|
+
],
|
|
646
|
+
});
|
|
647
|
+
ok(
|
|
648
|
+
output.includes(
|
|
649
|
+
"- metro resolved to 1 version (0.84.5) installed at 2 paths",
|
|
650
|
+
),
|
|
651
|
+
);
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
it("styles without moving anything: stripped, the two renders match", () => {
|
|
655
|
+
const options: Partial<DuplicatesReportOptions> = {
|
|
656
|
+
packages: [
|
|
657
|
+
metroPackage({
|
|
658
|
+
resolutions: [
|
|
659
|
+
{
|
|
660
|
+
resolution: "metro@0.84.5",
|
|
661
|
+
version: "0.84.5",
|
|
662
|
+
installations: ["metro@0.84.5", "metro@0.84.5(react@19)"],
|
|
663
|
+
},
|
|
664
|
+
],
|
|
665
|
+
dedupe: [{ from: ["0.84.5"], to: "0.87.0" }],
|
|
666
|
+
}),
|
|
667
|
+
],
|
|
668
|
+
clusterFixes: [
|
|
669
|
+
clusterFix({
|
|
670
|
+
members: ["@react-native/metro-config", "metro-config-long-name"],
|
|
671
|
+
memberVersions: {
|
|
672
|
+
"@react-native/metro-config": {
|
|
673
|
+
versions: ["0.84.5"],
|
|
674
|
+
nonNpmCount: 1,
|
|
675
|
+
},
|
|
676
|
+
"metro-config-long-name": {
|
|
677
|
+
versions: ["0.84.5", "0.87.0"],
|
|
678
|
+
nonNpmCount: 0,
|
|
679
|
+
},
|
|
680
|
+
},
|
|
681
|
+
floatingMembers: ["metro-config-long-name"],
|
|
682
|
+
anchor: "0.84.5",
|
|
683
|
+
reuseFixes: [
|
|
684
|
+
{
|
|
685
|
+
requester: "mini-deep@2.0.0",
|
|
686
|
+
requesterName: "mini-deep",
|
|
687
|
+
packageName: "metro-config",
|
|
688
|
+
range: "*",
|
|
689
|
+
from: "0.87.0",
|
|
690
|
+
to: "0.84.5",
|
|
691
|
+
},
|
|
692
|
+
],
|
|
693
|
+
excludedMembers: [
|
|
694
|
+
{
|
|
695
|
+
packageName: "@react-native/metro-config",
|
|
696
|
+
blockedBy: [
|
|
697
|
+
{
|
|
698
|
+
requester: "react-native-web@0.21.2",
|
|
699
|
+
requesterName: "react-native-web",
|
|
700
|
+
packageName: "@react-native/metro-config",
|
|
701
|
+
range: "^0.74.1",
|
|
702
|
+
},
|
|
703
|
+
],
|
|
704
|
+
},
|
|
705
|
+
],
|
|
706
|
+
}),
|
|
707
|
+
],
|
|
708
|
+
};
|
|
709
|
+
const stripped = render({ ...options, color: true }).replaceAll(
|
|
710
|
+
escapePattern,
|
|
711
|
+
"",
|
|
712
|
+
);
|
|
713
|
+
strictEqual(stripped, render(options));
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
it("emits no escape codes with color off, and some with it on", () => {
|
|
717
|
+
ok(!render({ clusterFixes: [clusterFix()] }).includes(escapeStart));
|
|
718
|
+
ok(
|
|
719
|
+
render({ color: true, clusterFixes: [clusterFix()] }).includes(
|
|
720
|
+
escapeStart,
|
|
721
|
+
),
|
|
722
|
+
);
|
|
723
|
+
});
|
|
724
|
+
});
|