• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1var fs = require('graceful-fs')
2var path = require('path')
3
4var mkdirp = require('mkdirp')
5var test = require('tap').test
6var rimraf = require('rimraf')
7
8var common = require('../common-tap')
9
10var pkg = common.pkg
11var cache = common.cache
12var tmp = path.resolve(pkg, 'tmp')
13
14var opts = { cwd: pkg }
15
16var fullyPopulated = {
17  'name': 'runscript',
18  'version': '1.2.3',
19  'scripts': {
20    'start': 'node -e "console.log(process.argv[1] || \'start\')"',
21    'prewith-pre': 'node -e "console.log(process.argv[1] || \'pre\')"',
22    'with-pre': 'node -e "console.log(process.argv[1] || \'main\')"',
23    'with-post': 'node -e "console.log(process.argv[1] || \'main\')"',
24    'postwith-post': 'node -e "console.log(process.argv[1] || \'post\')"',
25    'prewith-both': 'node -e "console.log(process.argv[1] || \'pre\')"',
26    'with-both': 'node -e "console.log(process.argv[1] || \'main\')"',
27    'postwith-both': 'node -e "console.log(process.argv[1] || \'post\')"',
28    'stop': 'node -e "console.log(process.argv[1] || \'stop\')"',
29    'env-vars': 'node -e "console.log(process.env.run_script_foo_var)"',
30    'npm-env-vars': 'node -e "console.log(process.env.npm_run_script_foo_var)"',
31    'package-env-vars': 'node -e "console.log(process.env.run_script_foo_var)"',
32    'prefixed-package-env-vars': 'node -e "console.log(process.env.npm_package_run_script_foo_var)"'
33  },
34  'run_script_foo_var': 'run_script_test_foo_val'
35}
36
37var lifecycleOnly = {
38  name: 'scripted',
39  version: '1.2.3',
40  scripts: {
41    'prestart': 'echo prestart'
42  }
43}
44
45var directOnly = {
46  name: 'scripted',
47  version: '1.2.3',
48  scripts: {
49    'whoa': 'echo whoa'
50  }
51}
52
53var both = {
54  name: 'scripted',
55  version: '1.2.3',
56  scripts: {
57    'prestart': 'echo prestart',
58    'whoa': 'echo whoa'
59  }
60}
61
62var preversionOnly = {
63  name: 'scripted',
64  version: '1.2.3',
65  scripts: {
66    'preversion': 'echo preversion'
67  }
68}
69
70var exitCode = {
71  name: 'scripted',
72  version: '1.2.3',
73  scripts: {
74    'start': 'node -e "process.exit(7)"'
75  }
76}
77
78var shell = {
79  name: 'scripted',
80  version: '1.2.3',
81  scripts: {
82    'start': 'echo foo'
83  }
84}
85
86function testOutput (t, command, er, code, stdout, stderr) {
87  var lines
88
89  if (er) throw er
90
91  if (stderr) {
92    throw new Error('npm ' + command + ' stderr: ' + stderr.toString())
93  }
94
95  lines = stdout.trim().split('\n')
96  stdout = lines.filter(function (line) {
97    return line.trim() !== '' && line[0] !== '>'
98  }).join(';')
99
100  t.equal(stdout, command)
101  t.end()
102}
103
104function writeMetadata (object) {
105  fs.writeFileSync(
106    path.resolve(pkg, 'package.json'),
107    JSON.stringify(object, null, 2) + '\n'
108  )
109}
110
111function cleanup () {
112  rimraf.sync(pkg)
113}
114
115test('setup', function (t) {
116  cleanup()
117  mkdirp.sync(cache)
118  mkdirp.sync(tmp)
119  writeMetadata(fullyPopulated)
120  t.end()
121})
122
123test('npm run-script start', function (t) {
124  common.npm(['run-script', 'start'], opts, testOutput.bind(null, t, 'start'))
125})
126
127test('npm run-script with args', function (t) {
128  common.npm(['run-script', 'start', '--', 'stop'], opts, testOutput.bind(null, t, 'stop'))
129})
130
131test('npm run-script with args that contain spaces', function (t) {
132  common.npm(['run-script', 'start', '--', 'hello world'], opts, testOutput.bind(null, t, 'hello world'))
133})
134
135test('npm run-script with args that contain single quotes', function (t) {
136  common.npm(['run-script', 'start', '--', 'they"re awesome'], opts, testOutput.bind(null, t, 'they"re awesome'))
137})
138
139test('npm run-script with args that contain double quotes', function (t) {
140  common.npm(['run-script', 'start', '--', 'what"s "up"?'], opts, testOutput.bind(null, t, 'what"s "up"?'))
141})
142
143test('npm run-script with args that contain ticks', function (t) {
144  common.npm(['run-script', 'start', '--', 'what\'s \'up\'?'], opts, testOutput.bind(null, t, 'what\'s \'up\'?'))
145})
146
147test('npm run-script with pre script', function (t) {
148  common.npm(['run-script', 'with-post'], opts, testOutput.bind(null, t, 'main;post'))
149})
150
151test('npm run-script with post script', function (t) {
152  common.npm(['run-script', 'with-pre'], opts, testOutput.bind(null, t, 'pre;main'))
153})
154
155test('npm run-script with both pre and post script', function (t) {
156  common.npm(['run-script', 'with-both'], opts, testOutput.bind(null, t, 'pre;main;post'))
157})
158
159test('npm run-script with both pre and post script and with args', function (t) {
160  common.npm(['run-script', 'with-both', '--', 'an arg'], opts, testOutput.bind(null, t, 'pre;an arg;post'))
161})
162
163test('npm run-script explicitly call pre script with arg', function (t) {
164  common.npm(['run-script', 'prewith-pre', '--', 'an arg'], opts, testOutput.bind(null, t, 'an arg'))
165})
166
167test('npm run-script test', function (t) {
168  common.npm(['run-script', 'test'], opts, function (er, code, stdout, stderr) {
169    t.ifError(er, 'npm run-script test ran without issue')
170    t.notOk(stderr, 'should not generate errors')
171    t.end()
172  })
173})
174
175test('npm run-script env', function (t) {
176  common.npm(['run-script', 'env'], opts, function (er, code, stdout, stderr) {
177    t.ifError(er, 'using default env script')
178    t.notOk(stderr, 'should not generate errors')
179    t.ok(stdout.indexOf('npm_config_init_version') > 0, 'expected values in var list')
180    t.end()
181  })
182})
183
184test('npm run-script nonexistent-script', function (t) {
185  common.npm(['run-script', 'nonexistent-script'], opts, function (er, code, stdout, stderr) {
186    t.ifError(er, 'npm run-script nonexistent-script did not cause npm to explode')
187    t.ok(stderr, 'should generate errors')
188    t.end()
189  })
190})
191
192test('npm run-script restart when there isn\'t restart', function (t) {
193  common.npm(['run-script', 'restart'], opts, testOutput.bind(null, t, 'stop;start'))
194})
195
196test('npm run-script nonexistent-script with --if-present flag', function (t) {
197  common.npm(['run-script', '--if-present', 'nonexistent-script'], opts, function (er, code, stdout, stderr) {
198    t.ifError(er, 'npm run-script --if-present non-existent-script ran without issue')
199    t.notOk(stderr, 'should not generate errors')
200    t.end()
201  })
202})
203
204test('npm run-script env vars accessible', function (t) {
205  process.env.run_script_foo_var = 'run_script_test_foo_val'
206  common.npm(['run-script', 'env-vars'], {
207    cwd: pkg
208  }, function (err, code, stdout, stderr) {
209    t.ifError(err, 'ran run-script without crashing')
210    t.equal(code, 0, 'exited normally')
211    t.equal(stderr, '', 'no error output')
212    t.match(stdout,
213      new RegExp(process.env.run_script_foo_var),
214      'script had env access')
215    t.end()
216  })
217})
218
219test('npm run-script package.json vars injected', function (t) {
220  common.npm(['run-script', 'package-env-vars'], {
221    cwd: pkg
222  }, function (err, code, stdout, stderr) {
223    t.ifError(err, 'ran run-script without crashing')
224    t.equal(code, 0, 'exited normally')
225    t.equal(stderr, '', 'no error output')
226    t.match(stdout,
227      new RegExp(fullyPopulated.run_script_foo_var),
228      'script injected package.json value')
229    t.end()
230  })
231})
232
233test('npm run-script package.json vars injected with prefix', function (t) {
234  common.npm(['run-script', 'prefixed-package-env-vars'], {
235    cwd: pkg
236  }, function (err, code, stdout, stderr) {
237    t.ifError(err, 'ran run-script without crashing')
238    t.equal(code, 0, 'exited normally')
239    t.equal(stderr, '', 'no error output')
240    t.match(stdout,
241      new RegExp(fullyPopulated.run_script_foo_var),
242      'script injected npm_package-prefixed package.json value')
243    t.end()
244  })
245})
246
247test('npm run-script env vars stripped npm-prefixed', function (t) {
248  process.env.npm_run_script_foo_var = 'run_script_test_foo_val'
249  common.npm(['run-script', 'npm-env-vars'], {
250    cwd: pkg
251  }, function (err, code, stdout, stderr) {
252    t.ifError(err, 'ran run-script without crashing')
253    t.equal(code, 0, 'exited normally')
254    t.equal(stderr, '', 'no error output')
255    t.notMatch(stdout,
256      new RegExp(process.env.npm_run_script_foo_var),
257      'script stripped npm-prefixed env var')
258    t.end()
259  })
260})
261
262test('npm run-script no-params (lifecycle only)', function (t) {
263  var expected = [
264    'Lifecycle scripts included in scripted:',
265    '  prestart',
266    '    echo prestart',
267    ''
268  ].join('\n')
269
270  writeMetadata(lifecycleOnly)
271
272  common.npm(['run-script'], opts, function (err, code, stdout, stderr) {
273    t.ifError(err, 'ran run-script without parameters without crashing')
274    t.notOk(code, 'npm exited without error code')
275    t.notOk(stderr, 'npm printed nothing to stderr')
276    t.equal(stdout, expected, 'got expected output')
277    t.end()
278  })
279})
280
281test('npm run-script no-params (preversion only)', function (t) {
282  var expected = [
283    'Lifecycle scripts included in scripted:',
284    '  preversion',
285    '    echo preversion',
286    ''
287  ].join('\n')
288
289  writeMetadata(preversionOnly)
290
291  common.npm(['run-script'], opts, function (err, code, stdout, stderr) {
292    t.ifError(err, 'ran run-script without parameters without crashing')
293    t.notOk(code, 'npm exited without error code')
294    t.notOk(stderr, 'npm printed nothing to stderr')
295    t.equal(stdout, expected, 'got expected output')
296    t.end()
297  })
298})
299
300test('npm run-script no-params (direct only)', function (t) {
301  var expected = [
302    'Scripts available in scripted via `npm run-script`:',
303    '  whoa',
304    '    echo whoa',
305    ''
306  ].join('\n')
307
308  writeMetadata(directOnly)
309
310  common.npm(['run-script'], opts, function (err, code, stdout, stderr) {
311    t.ifError(err, 'ran run-script without parameters without crashing')
312    t.notOk(code, 'npm exited without error code')
313    t.notOk(stderr, 'npm printed nothing to stderr')
314    t.equal(stdout, expected, 'got expected output')
315    t.end()
316  })
317})
318
319test('npm run-script script-shell config', function (t) {
320  writeMetadata(shell)
321
322  common.npm(['run-script', 'start', '--script-shell', 'echo'], opts, testOutput.bind(null, t, '-c echo foo'))
323})
324
325test('npm run-script no-params (direct only)', function (t) {
326  var expected = [
327    'Lifecycle scripts included in scripted:',
328    '  prestart',
329    '    echo prestart',
330    '',
331    'available via `npm run-script`:',
332    '  whoa',
333    '    echo whoa',
334    ''
335  ].join('\n')
336
337  writeMetadata(both)
338
339  common.npm(['run-script'], opts, function (err, code, stdout, stderr) {
340    t.ifError(err, 'ran run-script without parameters without crashing')
341    t.notOk(code, 'npm exited without error code')
342    t.notOk(stderr, 'npm printed nothing to stderr')
343    t.equal(stdout, expected, 'got expected output')
344    t.end()
345  })
346})
347
348test('npm run-script keep non-zero exit code', function (t) {
349  writeMetadata(exitCode)
350
351  common.npm(['run-script', 'start'], opts, function (err, code, stdout, stderr) {
352    t.ifError(err, 'ran run-script without parameters without crashing')
353    t.equal(code, 7, 'got expected exit code')
354    t.ok(stderr, 'should generate errors')
355    t.end()
356  })
357})
358
359test('npm run-script nonexistent script and display suggestions', function (t) {
360  writeMetadata(directOnly)
361
362  common.npm(['run-script', 'whoop'], opts, function (err, code, stdout, stderr) {
363    t.ifError(err, 'ran run-script without crashing')
364    t.equal(code, 1, 'got expected exit code')
365    t.has(stderr, 'Did you mean this?')
366    t.end()
367  })
368})
369
370test('cleanup', function (t) {
371  cleanup()
372  t.end()
373})
374