feat: show skipped requests with parsing errors in report (#6780)

* feat: add support for skipped files in run command and update HTML report template

* refactor: enhance skipped file handling in run command

* fix: improve error display in HTML report for skipped requests

* test: add unit test for HTML report generation of skipped requests with parsing errors

* test: update HTML report generation tests to check for skipped request summaries

* refactor: extract skipped result creation logic into a separate utility function

* refactor: enhance skipped result processing in run command to include additional metadata

* refactor: rename and enhance createSkippedResults function for improved skipped file processing

* refactor: remove unused stripExtension import from run command

* refactor: rename createSkippedResults to createSkippedFileResults for clarity and consistency
This commit is contained in:
Sanjai Kumar
2026-01-13 18:51:27 +05:30
committed by GitHub
parent e6a48a73bf
commit f4162e1ce6
4 changed files with 110 additions and 4 deletions

View File

@@ -17,6 +17,7 @@ const { parseDotEnv, parseEnvironment } = require('@usebruno/filestore');
const constants = require('../constants');
const { findItemInCollection, createCollectionJsonFromPathname, getCallStack, FORMAT_CONFIG } = require('../utils/collection');
const { hasExecutableTestInScript } = require('../utils/request');
const { createSkippedFileResults } = require('../utils/run');
const command = 'run [paths...]';
const desc = 'Run one or more requests/folders';
@@ -661,7 +662,8 @@ const handler = async function (argv) {
...result,
runDuration: process.hrtime(start)[0] + process.hrtime(start)[1] / 1e9,
suitename: pathname.replace('.bru', ''),
name
name,
path: result.test?.filename || path.relative(collectionPath, pathname)
});
if (reporterSkipAllHeaders) {
@@ -734,6 +736,9 @@ const handler = async function (argv) {
}
}
const skippedFileResults = createSkippedFileResults(global.brunoSkippedFiles || [], collectionPath);
results.push(...skippedFileResults);
const summary = printRunSummary(results);
const runCompletionTime = new Date().toISOString();
const totalTime = results.reduce((acc, res) => acc + res.response.responseTime, 0);

View File

@@ -0,0 +1,40 @@
const path = require('path');
const { stripExtension } = require('./filesystem');
const createSkippedFileResults = (skippedFiles, collectionPath) => {
return skippedFiles.map((skippedFile) => {
const relativePath = path.relative(collectionPath, skippedFile.path);
return {
test: {
filename: relativePath
},
request: {
method: null,
url: null,
headers: null,
data: null
},
response: {
status: 'skipped',
statusText: skippedFile.error,
data: null,
responseTime: 0
},
error: skippedFile.error,
status: 'skipped',
skipped: true,
assertionResults: [],
testResults: [],
preRequestTestResults: [],
postResponseTestResults: [],
runDuration: 0,
suitename: stripExtension(relativePath),
name: path.basename(skippedFile.path),
path: relativePath
};
});
};
module.exports = {
createSkippedFileResults
};

View File

@@ -49,4 +49,65 @@ describe('HTML Report Generation', () => {
expect(htmlString).toContain('{{ totalDataReceived }}');
expect(htmlString).toContain('{{ averageResponseTime }}');
});
it('should include skipped requests with parsing errors in the HTML report', async () => {
const mockResults = [
{
iterationIndex: 0,
results: [
{
test: {
filename: 'invalid-request.bru'
},
request: {
method: null,
url: null,
headers: null,
data: null
},
response: {
status: 'skipped',
statusText: 'Unexpected token',
data: null,
responseTime: 0
},
error: 'Unexpected token',
status: 'skipped',
skipped: true,
assertionResults: [],
testResults: [],
preRequestTestResults: [],
postResponseTestResults: [],
name: 'invalid-request.bru',
path: 'invalid-request.bru',
runDuration: 0
}
],
summary: {
totalRequests: 1,
passedRequests: 0,
failedRequests: 0,
errorRequests: 0,
skippedRequests: 1,
totalAssertions: 0,
passedAssertions: 0,
failedAssertions: 0,
totalTests: 0,
passedTests: 0,
failedTests: 0
}
}
];
const htmlString = generateHtmlReport({
runnerResults: mockResults,
version: 'usebruno v1.16.0',
environment: null,
runCompletionTime: '2024-01-15T14:30:45.123Z'
});
expect(htmlString).toContain('Request Skipped');
expect(htmlString).toContain('summarySkippedRequests');
expect(htmlString).toContain('result.response.status === \'skipped\'');
});
});

View File

@@ -310,7 +310,7 @@ export const htmlTemplateString = (resutsJsonString: string) => `<!DOCTYPE html>
:bordered="false"
>
<template #header>
{{result.path}} - {{result.response.status === 'skipped' ? 'Request Skipped' : (totalPassed + '/' + total + ' Passed')}} {{hasError ? " - (request failed)" : "" }}
{{result.path}} - {{result.response.status === 'skipped' ? 'Request Skipped' : (totalPassed + '/' + total + ' Passed')}} {{hasError && result.response.status !== 'skipped' ? " - (request failed)" : "" }}
</template>
</n-alert>
</template>
@@ -365,7 +365,7 @@ export const htmlTemplateString = (resutsJsonString: string) => `<!DOCTYPE html>
</n-card>
</n-gi>
</n-grid>
<n-alert v-if="hasError" title="Error" type="error">
<n-alert v-if="hasError || (result.response.status === 'skipped' && result.error)" title="Error" type="error">
{{result.error}}
</n-alert>
<n-card title="REQUEST HEADERS">
@@ -757,7 +757,7 @@ export const htmlTemplateString = (resutsJsonString: string) => `<!DOCTYPE html>
return (props?.result?.testResults?.length || 0) + (props?.result?.assertionResults?.length || 0);
});
const hasError = computed(() => !!props?.result?.error || props?.result?.status === 'error');
const hasError = computed(() => !!props?.result?.error || props?.result?.status === 'error' || (props?.result?.response?.status === 'skipped' && props?.result?.error));
const hasFailure = computed(() => total.value !== totalPassed.value);
const testDuration = computed(() => Math.round(props?.result?.runDuration * 1000) + ' ms');
const resultTitle = computed(() => props?.result?.path + ' ' + props?.result?.response?.status + ' ' + props?.result?.response?.statusText);