1const { resolve } = require('path')
2const t = require('tap')
3const getWorkspaces = require('../../../lib/workspaces/get-workspaces.js')
4
5const normalizePath = p => p
6  .replace(/\\+/g, '/')
7  .replace(/\r\n/g, '\n')
8
9const cleanOutput = (str, path) => normalizePath(str)
10  .replace(normalizePath(path), '{PATH}')
11
12const clean = (res, path) => {
13  const cleaned = new Map()
14  for (const [key, value] of res.entries()) {
15    cleaned.set(key, cleanOutput(value, path))
16  }
17  return cleaned
18}
19
20const path = t.testdir({
21  packages: {
22    a: {
23      'package.json': JSON.stringify({
24        name: 'a',
25        version: '1.0.0',
26        scripts: { glorp: 'echo a doing the glerp glop' },
27      }),
28    },
29    b: {
30      'package.json': JSON.stringify({
31        name: 'b',
32        version: '2.0.0',
33        scripts: { glorp: 'echo b doing the glerp glop' },
34      }),
35    },
36    c: {
37      'package.json': JSON.stringify({
38        name: 'c',
39        version: '1.0.0',
40        scripts: {
41          test: 'exit 0',
42          posttest: 'echo posttest',
43          lorem: 'echo c lorem',
44        },
45      }),
46    },
47    d: {
48      'package.json': JSON.stringify({
49        name: 'd',
50        version: '1.0.0',
51        scripts: {
52          test: 'exit 0',
53          posttest: 'echo posttest',
54        },
55      }),
56    },
57    e: {
58      'package.json': JSON.stringify({
59        name: 'e',
60        scripts: { test: 'exit 0', start: 'echo start something' },
61      }),
62    },
63    noscripts: {
64      'package.json': JSON.stringify({
65        name: 'noscripts',
66        version: '1.0.0',
67      }),
68    },
69  },
70  'package.json': JSON.stringify({
71    name: 'x',
72    version: '1.2.3',
73    workspaces: ['packages/*'],
74  }),
75})
76
77let workspaces
78
79t.test('filter by package name', async t => {
80  workspaces = await getWorkspaces(['a', 'b'], { path, relativeFrom: path })
81  t.same(
82    clean(workspaces, path),
83    new Map(Object.entries({
84      a: '{PATH}/packages/a',
85      b: '{PATH}/packages/b',
86    })),
87    'should filter by package name'
88  )
89})
90
91t.test('include workspace root', async t => {
92  workspaces = await getWorkspaces(['a', 'b'],
93    { path, includeWorkspaceRoot: true, relativeFrom: path })
94  t.same(
95    clean(workspaces, path),
96    new Map(Object.entries({
97      x: '{PATH}',
98      a: '{PATH}/packages/a',
99      b: '{PATH}/packages/b',
100    })),
101    'include rootspace root'
102  )
103})
104
105t.test('filter by package directory', async t => {
106  workspaces = await getWorkspaces(['./packages/c'], { path, relativeFrom: path })
107  t.same(
108    clean(workspaces, path),
109    new Map(Object.entries({
110      c: '{PATH}/packages/c',
111    })),
112    'should filter by package directory'
113  )
114})
115
116t.test('filter by rel package directory', async t => {
117  workspaces = await getWorkspaces(['packages/c'], { path, relativeFrom: path })
118  t.same(
119    clean(workspaces, path),
120    new Map(Object.entries({
121      c: '{PATH}/packages/c',
122    })),
123    'should filter by rel package directory'
124  )
125})
126
127t.test('filter by absolute package directory', async t => {
128  workspaces = await getWorkspaces([resolve(path, 'packages/c')], { path, relativeFrom: path })
129  t.same(
130    clean(workspaces, path),
131    new Map(Object.entries({
132      c: '{PATH}/packages/c',
133    })),
134    'should filter by absolute package directory'
135  )
136})
137
138t.test('filter by parent directory name', async t => {
139  workspaces = await getWorkspaces(['packages'], { path, relativeFrom: path })
140  t.same(
141    clean(workspaces, path),
142    new Map(Object.entries({
143      a: '{PATH}/packages/a',
144      b: '{PATH}/packages/b',
145      c: '{PATH}/packages/c',
146      d: '{PATH}/packages/d',
147      e: '{PATH}/packages/e',
148      noscripts: '{PATH}/packages/noscripts',
149    })),
150    'should filter by parent directory name'
151  )
152})
153
154t.test('filter by parent directory path', async t => {
155  workspaces = await getWorkspaces(['./packages/'], { path, relativeFrom: path })
156  t.same(
157    clean(workspaces, path),
158    new Map(Object.entries({
159      a: '{PATH}/packages/a',
160      b: '{PATH}/packages/b',
161      c: '{PATH}/packages/c',
162      d: '{PATH}/packages/d',
163      e: '{PATH}/packages/e',
164      noscripts: '{PATH}/packages/noscripts',
165    })),
166    'should filter by parent directory path'
167  )
168})
169
170t.test('filter by absolute parent directory path', async t => {
171  workspaces = await getWorkspaces([resolve(path, './packages')], { path, relativeFrom: path })
172  t.same(
173    clean(workspaces, path),
174    new Map(Object.entries({
175      a: '{PATH}/packages/a',
176      b: '{PATH}/packages/b',
177      c: '{PATH}/packages/c',
178      d: '{PATH}/packages/d',
179      e: '{PATH}/packages/e',
180      noscripts: '{PATH}/packages/noscripts',
181    })),
182    'should filter by absolute parent directory path'
183  )
184})
185
186t.test('no filter set', async t => {
187  workspaces = await getWorkspaces([], { path, relativeFrom: path })
188  t.same(
189    clean(workspaces, path),
190    new Map(Object.entries({
191      a: '{PATH}/packages/a',
192      b: '{PATH}/packages/b',
193      c: '{PATH}/packages/c',
194      d: '{PATH}/packages/d',
195      e: '{PATH}/packages/e',
196      noscripts: '{PATH}/packages/noscripts',
197    })),
198    'should return all workspaces if no filter set'
199  )
200})
201
202t.test('missing workspace', async t => {
203  await t.rejects(
204    getWorkspaces(['missing'], { path, relativeFrom: path }),
205    /No workspaces found/,
206    'should throw no workspaces found error'
207  )
208})
209
210t.test('no workspaces configured', async t => {
211  const unconfiguredWorkspaces = t.testdir({
212    'package.json': JSON.stringify({
213      name: 'no-configured-workspaces',
214      version: '1.0.0',
215    }),
216  })
217  await t.rejects(
218    getWorkspaces([], { path: unconfiguredWorkspaces, relativeFrom: path }),
219    /No workspaces found/,
220    'should throw no workspaces found error'
221  )
222})
223