Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ async function buildCliConfig() {
try {
return (await import(plugin)).default()
} catch (e) {
const msg = e.message || `Cannot find module '${plugin}'`
const msg = e.message || `Unknown error in '${plugin}'`
let prefix = msg.includes(plugin) ? '' : ` (${plugin})`
if (e.name && e.name !== 'Error') prefix += `: ${e.name}`
return error(`Plugin Error${prefix}: ${msg}'`)
error(`Plugin Error${prefix}: ${msg}`)
}
}),
)
Expand Down Expand Up @@ -85,8 +85,6 @@ buildCliConfig()
.then(() => {
if (argv.watch && !(argv.output || argv.replace || argv.dir)) {
error('Cannot write to stdout in watch mode')
// Need to explicitly exit here, since error() doesn't exit in watch mode
process.exit(1)
}

if (input && input.length) {
Expand Down Expand Up @@ -158,15 +156,14 @@ buildCliConfig()
return files([...new Set(recompile)])
.then((results) => watcher.add(dependencies(results)))
.then(printMessage)
.catch(error)
.catch((err) => {
// Watch mode shouldn't exit on file processing error
error(err, argv.watch)
})
})
}
})
.catch((err) => {
error(err)

process.exit(1)
})
.catch(error)

function rc(ctx, path) {
if (argv.use) return Promise.resolve(cliConfig)
Expand Down Expand Up @@ -331,7 +328,7 @@ function printVerbose(message) {
if (argv.verbose) console.warn(message)
}

function error(err) {
function error(err, dontExit) {
// Seperate error from logging output
if (argv.verbose) console.error()

Expand All @@ -342,8 +339,7 @@ function error(err) {
} else {
console.error(err)
}
// Watch mode shouldn't exit on error
if (argv.watch) return
if (dontExit) return
process.exit(1)
}

Expand Down
101 changes: 59 additions & 42 deletions test/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,68 @@ import test from 'ava'
import tmp from './helpers/tmp.js'
import cli from './helpers/cli.js'

test('multiple input files && --output', (t) => {
return cli(['test/fixtures/*.css', '-o', tmp()]).then(({ error, code }) => {
// ensure that configuration errors are thrown in watch mode as well as normal mode
;[false, true].forEach((watch) => {
const prefix = watch ? 'watch mode: ' : ''
const additionalArgs = watch ? ['--watch'] : []

test(`${prefix}multiple input files && --output`, (t) => {
return cli(['test/fixtures/*.css', '-o', tmp(), ...additionalArgs]).then(
({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(error.toString(), /Input Error: Must use --dir or --replace/)
},
)
})

test(`${prefix}plugin not found`, (t) => {
return cli([
'test/fixtures/a.css',
'-u',
'postcss-plugin',
'-o',
tmp(),
...additionalArgs,
]).then(({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(
error.toString(),
/Plugin Error: Cannot find package 'postcss-plugin'/,
)
})
})

test(`${prefix}plugin throws on require`, (t) => {
return cli([
'test/fixtures/a.css',
'-u',
'./test/fixtures/_bad-plugin.js',
'-o',
tmp(),
...additionalArgs,
]).then(({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(error.toString(), /Plugin Error \(.*bad-plugin.js\): This fails/)
})
})

test(`${prefix}fails on invalid explicit config`, async (t) => {
const output = tmp('output-ignore.css')

const { stderr, code } = await cli([
'test/fixtures/a.css',
'-o',
output,
'--config',
'/foo/bar',
...additionalArgs,
])
t.is(code, 1, 'expected non-zero error code')
t.regex(error.toString(), /Input Error: Must use --dir or --replace/)
t.regex(stderr, /No PostCSS Config found/)
})
})

// These errors cannot occur in watch mode; watch mode does not support stdout
test('multiple input files && writing to stdout', (t) => {
return cli(['test/fixtures/*.css']).then(({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
Expand All @@ -27,31 +82,7 @@ test('--map && writing to stdout', (t) => {
})
})

test('plugin not found', (t) => {
return cli(['test/fixtures/a.css', '-u', 'postcss-plugin', '-o', tmp()]).then(
({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(
error.toString(),
/Plugin Error: Cannot find package 'postcss-plugin'/,
)
},
)
})

test('plugin throws on require', (t) => {
return cli([
'test/fixtures/a.css',
'-u',
'./test/fixtures/_bad-plugin.js',
'-o',
tmp(),
]).then(({ error, code }) => {
t.is(code, 1, 'expected non-zero error code')
t.regex(error.toString(), /Plugin Error \(.*bad-plugin.js\): This fails/)
})
})

// Watch mode does not exit on CssSyntaxError, this is tested in ./watch.js
test('CssSyntaxError', (t) => {
return cli(['test/fixtures/a.css', '--parser', 'sugarss', '-o', tmp()]).then(
({ error, code }) => {
Expand All @@ -63,17 +94,3 @@ test('CssSyntaxError', (t) => {
},
)
})

test('fails on invalid explicit config', async (t) => {
const output = tmp('output-ignore.css')

const { stderr, code } = await cli([
'test/fixtures/a.css',
'-o',
output,
'--config',
'/foo/bar',
])
t.is(code, 1, 'expected non-zero error code')
t.regex(stderr, /No PostCSS Config found/)
})