Skip to content

Commit 72de59a

Browse files
committed
nullable http code and code documentation
1 parent 05ef71a commit 72de59a

File tree

10 files changed

+67
-16
lines changed

10 files changed

+67
-16
lines changed

src/main/resources/wfc/schemas/report.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ $defs:
9999
uniqueItems: true
100100
required: ["endpointId","testCaseId","httpStatus"]
101101
HttpStatus:
102-
type: integer
102+
type: [integer,"null"]
103103
minimum: 0
104104
maximum: 599
105105
FoundFault:

web-report/src/AppProvider.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,29 @@ export const AppProvider = ({ children }: AppProviderProps) => {
4444
setInvalidReportErrors(report.error.issues);
4545
return;
4646
}
47-
setData(jsonData);
47+
48+
const result = jsonData?.problemDetails?.rest?.coveredHttpStatus?.map(status => {
49+
const httpStatus = status?.httpStatus ?? [null];
50+
const httpStatusArray = Array.isArray(httpStatus) ? httpStatus : [httpStatus];
51+
const updatedHttpStatus = httpStatusArray.map(code => code === null ? -1 : code);
52+
return {
53+
...status,
54+
httpStatus: updatedHttpStatus
55+
};
56+
}) ?? [];
57+
58+
const updatedJsonData = {
59+
...jsonData,
60+
problemDetails: {
61+
...jsonData.problemDetails,
62+
rest: {
63+
...jsonData.problemDetails.rest,
64+
coveredHttpStatus: result
65+
}
66+
}
67+
} as WebFuzzingCommonsReport;
68+
69+
setData(updatedJsonData);
4870
} catch (error: Error | unknown) {
4971
if (error instanceof Error) {
5072
setError("Could not load the report file. Please check if the file exists and is accessible in main folder.");

web-report/src/components/EndpointAccordion.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const EndpointAccordion: React.FC<IEndpointAccordionProps> = ({
6666
<div className="flex flex-wrap justify-end gap-2 mr-4">
6767
{sortedStatusCodes.map((code, idx) => (
6868
<Badge key={`_${idx}`} className={`${getColor(code.code, true, false)} font-mono`}>
69-
H{code.code}
69+
{code.code == -1 ? "NO-RESPONSE" : `H${code.code}`}
7070
</Badge>
7171
))}
7272
{sortedFaults.map((code, idx) => (
@@ -87,7 +87,7 @@ export const EndpointAccordion: React.FC<IEndpointAccordionProps> = ({
8787
setIsFault(false);
8888
}}
8989
className={`${getColor(code.code, true, false)} ${getSelectedStyle(code.code, false)} hover:bg-green-600 cursor-pointer text-white font-mono text-base border-2 border-black shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]`}>
90-
{code.code}
90+
{code.code == -1 ? "NO-RESPONSE" : `H${code.code}`}
9191
</Badge>
9292
))
9393
}

web-report/src/components/StatusCodeFilterButton.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function StatusCodeFilterButton({ code, initialState = "inactive", onChan
1717
if(isFault) {
1818
return "bg-red-500"
1919
}
20-
20+
if (code == -1) return "bg-gray-500"
2121
if (code >= 200 && code < 300) return "bg-green-500"
2222
if (code >= 300 && code < 400) return "bg-blue-500"
2323
if (code >= 400 && code < 500) return "bg-orange-500"
@@ -49,7 +49,7 @@ export function StatusCodeFilterButton({ code, initialState = "inactive", onChan
4949

5050
return (
5151
<Badge className={getStyles()} onClick={toggleState}>
52-
{isFault ? `F${-1 * code}`: `H${code}`}
52+
{isFault ? `F${-1 * code}`: code == -1 ? `NO-RESPONSE`:`H${code}`}
5353
</Badge>
5454
)
5555
}

web-report/src/components/StatusCodeFilters.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {useState} from "react"
22
import {StatusCodeFilterButton} from "./StatusCodeFilterButton"
33
import {ITransformedReport} from "@/lib/utils.tsx";
4+
import {StatusCodeModal} from "@/components/StatusCodeModal.tsx";
45

56
type FilterState = "inactive" | "active" | "removed"
67

@@ -38,6 +39,9 @@ export function StatusCodeFilters({data, onFiltersChange}: StatusCodeFiltersProp
3839
onFiltersChange(newFilters)
3940
}
4041

42+
const [isModalOpen, setIsModalOpen] = useState(false)
43+
44+
4145
return (
4246
<div className="mb-6">
4347
<div className="items-center mb-2">
@@ -68,7 +72,11 @@ export function StatusCodeFilters({data, onFiltersChange}: StatusCodeFiltersProp
6872
</div>
6973
</div>
7074
<div className="text-xs text-gray-500 mt-1">Click to toggle: Default → Active → Removed → Default</div>
75+
<div className="items-center mb-2 flex justify-end">
76+
<div className="text-sm font-mono text-red-500 mt-1 cursor-help hover:text-green-300" onClick={() => setIsModalOpen(true)}>Code Documentation</div>
77+
</div>
7178
<div className="border-t border-black my-2"></div>
79+
<StatusCodeModal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} statusCode={-1} />
7280
</div>
7381
)
7482
}

web-report/src/components/TestCaseButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function TestCaseButton({ testName, statusCode, onClick, isFault }: TestC
3131
<span className="font-mono text-sm text-left">{testName}</span>
3232
</div>
3333
<div className="flex items-center">
34-
<span className={`font-bold mr-2 ${getColor(statusCode, false, isFault)}`}>{statusCode}</span>
34+
<span className={`font-bold mr-2 ${getColor(statusCode, false, isFault)}`}>{statusCode == -1 ? "NO-RESPONSE" : statusCode}</span>
3535
<ChevronRight
3636
className={`${
3737
isHovered ? "text-blue-600 transform translate-x-1" : "text-gray-400"

web-report/src/lib/utils.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ export function cn(...inputs: ClassValue[]) {
66
return twMerge(clsx(inputs))
77
}
88

9-
export const getColor = (code: string | number, isBackground: boolean, isFault: boolean) => {
9+
export const getColor = (code: string | number | null | undefined, isBackground: boolean, isFault: boolean) => {
1010
if (isFault) {
1111
return isBackground ? "bg-red-500" : "text-red-500";
1212
}
13+
14+
if(code === null || code === undefined || code === "") {
15+
return isBackground ? "bg-gray-500" : "text-gray-500";
16+
}
17+
1318
if (typeof code === "number") {
1419
return getColorNumber(code, isBackground);
1520
}
@@ -69,6 +74,7 @@ export const extractCodeLines = (
6974

7075
export const calculateAllStatusCounts = (coveredHttpStatus: CoveredEndpoint[], endpointIds:string[]) => {
7176
const allStatusCounts ={
77+
"NO_RESPONSE": 0,
7278
"2XX": 0,
7379
"3XX": 0,
7480
"4XX": 0,
@@ -84,6 +90,7 @@ export const calculateAllStatusCounts = (coveredHttpStatus: CoveredEndpoint[], e
8490
const uniqueStatusCodes = [...new Set(allStatusCodes)];
8591

8692
const isContainStatusCode = {
93+
"NO_RESPONSE": false,
8794
"2XX": false,
8895
"3XX": false,
8996
"4XX": false,
@@ -92,7 +99,10 @@ export const calculateAllStatusCounts = (coveredHttpStatus: CoveredEndpoint[], e
9299

93100
uniqueStatusCodes.map(
94101
(status) => {
95-
if (status >= 200 && status < 300) {
102+
if(status == null) {
103+
isContainStatusCode["NO_RESPONSE"] = true;
104+
}
105+
else if (status >= 200 && status < 300) {
96106
isContainStatusCode["2XX"] = true;
97107
} else if (status >= 300 && status < 400) {
98108
isContainStatusCode["3XX"] = true;
@@ -103,7 +113,9 @@ export const calculateAllStatusCounts = (coveredHttpStatus: CoveredEndpoint[], e
103113
}
104114
}
105115
)
106-
116+
if(isContainStatusCode["NO_RESPONSE"]){
117+
allStatusCounts["NO_RESPONSE"]++;
118+
}
107119
if (isContainStatusCode["2XX"]) {
108120
allStatusCounts["2XX"]++;
109121
}
@@ -259,12 +271,15 @@ export const transformWebFuzzingReport = (original: WebFuzzingCommonsReport | nu
259271

260272
const endpointData = endpointMap.get(status.endpointId);
261273

262-
status.httpStatus.forEach(code => {
274+
status.httpStatus?.forEach(code => {
263275
if (!endpointData) {
264276
return;
265277
}
266278
let existingStatus = endpointData.httpStatusCodes.find((s: { code: number; }) => s.code === code);
267279
if (!existingStatus) {
280+
if(code === null || code === undefined) {
281+
code = -1;
282+
}
268283
existingStatus = {code, testCases: []};
269284
endpointData.httpStatusCodes.push(existingStatus);
270285
}

web-report/src/pages/TestResults.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,16 @@ export const TestResults: React.FC<IProps> = ({testCaseName}) => {
2828
const allFaultCodes = relatedFaults.map((fault) =>
2929
fault.faultCategories.map((f) => f.code)).flat();
3030
const uniqueFaultCodes = [...new Set(allFaultCodes)].sort((a, b) => a - b);
31-
3231
const allStatusCodes = relatedHttpStatus.map((status) =>
33-
status.httpStatus.map((s) => s)).flat();
34-
const uniqueStatusCodes = [...new Set(allStatusCodes)].sort((a, b) => a - b);
32+
status.httpStatus?.map((s) => s)).flat();
33+
const uniqueStatusCodes = [...new Set(allStatusCodes)].sort((a, b) => {
34+
const codeA = Number(a);
35+
const codeB = Number(b);
36+
if (isNaN(codeA) || isNaN(codeB)) {
37+
return String(a).localeCompare(String(b));
38+
}
39+
return codeA - codeB;
40+
});
3541
const currentFile = testFiles.find((file) => file.name === testCase?.filePath);
3642

3743

web-report/src/types/GeneratedTypes.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export type OperationId = string;
1313
* A unique identifier for a test case. It could include its name and file location.
1414
*/
1515
export type TestCaseId = string;
16-
export type HttpStatus = number;
16+
export type HttpStatus = number | null;
1717
/**
1818
* A relative path used to unique locate a test suite file.
1919
*/

web-report/src/types/GeneratedTypesZod.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const operationIdSchema = z.string();
55

66
export const testCaseIdSchema = z.string();
77

8-
export const httpStatusSchema = z.number();
8+
export const httpStatusSchema = z.number().nullable();
99

1010
export const testFilePathSchema = z.string();
1111

0 commit comments

Comments
 (0)