diff --git a/src/lib/snyk-test/common.ts b/src/lib/snyk-test/common.ts index 50c239c8b0..67db2866f7 100644 --- a/src/lib/snyk-test/common.ts +++ b/src/lib/snyk-test/common.ts @@ -204,7 +204,10 @@ export async function printDepGraphError( return new Promise((res, rej) => { // Normalize the target file path to be relative to root, consistent with printDepGraphJsonl const normalisedTargetFile = failedProjectScanError.targetFile - ? path.relative(root, failedProjectScanError.targetFile) + ? path.relative( + root, + path.resolve(root, failedProjectScanError.targetFile), + ) : failedProjectScanError.targetFile; const problemError = getOrCreateErrorCatalogError(failedProjectScanError); diff --git a/test/jest/unit/lib/snyk-test/common.spec.ts b/test/jest/unit/lib/snyk-test/common.spec.ts index 07a1d6ad75..de9ebedcd4 100644 --- a/test/jest/unit/lib/snyk-test/common.spec.ts +++ b/test/jest/unit/lib/snyk-test/common.spec.ts @@ -1,9 +1,11 @@ +import { PassThrough } from 'stream'; import { CLI, ProblemError } from '@snyk/error-catalog-nodejs-public'; import { CustomError } from '../../../../../src/lib/errors'; import { FailedProjectScanError } from '../../../../../src/lib/plugins/get-multi-plugin-result'; import { getOrCreateErrorCatalogError, getRequestConcurrency, + printDepGraphError, } from '../../../../../src/lib/snyk-test/common'; describe('getOrCreateErrorCatalogError', () => { @@ -120,6 +122,66 @@ describe('getOrCreateErrorCatalogError', () => { }); }); +describe('printDepGraphError', () => { + function collectStream(stream: PassThrough): Promise { + return new Promise((resolve) => { + const chunks: Buffer[] = []; + stream.on('data', (chunk) => chunks.push(Buffer.from(chunk))); + stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8'))); + }); + } + + it('normalises a relative targetFile to stay relative to root', async () => { + const root = '/project'; + const failedProjectScanError: FailedProjectScanError = { + errMessage: 'scan failed', + error: undefined, + targetFile: 'subdir/package.json', + }; + const output = new PassThrough(); + const collected = collectStream(output); + + await printDepGraphError(root, failedProjectScanError, output); + output.end(); + + const result = JSON.parse(await collected); + expect(result.normalisedTargetFile).toBe('subdir/package.json'); + }); + + it('normalises an absolute targetFile to be relative to root', async () => { + const root = '/project'; + const failedProjectScanError: FailedProjectScanError = { + errMessage: 'scan failed', + error: undefined, + targetFile: '/project/subdir/package.json', + }; + const output = new PassThrough(); + const collected = collectStream(output); + + await printDepGraphError(root, failedProjectScanError, output); + output.end(); + + const result = JSON.parse(await collected); + expect(result.normalisedTargetFile).toBe('subdir/package.json'); + }); + + it('keeps targetFile undefined when it is not provided', async () => { + const root = '/project'; + const failedProjectScanError: FailedProjectScanError = { + errMessage: 'scan failed', + error: undefined, + }; + const output = new PassThrough(); + const collected = collectStream(output); + + await printDepGraphError(root, failedProjectScanError, output); + output.end(); + + const result = JSON.parse(await collected); + expect(result.normalisedTargetFile).toBeUndefined(); + }); +}); + describe('getRequestConcurrency', () => { const originalValue = process.env.SNYK_INTERNAL_REQUEST_CONCURRENCY;