dpdm 3.13.1 → 3.15.1

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/src/utils.spec.ts CHANGED
@@ -3,27 +3,227 @@
3
3
  * @since 2019-07-17 18:45:47
4
4
  */
5
5
 
6
+ import fs from 'fs-extra';
6
7
  import { dirname, join } from 'path';
7
- import { simpleResolver } from './utils';
8
+ import { parseCircular, simpleResolver } from './utils';
9
+ import type { Dependency } from './types';
10
+ import { DependencyKind } from './consts';
8
11
 
9
12
  describe('util', () => {
10
13
  it('should resolve correctly', async () => {
11
14
  const ext = ['', '.js', '.jsx', '.ts', '.tsx', '.json'];
12
15
  const local = await simpleResolver(__dirname, './bin/dpdm', ext);
13
16
  const index = await simpleResolver(__dirname, '.', ext);
14
- // dependents on yarn.lock
15
- const pkg = await simpleResolver(__dirname, 'string_decoder', ext);
16
- const deepPkg = await simpleResolver(dirname(pkg!), 'safe-buffer', ext);
17
+
18
+ await fs.outputJSON('node_modules/dpdm-ut-parent/package.json', {
19
+ name: 'dpdm-ut-parent',
20
+ version: '1.0.0',
21
+ main: 'index.js',
22
+ dependencies: {
23
+ 'dpdm-ut-deep': '^1.0.0',
24
+ },
25
+ });
26
+ await fs.outputFile('node_modules/dpdm-ut-parent/index.js', '');
27
+
28
+ await fs.outputJSON(
29
+ 'node_modules/dpdm-ut-parent/node_modules/dpdm-ut-deep/package.json',
30
+ {
31
+ name: 'dpdm-ut-deep',
32
+ version: '1.0.0',
33
+ main: 'index.js',
34
+ },
35
+ );
36
+ await fs.outputFile(
37
+ 'node_modules/dpdm-ut-parent/node_modules/dpdm-ut-deep/index.js',
38
+ '',
39
+ );
40
+
41
+ await fs.outputJSON('node_modules/dpdm-ut-deep/package.json', {
42
+ name: 'dpdm-ut-deep',
43
+ version: '2.0.0',
44
+ main: 'index.js',
45
+ });
46
+ await fs.outputFile('node_modules/dpdm-ut-deep/index.js', '');
47
+
48
+ const pkg = await simpleResolver(__dirname, 'dpdm-ut-parent', ext);
49
+ const deepPkg = await simpleResolver(dirname(pkg!), 'dpdm-ut-deep', ext);
17
50
  const notFound = await simpleResolver(__dirname, './utils.tsx', ext);
18
51
  expect([local, index, pkg, deepPkg, notFound]).toEqual([
19
52
  join(__dirname, 'bin/dpdm.ts'),
20
53
  join(__dirname, 'index.ts'),
21
- join(__dirname, '../node_modules/string_decoder/lib/string_decoder.js'),
54
+ join(__dirname, '../node_modules/dpdm-ut-parent/index.js'),
22
55
  join(
23
56
  __dirname,
24
- '../node_modules/string_decoder/node_modules/safe-buffer/index.js',
57
+ '../node_modules/dpdm-ut-parent/node_modules/dpdm-ut-deep/index.js',
25
58
  ),
26
59
  null,
27
60
  ]);
28
61
  });
62
+
63
+ describe('When parsing circular', () => {
64
+ function dependencyFactory(id: string): Dependency {
65
+ return {
66
+ issuer: '',
67
+ request: '',
68
+ kind: DependencyKind.StaticImport,
69
+ id,
70
+ };
71
+ }
72
+
73
+ describe('When tree is empty', () => {
74
+ const tree = {};
75
+ it('Should return empty array', () => {
76
+ const actual = parseCircular(tree);
77
+ expect(actual.length).toBe(0);
78
+ });
79
+ });
80
+
81
+ describe('When tree has just a root with no dependencies', () => {
82
+ const tree = { a: [] };
83
+ it('Should return empty array', () => {
84
+ const actual = parseCircular(tree);
85
+ expect(actual.length).toBe(0);
86
+ });
87
+ });
88
+
89
+ describe('When tree has 2 nodes, no cycle', () => {
90
+ const tree = { a: [dependencyFactory('b')], b: [] };
91
+ it('Should return empty array', () => {
92
+ const actual = parseCircular(tree);
93
+ expect(actual.length).toBe(0);
94
+ });
95
+ });
96
+
97
+ describe('When tree has 2 nodes, with cycle', () => {
98
+ const id1 = 'a';
99
+ const id2 = 'b';
100
+ const tree = {
101
+ [id1]: [dependencyFactory(id2)],
102
+ [id2]: [dependencyFactory(id1)],
103
+ };
104
+
105
+ let actual: Array<string[]>;
106
+ beforeAll(() => {
107
+ actual = parseCircular(tree);
108
+ });
109
+
110
+ it('Should return non-empty array', () => {
111
+ expect(actual.length).toBeGreaterThan(0);
112
+ });
113
+
114
+ it('Should count only one cycle', () => {
115
+ expect(actual.length).toBe(1);
116
+ });
117
+
118
+ it('Should include the ids involved in the cycle', () => {
119
+ expect(actual[0]).toMatchObject([id1, id2]);
120
+ });
121
+ });
122
+
123
+ describe('When tree has a deep cycle', () => {
124
+ const ids = ['a', 'b', 'c'];
125
+ const tree = {
126
+ [ids[0]]: [dependencyFactory(ids[1])],
127
+ [ids[1]]: [dependencyFactory(ids[2])],
128
+ [ids[2]]: [dependencyFactory(ids[0])],
129
+ };
130
+
131
+ let actual: Array<string[]>;
132
+ beforeAll(() => {
133
+ actual = parseCircular(tree);
134
+ });
135
+
136
+ it('Should return non-empty array', () => {
137
+ expect(actual.length).toBeGreaterThan(0);
138
+ });
139
+
140
+ it('Should count only one cycle', () => {
141
+ expect(actual.length).toBe(1);
142
+ });
143
+
144
+ it('Should include the ids involved in the cycle', () => {
145
+ expect(actual[0]).toMatchObject(ids);
146
+ });
147
+ });
148
+
149
+ describe('When tree has 2 cycles with no intersection', () => {
150
+ const tree = {
151
+ left1: [dependencyFactory('left2')],
152
+ left2: [dependencyFactory('left1')],
153
+ right1: [dependencyFactory('right2')],
154
+ right2: [dependencyFactory('right1')],
155
+ };
156
+
157
+ let actual: Array<string[]>;
158
+ beforeAll(() => {
159
+ actual = parseCircular(tree);
160
+ });
161
+
162
+ it('Should return non-empty array', () => {
163
+ expect(actual.length).toBeGreaterThan(0);
164
+ });
165
+
166
+ it('Should count two cycles', () => {
167
+ expect(actual.length).toBe(2);
168
+ });
169
+
170
+ it('Should include the ids involved in the cycle', () => {
171
+ expect(actual[0]).toMatchObject(['left1', 'left2']);
172
+ expect(actual[1]).toMatchObject(['right1', 'right2']);
173
+ });
174
+ });
175
+
176
+ describe('When tree has 2 cycles from common node', () => {
177
+ const tree = {
178
+ start: [dependencyFactory('left'), dependencyFactory('right')],
179
+ left: [dependencyFactory('start')],
180
+ right: [dependencyFactory('start')],
181
+ };
182
+
183
+ let actual: Array<string[]>;
184
+ beforeAll(() => {
185
+ actual = parseCircular(tree);
186
+ });
187
+
188
+ it('Should return non-empty array', () => {
189
+ expect(actual.length).toBeGreaterThan(0);
190
+ });
191
+
192
+ it('Should count two cycles', () => {
193
+ expect(actual.length).toBe(2);
194
+ });
195
+
196
+ it('Should include the ids involved in the cycle', () => {
197
+ expect(actual[0]).toMatchObject(['start', 'left']);
198
+ expect(actual[1]).toMatchObject(['start', 'right']);
199
+ });
200
+ });
201
+
202
+ describe('When tree has 2 cycles with multi-node intersection', () => {
203
+ const tree = {
204
+ start: [dependencyFactory('mid')],
205
+ mid: [dependencyFactory('left'), dependencyFactory('right')],
206
+ left: [dependencyFactory('start')],
207
+ right: [dependencyFactory('start')],
208
+ };
209
+
210
+ let actual: Array<string[]>;
211
+ beforeAll(() => {
212
+ actual = parseCircular(tree);
213
+ });
214
+
215
+ it('Should return non-empty array', () => {
216
+ expect(actual.length).toBeGreaterThan(0);
217
+ });
218
+
219
+ it('Should count two cycles', () => {
220
+ expect(actual.length).toBe(2);
221
+ });
222
+
223
+ it('Should include the ids involved in the cycle', () => {
224
+ expect(actual[0]).toMatchObject(['start', 'mid', 'left']);
225
+ expect(actual[1]).toMatchObject(['start', 'mid', 'right']);
226
+ });
227
+ });
228
+ });
29
229
  });
package/src/utils.ts CHANGED
@@ -120,7 +120,7 @@ export function shortenTree(
120
120
  ...item,
121
121
  issuer: shortKey,
122
122
  id: item.id === null ? null : path.relative(context, item.id),
123
- } as Dependency),
123
+ }) as Dependency,
124
124
  )
125
125
  : null;
126
126
  }
@@ -287,3 +287,15 @@ export function prettyWarning(warnings: string[], prefix = ' ') {
287
287
  })
288
288
  .join('\n');
289
289
  }
290
+
291
+ export function isEmpty(v: unknown) {
292
+ if (v == null) {
293
+ return true;
294
+ }
295
+ for (const k in v) {
296
+ if (v.hasOwnProperty(k)) {
297
+ return false;
298
+ }
299
+ }
300
+ return true;
301
+ }