Skip to content

Commit dc52222

Browse files
committedJan 1, 2023
fix(init): write package.json workspaces paths with / separators
This also refactors the test to use `mockNpm`
1 parent 31af1aa commit dc52222

File tree

3 files changed

+208
-333
lines changed

3 files changed

+208
-333
lines changed
 

‎lib/commands/init.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const PackageJson = require('@npmcli/package-json')
1010
const log = require('../utils/log-shim.js')
1111
const updateWorkspaces = require('../workspaces/update-workspaces.js')
1212

13+
const posixPath = p => p.split('\\').join('/')
14+
1315
const BaseCommand = require('../base-command.js')
1416

1517
class Init extends BaseCommand {
@@ -203,7 +205,7 @@ class Init extends BaseCommand {
203205
pkgJson.update({
204206
workspaces: [
205207
...(pkgJson.content.workspaces || []),
206-
relative(this.npm.localPrefix, workspacePath),
208+
posixPath(relative(this.npm.localPrefix, workspacePath)),
207209
],
208210
})
209211

‎tap-snapshots/test/lib/commands/init.js.test.cjs

+13-22
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,25 @@
55
* Make sure to inspect the output below. Do not ignore changes!
66
*/
77
'use strict'
8-
exports[`test/lib/commands/init.js TAP npm init workspces with root > does not print helper info 1`] = `
9-
Array []
10-
`
8+
exports[`test/lib/commands/init.js TAP displays output > displays helper info 1`] = `
9+
This utility will walk you through creating a package.json file.
10+
It only covers the most common items, and tries to guess sensible defaults.
1111
12-
exports[`test/lib/commands/init.js TAP workspaces no args > should print helper info 1`] = `
13-
Array []
14-
`
12+
See \`npm help init\` for definitive documentation on these fields
13+
and exactly what they do.
14+
15+
Use \`npm install <pkg>\` afterwards to install a package and
16+
save it as a dependency in the package.json file.
1517
16-
exports[`test/lib/commands/init.js TAP workspaces no args, existing folder > should print helper info 1`] = `
17-
Array []
18+
Press ^C at any time to quit.
1819
`
1920

20-
exports[`test/lib/commands/init.js TAP workspaces post workspace-init reify > should print helper info 1`] = `
21-
Array [
22-
Array [
23-
String(
24-
25-
added 1 package in 100ms
26-
),
27-
],
28-
]
21+
exports[`test/lib/commands/init.js TAP workspaces no args -- yes > should print helper info 1`] = `
22+
23+
added 1 package in {TIME}
2924
`
3025

31-
exports[`test/lib/commands/init.js TAP workspaces post workspace-init reify > should reify tree on init ws complete 1`] = `
26+
exports[`test/lib/commands/init.js TAP workspaces no args -- yes > should reify tree on init ws complete 1`] = `
3227
{
3328
"name": "top-level",
3429
"lockfileVersion": 3,
@@ -53,7 +48,3 @@ exports[`test/lib/commands/init.js TAP workspaces post workspace-init reify > sh
5348
}
5449
5550
`
56-
57-
exports[`test/lib/commands/init.js TAP workspaces with arg but missing workspace folder > should print helper info 1`] = `
58-
Array []
59-
`

‎test/lib/commands/init.js

+192-310
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,105 @@
11
const t = require('tap')
2-
const fs = require('fs')
3-
const { resolve } = require('path')
4-
const { fake: mockNpm } = require('../../fixtures/mock-npm')
5-
6-
const config = {
7-
cache: 'bad-cache-dir',
8-
'init-module': '~/.npm-init.js',
9-
yes: true,
10-
}
11-
const flatOptions = {
12-
cache: 'test-config-dir/_cacache',
13-
npxCache: 'test-config-dir/_npx',
14-
}
15-
const npm = mockNpm({
16-
flatOptions,
17-
config,
18-
})
19-
const mocks = {
20-
npmlog: {
21-
disableProgress: () => null,
22-
enableProgress: () => null,
23-
},
24-
'proc-log': {
25-
info: () => null,
26-
pause: () => null,
27-
resume: () => null,
28-
silly: () => null,
29-
},
2+
const fs = require('fs/promises')
3+
const { resolve, basename } = require('path')
4+
const _mockNpm = require('../../fixtures/mock-npm')
5+
const { cleanTime } = require('../../fixtures/clean-snapshot')
6+
7+
t.cleanSnapshot = cleanTime
8+
9+
const mockNpm = async (t, { noLog, libnpmexec, initPackageJson, packageJson, ...opts } = {}) => {
10+
const res = await _mockNpm(t, {
11+
...opts,
12+
mocks: {
13+
...(libnpmexec ? { libnpmexec } : {}),
14+
...(initPackageJson ? { 'init-package-json': initPackageJson } : {}),
15+
...(packageJson ? { '@npmcli/package-json': packageJson } : {}),
16+
},
17+
globals: {
18+
// init-package-json prints directly to console.log
19+
// this avoids poluting test output with those logs
20+
...(noLog ? { 'console.log': () => {} } : {}),
21+
},
22+
})
23+
24+
return res
3025
}
31-
const Init = t.mock('../../../lib/commands/init.js', mocks)
32-
const init = new Init(npm)
33-
const _cwd = process.cwd()
34-
const _consolelog = console.log
35-
const noop = () => {}
36-
37-
t.afterEach(() => {
38-
config.yes = true
39-
config.package = undefined
40-
process.chdir(_cwd)
41-
console.log = _consolelog
26+
27+
t.test('displays output', async t => {
28+
const { npm, joinedOutput } = await mockNpm(t, {
29+
initPackageJson: (...args) => args[3](),
30+
})
31+
32+
await npm.exec('init', [])
33+
t.matchSnapshot(joinedOutput(), 'displays helper info')
4234
})
4335

4436
t.test('classic npm init -y', async t => {
45-
npm.localPrefix = t.testdir({})
46-
47-
// init-package-json prints directly to console.log
48-
// this avoids poluting test output with those logs
49-
console.log = noop
37+
const { npm, prefix } = await mockNpm(t, {
38+
config: { yes: true },
39+
noLog: true,
40+
})
5041

51-
process.chdir(npm.localPrefix)
52-
await init.exec([])
42+
await npm.exec('init', [])
5343

54-
const pkg = require(resolve(npm.localPrefix, 'package.json'))
44+
const pkg = require(resolve(prefix, 'package.json'))
5545
t.equal(pkg.version, '1.0.0')
5646
t.equal(pkg.license, 'ISC')
5747
})
5848

5949
t.test('classic interactive npm init', async t => {
60-
npm.localPrefix = t.testdir({})
61-
config.yes = undefined
50+
t.plan(1)
6251

63-
const Init = t.mock('../../../lib/commands/init.js', {
64-
...mocks,
65-
'init-package-json': (path, initFile, config, cb) => {
52+
const { npm } = await mockNpm(t, {
53+
initPackageJson: (...args) => {
6654
t.equal(
67-
path,
55+
args[0],
6856
resolve(npm.localPrefix),
6957
'should start init package.json in expected path'
7058
)
71-
cb()
59+
args[3]()
7260
},
7361
})
74-
const init = new Init(npm)
7562

76-
process.chdir(npm.localPrefix)
77-
await init.exec([])
63+
await npm.exec('init', [])
7864
})
7965

8066
t.test('npm init <arg>', async t => {
81-
t.plan(3)
82-
npm.localPrefix = t.testdir({})
67+
t.plan(1)
8368

84-
const Init = t.mock('../../../lib/commands/init.js', {
85-
libnpmexec: ({ args, cache, npxCache }) => {
69+
const { npm } = await mockNpm(t, {
70+
libnpmexec: ({ args }) => {
8671
t.same(
8772
args,
8873
['create-react-app@*'],
8974
'should npx with listed packages'
9075
)
91-
t.same(cache, flatOptions.cache)
92-
t.same(npxCache, flatOptions.npxCache)
9376
},
9477
})
95-
const init = new Init(npm)
9678

97-
process.chdir(npm.localPrefix)
98-
await init.exec(['react-app'])
79+
await npm.exec('init', ['react-app'])
9980
})
10081

10182
t.test('npm init <arg> -- other-args', async t => {
10283
t.plan(1)
103-
npm.localPrefix = t.testdir({})
10484

105-
const Init = t.mock('../../../lib/commands/init.js', {
85+
const { npm } = await mockNpm(t, {
10686
libnpmexec: ({ args }) => {
10787
t.same(
10888
args,
10989
['create-react-app@*', 'my-path', '--some-option', 'some-value'],
11090
'should npm exec with expected args'
11191
)
11292
},
93+
11394
})
114-
const init = new Init(npm)
11595

116-
process.chdir(npm.localPrefix)
117-
await init.exec(['react-app', 'my-path', '--some-option', 'some-value'])
96+
await npm.exec('init', ['react-app', 'my-path', '--some-option', 'some-value'])
11897
})
11998

12099
t.test('npm init @scope/name', async t => {
121100
t.plan(1)
122-
npm.localPrefix = t.testdir({})
123101

124-
const Init = t.mock('../../../lib/commands/init.js', {
102+
const { npm } = await mockNpm(t, {
125103
libnpmexec: ({ args }) => {
126104
t.same(
127105
args,
@@ -130,17 +108,14 @@ t.test('npm init @scope/name', async t => {
130108
)
131109
},
132110
})
133-
const init = new Init(npm)
134111

135-
process.chdir(npm.localPrefix)
136-
await init.exec(['@npmcli/something'])
112+
await npm.exec('init', ['@npmcli/something'])
137113
})
138114

139115
t.test('npm init @scope@spec', async t => {
140116
t.plan(1)
141-
npm.localPrefix = t.testdir({})
142117

143-
const Init = t.mock('../../../lib/commands/init.js', {
118+
const { npm } = await mockNpm(t, {
144119
libnpmexec: ({ args }) => {
145120
t.same(
146121
args,
@@ -149,17 +124,14 @@ t.test('npm init @scope@spec', async t => {
149124
)
150125
},
151126
})
152-
const init = new Init(npm)
153127

154-
process.chdir(npm.localPrefix)
155-
await init.exec(['@npmcli@foo'])
128+
await npm.exec('init', ['@npmcli@foo'])
156129
})
157130

158131
t.test('npm init @scope/name@spec', async t => {
159132
t.plan(1)
160-
npm.localPrefix = t.testdir({})
161133

162-
const Init = t.mock('../../../lib/commands/init.js', {
134+
const { npm } = await mockNpm(t, {
163135
libnpmexec: ({ args }) => {
164136
t.same(
165137
args,
@@ -168,17 +140,13 @@ t.test('npm init @scope/name@spec', async t => {
168140
)
169141
},
170142
})
171-
const init = new Init(npm)
172143

173-
process.chdir(npm.localPrefix)
174-
await init.exec(['@npmcli/something@foo'])
144+
await npm.exec('init', ['@npmcli/something@foo'])
175145
})
176146

177147
t.test('npm init git spec', async t => {
178148
t.plan(1)
179-
npm.localPrefix = t.testdir({})
180-
181-
const Init = t.mock('../../../lib/commands/init.js', {
149+
const { npm } = await mockNpm(t, {
182150
libnpmexec: ({ args }) => {
183151
t.same(
184152
args,
@@ -187,17 +155,14 @@ t.test('npm init git spec', async t => {
187155
)
188156
},
189157
})
190-
const init = new Init(npm)
191158

192-
process.chdir(npm.localPrefix)
193-
await init.exec(['npm/something'])
159+
await npm.exec('init', ['npm/something'])
194160
})
195161

196162
t.test('npm init @scope', async t => {
197163
t.plan(1)
198-
npm.localPrefix = t.testdir({})
199164

200-
const Init = t.mock('../../../lib/commands/init.js', {
165+
const { npm } = await mockNpm(t, {
201166
libnpmexec: ({ args }) => {
202167
t.same(
203168
args,
@@ -206,28 +171,24 @@ t.test('npm init @scope', async t => {
206171
)
207172
},
208173
})
209-
const init = new Init(npm)
210174

211-
process.chdir(npm.localPrefix)
212-
await init.exec(['@npmcli'])
175+
await npm.exec('init', ['@npmcli'])
213176
})
214177

215178
t.test('npm init tgz', async t => {
216-
npm.localPrefix = t.testdir({})
179+
const { npm } = await mockNpm(t)
217180

218-
process.chdir(npm.localPrefix)
219181
await t.rejects(
220-
init.exec(['something.tgz']),
182+
npm.exec('init', ['something.tgz']),
221183
/Unrecognized initializer: something.tgz/,
222184
'should throw error when using an unsupported spec'
223185
)
224186
})
225187

226188
t.test('npm init <arg>@next', async t => {
227189
t.plan(1)
228-
npm.localPrefix = t.testdir({})
229190

230-
const Init = t.mock('../../../lib/commands/init.js', {
191+
const { npm } = await mockNpm(t, {
231192
libnpmexec: ({ args }) => {
232193
t.same(
233194
args,
@@ -236,35 +197,28 @@ t.test('npm init <arg>@next', async t => {
236197
)
237198
},
238199
})
239-
const init = new Init(npm)
240200

241-
process.chdir(npm.localPrefix)
242-
await init.exec(['something@next'])
201+
await npm.exec('init', ['something@next'])
243202
})
244203

245204
t.test('npm init exec error', async t => {
246-
npm.localPrefix = t.testdir({})
247-
248-
const Init = t.mock('../../../lib/commands/init.js', {
249-
libnpmexec: async ({ args }) => {
205+
const { npm } = await mockNpm(t, {
206+
libnpmexec: async () => {
250207
throw new Error('ERROR')
251208
},
252209
})
253-
const init = new Init(npm)
254210

255-
process.chdir(npm.localPrefix)
256211
await t.rejects(
257-
init.exec(['something@next']),
212+
npm.exec('init', ['something@next']),
258213
/ERROR/,
259214
'should exit with exec error'
260215
)
261216
})
262217

263218
t.test('should not rewrite flatOptions', async t => {
264219
t.plan(1)
265-
npm.localPrefix = t.testdir({})
266220

267-
const Init = t.mock('../../../lib/commands/init.js', {
221+
const { npm } = await mockNpm(t, {
268222
libnpmexec: async ({ args }) => {
269223
t.same(
270224
args,
@@ -273,270 +227,198 @@ t.test('should not rewrite flatOptions', async t => {
273227
)
274228
},
275229
})
276-
const init = new Init(npm)
277230

278-
process.chdir(npm.localPrefix)
279-
await init.exec(['react-app', 'my-app'])
231+
await npm.exec('init', ['react-app', 'my-app'])
280232
})
281233

282234
t.test('npm init cancel', async t => {
283-
t.plan(2)
284-
npm.localPrefix = t.testdir({})
285-
286-
const Init = t.mock('../../../lib/commands/init.js', {
287-
...mocks,
288-
'init-package-json': (dir, initFile, config, cb) => cb(
235+
const { npm, logs } = await mockNpm(t, {
236+
initPackageJson: (...args) => args[3](
289237
new Error('canceled')
290238
),
291-
'proc-log': {
292-
...mocks['proc-log'],
293-
warn: (title, msg) => {
294-
t.equal(title, 'init', 'should have init title')
295-
t.equal(msg, 'canceled', 'should log canceled')
296-
},
297-
},
298239
})
299-
const init = new Init(npm)
300240

301-
process.chdir(npm.localPrefix)
302-
await init.exec([])
241+
await npm.exec('init', [])
242+
243+
t.equal(logs.warn[0][0], 'init', 'should have init title')
244+
t.equal(logs.warn[0][1], 'canceled', 'should log canceled')
303245
})
304246

305247
t.test('npm init error', async t => {
306-
npm.localPrefix = t.testdir({})
307-
308-
const Init = t.mock('../../../lib/commands/init.js', {
309-
...mocks,
310-
'init-package-json': (dir, initFile, config, cb) => cb(
248+
const { npm } = await mockNpm(t, {
249+
initPackageJson: (...args) => args[3](
311250
new Error('Unknown Error')
312251
),
313252
})
314-
const init = new Init(npm)
315253

316-
process.chdir(npm.localPrefix)
317254
await t.rejects(
318-
init.exec([]),
255+
npm.exec('init', []),
319256
/Unknown Error/,
320257
'should throw error'
321258
)
322259
})
323260

324-
t.test('workspaces', t => {
325-
t.test('no args', async t => {
326-
t.teardown(() => {
327-
npm._mockOutputs.length = 0
328-
})
329-
npm._mockOutputs.length = 0
330-
npm.localPrefix = t.testdir({
331-
'package.json': JSON.stringify({
332-
name: 'top-level',
333-
}),
334-
})
335-
336-
const Init = t.mock('../../../lib/commands/init.js', {
337-
...mocks,
338-
'init-package-json': (dir, initFile, config, cb) => {
339-
t.equal(dir, resolve(npm.localPrefix, 'a'), 'should use the ws path')
340-
cb()
341-
},
342-
})
343-
const init = new Init(npm)
344-
await init.execWorkspaces([], ['a'])
345-
t.matchSnapshot(npm._mockOutputs, 'should print helper info')
346-
})
347-
348-
t.test('post workspace-init reify', async t => {
349-
const _consolelog = console.log
350-
console.log = () => null
351-
t.teardown(() => {
352-
console.log = _consolelog
353-
npm._mockOutputs.length = 0
354-
delete npm.flatOptions.workspacesUpdate
355-
})
356-
npm.started = Date.now()
357-
npm._mockOutputs.length = 0
358-
npm.flatOptions.workspacesUpdate = true
359-
npm.localPrefix = t.testdir({
360-
'package.json': JSON.stringify({
361-
name: 'top-level',
362-
}),
363-
})
364-
365-
const Init = t.mock('../../../lib/commands/init.js', {
366-
...mocks,
367-
'init-package-json': (dir, initFile, config, cb) => {
368-
t.equal(dir, resolve(npm.localPrefix, 'a'), 'should use the ws path')
369-
return require('init-package-json')(dir, initFile, config, cb)
261+
t.test('workspaces', async t => {
262+
await t.test('no args -- yes', async t => {
263+
const { npm, prefix, joinedOutput } = await mockNpm(t, {
264+
prefixDir: {
265+
'package.json': JSON.stringify({
266+
name: 'top-level',
267+
}),
370268
},
269+
config: { workspace: 'a', yes: true },
270+
noLog: true,
371271
})
372-
const init = new Init(npm)
373-
await init.execWorkspaces([], ['a'])
374-
const output = npm._mockOutputs.map(arr => arr.map(i => i.replace(/[0-9]*m?s$/, '100ms')))
375-
t.matchSnapshot(output, 'should print helper info')
376-
const lockFilePath = resolve(npm.localPrefix, 'package-lock.json')
377-
const lockFile = fs.readFileSync(lockFilePath, { encoding: 'utf8' })
378-
t.matchSnapshot(lockFile, 'should reify tree on init ws complete')
379-
})
380272

381-
t.test('no args, existing folder', async t => {
382-
t.teardown(() => {
383-
npm._mockOutputs.length = 0
384-
})
385-
// init-package-json prints directly to console.log
386-
// this avoids poluting test output with those logs
387-
console.log = noop
273+
await npm.exec('init', [])
388274

389-
npm.localPrefix = t.testdir({
390-
packages: {
391-
a: {
392-
'package.json': JSON.stringify({
393-
name: 'a',
394-
version: '1.0.0',
395-
}),
396-
},
397-
},
398-
'package.json': JSON.stringify({
399-
name: 'top-level',
400-
workspaces: ['packages/a'],
401-
}),
402-
})
275+
const pkg = require(resolve(prefix, 'a/package.json'))
276+
t.equal(pkg.name, 'a')
277+
t.equal(pkg.version, '1.0.0')
278+
t.equal(pkg.license, 'ISC')
403279

404-
await init.execWorkspaces([], ['packages/a'])
280+
t.matchSnapshot(joinedOutput(), 'should print helper info')
405281

406-
t.matchSnapshot(npm._mockOutputs, 'should print helper info')
282+
const lock = require(resolve(prefix, 'package-lock.json'))
283+
t.ok(lock.packages.a)
407284
})
408285

409-
t.test('with arg but missing workspace folder', async t => {
410-
t.teardown(() => {
411-
npm._mockOutputs.length = 0
412-
})
413-
// init-package-json prints directly to console.log
414-
// this avoids poluting test output with those logs
415-
console.log = noop
416-
417-
npm.localPrefix = t.testdir({
418-
node_modules: {
419-
a: t.fixture('symlink', '../a'),
420-
'create-index': {
421-
'index.js': ``,
286+
await t.test('no args, existing folder', async t => {
287+
const { npm, prefix } = await mockNpm(t, {
288+
prefixDir: {
289+
packages: {
290+
a: {
291+
'package.json': JSON.stringify({
292+
name: 'a',
293+
version: '2.0.0',
294+
}),
295+
},
422296
},
423-
},
424-
a: {
425297
'package.json': JSON.stringify({
426-
name: 'a',
427-
version: '1.0.0',
298+
name: 'top-level',
299+
workspaces: ['packages/a'],
428300
}),
429301
},
430-
'package.json': JSON.stringify({
431-
name: 'top-level',
432-
}),
302+
config: { workspace: 'packages/a', yes: true },
303+
noLog: true,
433304
})
434305

435-
await init.execWorkspaces([], ['packages/a'])
306+
await npm.exec('init', [])
436307

437-
t.matchSnapshot(npm._mockOutputs, 'should print helper info')
308+
const pkg = require(resolve(prefix, 'packages/a/package.json'))
309+
t.equal(pkg.name, 'a')
310+
t.equal(pkg.version, '2.0.0')
311+
t.equal(pkg.license, 'ISC')
438312
})
439313

440-
t.test('fail parsing top-level package.json to set workspace', async t => {
441-
// init-package-json prints directly to console.log
442-
// this avoids poluting test output with those logs
443-
console.log = noop
444-
445-
npm.localPrefix = t.testdir({
446-
'package.json': JSON.stringify({
447-
name: 'top-level',
448-
}),
449-
})
450-
451-
const Init = t.mock('../../../lib/commands/init.js', {
452-
...mocks,
453-
'@npmcli/package-json': {
314+
await t.test('fail parsing top-level package.json to set workspace', async t => {
315+
const { npm } = await mockNpm(t, {
316+
prefixDir: {
317+
'package.json': JSON.stringify({
318+
name: 'top-level',
319+
}),
320+
},
321+
packageJson: {
454322
async load () {
455323
throw new Error('ERR')
456324
},
457325
},
326+
config: { workspace: 'a', yes: true },
327+
noLog: true,
458328
})
459-
const init = new Init(npm)
460329

461330
await t.rejects(
462-
init.execWorkspaces([], ['a']),
331+
npm.exec('init', []),
463332
/ERR/,
464333
'should exit with error'
465334
)
466335
})
467336

468-
t.test('missing top-level package.json when settting workspace', async t => {
469-
// init-package-json prints directly to console.log
470-
// this avoids poluting test output with those logs
471-
console.log = noop
472-
473-
npm.localPrefix = t.testdir({})
474-
475-
const Init = require('../../../lib/commands/init.js')
476-
const init = new Init(npm)
337+
await t.test('missing top-level package.json when settting workspace', async t => {
338+
const { npm } = await mockNpm(t, {
339+
config: { workspace: 'a' },
340+
})
477341

478342
await t.rejects(
479-
init.execWorkspaces([], ['a']),
343+
npm.exec('init', []),
480344
{ code: 'ENOENT' },
481345
'should exit with missing package.json file error'
482346
)
483347
})
484348

485-
t.test('using args', async t => {
486-
npm.localPrefix = t.testdir({
487-
b: {
349+
await t.test('using args - no package.json', async t => {
350+
const { npm, prefix } = await mockNpm(t, {
351+
prefixDir: {
352+
b: {
353+
'package.json': JSON.stringify({
354+
name: 'b',
355+
}),
356+
},
488357
'package.json': JSON.stringify({
489-
name: 'b',
358+
name: 'top-level',
359+
workspaces: ['b'],
490360
}),
491361
},
492-
'package.json': JSON.stringify({
493-
name: 'top-level',
494-
workspaces: ['b'],
495-
}),
362+
// Important: exec did not write a package.json here
363+
libnpmexec: async () => {},
364+
config: { workspace: 'a', yes: true },
496365
})
497366

498-
const Init = t.mock('../../../lib/commands/init.js', {
499-
...mocks,
500-
libnpmexec: ({ args, path }) => {
501-
t.same(
502-
args,
503-
['create-react-app@*'],
504-
'should npx with listed packages'
505-
)
506-
t.same(
507-
path,
508-
resolve(npm.localPrefix, 'a'),
509-
'should use workspace path'
510-
)
511-
fs.writeFileSync(
512-
resolve(npm.localPrefix, 'a/package.json'),
513-
JSON.stringify({ name: 'a' })
514-
)
367+
await npm.exec('init', ['react-app'])
368+
369+
const pkg = require(resolve(prefix, 'package.json'))
370+
t.strictSame(pkg.workspaces, ['b'], 'pkg workspaces did not get updated')
371+
})
372+
373+
await t.test('init template - bad package.json', async t => {
374+
const { npm, prefix } = await mockNpm(t, {
375+
prefixDir: {
376+
b: {
377+
'package.json': JSON.stringify({
378+
name: 'b',
379+
}),
380+
},
381+
'package.json': JSON.stringify({
382+
name: 'top-level',
383+
workspaces: ['b'],
384+
}),
515385
},
386+
initPackageJson: async (...args) => {
387+
const [dir] = args
388+
if (dir.endsWith('c')) {
389+
await fs.writeFile(resolve(dir, 'package.json'), JSON.stringify({
390+
name: basename(dir),
391+
}), 'utf-8')
392+
}
393+
args[3]()
394+
},
395+
config: { yes: true, workspace: ['a', 'c'] },
516396
})
517397

518-
const init = new Init(npm)
519-
await init.execWorkspaces(['react-app'], ['a'])
520-
})
398+
await npm.exec('init', [])
521399

522-
t.end()
523-
})
400+
const pkg = require(resolve(prefix, 'package.json'))
401+
t.strictSame(pkg.workspaces, ['b', 'c'])
524402

525-
t.test('npm init workspces with root', async t => {
526-
t.teardown(() => {
527-
npm._mockOutputs.length = 0
403+
const lock = require(resolve(prefix, 'package-lock.json'))
404+
t.notOk(lock.packages.a)
528405
})
529-
npm.localPrefix = t.testdir({})
530-
npm.flatOptions.includeWorkspaceRoot = true
531406

532-
// init-package-json prints directly to console.log
533-
// this avoids poluting test output with those logs
534-
console.log = noop
407+
t.test('workspace root', async t => {
408+
const { npm } = await mockNpm(t, {
409+
config: { workspace: 'packages/a', 'include-workspace-root': true, yes: true },
410+
noLog: true,
411+
})
535412

536-
process.chdir(npm.localPrefix)
537-
await init.execWorkspaces([], ['packages/a'])
538-
const pkg = require(resolve(npm.localPrefix, 'package.json'))
539-
t.equal(pkg.version, '1.0.0')
540-
t.equal(pkg.license, 'ISC')
541-
t.matchSnapshot(npm._mockOutputs, 'does not print helper info')
413+
await npm.exec('init', [])
414+
415+
const pkg = require(resolve(npm.localPrefix, 'package.json'))
416+
t.equal(pkg.version, '1.0.0')
417+
t.equal(pkg.license, 'ISC')
418+
t.strictSame(pkg.workspaces, ['packages/a'])
419+
420+
const ws = require(resolve(npm.localPrefix, 'packages/a/package.json'))
421+
t.equal(ws.version, '1.0.0')
422+
t.equal(ws.license, 'ISC')
423+
})
542424
})

0 commit comments

Comments
 (0)
Please sign in to comment.