@cloud-ru/ft-deps-validator 1.1.1 → 1.1.2-preview-8996d18.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.
Files changed (115) hide show
  1. package/README.md +34 -15
  2. package/dist/cjs/Checker/MonorepoChecker.d.ts +10 -0
  3. package/dist/cjs/Checker/MonorepoChecker.js +57 -0
  4. package/dist/cjs/Checker/RepoChecker.d.ts +8 -0
  5. package/dist/cjs/Checker/RepoChecker.js +36 -0
  6. package/dist/cjs/Checker/__tests__/MonorepoChecker.spec.js +305 -0
  7. package/dist/cjs/Checker/__tests__/RepoChecker.spec.js +116 -0
  8. package/dist/cjs/Checker/index.d.ts +2 -0
  9. package/dist/cjs/Checker/index.js +7 -0
  10. package/dist/cjs/Config/MonorepoConfig.d.ts +12 -0
  11. package/dist/cjs/Config/MonorepoConfig.js +42 -0
  12. package/dist/cjs/Config/RepoConfig.d.ts +10 -0
  13. package/dist/cjs/Config/RepoConfig.js +27 -0
  14. package/dist/cjs/Config/__tests__/MonorepoConfig.spec.js +291 -0
  15. package/dist/cjs/Config/__tests__/RepoConfig.spec.d.ts +1 -0
  16. package/dist/cjs/Config/__tests__/RepoConfig.spec.js +99 -0
  17. package/dist/cjs/Config/index.d.ts +2 -0
  18. package/dist/cjs/Config/index.js +7 -0
  19. package/dist/cjs/Report/__tests__/Report.spec.d.ts +1 -0
  20. package/dist/cjs/Report/__tests__/Report.spec.js +176 -0
  21. package/dist/cjs/Report/index.d.ts +11 -0
  22. package/dist/cjs/Report/index.js +55 -0
  23. package/dist/cjs/index.d.ts +0 -1
  24. package/dist/cjs/index.js +13 -57
  25. package/dist/{esm/types/config.d.ts → cjs/types.d.ts} +14 -3
  26. package/dist/cjs/utils/__tests__/getCliArguments.spec.d.ts +1 -0
  27. package/dist/cjs/utils/__tests__/getCliArguments.spec.js +70 -0
  28. package/dist/cjs/utils/getCliArguments.d.ts +6 -6
  29. package/dist/cjs/utils/getCliArguments.js +1 -27
  30. package/dist/cjs/utils/getConfigFile.d.ts +4 -3
  31. package/dist/cjs/utils/getConfigFile.js +3 -9
  32. package/dist/cjs/utils/getEnvironment.d.ts +3 -0
  33. package/dist/cjs/utils/getEnvironment.js +50 -0
  34. package/dist/cjs/utils/readPackageJsonFile.d.ts +9 -0
  35. package/dist/cjs/utils/readPackageJsonFile.js +28 -0
  36. package/dist/esm/Checker/MonorepoChecker.d.ts +10 -0
  37. package/dist/esm/Checker/MonorepoChecker.js +53 -0
  38. package/dist/esm/Checker/RepoChecker.d.ts +8 -0
  39. package/dist/esm/Checker/RepoChecker.js +29 -0
  40. package/dist/esm/Checker/__tests__/MonorepoChecker.spec.d.ts +1 -0
  41. package/dist/esm/Checker/__tests__/MonorepoChecker.spec.js +300 -0
  42. package/dist/esm/Checker/__tests__/RepoChecker.spec.d.ts +1 -0
  43. package/dist/esm/Checker/__tests__/RepoChecker.spec.js +111 -0
  44. package/dist/esm/Checker/index.d.ts +2 -0
  45. package/dist/esm/Checker/index.js +2 -0
  46. package/dist/esm/Config/MonorepoConfig.d.ts +12 -0
  47. package/dist/esm/Config/MonorepoConfig.js +35 -0
  48. package/dist/esm/Config/RepoConfig.d.ts +10 -0
  49. package/dist/esm/Config/RepoConfig.js +20 -0
  50. package/dist/esm/Config/__tests__/MonorepoConfig.spec.d.ts +1 -0
  51. package/dist/esm/Config/__tests__/MonorepoConfig.spec.js +289 -0
  52. package/dist/esm/Config/__tests__/RepoConfig.spec.d.ts +1 -0
  53. package/dist/esm/Config/__tests__/RepoConfig.spec.js +94 -0
  54. package/dist/esm/Config/index.d.ts +2 -0
  55. package/dist/esm/Config/index.js +2 -0
  56. package/dist/esm/Report/__tests__/Report.spec.d.ts +1 -0
  57. package/dist/esm/Report/__tests__/Report.spec.js +174 -0
  58. package/dist/esm/Report/index.d.ts +11 -0
  59. package/dist/esm/Report/index.js +51 -0
  60. package/dist/esm/index.d.ts +0 -1
  61. package/dist/esm/index.js +14 -55
  62. package/dist/{cjs/types/config.d.ts → esm/types.d.ts} +14 -3
  63. package/dist/esm/types.js +1 -0
  64. package/dist/esm/utils/__tests__/getCliArguments.spec.d.ts +1 -0
  65. package/dist/esm/utils/__tests__/getCliArguments.spec.js +68 -0
  66. package/dist/esm/utils/getCliArguments.d.ts +6 -6
  67. package/dist/esm/utils/getCliArguments.js +1 -27
  68. package/dist/esm/utils/getConfigFile.d.ts +4 -3
  69. package/dist/esm/utils/getConfigFile.js +3 -9
  70. package/dist/esm/utils/getEnvironment.d.ts +3 -0
  71. package/dist/esm/utils/getEnvironment.js +42 -0
  72. package/dist/esm/utils/readPackageJsonFile.d.ts +9 -0
  73. package/dist/esm/utils/readPackageJsonFile.js +20 -0
  74. package/package.json +2 -2
  75. package/src/Checker/MonorepoChecker.ts +45 -0
  76. package/src/Checker/RepoChecker.ts +23 -0
  77. package/src/Checker/__tests__/MonorepoChecker.spec.ts +330 -0
  78. package/src/Checker/__tests__/RepoChecker.spec.ts +132 -0
  79. package/src/Checker/index.ts +2 -0
  80. package/src/Config/MonorepoConfig.ts +51 -0
  81. package/src/Config/RepoConfig.ts +30 -0
  82. package/src/Config/__tests__/MonorepoConfig.spec.ts +346 -0
  83. package/src/Config/__tests__/RepoConfig.spec.ts +131 -0
  84. package/src/Config/index.ts +2 -0
  85. package/src/Report/__tests__/Report.spec.ts +221 -0
  86. package/src/Report/index.ts +75 -0
  87. package/src/index.ts +14 -67
  88. package/src/{types/config.ts → types.ts} +15 -3
  89. package/src/utils/__tests__/getCliArguments.spec.ts +89 -0
  90. package/src/utils/getCliArguments.ts +1 -35
  91. package/src/utils/getConfigFile.ts +7 -11
  92. package/src/utils/getEnvironment.ts +53 -0
  93. package/src/utils/readPackageJsonFile.ts +20 -0
  94. package/dist/cjs/types/cliArguments.d.ts +0 -4
  95. package/dist/cjs/types/config.js +0 -2
  96. package/dist/cjs/types/state.d.ts +0 -6
  97. package/dist/cjs/types/state.js +0 -2
  98. package/dist/cjs/utils/getMonorepoPrefix.d.ts +0 -6
  99. package/dist/cjs/utils/getMonorepoPrefix.js +0 -33
  100. package/dist/cjs/utils/initializeState.d.ts +0 -8
  101. package/dist/cjs/utils/initializeState.js +0 -40
  102. package/dist/esm/types/cliArguments.d.ts +0 -4
  103. package/dist/esm/types/state.d.ts +0 -6
  104. package/dist/esm/utils/getMonorepoPrefix.d.ts +0 -6
  105. package/dist/esm/utils/getMonorepoPrefix.js +0 -27
  106. package/dist/esm/utils/initializeState.d.ts +0 -8
  107. package/dist/esm/utils/initializeState.js +0 -34
  108. package/src/types/cliArguments.ts +0 -5
  109. package/src/types/state.ts +0 -6
  110. package/src/utils/getMonorepoPrefix.ts +0 -32
  111. package/src/utils/initializeState.ts +0 -51
  112. /package/dist/{esm/types/cliArguments.js → cjs/Checker/__tests__/MonorepoChecker.spec.d.ts} +0 -0
  113. /package/dist/{esm/types/config.js → cjs/Checker/__tests__/RepoChecker.spec.d.ts} +0 -0
  114. /package/dist/{esm/types/state.js → cjs/Config/__tests__/MonorepoConfig.spec.d.ts} +0 -0
  115. /package/dist/cjs/{types/cliArguments.js → types.js} +0 -0
@@ -0,0 +1,346 @@
1
+ import { globSync } from 'glob';
2
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
3
+
4
+ import { MonorepoConfig } from '../MonorepoConfig';
5
+
6
+ vi.mock('glob', () => ({
7
+ globSync: vi.fn(),
8
+ }));
9
+
10
+ describe('MonorepoConfig', () => {
11
+ const mockGlobSync = vi.mocked(globSync);
12
+
13
+ beforeEach(() => {
14
+ vi.clearAllMocks();
15
+ });
16
+
17
+ describe('constructor', () => {
18
+ it('should initialize with required fields', () => {
19
+ const testCwd = '/test/directory';
20
+ const rootPackagesFolderPattern = 'packages/*';
21
+ mockGlobSync.mockReturnValueOnce(['packages/package1']);
22
+ const config = new MonorepoConfig({
23
+ cwd: testCwd,
24
+ rootPackagesFolderPattern,
25
+ });
26
+
27
+ expect(config.getFolders()).toBeDefined();
28
+ });
29
+
30
+ it('should use empty array as default for ignoredPackagesFolderFiles', () => {
31
+ const testCwd = '/test/directory';
32
+ const rootPackagesFolderPattern = 'packages/*';
33
+ const config = new MonorepoConfig({
34
+ cwd: testCwd,
35
+ rootPackagesFolderPattern,
36
+ });
37
+
38
+ mockGlobSync.mockReturnValueOnce(['packages/package1']);
39
+ config.getFolders();
40
+
41
+ expect(mockGlobSync).toHaveBeenCalledWith(rootPackagesFolderPattern, {
42
+ ignore: [],
43
+ });
44
+ });
45
+
46
+ it('should initialize with packages', () => {
47
+ const testCwd = '/test/directory';
48
+ const rootPackagesFolderPattern = 'packages/*';
49
+ const packages = {
50
+ package1: {
51
+ ignorePatterns: ['dist'],
52
+ ignoreMatches: ['@cloud-ru/test'],
53
+ },
54
+ };
55
+ const config = new MonorepoConfig({
56
+ cwd: testCwd,
57
+ rootPackagesFolderPattern,
58
+ packages,
59
+ });
60
+
61
+ const options = config.getFolderOptions('/test/directory/packages/package1');
62
+
63
+ expect(options.ignorePatterns).toContain('dist');
64
+ expect(options.ignoreMatches).toContain('@cloud-ru/test');
65
+ });
66
+
67
+ it('should use empty object as default for packages', () => {
68
+ const testCwd = '/test/directory';
69
+ const rootPackagesFolderPattern = 'packages/*';
70
+ const config = new MonorepoConfig({
71
+ cwd: testCwd,
72
+ rootPackagesFolderPattern,
73
+ });
74
+
75
+ const options = config.getFolderOptions('/test/directory/packages/package1');
76
+
77
+ expect(options).toEqual({
78
+ ignoreBinPackage: false,
79
+ skipMissing: false,
80
+ ignorePatterns: [],
81
+ ignoreMatches: [],
82
+ });
83
+ });
84
+
85
+ it('should call parent constructor with cwd', () => {
86
+ const testCwd = '/test/directory';
87
+ const rootPackagesFolderPattern = 'packages/*';
88
+ const config = new MonorepoConfig({
89
+ cwd: testCwd,
90
+ rootPackagesFolderPattern,
91
+ });
92
+
93
+ mockGlobSync.mockReturnValueOnce(['packages/package1']);
94
+ const folders = config.getFolders();
95
+
96
+ expect(mockGlobSync).toHaveBeenCalled();
97
+ expect(folders).toEqual(['packages/package1']);
98
+ });
99
+ });
100
+
101
+ describe('getFolders', () => {
102
+ it('should return folders from globSync', () => {
103
+ const testCwd = '/test/directory';
104
+ const rootPackagesFolderPattern = 'packages/*';
105
+ const mockFolders = ['packages/package1', 'packages/package2'];
106
+ mockGlobSync.mockReturnValueOnce(mockFolders);
107
+
108
+ const config = new MonorepoConfig({
109
+ cwd: testCwd,
110
+ rootPackagesFolderPattern,
111
+ });
112
+
113
+ const folders = config.getFolders();
114
+
115
+ expect(folders).toEqual(mockFolders);
116
+ expect(mockGlobSync).toHaveBeenCalledWith(rootPackagesFolderPattern, {
117
+ ignore: [],
118
+ });
119
+ });
120
+
121
+ it('should use ignoredPackagesFolderFiles in globSync', () => {
122
+ const testCwd = '/test/directory';
123
+ const rootPackagesFolderPattern = 'packages/*';
124
+ const ignoredPackagesFolderFiles = ['file1.json'];
125
+ const mockFolders = ['packages/package1'];
126
+ mockGlobSync.mockReturnValueOnce(mockFolders);
127
+
128
+ const config = new MonorepoConfig({
129
+ cwd: testCwd,
130
+ rootPackagesFolderPattern,
131
+ ignoredPackagesFolderFiles,
132
+ });
133
+
134
+ const folders = config.getFolders();
135
+
136
+ expect(folders).toEqual(mockFolders);
137
+ expect(mockGlobSync).toHaveBeenCalledWith(rootPackagesFolderPattern, {
138
+ ignore: ignoredPackagesFolderFiles,
139
+ });
140
+ });
141
+
142
+ it('should cache folders result', () => {
143
+ const testCwd = '/test/directory';
144
+ const rootPackagesFolderPattern = 'packages/*';
145
+ const mockFolders = ['packages/package1'];
146
+ mockGlobSync.mockReturnValueOnce(mockFolders);
147
+
148
+ const config = new MonorepoConfig({
149
+ cwd: testCwd,
150
+ rootPackagesFolderPattern,
151
+ });
152
+
153
+ const folders1 = config.getFolders();
154
+ const folders2 = config.getFolders();
155
+
156
+ expect(folders1).toEqual(mockFolders);
157
+ expect(folders2).toEqual(mockFolders);
158
+ expect(mockGlobSync).toHaveBeenCalledTimes(1);
159
+ });
160
+ });
161
+
162
+ describe('getFolderOptions', () => {
163
+ it('should return Options object with correct structure', () => {
164
+ const testCwd = '/test/directory';
165
+ const rootPackagesFolderPattern = 'packages/*';
166
+ const config = new MonorepoConfig({
167
+ cwd: testCwd,
168
+ rootPackagesFolderPattern,
169
+ });
170
+
171
+ const options = config.getFolderOptions('/test/directory/packages/package1');
172
+
173
+ expect(options).toHaveProperty('ignoreBinPackage');
174
+ expect(options).toHaveProperty('skipMissing');
175
+ expect(options).toHaveProperty('ignorePatterns');
176
+ expect(options).toHaveProperty('ignoreMatches');
177
+ });
178
+
179
+ it('should merge ignorePatterns from parent and package config', () => {
180
+ const testCwd = '/test/directory';
181
+ const rootPackagesFolderPattern = 'packages/*';
182
+ const parentIgnorePatterns = ['dist', 'node_modules'];
183
+ const packageIgnorePatterns = ['build', 'coverage'];
184
+ const config = new MonorepoConfig({
185
+ cwd: testCwd,
186
+ rootPackagesFolderPattern,
187
+ ignorePatterns: parentIgnorePatterns,
188
+ packages: {
189
+ package1: {
190
+ ignorePatterns: packageIgnorePatterns,
191
+ },
192
+ },
193
+ });
194
+
195
+ const options = config.getFolderOptions('/test/directory/packages/package1');
196
+
197
+ expect(options.ignorePatterns).toEqual([...parentIgnorePatterns, ...packageIgnorePatterns]);
198
+ });
199
+
200
+ it('should merge ignoreMatches from parent and package config', () => {
201
+ const testCwd = '/test/directory';
202
+ const rootPackagesFolderPattern = 'packages/*';
203
+ const parentIgnoreMatches = ['@cloud-ru/package1'];
204
+ const packageIgnoreMatches = ['@cloud-ru/package2'];
205
+ const config = new MonorepoConfig({
206
+ cwd: testCwd,
207
+ rootPackagesFolderPattern,
208
+ ignoreMatches: parentIgnoreMatches,
209
+ packages: {
210
+ package1: {
211
+ ignoreMatches: packageIgnoreMatches,
212
+ },
213
+ },
214
+ });
215
+
216
+ const options = config.getFolderOptions('/test/directory/packages/package1');
217
+
218
+ expect(options.ignoreMatches).toEqual([...parentIgnoreMatches, ...packageIgnoreMatches]);
219
+ });
220
+
221
+ it('should merge both ignorePatterns and ignoreMatches from package config', () => {
222
+ const testCwd = '/test/directory';
223
+ const rootPackagesFolderPattern = 'packages/*';
224
+ const parentIgnorePatterns = ['dist'];
225
+ const parentIgnoreMatches = ['@cloud-ru/package1'];
226
+ const packageIgnorePatterns = ['build'];
227
+ const packageIgnoreMatches = ['@cloud-ru/package2'];
228
+ const config = new MonorepoConfig({
229
+ cwd: testCwd,
230
+ rootPackagesFolderPattern,
231
+ ignorePatterns: parentIgnorePatterns,
232
+ ignoreMatches: parentIgnoreMatches,
233
+ packages: {
234
+ package1: {
235
+ ignorePatterns: packageIgnorePatterns,
236
+ ignoreMatches: packageIgnoreMatches,
237
+ },
238
+ },
239
+ });
240
+
241
+ const options = config.getFolderOptions('/test/directory/packages/package1');
242
+
243
+ expect(options.ignorePatterns).toEqual([...parentIgnorePatterns, ...packageIgnorePatterns]);
244
+ expect(options.ignoreMatches).toEqual([...parentIgnoreMatches, ...packageIgnoreMatches]);
245
+ });
246
+
247
+ it('should use only parent options when package config is not provided', () => {
248
+ const testCwd = '/test/directory';
249
+ const rootPackagesFolderPattern = 'packages/*';
250
+ const parentIgnorePatterns = ['dist'];
251
+ const parentIgnoreMatches = ['@cloud-ru/package1'];
252
+ const config = new MonorepoConfig({
253
+ cwd: testCwd,
254
+ rootPackagesFolderPattern,
255
+ ignorePatterns: parentIgnorePatterns,
256
+ ignoreMatches: parentIgnoreMatches,
257
+ });
258
+
259
+ const options = config.getFolderOptions('/test/directory/packages/package1');
260
+
261
+ expect(options.ignorePatterns).toEqual(parentIgnorePatterns);
262
+ expect(options.ignoreMatches).toEqual(parentIgnoreMatches);
263
+ });
264
+
265
+ it('should use only parent options when package config does not have ignorePatterns', () => {
266
+ const testCwd = '/test/directory';
267
+ const rootPackagesFolderPattern = 'packages/*';
268
+ const parentIgnorePatterns = ['dist'];
269
+ const config = new MonorepoConfig({
270
+ cwd: testCwd,
271
+ rootPackagesFolderPattern,
272
+ ignorePatterns: parentIgnorePatterns,
273
+ packages: {
274
+ package1: {
275
+ ignoreMatches: ['@cloud-ru/package2'],
276
+ },
277
+ },
278
+ });
279
+
280
+ const options = config.getFolderOptions('/test/directory/packages/package1');
281
+
282
+ expect(options.ignorePatterns).toEqual(parentIgnorePatterns);
283
+ });
284
+
285
+ it('should use only parent options when package config does not have ignoreMatches', () => {
286
+ const testCwd = '/test/directory';
287
+ const rootPackagesFolderPattern = 'packages/*';
288
+ const parentIgnoreMatches = ['@cloud-ru/package1'];
289
+ const config = new MonorepoConfig({
290
+ cwd: testCwd,
291
+ rootPackagesFolderPattern,
292
+ ignoreMatches: parentIgnoreMatches,
293
+ packages: {
294
+ package1: {
295
+ ignorePatterns: ['build'],
296
+ },
297
+ },
298
+ });
299
+
300
+ const options = config.getFolderOptions('/test/directory/packages/package1');
301
+
302
+ expect(options.ignoreMatches).toEqual(parentIgnoreMatches);
303
+ });
304
+
305
+ it('should use folder name from path to get package config', () => {
306
+ const testCwd = '/test/directory';
307
+ const rootPackagesFolderPattern = 'packages/*';
308
+ const config = new MonorepoConfig({
309
+ cwd: testCwd,
310
+ rootPackagesFolderPattern,
311
+ packages: {
312
+ package1: {
313
+ ignorePatterns: ['dist'],
314
+ },
315
+ package2: {
316
+ ignorePatterns: ['build'],
317
+ },
318
+ },
319
+ });
320
+
321
+ const options1 = config.getFolderOptions('/test/directory/packages/package1');
322
+ const options2 = config.getFolderOptions('/test/directory/packages/package2');
323
+
324
+ expect(options1.ignorePatterns).toContain('dist');
325
+ expect(options2.ignorePatterns).toContain('build');
326
+ });
327
+
328
+ it('should return parent options when package config is empty', () => {
329
+ const testCwd = '/test/directory';
330
+ const rootPackagesFolderPattern = 'packages/*';
331
+ const parentIgnorePatterns = ['dist'];
332
+ const config = new MonorepoConfig({
333
+ cwd: testCwd,
334
+ rootPackagesFolderPattern,
335
+ ignorePatterns: parentIgnorePatterns,
336
+ packages: {
337
+ package1: {},
338
+ },
339
+ });
340
+
341
+ const options = config.getFolderOptions('/test/directory/packages/package1');
342
+
343
+ expect(options.ignorePatterns).toEqual(parentIgnorePatterns);
344
+ });
345
+ });
346
+ });
@@ -0,0 +1,131 @@
1
+ import path from 'path';
2
+
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ import { RepoConfig } from '../RepoConfig';
6
+
7
+ describe('RepoConfig', () => {
8
+ describe('constructor', () => {
9
+ it('should initialize with cwd and resolve path', () => {
10
+ const testCwd = '/test/directory';
11
+ const config = new RepoConfig({ cwd: testCwd });
12
+
13
+ expect(config.getFolders()).toEqual([path.resolve(testCwd)]);
14
+ });
15
+
16
+ it('should initialize with ignorePatterns', () => {
17
+ const testCwd = '/test/directory';
18
+ const ignorePatterns = ['dist', 'node_modules'];
19
+ const config = new RepoConfig({ cwd: testCwd, ignorePatterns });
20
+
21
+ const options = config.getFolderOptions('any-folder');
22
+
23
+ expect(options.ignorePatterns).toEqual(ignorePatterns);
24
+ });
25
+
26
+ it('should initialize with ignoreMatches', () => {
27
+ const testCwd = '/test/directory';
28
+ const ignoreMatches = ['@cloud-ru/package1', '@cloud-ru/package2'];
29
+ const config = new RepoConfig({ cwd: testCwd, ignoreMatches });
30
+
31
+ const options = config.getFolderOptions('any-folder');
32
+
33
+ expect(options.ignoreMatches).toEqual(ignoreMatches);
34
+ });
35
+
36
+ it('should initialize with both ignorePatterns and ignoreMatches', () => {
37
+ const testCwd = '/test/directory';
38
+ const ignorePatterns = ['dist'];
39
+ const ignoreMatches = ['@cloud-ru/package'];
40
+ const config = new RepoConfig({ cwd: testCwd, ignorePatterns, ignoreMatches });
41
+
42
+ const options = config.getFolderOptions('any-folder');
43
+
44
+ expect(options.ignorePatterns).toEqual(ignorePatterns);
45
+ expect(options.ignoreMatches).toEqual(ignoreMatches);
46
+ });
47
+
48
+ it('should use empty arrays as default for optional fields', () => {
49
+ const testCwd = '/test/directory';
50
+ const config = new RepoConfig({ cwd: testCwd });
51
+
52
+ const options = config.getFolderOptions('any-folder');
53
+
54
+ expect(options.ignorePatterns).toEqual([]);
55
+ expect(options.ignoreMatches).toEqual([]);
56
+ });
57
+
58
+ it('should resolve relative cwd path to absolute', () => {
59
+ const relativePath = './test';
60
+ const config = new RepoConfig({ cwd: relativePath });
61
+
62
+ const folders = config.getFolders();
63
+
64
+ expect(folders[0]).toBe(path.resolve(relativePath));
65
+ expect(path.isAbsolute(folders[0])).toBe(true);
66
+ });
67
+ });
68
+
69
+ describe('getFolders', () => {
70
+ it('should return array with resolved pwd', () => {
71
+ const testCwd = '/test/directory';
72
+ const config = new RepoConfig({ cwd: testCwd });
73
+
74
+ const folders = config.getFolders();
75
+
76
+ expect(folders).toEqual([path.resolve(testCwd)]);
77
+ });
78
+
79
+ it('should always return absolute path', () => {
80
+ const relativeCwd = '../test';
81
+ const config = new RepoConfig({ cwd: relativeCwd });
82
+
83
+ const folders = config.getFolders();
84
+
85
+ expect(path.isAbsolute(folders[0])).toBe(true);
86
+ });
87
+ });
88
+
89
+ describe('getFolderOptions', () => {
90
+ it('should return Options object with correct structure', () => {
91
+ const testCwd = '/test/directory';
92
+ const config = new RepoConfig({ cwd: testCwd });
93
+ const folder = 'any-folder';
94
+
95
+ const options = config.getFolderOptions(folder);
96
+
97
+ expect(options).toHaveProperty('ignoreBinPackage');
98
+ expect(options).toHaveProperty('skipMissing');
99
+ expect(options).toHaveProperty('ignorePatterns');
100
+ expect(options).toHaveProperty('ignoreMatches');
101
+ });
102
+
103
+ it('should return ignoreBinPackage as false', () => {
104
+ const testCwd = '/test/directory';
105
+ const config = new RepoConfig({ cwd: testCwd });
106
+
107
+ const options = config.getFolderOptions('any-folder');
108
+
109
+ expect(options.ignoreBinPackage).toBe(false);
110
+ });
111
+
112
+ it('should return skipMissing as false', () => {
113
+ const testCwd = '/test/directory';
114
+ const config = new RepoConfig({ cwd: testCwd });
115
+
116
+ const options = config.getFolderOptions('any-folder');
117
+
118
+ expect(options.skipMissing).toBe(false);
119
+ });
120
+
121
+ it('should return empty arrays when optional fields are not provided', () => {
122
+ const testCwd = '/test/directory';
123
+ const config = new RepoConfig({ cwd: testCwd });
124
+
125
+ const options = config.getFolderOptions('any-folder');
126
+
127
+ expect(options.ignorePatterns).toEqual([]);
128
+ expect(options.ignoreMatches).toEqual([]);
129
+ });
130
+ });
131
+ });
@@ -0,0 +1,2 @@
1
+ export { RepoConfig } from './RepoConfig';
2
+ export { MonorepoConfig } from './MonorepoConfig';
@@ -0,0 +1,221 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ import { logError, logInfo } from '../../utils/console';
4
+ import { Report } from '../index';
5
+
6
+ vi.mock('../../utils/console', () => ({
7
+ logError: vi.fn(),
8
+ logInfo: vi.fn(),
9
+ }));
10
+
11
+ describe('Report', () => {
12
+ let report: Report;
13
+
14
+ beforeEach(() => {
15
+ report = new Report();
16
+ vi.clearAllMocks();
17
+ });
18
+
19
+ describe('add', () => {
20
+ it('should add state to storage', () => {
21
+ const folder = 'packages/test-package';
22
+ const state = {
23
+ dependencies: ['unused-dep'],
24
+ wrongVersions: ['@cloud-ru/package'],
25
+ };
26
+
27
+ report.add(folder, state);
28
+
29
+ const exitCode = report.printResultAndGetExitCode();
30
+ expect(exitCode).toBe(1);
31
+ expect(logInfo).toHaveBeenCalled();
32
+ expect(logError).toHaveBeenCalled();
33
+ });
34
+
35
+ it('should throw error when trying to add state for existing folder', () => {
36
+ const folder = 'packages/test-package';
37
+ const firstState = {
38
+ dependencies: ['unused-dep'],
39
+ };
40
+ const secondState = {
41
+ wrongVersions: ['@cloud-ru/package'],
42
+ };
43
+
44
+ report.add(folder, firstState);
45
+
46
+ expect(() => {
47
+ report.add(folder, secondState);
48
+ }).toThrow(`There is check state in storage already for: ${folder}`);
49
+ });
50
+ });
51
+
52
+ describe('printResultAndGetExitCode', () => {
53
+ it('should return 0 when storage is empty', () => {
54
+ const exitCode = report.printResultAndGetExitCode();
55
+
56
+ expect(exitCode).toBe(0);
57
+ expect(logInfo).not.toHaveBeenCalled();
58
+ expect(logError).not.toHaveBeenCalled();
59
+ });
60
+
61
+ it('should return 0 when there are no errors', () => {
62
+ report.add('packages/test-package', {
63
+ dependencies: [],
64
+ wrongVersions: [],
65
+ internalAsDev: [],
66
+ missing: {},
67
+ });
68
+
69
+ const exitCode = report.printResultAndGetExitCode();
70
+
71
+ expect(exitCode).toBe(0);
72
+ expect(logInfo).not.toHaveBeenCalled();
73
+ expect(logError).not.toHaveBeenCalled();
74
+ });
75
+
76
+ it('should return 1 and log errors when wrongVersions exist', () => {
77
+ const folder = 'packages/test-package';
78
+ const wrongVersions = ['@cloud-ru/package1', '@cloud-ru/package2'];
79
+
80
+ report.add(folder, {
81
+ wrongVersions,
82
+ });
83
+
84
+ const exitCode = report.printResultAndGetExitCode();
85
+
86
+ expect(exitCode).toBe(1);
87
+ expect(logInfo).toHaveBeenCalledWith(folder);
88
+ expect(logError).toHaveBeenCalledWith('\twrong version of internal packages:');
89
+ expect(logError).toHaveBeenCalledWith('\t\t@cloud-ru/package1');
90
+ expect(logError).toHaveBeenCalledWith('\t\t@cloud-ru/package2');
91
+ });
92
+
93
+ it('should return 1 and log errors when internalAsDev exist', () => {
94
+ const folder = 'packages/test-package';
95
+ const internalAsDev = ['@cloud-ru/package1', '@cloud-ru/package2'];
96
+
97
+ report.add(folder, {
98
+ internalAsDev,
99
+ });
100
+
101
+ const exitCode = report.printResultAndGetExitCode();
102
+
103
+ expect(exitCode).toBe(1);
104
+ expect(logInfo).toHaveBeenCalledWith(folder);
105
+ expect(logError).toHaveBeenCalledWith('\tincorrect usage as dev dep of internal packages:');
106
+ expect(logError).toHaveBeenCalledWith('\t\t@cloud-ru/package1');
107
+ expect(logError).toHaveBeenCalledWith('\t\t@cloud-ru/package2');
108
+ });
109
+
110
+ it('should return 1 and log errors when dependencies exist', () => {
111
+ const folder = 'packages/test-package';
112
+ const dependencies = ['unused-dep1', 'unused-dep2'];
113
+
114
+ report.add(folder, {
115
+ dependencies,
116
+ });
117
+
118
+ const exitCode = report.printResultAndGetExitCode();
119
+
120
+ expect(exitCode).toBe(1);
121
+ expect(logInfo).toHaveBeenCalledWith(folder);
122
+ expect(logError).toHaveBeenCalledWith('\tunused dependencies:');
123
+ expect(logError).toHaveBeenCalledWith('\t\tunused-dep1');
124
+ expect(logError).toHaveBeenCalledWith('\t\tunused-dep2');
125
+ });
126
+
127
+ it('should return 1 and log errors when missing dependencies exist', () => {
128
+ const folder = 'packages/test-package';
129
+ const missing = {
130
+ 'missing-package1': ['file1.ts', 'file2.ts'],
131
+ 'missing-package2': ['file3.ts'],
132
+ };
133
+
134
+ report.add(folder, {
135
+ missing,
136
+ });
137
+
138
+ const exitCode = report.printResultAndGetExitCode();
139
+
140
+ expect(exitCode).toBe(1);
141
+ expect(logInfo).toHaveBeenCalledWith(folder);
142
+ expect(logError).toHaveBeenCalledWith('\tmissing dependencies:');
143
+ expect(logError).toHaveBeenCalledWith('\t\tmissing-package1');
144
+ expect(logError).toHaveBeenCalledWith('\t\tfile1.ts');
145
+ expect(logError).toHaveBeenCalledWith('\t\tfile2.ts');
146
+ expect(logError).toHaveBeenCalledWith('\t\tmissing-package2');
147
+ expect(logError).toHaveBeenCalledWith('\t\tfile3.ts');
148
+ });
149
+
150
+ it('should handle all error types together', () => {
151
+ const folder = 'packages/test-package';
152
+
153
+ report.add(folder, {
154
+ wrongVersions: ['@cloud-ru/package1'],
155
+ internalAsDev: ['@cloud-ru/package2'],
156
+ dependencies: ['unused-dep'],
157
+ missing: {
158
+ 'missing-package': ['file.ts'],
159
+ },
160
+ });
161
+
162
+ const exitCode = report.printResultAndGetExitCode();
163
+
164
+ expect(exitCode).toBe(1);
165
+ expect(logInfo).toHaveBeenCalledWith(folder);
166
+ expect(logError).toHaveBeenCalledWith('\twrong version of internal packages:');
167
+ expect(logError).toHaveBeenCalledWith('\t\t@cloud-ru/package1');
168
+ expect(logError).toHaveBeenCalledWith('\tincorrect usage as dev dep of internal packages:');
169
+ expect(logError).toHaveBeenCalledWith('\t\t@cloud-ru/package2');
170
+ expect(logError).toHaveBeenCalledWith('\tunused dependencies:');
171
+ expect(logError).toHaveBeenCalledWith('\t\tunused-dep');
172
+ expect(logError).toHaveBeenCalledWith('\tmissing dependencies:');
173
+ expect(logError).toHaveBeenCalledWith('\t\tmissing-package');
174
+ expect(logError).toHaveBeenCalledWith('\t\tfile.ts');
175
+ });
176
+
177
+ it('should process multiple packages', () => {
178
+ report.add('packages/package1', {
179
+ wrongVersions: ['@cloud-ru/package'],
180
+ });
181
+
182
+ report.add('packages/package2', {
183
+ dependencies: ['unused-dep'],
184
+ });
185
+
186
+ const exitCode = report.printResultAndGetExitCode();
187
+
188
+ expect(exitCode).toBe(1);
189
+ expect(logInfo).toHaveBeenCalledWith('packages/package1');
190
+ expect(logError).toHaveBeenCalledWith(expect.stringContaining('wrong version'));
191
+ expect(logInfo).toHaveBeenCalledWith('packages/package2');
192
+ expect(logError).toHaveBeenCalledWith(expect.stringContaining('unused dependencies'));
193
+ });
194
+
195
+ it('should use default values for undefined fields', () => {
196
+ const folder = 'packages/test-package';
197
+
198
+ report.add(folder, {});
199
+
200
+ const exitCode = report.printResultAndGetExitCode();
201
+
202
+ expect(exitCode).toBe(0);
203
+ expect(logInfo).not.toHaveBeenCalled();
204
+ expect(logError).not.toHaveBeenCalled();
205
+ });
206
+
207
+ it('should format messages with correct tabs', () => {
208
+ const folder = 'packages/test-package';
209
+
210
+ report.add(folder, {
211
+ wrongVersions: ['@cloud-ru/package'],
212
+ });
213
+
214
+ report.printResultAndGetExitCode();
215
+
216
+ expect(logInfo).toHaveBeenCalledWith('packages/test-package');
217
+ expect(logError).toHaveBeenCalledWith('\twrong version of internal packages:');
218
+ expect(logError).toHaveBeenCalledWith('\t\t@cloud-ru/package');
219
+ });
220
+ });
221
+ });