fix(cli): make sure errors passed to the storage are serialized correctly

This commit is contained in:
Joakim Carlstein 2024-01-26 11:25:34 +01:00 committed by Joakim Carlstein
parent f1b9098750
commit f2d4bb346e
3 changed files with 138 additions and 54 deletions

View file

@ -0,0 +1,5 @@
---
'@emigrate/cli': patch
---
Set Emigrate error instance names from their respective constructor's name for consistency and correct error deserialization.

View file

@ -8,7 +8,7 @@ import {
type SerializedError,
type MigrationMetadataFinished,
} from '@emigrate/types';
import { deserializeError, serializeError } from 'serialize-error';
import { deserializeError } from 'serialize-error';
import { version } from '../get-package-info.js';
import {
BadOptionError,
@ -17,6 +17,7 @@ import {
MigrationHistoryError,
MigrationRunError,
StorageInitError,
toSerializedError,
} from '../errors.js';
import { toEntries, toEntry, toMigrations } from '../test-utils.js';
import upCommand from './up.js';
@ -37,39 +38,43 @@ describe('up', () => {
});
it('returns 0 and finishes without an error when there are no migrations to run', async () => {
const { reporter, run } = getUpCommand([], getStorage([]));
const storage = getStorage([]);
const { reporter, run } = getUpCommand([], storage);
const exitCode = await run();
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, []);
assertPreconditionsFulfilled({ dry: false }, reporter, storage, []);
});
it('returns 0 and finishes without an error when all migrations have already been run', async () => {
const { reporter, run } = getUpCommand(['my_migration.js'], getStorage(['my_migration.js']));
const storage = getStorage(['my_migration.js']);
const { reporter, run } = getUpCommand(['my_migration.js'], storage);
const exitCode = await run();
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, []);
assertPreconditionsFulfilled({ dry: false }, reporter, storage, []);
});
it('returns 0 and finishes without an error when all migrations have already been run even when the history responds without file extensions', async () => {
const { reporter, run } = getUpCommand(['my_migration.js'], getStorage(['my_migration']));
const storage = getStorage(['my_migration']);
const { reporter, run } = getUpCommand(['my_migration.js'], storage);
const exitCode = await run();
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, []);
assertPreconditionsFulfilled({ dry: false }, reporter, storage, []);
});
it('returns 0 and finishes without an error when all pending migrations are run successfully', async () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['some_already_run_migration.js', 'some_migration.js', 'some_other_migration.js'],
getStorage(['some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -83,7 +88,7 @@ describe('up', () => {
const exitCode = await run();
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: 'some_migration.js', status: 'done', started: true },
{ name: 'some_other_migration.js', status: 'done', started: true },
]);
@ -91,9 +96,10 @@ describe('up', () => {
});
it('returns 1 and finishes with an error when a pending migration throw when run', async () => {
const storage = getStorage(['some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['some_already_run_migration.js', 'some_migration.js', 'fail.js', 'some_other_migration.js'],
getStorage(['some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -114,6 +120,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: false },
reporter,
storage,
[
{ name: 'some_migration.js', status: 'done', started: true },
{ name: 'fail.js', status: 'failed', started: true, error: new Error('Oh noes!') },
@ -125,7 +132,8 @@ describe('up', () => {
describe('each migration file extension needs a corresponding loader plugin', () => {
it('returns 1 and finishes with an error when there are migration file extensions without a corresponding loader plugin', async () => {
const { reporter, run } = getUpCommand(['some_other.js', 'some_file.sql'], getStorage([]));
const storage = getStorage([]);
const { reporter, run } = getUpCommand(['some_other.js', 'some_file.sql'], storage);
const exitCode = await run();
@ -133,6 +141,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: false },
reporter,
storage,
[
{ name: 'some_other.js', status: 'skipped' },
{
@ -146,7 +155,8 @@ describe('up', () => {
});
it('returns 1 and finishes with an error when there are migration file extensions without a corresponding loader plugin in dry-run mode as well', async () => {
const { reporter, run } = getUpCommand(['some_other.js', 'some_file.sql'], getStorage([]));
const storage = getStorage([]);
const { reporter, run } = getUpCommand(['some_other.js', 'some_file.sql'], storage);
const exitCode = await run({ dry: true });
@ -154,6 +164,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: true },
reporter,
storage,
[
{ name: 'some_other.js', status: 'skipped' },
{
@ -170,7 +181,8 @@ describe('up', () => {
describe('failed migrations in the history are blocking', () => {
it('returns 1 and finishes with an error when there are failed migrations in the history', async () => {
const failedEntry = toEntry('some_failed_migration.js', 'failed');
const { reporter, run } = getUpCommand([failedEntry.name, 'some_file.js'], getStorage([failedEntry]));
const storage = getStorage([failedEntry]);
const { reporter, run } = getUpCommand([failedEntry.name, 'some_file.js'], storage);
const exitCode = await run();
@ -178,6 +190,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: false },
reporter,
storage,
[
{
name: 'some_failed_migration.js',
@ -198,7 +211,8 @@ describe('up', () => {
it('returns 1 and finishes with an error when there are failed migrations in the history in dry-run mode as well', async () => {
const failedEntry = toEntry('some_failed_migration.js', 'failed');
const { reporter, run } = getUpCommand([failedEntry.name, 'some_file.js'], getStorage([failedEntry]));
const storage = getStorage([failedEntry]);
const { reporter, run } = getUpCommand([failedEntry.name, 'some_file.js'], storage);
const exitCode = await run({ dry: true });
@ -206,6 +220,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: true },
reporter,
storage,
[
{
name: 'some_failed_migration.js',
@ -226,12 +241,13 @@ describe('up', () => {
it('returns 0 and finishes without an error when the failed migrations in the history are not part of the current set of migrations', async () => {
const failedEntry = toEntry('some_failed_migration.js', 'failed');
const { reporter, run } = getUpCommand([], getStorage([failedEntry]));
const storage = getStorage([failedEntry]);
const { reporter, run } = getUpCommand([], storage);
const exitCode = await run();
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, []);
assertPreconditionsFulfilled({ dry: false }, reporter, storage, []);
});
});
@ -239,9 +255,10 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['some_already_run_migration.js', 'some_migration.js', 'some_other_migration.js'],
getStorage(['some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -255,7 +272,7 @@ describe('up', () => {
const exitCode = await run({ limit: 1 });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: 'some_migration.js', status: 'done', started: true },
{ name: 'some_other_migration.js', status: 'skipped' },
]);
@ -264,15 +281,16 @@ describe('up', () => {
describe('limiting which pending migrations to run', () => {
it('returns 0 and finishes without an error with the given number of pending migrations are validated and listed successfully in dry-mode', async () => {
const storage = getStorage(['some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['some_already_run_migration.js', 'some_migration.js', 'some_other_migration.js'],
getStorage(['some_already_run_migration.js']),
storage,
);
const exitCode = await run({ dry: true, limit: 1 });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: true }, reporter, [
assertPreconditionsFulfilled({ dry: true }, reporter, storage, [
{ name: 'some_migration.js', status: 'pending' },
{ name: 'some_other_migration.js', status: 'skipped' },
]);
@ -282,6 +300,7 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -289,7 +308,7 @@ describe('up', () => {
'3_existing_migration.js',
'4_some_other_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -303,7 +322,7 @@ describe('up', () => {
const exitCode = await run({ from: '3_existing_migration.js' });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '3_existing_migration.js', status: 'done', started: true },
{ name: '4_some_other_migration.js', status: 'done', started: true },
@ -315,6 +334,7 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -322,7 +342,7 @@ describe('up', () => {
'3_existing_migration.js',
'4_some_other_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -336,7 +356,7 @@ describe('up', () => {
const exitCode = await run({ from: 'migrations/3_existing_migration.js' });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '3_existing_migration.js', status: 'done', started: true },
{ name: '4_some_other_migration.js', status: 'done', started: true },
@ -348,9 +368,10 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['1_some_already_run_migration.js', '2_some_migration.js', '4_some_other_migration.js'],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -364,7 +385,7 @@ describe('up', () => {
const exitCode = await run({ from: '1_some_already_run_migration.js' });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: '2_some_migration.js', status: 'done', started: true },
{ name: '4_some_other_migration.js', status: 'done', started: true },
]);
@ -375,9 +396,10 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['1_some_already_run_migration.js', '2_some_migration.js', '4_some_other_migration.js'],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -394,6 +416,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: false },
reporter,
storage,
[
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '4_some_other_migration.js', status: 'skipped' },
@ -407,15 +430,16 @@ describe('up', () => {
});
it('returns 0 and finishes without an error when pending migrations after given "from" parameter are validated and listed successfully in dry-mode', async () => {
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['1_some_already_run_migration.js', '2_some_migration.js', '3_some_other_migration.js'],
getStorage(['1_some_already_run_migration.js']),
storage,
);
const exitCode = await run({ dry: true, from: '3_some_other_migration.js' });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: true }, reporter, [
assertPreconditionsFulfilled({ dry: true }, reporter, storage, [
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '3_some_other_migration.js', status: 'pending' },
]);
@ -425,6 +449,7 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -432,7 +457,7 @@ describe('up', () => {
'3_existing_migration.js',
'4_some_other_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -446,7 +471,7 @@ describe('up', () => {
const exitCode = await run({ to: '3_existing_migration.js' });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: '2_some_migration.js', status: 'done', started: true },
{ name: '3_existing_migration.js', status: 'done', started: true },
{ name: '4_some_other_migration.js', status: 'skipped' },
@ -458,9 +483,10 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['1_some_already_run_migration.js', '2_some_migration.js', '4_some_other_migration.js'],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -477,6 +503,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: false },
reporter,
storage,
[
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '4_some_other_migration.js', status: 'skipped' },
@ -490,9 +517,10 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
['1_some_already_run_migration.js', '2_some_migration.js', '4_some_other_migration.js'],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -506,7 +534,7 @@ describe('up', () => {
const exitCode = await run({ to: '1_some_already_run_migration.js' });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '4_some_other_migration.js', status: 'skipped' },
]);
@ -514,6 +542,7 @@ describe('up', () => {
});
it('returns 0 and finishes without an error when pending migrations after given "to" parameter are validated and listed successfully in dry-mode', async () => {
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -521,13 +550,13 @@ describe('up', () => {
'3_existing_migration.js',
'4_some_other_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
);
const exitCode = await run({ dry: true, to: '3_existing_migration.js' });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: true }, reporter, [
assertPreconditionsFulfilled({ dry: true }, reporter, storage, [
{ name: '2_some_migration.js', status: 'pending' },
{ name: '3_existing_migration.js', status: 'pending' },
{ name: '4_some_other_migration.js', status: 'skipped' },
@ -538,6 +567,7 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -547,7 +577,7 @@ describe('up', () => {
'5_yet_another_migration.js',
'6_some_more_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -561,7 +591,7 @@ describe('up', () => {
const exitCode = await run({ from: '3_another_migration.js', to: '5_yet_another_migration.js', limit: 2 });
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '3_another_migration.js', status: 'done', started: true },
{ name: '4_some_other_migration.js', status: 'done', started: true },
@ -577,6 +607,7 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -586,7 +617,7 @@ describe('up', () => {
'5_yet_another_migration.js',
'6_some_more_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -605,7 +636,7 @@ describe('up', () => {
});
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '3_another_migration.js', status: 'done', started: true },
{ name: '4_some_other_migration.js', status: 'done', started: true },
@ -620,6 +651,7 @@ describe('up', () => {
const migration = mock.fn(async () => {
// Success
});
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -629,7 +661,7 @@ describe('up', () => {
'5_yet_another_migration.js',
'6_some_more_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -648,7 +680,7 @@ describe('up', () => {
});
assert.strictEqual(exitCode, 0, 'Exit code');
assertPreconditionsFulfilled({ dry: false }, reporter, [
assertPreconditionsFulfilled({ dry: false }, reporter, storage, [
{ name: '2_some_migration.js', status: 'skipped' },
{ name: '3_another_migration.js', status: 'done', started: true },
{ name: '4_some_other_migration.sql', status: 'done', started: true },
@ -671,6 +703,7 @@ describe('up', () => {
},
{ times: 1 },
);
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -680,7 +713,7 @@ describe('up', () => {
'5_yet_another_migration.js',
'6_some_more_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -699,6 +732,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: false },
reporter,
storage,
[
{ name: '2_some_migration.js', status: 'done', started: true },
{ name: '3_another_migration.js', status: 'done', started: true },
@ -728,6 +762,7 @@ describe('up', () => {
},
{ times: 1 },
);
const storage = getStorage(['1_some_already_run_migration.js']);
const { reporter, run } = getUpCommand(
[
'1_some_already_run_migration.js',
@ -737,7 +772,7 @@ describe('up', () => {
'5_yet_another_migration.js',
'6_some_more_migration.js',
],
getStorage(['1_some_already_run_migration.js']),
storage,
[
{
loadableExtensions: ['.js'],
@ -757,6 +792,7 @@ describe('up', () => {
assertPreconditionsFulfilled(
{ dry: false },
reporter,
storage,
[
{ name: '2_some_migration.js', status: 'done', started: true },
{
@ -864,6 +900,7 @@ function getUpCommand(migrationFiles: string[], storage?: Mocked<Storage>, plugi
function assertPreconditionsFulfilled(
options: { dry: boolean },
reporter: Mocked<Required<EmigrateReporter>>,
storage: Mocked<Storage>,
expected: Array<{ name: string; status: MigrationMetadataFinished['status']; started?: boolean; error?: Error }>,
finishedError?: Error,
) {
@ -884,7 +921,9 @@ function assertPreconditionsFulfilled(
let failed = 0;
let skipped = 0;
let pending = 0;
let failedAndStarted = 0;
const failedEntries: typeof expected = [];
const successfulEntries: typeof expected = [];
for (const entry of expected) {
if (entry.started) {
@ -895,12 +934,22 @@ function assertPreconditionsFulfilled(
switch (entry.status) {
case 'done': {
done++;
if (entry.started) {
successfulEntries.push(entry);
}
break;
}
case 'failed': {
failed++;
failedEntries.push(entry);
if (entry.started) {
failedAndStarted++;
}
break;
}
@ -922,28 +971,29 @@ function assertPreconditionsFulfilled(
assert.strictEqual(reporter.onMigrationSuccess.mock.calls.length, done, 'Successful migrations');
assert.strictEqual(reporter.onMigrationError.mock.calls.length, failed, 'Failed migrations');
assert.strictEqual(storage.onSuccess.mock.calls.length, successfulEntries.length, 'Storage onSuccess calls');
assert.strictEqual(storage.onError.mock.calls.length, failedAndStarted, 'Storage onError calls');
for (const [index, entry] of failedEntries.entries()) {
if (entry.status === 'failed') {
const error = reporter.onMigrationError.mock.calls[index]?.arguments[1];
assert.deepStrictEqual(error, entry.error, 'Error');
const cause = entry.error?.cause;
assert.deepStrictEqual(error?.cause, cause ? deserializeError(cause) : cause, 'Error cause');
if (entry.started) {
const [finishedMigration, error] = storage.onError.mock.calls[index]?.arguments ?? [];
assert.strictEqual(finishedMigration?.name, entry.name);
assert.strictEqual(finishedMigration?.status, entry.status);
assertErrorEqualEnough(error, entry.error);
}
}
}
assert.strictEqual(reporter.onMigrationSkip.mock.calls.length, pending + skipped, 'Total pending and skipped');
assert.strictEqual(reporter.onFinished.mock.calls.length, 1, 'Finished called once');
const [entries, error] = reporter.onFinished.mock.calls[0]?.arguments ?? [];
if (finishedError instanceof DOMException || error instanceof DOMException) {
// The assert library doesn't support DOMException apparently, so ugly workaround here:
assert.deepStrictEqual(
deserializeError(serializeError(error)),
deserializeError(serializeError(finishedError)),
'Finished error',
);
} else {
assert.deepStrictEqual(error, finishedError, 'Finished error');
}
assertErrorEqualEnough(error, finishedError);
const cause = getErrorCause(error);
const expectedCause = finishedError?.cause;
@ -958,6 +1008,14 @@ function assertPreconditionsFulfilled(
expected.map((entry) => `${entry.name} (${entry.status})`),
'Finished entries',
);
for (const [index, entry] of successfulEntries.entries()) {
const [finishedMigration] = storage.onSuccess.mock.calls[index]?.arguments ?? [];
assert.strictEqual(finishedMigration?.name, entry.name);
assert.strictEqual(finishedMigration?.status, entry.status);
}
assert.strictEqual(storage.end.mock.calls.length, 1, 'Storage end should always be called');
}
function assertPreconditionsFailed(
@ -994,3 +1052,23 @@ function assertPreconditionsFailed(
);
assert.strictEqual(entries?.length, 0, 'Finished entries length');
}
function assertErrorEqualEnough(actual?: Error | SerializedError, expected?: Error) {
if (expected === undefined) {
assert.strictEqual(actual, undefined);
return;
}
const {
cause: actualCause,
stack: actualStack,
...actualError
} = actual instanceof Error ? toSerializedError(actual) : actual ?? {};
const { cause: expectedCause, stack: expectedStack, ...expectedError } = toSerializedError(expected);
// @ts-expect-error Ignore
const { stack: actualCauseStack, ...actualCauseRest } = actualCause ?? {};
// @ts-expect-error Ignore
const { stack: expectedCauseStack, ...expectedCauseRest } = expectedCause ?? {};
assert.deepStrictEqual(actualError, expectedError);
assert.deepStrictEqual(actualCauseRest, expectedCauseRest);
}

View file

@ -23,6 +23,7 @@ export class EmigrateError extends Error {
public code?: string,
) {
super(message, options);
this.name = this.constructor.name;
}
}