Skip to content
28 changes: 24 additions & 4 deletions console/atest-ui/src/views/TestCase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,17 @@ const parseResponseBody = (body: any) => {
}
}

const handleTestResult = (e: any) => {
/**
* Handles test result data from API response
*
* Processes the test response with proper error handling and content type detection:
* - For JSON responses: Parses and makes it available for filtering/display
* - For plain text responses: Displays as raw text without JSON parsing
* - For file responses: Handles as downloadable content
*
* @param e The test result data from API
*/
const handleTestResult = (e: any): void => {
testResult.value = e;

if (!isHistoryTestCase.value) {
Expand All @@ -124,9 +134,19 @@ const handleTestResult = (e: any) => {
isResponseFile.value = true
} else if(e.body !== ''){
testResult.value.bodyLength = e.body.length
testResult.value.bodyObject = JSON.parse(e.body);
testResult.value.originBodyObject = JSON.parse(e.body);
responseBodyFilter()
try {
// Try to parse as JSON, fallback to plain text if parsing fails
testResult.value.bodyObject = JSON.parse(e.body);
testResult.value.originBodyObject = JSON.parse(e.body);
responseBodyFilter()
} catch (error) {
// This is an expected case for non-JSON responses (like text/plain)
// We intentionally display as plain text instead of attempting JSON parsing
console.debug("Response body is not valid JSON, displaying as plain text:", error);
testResult.value.bodyText = e.body;
testResult.value.bodyObject = null;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type 'null' is not assignable to type '{}'.ts-plugin(2322)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can check the content type, then handle JSON or not.

image

testResult.value.originBodyObject = null;
}
}

Cache.SetTestCaseResponseCache(suite + '-' + name, {
Expand Down
80 changes: 73 additions & 7 deletions console/atest-ui/src/views/net.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,78 @@ limitations under the License.
*/
import { Cache } from './cache'

async function DefaultResponseProcess(response: any) {
/**
* Process HTTP response with proper content type handling
*
* This function handles both JSON and non-JSON responses:
* 1. For JSON responses, parses and returns the JSON object
* 2. For non-JSON responses (like text/plain), returns the raw text
*
* @param response The fetch API response object
* @returns Parsed JSON object or raw text content
*/
async function DefaultResponseProcess(response: any): Promise<any> {
if (!response.ok) {
switch (response.status) {
case 401:
throw new Error("Unauthenticated")
throw new Error("Unauthenticated");
// Potentially add other specific status code handling here
}

const message = await response.json().then((data: any) => data.message)
throw new Error(message)
} else {
return response.json()
// For non-OK responses, attempt to parse error details from the body
let errorMessage = `Request failed with status ${response.status}`;
const clonedResponseForErrorJson = response.clone();
try {
const errorData = await clonedResponseForErrorJson.json();
errorMessage = errorData?.message || JSON.stringify(errorData);
} catch (jsonError: any) {
console.debug(
`Error response body (status ${response.status}) was not valid JSON. Attempting to read as text. JSON parse error:`,
jsonError
);
// Body consumed by failed .json() attempt on clone, try .text() on a new clone of original response
const clonedResponseForErrorText = response.clone();
try {
const textData = await clonedResponseForErrorText.text();
if (textData) {
errorMessage = textData;
} else {
errorMessage = `Request failed with status ${response.status} (empty error body).`;
}
} catch (textError: any) {
console.debug(
`Error response body (status ${response.status}) also failed to be read as text. Text parse error:`,
textError
);
// Fallback error message if body is entirely unreadable
errorMessage = `Request failed with status ${response.status} and error body was unreadable.`;
}
}
throw new Error(errorMessage);
}

// For OK responses, handle content based on Content-Type
const contentType = response.headers.get('Content-Type') ?? '';
if (contentType.startsWith('text/plain')) {
// For text/plain, directly return the text
return await response.text();
}

// For all other types (or if Content-Type is missing/unexpected), try parsing as JSON first
try {
return await response.json();
} catch (jsonParseError: any) {
// This catch block is an intentional part of the content negotiation.
// If the response, despite its Content-Type (or lack thereof), isn't valid JSON,
// we fall back to treating it as plain text. The original error is logged for debugging.
console.debug(
`Response body was not valid JSON (Content-Type: '${contentType}'). Falling back to plain text. JSON parse error:`,
jsonParseError
);
// The body stream was already consumed by the failed response.json() attempt.
// A clone of the original response is needed to read the body as text.
const clonedResponseForTextFallback = response.clone();
return await clonedResponseForTextFallback.text();
}
}

Expand Down Expand Up @@ -754,7 +815,12 @@ function GetTestCaseAllHistory(req: TestCase,
.then(callback).catch(errHandle)
}

function DownloadResponseFile(testcase,
interface ResponseFile {
body: string;
[key: string]: any;
}

function DownloadResponseFile(testcase: ResponseFile,
callback: (d: any) => void, errHandle?: (e: any) => void | null) {
const requestOptions = {
method: 'POST',
Expand Down
Loading