Skip to content
Open
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
6 changes: 3 additions & 3 deletions example.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const tasks = new Listr([

delay(2000)
.then(() => {
observer.next(`bar`);
observer.next('bar');
return delay(2000);
})
.then(() => {
Expand Down Expand Up @@ -79,6 +79,6 @@ const tasks = new Listr([
renderer
});

tasks.run().catch(err => {
console.error(err.message);
tasks.run().catch(error => {
console.error(error.message);
});
19 changes: 10 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class Listr {
showSubtasks: true,
concurrent: false,
renderer: 'default',
nonTTYRenderer: 'verbose'
nonTTYRenderer: 'verbose',
failParentTaskOnErrors: true
}, opts);
this._tasks = [];

Expand Down Expand Up @@ -98,20 +99,20 @@ class Listr {

return tasks
.then(() => {
if (errors.length > 0) {
const err = new ListrError('Something went wrong');
err.errors = errors;
throw err;
if (this._options.failParentTaskOnErrors && errors.length > 0) {
const error = new ListrError('Something went wrong');
error.errors = errors;
throw error;
}

this._renderer.end();

return context;
})
.catch(err => {
err.context = context;
this._renderer.end(err);
throw err;
.catch(error => {
error.context = context;
this._renderer.end(error);
throw error;
});
}
}
Expand Down
14 changes: 7 additions & 7 deletions lib/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,29 +171,29 @@ class Task extends Subject {
this.state = state.COMPLETED;
}
})
.catch(err => {
.catch(error => {
this.state = state.FAILED;

if (err instanceof ListrError) {
wrapper.report(err);
if (error instanceof ListrError) {
wrapper.report(error);
return;
}

if (!this.hasSubtasks()) {
// Do not show the message if we have subtasks as the error is already shown in the subtask
this.output = err.message;
this.output = error.message;
}

this.next({
type: 'DATA',
data: err.message
data: error.message
});

wrapper.report(err);
wrapper.report(error);

if (this._listr.exitOnError !== false) {
// Do not exit when explicitely set to `false`
throw err;
throw error;
}
})
.then(() => {
Expand Down
8 changes: 8 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,14 @@ Default: `true`

Set to `false` if you don't want to stop the execution of other tasks when one or more tasks fail.

##### failParentTaskOnErrors

Type: `boolean`<br>
Default: `true`

Set to `false` if you don't want show failed state in parent task when a sub tasks fails.


##### renderer

Type: `string` `object`<br>
Expand Down
101 changes: 77 additions & 24 deletions test/exit-on-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ test('exit on error', async t => {

try {
await list.run();
} catch (err) {
t.is(err.message, 'Something went wrong');
} catch (error) {
t.is(error.message, 'Something went wrong');
}
});

Expand All @@ -54,9 +54,9 @@ test('set `exitOnError` to false', async t => {

try {
await list.run();
} catch (err) {
t.is(err.message, 'Something went wrong');
t.is(err.errors.length, 1);
} catch (error) {
t.is(error.message, 'Something went wrong');
t.is(error.errors.length, 1);
}
});

Expand Down Expand Up @@ -110,10 +110,10 @@ test('set `exitOnError` to false in nested list', async t => {

try {
await list.run();
} catch (err) {
t.is(err.message, 'Something went wrong');
t.is(err.errors.length, 1);
t.is(err.errors[0].message, 'Unicorn failed');
} catch (error) {
t.is(error.message, 'Something went wrong');
t.is(error.errors.length, 1);
t.is(error.errors[0].message, 'Unicorn failed');
}
});

Expand Down Expand Up @@ -167,14 +167,67 @@ test('set `exitOnError` to false in root', async t => {

try {
await list.run();
} catch (err) {
t.is(err.name, 'ListrError');
t.is(err.errors.length, 2);
t.is(err.errors[0].message, 'Foo failed');
t.is(err.errors[1].message, 'Unicorn failed');
} catch (error) {
t.is(error.name, 'ListrError');
t.is(error.errors.length, 2);
t.is(error.errors[0].message, 'Foo failed');
t.is(error.errors[1].message, 'Unicorn failed');
}
});

test('set `exitOnError` to false in root, set `failParentTaskOnErrors` to false in child task and do not raise ListError', async t => {
t.plan(13);

const list = new Listr([
{
title: 'foo',
task: () => Promise.reject(new Error('Foo failed'))
},
{
title: 'bar',
task: () => {
return new Listr([
{
title: 'unicorn',
task: () => Promise.reject(new Error('Unicorn failed'))
},
{
title: 'rainbow',
task: () => Promise.resolve()
}
], {
failParentTaskOnErrors: false
});
}
},
{
title: 'baz',
task: () => Promise.resolve()
}
], {
exitOnError: false,
renderer: SimpleRenderer
});

testOutput(t, [
'foo [started]',
'foo [failed]',
'> Foo failed',
'bar [started]',
'unicorn [started]',
'unicorn [failed]',
'> Unicorn failed',
'rainbow [started]',
'rainbow [completed]',
'bar [completed]',
'baz [started]',
'baz [completed]',
'done'
]);

await list.run();
});

test('set `exitOnError` to false in root and true in child', async t => {
t.plan(16);

Expand Down Expand Up @@ -226,11 +279,11 @@ test('set `exitOnError` to false in root and true in child', async t => {

try {
await list.run();
} catch (err) {
t.is(err.name, 'ListrError');
t.is(err.errors.length, 2);
t.is(err.errors[0].message, 'Foo failed');
t.is(err.errors[1].message, 'Unicorn failed');
} catch (error) {
t.is(error.name, 'ListrError');
t.is(error.errors.length, 2);
t.is(error.errors[0].message, 'Foo failed');
t.is(error.errors[1].message, 'Unicorn failed');
}
});

Expand Down Expand Up @@ -264,10 +317,10 @@ test('exit on error throws error object with context', async t => {

try {
await list.run();
} catch (err) {
t.is(err.name, 'ListrError');
t.is(err.errors.length, 1);
t.is(err.errors[0].message, 'Foo failed');
t.deepEqual(err.context, {foo: 'bar'});
} catch (error) {
t.is(error.name, 'ListrError');
t.is(error.errors.length, 1);
t.is(error.errors[0].message, 'Foo failed');
t.deepEqual(error.context, {foo: 'bar'});
}
});
6 changes: 3 additions & 3 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ test('context is attached to error object', async t => {
try {
await list.run();
t.fail('Should throw error');
} catch (err) {
t.is(err.message, 'foo bar');
t.deepEqual(err.context, {
} catch (error) {
t.is(error.message, 'foo bar');
t.deepEqual(error.context, {
foo: 'bar'
});
}
Expand Down