@monorepolint/rules 0.5.0-alpha.82 → 0.5.0-alpha.85

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.
Files changed (106) hide show
  1. package/lib/__tests__/alphabeticalScripts.spec.js +22 -24
  2. package/lib/__tests__/alphabeticalScripts.spec.js.map +1 -1
  3. package/lib/__tests__/bannedDependencies.spec.js +67 -9
  4. package/lib/__tests__/bannedDependencies.spec.js.map +1 -1
  5. package/lib/__tests__/consistentDependencies.spec.js +11 -10
  6. package/lib/__tests__/consistentDependencies.spec.js.map +1 -1
  7. package/lib/__tests__/consistentVersions.spec.js +23 -22
  8. package/lib/__tests__/consistentVersions.spec.js.map +1 -1
  9. package/lib/__tests__/fileContents.spec.js +25 -32
  10. package/lib/__tests__/fileContents.spec.js.map +1 -1
  11. package/lib/__tests__/mustSatisfyPeerDependencies.spec.js +49 -48
  12. package/lib/__tests__/mustSatisfyPeerDependencies.spec.js.map +1 -1
  13. package/lib/__tests__/nestedWorkspaces.spec.js +10 -8
  14. package/lib/__tests__/nestedWorkspaces.spec.js.map +1 -1
  15. package/lib/__tests__/packageEntry.spec.js +47 -40
  16. package/lib/__tests__/packageEntry.spec.js.map +1 -1
  17. package/lib/__tests__/packageOrder.spec.js +34 -33
  18. package/lib/__tests__/packageOrder.spec.js.map +1 -1
  19. package/lib/__tests__/packageScript.spec.js +50 -51
  20. package/lib/__tests__/packageScript.spec.js.map +1 -1
  21. package/lib/__tests__/requireDependency.spec.js +12 -11
  22. package/lib/__tests__/requireDependency.spec.js.map +1 -1
  23. package/lib/__tests__/utils.d.ts +68 -1
  24. package/lib/__tests__/utils.d.ts.map +1 -1
  25. package/lib/__tests__/utils.js +70 -21
  26. package/lib/__tests__/utils.js.map +1 -1
  27. package/lib/alphabeticalDependencies.js +3 -3
  28. package/lib/alphabeticalDependencies.js.map +1 -1
  29. package/lib/alphabeticalScripts.js +1 -1
  30. package/lib/alphabeticalScripts.js.map +1 -1
  31. package/lib/bannedDependencies.d.ts +21 -12
  32. package/lib/bannedDependencies.d.ts.map +1 -1
  33. package/lib/bannedDependencies.js +86 -57
  34. package/lib/bannedDependencies.js.map +1 -1
  35. package/lib/consistentDependencies.d.ts +6 -6
  36. package/lib/consistentDependencies.d.ts.map +1 -1
  37. package/lib/consistentDependencies.js +2 -3
  38. package/lib/consistentDependencies.js.map +1 -1
  39. package/lib/consistentVersions.d.ts +1 -1
  40. package/lib/consistentVersions.js +8 -8
  41. package/lib/consistentVersions.js.map +1 -1
  42. package/lib/fileContents.d.ts +8 -8
  43. package/lib/fileContents.d.ts.map +1 -1
  44. package/lib/fileContents.js +32 -31
  45. package/lib/fileContents.js.map +1 -1
  46. package/lib/index.js +1 -0
  47. package/lib/index.js.map +1 -1
  48. package/lib/mustSatisfyPeerDependencies.d.ts +31 -31
  49. package/lib/mustSatisfyPeerDependencies.d.ts.map +1 -1
  50. package/lib/mustSatisfyPeerDependencies.js +18 -16
  51. package/lib/mustSatisfyPeerDependencies.js.map +1 -1
  52. package/lib/packageEntry.d.ts +11 -20
  53. package/lib/packageEntry.d.ts.map +1 -1
  54. package/lib/packageEntry.js +15 -7
  55. package/lib/packageEntry.js.map +1 -1
  56. package/lib/packageOrder.d.ts +3 -3
  57. package/lib/packageOrder.d.ts.map +1 -1
  58. package/lib/packageOrder.js +2 -3
  59. package/lib/packageOrder.js.map +1 -1
  60. package/lib/packageScript.d.ts +10 -10
  61. package/lib/packageScript.js +4 -4
  62. package/lib/packageScript.js.map +1 -1
  63. package/lib/requireDependency.d.ts +6 -6
  64. package/lib/requireDependency.d.ts.map +1 -1
  65. package/lib/requireDependency.js +3 -3
  66. package/lib/requireDependency.js.map +1 -1
  67. package/lib/standardTsconfig.d.ts +10 -10
  68. package/lib/standardTsconfig.d.ts.map +1 -1
  69. package/lib/standardTsconfig.js +26 -21
  70. package/lib/standardTsconfig.js.map +1 -1
  71. package/lib/util/checkAlpha.d.ts +1 -0
  72. package/lib/util/checkAlpha.d.ts.map +1 -1
  73. package/lib/util/checkAlpha.js +8 -5
  74. package/lib/util/checkAlpha.js.map +1 -1
  75. package/lib/util/makeDirectory.js +2 -2
  76. package/lib/util/makeDirectory.js.map +1 -1
  77. package/lib/util/packageDependencyGraphService.d.ts +3 -3
  78. package/lib/util/packageDependencyGraphService.d.ts.map +1 -1
  79. package/lib/util/packageDependencyGraphService.js +3 -3
  80. package/lib/util/packageDependencyGraphService.js.map +1 -1
  81. package/package.json +8 -9
  82. package/src/__tests__/alphabeticalScripts.spec.ts +27 -28
  83. package/src/__tests__/bannedDependencies.spec.ts +80 -6
  84. package/src/__tests__/consistentDependencies.spec.ts +11 -6
  85. package/src/__tests__/consistentVersions.spec.ts +32 -27
  86. package/src/__tests__/fileContents.spec.ts +32 -40
  87. package/src/__tests__/mustSatisfyPeerDependencies.spec.ts +52 -47
  88. package/src/__tests__/nestedWorkspaces.spec.ts +12 -6
  89. package/src/__tests__/packageEntry.spec.ts +64 -45
  90. package/src/__tests__/packageOrder.spec.ts +46 -40
  91. package/src/__tests__/packageScript.spec.ts +62 -54
  92. package/src/__tests__/requireDependency.spec.ts +11 -6
  93. package/src/__tests__/utils.ts +109 -19
  94. package/src/bannedDependencies.ts +106 -74
  95. package/src/consistentDependencies.ts +1 -2
  96. package/src/consistentVersions.ts +2 -2
  97. package/src/fileContents.ts +32 -30
  98. package/src/mustSatisfyPeerDependencies.ts +6 -2
  99. package/src/packageEntry.ts +13 -5
  100. package/src/packageOrder.ts +1 -2
  101. package/src/packageScript.ts +2 -2
  102. package/src/requireDependency.ts +2 -2
  103. package/src/standardTsconfig.ts +22 -19
  104. package/src/util/checkAlpha.ts +6 -3
  105. package/src/util/packageDependencyGraphService.ts +8 -5
  106. package/tsconfig.tsbuildinfo +1 -6233
@@ -6,12 +6,8 @@
6
6
  */
7
7
 
8
8
  // tslint:disable:no-console
9
- import { createMockFiles } from "./utils";
10
-
11
- // done first since this also mocks 'fs'
12
- const mockFiles: Map<string, string> = createMockFiles();
13
-
14
- import { Context, Failure, PackageContext } from "@monorepolint/core";
9
+ import { AddErrorSpy, createTestingWorkspace, HOST_FACTORIES, TestingWorkspace } from "./utils";
10
+ import { Context, Failure } from "@monorepolint/core";
15
11
  import { packageOrder } from "../packageOrder";
16
12
 
17
13
  const PACKAGE_UNORDERED =
@@ -85,26 +81,24 @@ const PACKAGE_ORDERED_UNKOWN_KEYS =
85
81
  2
86
82
  ) + "\n";
87
83
 
88
- describe("expectPackageOrder", () => {
89
- afterEach(() => {
90
- mockFiles.clear();
91
- });
92
-
84
+ describe.each(HOST_FACTORIES)("expectPackageOrder ($name)", (hostFactory) => {
93
85
  describe("fix: true", () => {
94
- const context = new PackageContext(".", {
95
- rules: [],
96
- fix: true,
97
- verbose: false,
98
- silent: true,
99
- });
100
- const spy = jest.spyOn(context, "addError");
86
+ let workspace: TestingWorkspace;
87
+ let spy: AddErrorSpy;
88
+ let context: Context;
89
+
90
+ beforeEach(async () => {
91
+ workspace = await createTestingWorkspace({
92
+ fixFlag: true,
93
+ host: hostFactory.make(),
94
+ });
95
+ context = workspace.context; // minimizing delta
101
96
 
102
- afterEach(() => {
103
- spy.mockClear();
97
+ spy = jest.spyOn(workspace.context, "addError");
104
98
  });
105
99
 
106
100
  it("fixes order for expected keys", () => {
107
- mockFiles.set("package.json", PACKAGE_UNORDERED);
101
+ workspace.writeFile("package.json", PACKAGE_UNORDERED);
108
102
 
109
103
  packageOrder.check(context, {
110
104
  order: orderArray,
@@ -113,15 +107,19 @@ describe("expectPackageOrder", () => {
113
107
  expect(spy).toHaveBeenCalledTimes(1);
114
108
 
115
109
  const failure: Failure = spy.mock.calls[0][0];
116
- expect(failure.file).toBe("package.json");
117
- expect(failure.fixer).not.toBeUndefined();
118
- expect(failure.message).toBe("Incorrect order of fields in package.json");
119
-
120
- expect(mockFiles.get("package.json")).toEqual(PACKAGE_ORDERED);
110
+ expect(failure).toMatchObject(
111
+ workspace.failureMatcher({
112
+ file: "package.json",
113
+ hasFixer: true,
114
+ message: "Incorrect order of fields in package.json",
115
+ })
116
+ );
117
+
118
+ expect(workspace.readFile("package.json")).toEqual(PACKAGE_ORDERED);
121
119
  });
122
120
 
123
121
  it("fixes order for unexpected keys", () => {
124
- mockFiles.set("package.json", PACKAGE_UNORDERED_UNKOWN_KEYS);
122
+ workspace.writeFile("package.json", PACKAGE_UNORDERED_UNKOWN_KEYS);
125
123
 
126
124
  packageOrder.check(context, {
127
125
  order: orderArray,
@@ -130,15 +128,19 @@ describe("expectPackageOrder", () => {
130
128
  expect(spy).toHaveBeenCalledTimes(1);
131
129
 
132
130
  const failure: Failure = spy.mock.calls[0][0];
133
- expect(failure.file).toBe("package.json");
134
- expect(failure.fixer).not.toBeUndefined();
135
- expect(failure.message).toBe("Incorrect order of fields in package.json");
136
-
137
- expect(mockFiles.get("package.json")).toEqual(PACKAGE_ORDERED_UNKOWN_KEYS);
131
+ expect(failure).toMatchObject(
132
+ workspace.failureMatcher({
133
+ file: "package.json",
134
+ hasFixer: true,
135
+ message: "Incorrect order of fields in package.json",
136
+ })
137
+ );
138
+
139
+ expect(workspace.readFile("package.json")).toEqual(PACKAGE_ORDERED_UNKOWN_KEYS);
138
140
  });
139
141
 
140
142
  it("fixes order using function", () => {
141
- mockFiles.set("package.json", PACKAGE_UNORDERED);
143
+ workspace.writeFile("package.json", PACKAGE_UNORDERED);
142
144
 
143
145
  packageOrder.check(context, {
144
146
  order: orderFunction,
@@ -147,15 +149,19 @@ describe("expectPackageOrder", () => {
147
149
  expect(spy).toHaveBeenCalledTimes(1);
148
150
 
149
151
  const failure: Failure = spy.mock.calls[0][0];
150
- expect(failure.file).toBe("package.json");
151
- expect(failure.fixer).not.toBeUndefined();
152
- expect(failure.message).toBe("Incorrect order of fields in package.json");
153
-
154
- expect(mockFiles.get("package.json")).toEqual(PACKAGE_ORDERED_BY_LENGTH);
152
+ expect(failure).toMatchObject(
153
+ workspace.failureMatcher({
154
+ file: "package.json",
155
+ hasFixer: true,
156
+ message: "Incorrect order of fields in package.json",
157
+ })
158
+ );
159
+
160
+ expect(workspace.readFile("package.json")).toEqual(PACKAGE_ORDERED_BY_LENGTH);
155
161
  });
156
162
 
157
163
  it("does nothing if already order", () => {
158
- mockFiles.set("package.json", PACKAGE_ORDERED_UNKOWN_KEYS);
164
+ workspace.writeFile("package.json", PACKAGE_ORDERED_UNKOWN_KEYS);
159
165
 
160
166
  packageOrder.check(context, {
161
167
  order: orderArray,
@@ -163,7 +169,7 @@ describe("expectPackageOrder", () => {
163
169
 
164
170
  expect(spy).not.toHaveBeenCalled();
165
171
 
166
- expect(mockFiles.get("package.json")).toEqual(PACKAGE_ORDERED_UNKOWN_KEYS);
172
+ expect(workspace.readFile("package.json")).toEqual(PACKAGE_ORDERED_UNKOWN_KEYS);
167
173
  });
168
174
  });
169
175
  });
@@ -6,13 +6,10 @@
6
6
  */
7
7
 
8
8
  // tslint:disable:no-console
9
- import { createMockFiles } from "./utils";
10
9
 
11
- // done first since this also mocks 'fs'
12
- const mockFiles: Map<string, string> = createMockFiles();
13
-
14
- import { Failure, PackageContext } from "@monorepolint/core";
10
+ import { Context, Failure } from "@monorepolint/core";
15
11
  import { packageScript } from "../packageScript";
12
+ import { AddErrorSpy, createTestingWorkspace, HOST_FACTORIES, TestingWorkspace } from "./utils";
16
13
 
17
14
  const json = (a: unknown) => JSON.stringify(a, undefined, 2) + "\n";
18
15
 
@@ -33,29 +30,24 @@ const PACKAGE_WITH_SCRIPTS = json({
33
30
  },
34
31
  });
35
32
 
36
- describe("expectPackageScript", () => {
37
- afterEach(() => {
38
- mockFiles.clear();
39
- });
40
-
33
+ describe.each(HOST_FACTORIES)("expectPackageScript ($name)", (hostFactory) => {
41
34
  describe("fix: false", () => {
42
- const context = new PackageContext(".", {
43
- rules: [],
44
- fix: false,
45
- verbose: false,
46
- silent: true,
47
- });
35
+ let workspace: TestingWorkspace;
36
+ let spy: AddErrorSpy;
48
37
 
49
- const spy = jest.spyOn(context, "addError");
38
+ beforeEach(async () => {
39
+ workspace = await createTestingWorkspace({
40
+ fixFlag: false,
41
+ host: hostFactory.make(),
42
+ });
50
43
 
51
- afterEach(() => {
52
- spy.mockClear();
44
+ spy = jest.spyOn(workspace.context, "addError");
53
45
  });
54
46
 
55
47
  it("handles an empty script section", () => {
56
- mockFiles.set("package.json", PACKAGE_WITHOUT_SCRIPTS);
48
+ workspace.writeFile("package.json", PACKAGE_WITHOUT_SCRIPTS);
57
49
 
58
- packageScript.check(context, {
50
+ packageScript.check(workspace.context, {
59
51
  scripts: {
60
52
  foo: "bar",
61
53
  },
@@ -64,27 +56,33 @@ describe("expectPackageScript", () => {
64
56
  expect(spy).toHaveBeenCalledTimes(1);
65
57
 
66
58
  const failure: Failure = spy.mock.calls[0][0];
67
- expect(failure.file).toBe("package.json");
68
- expect(failure.fixer).not.toBeUndefined();
69
- expect(failure.message).toBe("No scripts block in package.json");
59
+ expect(failure).toMatchObject(
60
+ workspace.failureMatcher({
61
+ file: "package.json",
62
+ hasFixer: true,
63
+ message: "No scripts block in package.json",
64
+ })
65
+ );
70
66
  });
71
67
  });
72
68
 
73
69
  describe("fix: true", () => {
74
- const context = new PackageContext(".", {
75
- rules: [],
76
- fix: true,
77
- verbose: false,
78
- silent: true,
79
- });
80
- const spy = jest.spyOn(context, "addError");
70
+ let workspace: TestingWorkspace;
71
+ let spy: AddErrorSpy;
72
+ let context: Context;
73
+
74
+ beforeEach(async () => {
75
+ workspace = await createTestingWorkspace({
76
+ fixFlag: true,
77
+ host: hostFactory.make(),
78
+ });
81
79
 
82
- afterEach(() => {
83
- spy.mockClear();
80
+ spy = jest.spyOn(workspace.context, "addError");
81
+ context = workspace.context; // minimizing delta
84
82
  });
85
83
 
86
84
  it("fixes an empty script section", () => {
87
- mockFiles.set("package.json", PACKAGE_WITHOUT_SCRIPTS);
85
+ workspace.writeFile("package.json", PACKAGE_WITHOUT_SCRIPTS);
88
86
 
89
87
  packageScript.check(context, {
90
88
  scripts: {
@@ -95,15 +93,19 @@ describe("expectPackageScript", () => {
95
93
  expect(spy).toHaveBeenCalledTimes(1);
96
94
 
97
95
  const failure: Failure = spy.mock.calls[0][0];
98
- expect(failure.file).toBe("package.json");
99
- expect(failure.fixer).not.toBeUndefined();
100
- expect(failure.message).toBe("No scripts block in package.json");
101
-
102
- expect(JSON.parse(mockFiles.get("package.json")!).scripts).toEqual({});
96
+ expect(failure).toMatchObject(
97
+ workspace.failureMatcher({
98
+ file: "package.json",
99
+ hasFixer: true,
100
+ message: "No scripts block in package.json",
101
+ })
102
+ );
103
+
104
+ expect(JSON.parse(workspace.readFile("package.json")!).scripts).toEqual({});
103
105
  });
104
106
 
105
107
  it("adds a script", () => {
106
- mockFiles.set("package.json", PACKAGE_WITH_SCRIPTS);
108
+ workspace.writeFile("package.json", PACKAGE_WITH_SCRIPTS);
107
109
 
108
110
  packageScript.check(context, {
109
111
  scripts: {
@@ -114,15 +116,21 @@ describe("expectPackageScript", () => {
114
116
  expect(spy).toHaveBeenCalledTimes(1);
115
117
 
116
118
  const failure: Failure = spy.mock.calls[0][0];
117
- expect(failure.file).toBe("package.json");
118
- expect(failure.fixer).not.toBeUndefined();
119
- expect(failure.message).toMatch(`Expected standardized script entry for '${MISSING_SCRIPT_NAME}'`);
120
-
121
- expect(JSON.parse(mockFiles.get("package.json")!).scripts[MISSING_SCRIPT_NAME]).toEqual(MISSING_SCRIPT_VALUE);
119
+ expect(failure).toMatchObject(
120
+ workspace.failureMatcher({
121
+ file: "package.json",
122
+ hasFixer: true,
123
+ message: expect.stringContaining(`Expected standardized script entry for '${MISSING_SCRIPT_NAME}'`),
124
+ })
125
+ );
126
+
127
+ expect(JSON.parse(workspace.readFile("package.json")!).scripts[MISSING_SCRIPT_NAME]).toEqual(
128
+ MISSING_SCRIPT_VALUE
129
+ );
122
130
  });
123
131
 
124
132
  it("does nothing if the value exists", () => {
125
- mockFiles.set("package.json", PACKAGE_WITH_SCRIPTS);
133
+ workspace.writeFile("package.json", PACKAGE_WITH_SCRIPTS);
126
134
 
127
135
  packageScript.check(context, {
128
136
  scripts: {
@@ -132,13 +140,13 @@ describe("expectPackageScript", () => {
132
140
 
133
141
  expect(spy).not.toHaveBeenCalled();
134
142
 
135
- expect(JSON.parse(mockFiles.get("package.json")!).scripts).toEqual({
143
+ expect(JSON.parse(workspace.readFile("package.json")!).scripts).toEqual({
136
144
  [SCRIPT_NAME]: SCRIPT_VALUE,
137
145
  });
138
146
  });
139
147
 
140
148
  it("errors if long form is used and no value matches and there is no fixValue", () => {
141
- mockFiles.set("package.json", PACKAGE_WITH_SCRIPTS);
149
+ workspace.writeFile("package.json", PACKAGE_WITH_SCRIPTS);
142
150
 
143
151
  packageScript.check(context, {
144
152
  scripts: {
@@ -155,7 +163,7 @@ describe("expectPackageScript", () => {
155
163
  });
156
164
 
157
165
  it("uses the fixValue for fixing if provided", () => {
158
- mockFiles.set("package.json", PACKAGE_WITH_SCRIPTS);
166
+ workspace.writeFile("package.json", PACKAGE_WITH_SCRIPTS);
159
167
 
160
168
  packageScript.check(context, {
161
169
  scripts: {
@@ -171,14 +179,14 @@ describe("expectPackageScript", () => {
171
179
  expect(errors.length).toBe(1);
172
180
  expect(errors[0][0].fixer).toBeDefined();
173
181
 
174
- expect(JSON.parse(mockFiles.get("package.json")!).scripts).toEqual({
182
+ expect(JSON.parse(workspace.readFile("package.json")!).scripts).toEqual({
175
183
  [SCRIPT_NAME]: SCRIPT_VALUE,
176
184
  foo: "a",
177
185
  });
178
186
  });
179
187
 
180
188
  it("can fix to empty", () => {
181
- mockFiles.set("package.json", PACKAGE_WITH_SCRIPTS);
189
+ workspace.writeFile("package.json", PACKAGE_WITH_SCRIPTS);
182
190
 
183
191
  packageScript.check(context, {
184
192
  scripts: {
@@ -194,11 +202,11 @@ describe("expectPackageScript", () => {
194
202
  expect(errors.length).toBe(1);
195
203
  expect(errors[0][0].fixer).toBeDefined();
196
204
 
197
- expect(JSON.parse(mockFiles.get("package.json")!).scripts).toEqual({});
205
+ expect(JSON.parse(workspace.readFile("package.json")!).scripts).toEqual({});
198
206
  });
199
207
 
200
208
  it("can allow only empty", () => {
201
- mockFiles.set("package.json", PACKAGE_WITH_SCRIPTS);
209
+ workspace.writeFile("package.json", PACKAGE_WITH_SCRIPTS);
202
210
 
203
211
  packageScript.check(context, {
204
212
  scripts: {
@@ -214,7 +222,7 @@ describe("expectPackageScript", () => {
214
222
  expect(errors.length).toBe(1);
215
223
  expect(errors[0][0].fixer).toBeDefined();
216
224
 
217
- expect(JSON.parse(mockFiles.get("package.json")!).scripts).toEqual({});
225
+ expect(JSON.parse(workspace.readFile("package.json")!).scripts).toEqual({});
218
226
  });
219
227
  });
220
228
  });
@@ -5,6 +5,7 @@
5
5
  *
6
6
  */
7
7
  import { WorkspaceContext } from "@monorepolint/core";
8
+ import { SimpleHost } from "@monorepolint/utils";
8
9
  import { readFileSync, writeFileSync } from "fs";
9
10
  import * as path from "path";
10
11
  import * as tmp from "tmp";
@@ -73,12 +74,16 @@ describe("requireDependency", () => {
73
74
  const dir: tmp.DirResult = tmp.dirSync({ unsafeCleanup: true });
74
75
  cleanupJobs.push(() => dir.removeCallback());
75
76
 
76
- const workspaceContext = new WorkspaceContext(dir.name, {
77
- rules: [],
78
- fix,
79
- verbose: false,
80
- silent: true,
81
- });
77
+ const workspaceContext = new WorkspaceContext(
78
+ dir.name,
79
+ {
80
+ rules: [],
81
+ fix,
82
+ verbose: false,
83
+ silent: true,
84
+ },
85
+ new SimpleHost()
86
+ );
82
87
 
83
88
  function checkAndSpy(q: string) {
84
89
  const context = workspaceContext.createChildContext(path.resolve(dir.name, q));
@@ -5,31 +5,121 @@
5
5
  *
6
6
  */
7
7
 
8
- export function createMockFiles() {
9
- const mockFiles: Map<string, string> = new Map();
8
+ import { AddErrorOptions, WorkspaceContext } from "@monorepolint/core";
9
+ import { CachingHost, Host, SimpleHost } from "@monorepolint/utils";
10
+ import * as path from "path";
11
+ import * as tmp from "tmp";
10
12
 
11
- jest.mock("fs", () => ({
12
- writeFileSync: function writeFileSync(filePath: string, contents: string) {
13
- mockFiles.set(filePath, contents);
14
- },
13
+ export function jsonToString(obj: {}) {
14
+ return JSON.stringify(obj, undefined, 2) + "\n";
15
+ }
15
16
 
16
- // tslint:disable-next-line: variable-name
17
- readFileSync: function readFileSync(filePath: string, _contentType: string) {
18
- return mockFiles.get(filePath);
19
- },
17
+ interface TestingWorkspaceOpts {
18
+ host: Host;
19
+ rootProjectName?: string;
20
+ fixFlag: boolean;
21
+ }
20
22
 
21
- existsSync: function existsSync(filePath: string) {
22
- return mockFiles.has(filePath);
23
- },
23
+ export async function createTestingWorkspace(inboundOpts: TestingWorkspaceOpts) {
24
+ tmp.setGracefulCleanup();
25
+ const tmpdir = tmp.dirSync();
26
+ const opts = {
27
+ ...inboundOpts,
28
+ rootProjectName: inboundOpts.rootProjectName ?? "rootProject",
29
+ };
30
+ const rootPath = tmpdir.name;
31
+ opts.host.mkdir(rootPath, { recursive: true });
24
32
 
25
- mkdirSync: function mkdirSync(directoryPath: string) {
26
- return mockFiles.set(directoryPath, "");
33
+ opts.host.writeJson(path.join(rootPath, "package.json"), {
34
+ name: opts.rootProjectName,
35
+ workspaces: {
36
+ packages: ["packages/*"],
27
37
  },
28
- }));
38
+ });
29
39
 
30
- return mockFiles;
40
+ await opts.host.flush();
41
+
42
+ return new DefaultTestingWorkspace(
43
+ { ...opts, rootPath },
44
+ new WorkspaceContext(rootPath, { fix: opts.fixFlag, rules: [] }, opts.host)
45
+ );
31
46
  }
32
47
 
33
- export function jsonToString(obj: {}) {
34
- return JSON.stringify(obj, undefined, 2) + "\n";
48
+ interface RealTestingWorkspaceOpts extends Required<TestingWorkspaceOpts> {
49
+ rootPath: string;
35
50
  }
51
+
52
+ export interface TestingWorkspace {
53
+ /**
54
+ * Adds a utf8 file to `packageName` with `relativePath` to the package directory.
55
+ *
56
+ * @param packageName The child package to add to or undefined for root package
57
+ * @param filePath The path of the file to be written. Will be prepended with package dir
58
+ * @param contents the contents to be written (as utf8)
59
+ */
60
+ writeFile(filePath: string, contents: string): void;
61
+
62
+ writeJsonFile(filePath: string, json: object): void;
63
+ addProject(name: string, fields: object): void;
64
+ getFilePath(filePath: string): string;
65
+ readFile(filePath: string): string;
66
+
67
+ /**
68
+ * Helper method for matching failures via jest `expect().toMatchObject
69
+ *
70
+ */
71
+ failureMatcher(opts: { file: string; message: string; hasFixer: boolean }): any;
72
+
73
+ readonly context: WorkspaceContext;
74
+ }
75
+
76
+ class DefaultTestingWorkspace implements TestingWorkspace {
77
+ constructor(private opts: RealTestingWorkspaceOpts, public readonly context: WorkspaceContext) {}
78
+
79
+ addProject(name: string, fields: object) {
80
+ this.writeJsonFile(path.join("packages", name, "package.json"), {
81
+ name,
82
+ ...fields,
83
+ });
84
+ }
85
+
86
+ writeJsonFile(filePath: string, json: object) {
87
+ this.writeFile(filePath, JSON.stringify(json, undefined, 2));
88
+ }
89
+
90
+ /**
91
+ * Adds a utf8 file to `packageName` with `relativePath` to the package directory.
92
+ *
93
+ * @param packageName The child package to add to or undefined for root package
94
+ * @param filePath The path of the file to be written. Will be prepended with package dir
95
+ * @param contents the contents to be written (as utf8)
96
+ */
97
+ writeFile(filePath: string, contents: string) {
98
+ const fullFilePath = this.getFilePath(filePath);
99
+ this.opts.host.mkdir(path.dirname(fullFilePath), { recursive: true });
100
+ this.opts.host.writeFile(fullFilePath, contents, { encoding: "utf-8" });
101
+ }
102
+
103
+ getFilePath(filePath: string) {
104
+ return path.join(this.opts.rootPath, filePath);
105
+ }
106
+
107
+ readFile(filePath: string) {
108
+ return this.opts.host.readFile(this.getFilePath(filePath), { encoding: "utf-8" });
109
+ }
110
+
111
+ failureMatcher(opts: { file: string; message: string; hasFixer: boolean }) {
112
+ return {
113
+ file: this.getFilePath(opts.file),
114
+ message: opts.message,
115
+ ...(opts.hasFixer ? { fixer: expect.any(Function) } : {}),
116
+ };
117
+ }
118
+ }
119
+
120
+ export type AddErrorSpy = jest.SpyInstance<void, [AddErrorOptions]>;
121
+
122
+ export const HOST_FACTORIES: Array<{ name: string; make: () => Host }> = [
123
+ { name: "SimpleHost", make: () => new SimpleHost() },
124
+ { name: "CachingHost", make: () => new CachingHost() },
125
+ ];