From 88bd60311572503f1d9f27ff3df57ac6fcfd5cc5 Mon Sep 17 00:00:00 2001 From: Andrew Goodman Date: Mon, 8 Aug 2022 14:02:03 +0100 Subject: [PATCH 1/2] Improve processor error handling It's useful to provide context to the error i.e. which file failed processing. The failure could also occur in reading or writing - without this error handling it's difficult to know which file has the issue. --- src/processor.ts | 24 ++++++++++++++---------- test/proccessor.test.ts | 10 +++++----- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/processor.ts b/src/processor.ts index a90c301..85ccd6a 100644 --- a/src/processor.ts +++ b/src/processor.ts @@ -63,21 +63,25 @@ export async function processor(baseDirOrOptions: string | ProcessorOptions, pat file.disableParser(); } - const data = await file.read(); - const filename = file.getFile().replace(options.baseDir + path.sep, ''); - const processorResponse = await options.processorFunction(data.data, filename); + try { + const data = await file.read(); - if (data.type === DataType.String && processorResponse === undefined) { - throw new Error('When working with data as a string - the processor function must return data (or null)'); - } + const processorResponse = await options.processorFunction(data.data, filename); - if (processorResponse !== undefined) { - data.data = processorResponse; - } + if (data.type === DataType.String && processorResponse === undefined) { + throw new Error('When working with data as a string - the processor function must return data (or null)'); + } - await file.write(); + if (processorResponse !== undefined) { + data.data = processorResponse; + } + + await file.write(); + } catch (fileEx) { + throw new Error('Failed to process: ' + filename + '. Error: ' + (fileEx.message || fileEx)); + } updatedFiles.push(filename); } diff --git a/test/proccessor.test.ts b/test/proccessor.test.ts index 12a6526..933057d 100644 --- a/test/proccessor.test.ts +++ b/test/proccessor.test.ts @@ -493,7 +493,7 @@ describe('processor', () => { const mockProcessor = jest.fn((data: any, filename: string) => { data.replace('value', 'not-returned') }); return expect(processor(folderPath, '**/*.txt', mockProcessor, ProcessorDataFormat.String)) - .rejects.toEqual('Metadata processor failed: When working with data as a string - the processor function must return data (or null)'); + .rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: When working with data as a string - the processor function must return data (or null)'); }); it('string processor function returns null which is ok and will legitimately empty a file', async () => { @@ -523,7 +523,7 @@ describe('processor', () => { // tslint:disable-next-line:no-string-throw throw "THROW"; }, ProcessorDataFormat.String) - ).rejects.toEqual('Metadata processor failed: THROW'); + ).rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: THROW'); }); it('processing function throws an error (object) - error is caught and processor rejects', () => { @@ -534,7 +534,7 @@ describe('processor', () => { processor(folderPath, '**/*.txt', (data: any, filename: string) => { throw new Error("THROW"); }, ProcessorDataFormat.String) - ).rejects.toEqual('Metadata processor failed: THROW'); + ).rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: THROW'); }); it('processing async function rejects (string) - error is caught and processor rejects', () => { @@ -543,7 +543,7 @@ describe('processor', () => { return expect( processor(folderPath, '**/*.txt', async (data: any, filename: string) => Promise.reject('REJECT'), ProcessorDataFormat.String) - ).rejects.toEqual('Metadata processor failed: REJECT'); + ).rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: REJECT'); }); it('processing async function rejects (object) - error is caught and processor rejects', () => { @@ -552,6 +552,6 @@ describe('processor', () => { return expect( processor(folderPath, '**/*.txt', async (data: any, filename: string) => Promise.reject(new Error('REJECT')), ProcessorDataFormat.String) - ).rejects.toEqual('Metadata processor failed: REJECT'); + ).rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: REJECT'); }); }); \ No newline at end of file From 822d412aff6b5b62e3b7bcfcbcf5df19a9e5d57d Mon Sep 17 00:00:00 2001 From: Andrew Goodman Date: Mon, 8 Aug 2022 15:00:36 +0100 Subject: [PATCH 2/2] Fix error handling tests on Windows --- test/proccessor.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/proccessor.test.ts b/test/proccessor.test.ts index 933057d..93559f3 100644 --- a/test/proccessor.test.ts +++ b/test/proccessor.test.ts @@ -493,7 +493,7 @@ describe('processor', () => { const mockProcessor = jest.fn((data: any, filename: string) => { data.replace('value', 'not-returned') }); return expect(processor(folderPath, '**/*.txt', mockProcessor, ProcessorDataFormat.String)) - .rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: When working with data as a string - the processor function must return data (or null)'); + .rejects.toEqual('Metadata processor failed: Failed to process: ' + path.join('folder1', 'foldera', 'text-file.txt') + '. Error: When working with data as a string - the processor function must return data (or null)'); }); it('string processor function returns null which is ok and will legitimately empty a file', async () => { @@ -523,7 +523,7 @@ describe('processor', () => { // tslint:disable-next-line:no-string-throw throw "THROW"; }, ProcessorDataFormat.String) - ).rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: THROW'); + ).rejects.toEqual('Metadata processor failed: Failed to process: ' + path.join('folder1', 'foldera', 'text-file.txt') + '. Error: THROW'); }); it('processing function throws an error (object) - error is caught and processor rejects', () => { @@ -534,7 +534,7 @@ describe('processor', () => { processor(folderPath, '**/*.txt', (data: any, filename: string) => { throw new Error("THROW"); }, ProcessorDataFormat.String) - ).rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: THROW'); + ).rejects.toEqual('Metadata processor failed: Failed to process: ' + path.join('folder1', 'foldera', 'text-file.txt') + '. Error: THROW'); }); it('processing async function rejects (string) - error is caught and processor rejects', () => { @@ -543,7 +543,7 @@ describe('processor', () => { return expect( processor(folderPath, '**/*.txt', async (data: any, filename: string) => Promise.reject('REJECT'), ProcessorDataFormat.String) - ).rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: REJECT'); + ).rejects.toEqual('Metadata processor failed: Failed to process: ' + path.join('folder1', 'foldera', 'text-file.txt') + '. Error: REJECT'); }); it('processing async function rejects (object) - error is caught and processor rejects', () => { @@ -552,6 +552,6 @@ describe('processor', () => { return expect( processor(folderPath, '**/*.txt', async (data: any, filename: string) => Promise.reject(new Error('REJECT')), ProcessorDataFormat.String) - ).rejects.toEqual('Metadata processor failed: Failed to process: folder1/foldera/text-file.txt. Error: REJECT'); + ).rejects.toEqual('Metadata processor failed: Failed to process: ' + path.join('folder1', 'foldera', 'text-file.txt') + '. Error: REJECT'); }); }); \ No newline at end of file