Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/resources/wfc/schemas/auth.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: "Web Fuzzing Commons Authentication"
description: "Schema Definition for Web Fuzzing Commons Authentication"
type: object
properties:
schema_version:
schemaVersion:
type: string
description: "The schema version of WFC needed to use to validate and process this document."
auth:
Expand Down
60 changes: 30 additions & 30 deletions src/main/resources/wfc/schemas/report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,45 @@ description: "Schema Definition for Web Fuzzing Commons Reports"
type: object
properties:
# REQUIRED
schema_version:
schemaVersion:
type: string
description: "The schema version of WFC needed to use to validate and process this document."
tool_name:
toolName:
type: string
description: "The name of the tool used to create the test cases reported in this document."
tool_version:
toolVersion:
type: string
description: "The version number of the used tool, e.g., 1.0.0."
creation_time:
creationTime:
type: string
format: date-time
description: "The timestamp of when this report file was created."
faults:
$ref: "#/$defs/Faults"
#### Unfortunately, there is no support for oneOf in jsonschema2pojo
# problem_details:
# problemDetails:
# type: object
# oneOf:
# - $ref: "#/$defs/RESTReport"
# # TODO GraphQL, RPC and Web
problem_details:
problemDetails:
type: object
properties:
rest:
$ref: "#/$defs/RESTReport"
# TODO GraphQL, RPC and Web
# expressing that only 1 should be present is possible, but super-verbose and convoluted
total_tests:
totalTests:
type: integer
minimum: 0
description: "The total number of test cases generated by the tool."
test_file_paths:
testFilePaths:
type: array
items:
$ref: "#/$defs/TestFilePath"
uniqueItems: true
description: "The list of relative paths (compared to this document) of all the generated test suite files."
test_cases:
testCases:
description: "Information on each generated test case."
type: array
items:
Expand All @@ -55,7 +55,7 @@ properties:
items:
$ref: "#/$defs/Coverage"

required: ["schema_version","tool_name","tool_version","creation_time","faults","problem_details","total_tests","test_file_paths","test_cases"]
required: ["schemaVersion","toolName","toolVersion","creationTime","faults","problemDetails","totalTests","testFilePaths","testCases"]

$defs:
OperationId:
Expand Down Expand Up @@ -84,19 +84,19 @@ $defs:
description: "Data-structure to represent which HTTP status code where covered on an endpoint by any of the generated tests."
type: object
properties:
endpoint_id:
endpointId:
$ref: "#/$defs/OperationId"
test_case_id:
testCaseId:
$ref: "#/$defs/TestCaseId"
http_status:
httpStatus:
description: "As in a test case the same endpoint could be called more than once, here we report all of the
obtained HTTP status codes"
type: array
items:
$ref: "#/$defs/HttpStatus"
minItems: 1
uniqueItems: true
required: ["endpoint_id","test_case_id","http_status"]
required: ["endpointId","testCaseId","httpStatus"]
HttpStatus:
type: integer
minimum: 0
Expand All @@ -106,85 +106,85 @@ $defs:
in GraphQL and RPC) and which tests find faults in them."
type: object
properties:
operation_id:
operationId:
$ref: "#/$defs/OperationId"
test_case_id:
testCaseId:
$ref: "#/$defs/TestCaseId"
fault_categories:
faultCategories:
type: array
items:
$ref: "#/$defs/FaultCategoryId"
minItems: 1
uniqueItems: true
required: ["endpoint_id","test_case_id","fault_categories"]
required: ["endpointId","testCaseId","faultCategories"]

RESTReport:
type: object
properties:
total_http_calls:
totalHttpCalls:
description: "Total number of HTTP calls made in all the test cases. A test case could contain several HTTP calls, \
e.g., a POST followed by a GET and then a DELETE."
type: integer
minimum: 0
endpoint_ids:
endpointIds:
description: "Unique ids of all the endpoints in the tested API."
type: array
items:
$ref: "#/$defs/OperationId"
uniqueItems: true
covered_http_status:
coveredHttpStatus:
description: "List of which HTTP status codes were covered, based on endpoints."
type: array
items:
$ref: "#/$defs/CoveredEndpoint"
required: ["total_http_calls","endpoint_ids","covered_http_status"]
required: ["totalHttpCalls","endpointIds","coveredHttpStatus"]

TestCase:
type: object
properties:
id:
$ref: "#/$defs/TestCaseId"
file_path:
filePath:
$ref: "#/$defs/TestFilePath"
name:
description: "The name of the test case, as it appears in the generated test file."
type: string
start_line:
startLine:
description: "The line number in the generated test suite file where the code of this test case starts."
type: integer
minimum: 0
end_line:
endLine:
description: "The line number in the generated test suite file where the code of this test case ends."
type: integer
minimum: 0

Faults:
type: object
properties:
total_number:
totalNumber:
description: "The total number of potential faults identified in the generated test suites. \
Each fault is uniquely identified with its 'code' category and 'context'. \
Note that different tests can detect the same fault, and a test case can detect several different faults."
type: integer
minimum: 0
found_faults:
foundFaults:
description: "Information on all the identified potential faults."
type: array
items:
$ref: "#/$defs/FoundFault"
required: ["total_number","found_faults"]
required: ["totalNumber","foundFaults"]

Coverage:
type: object
properties:
tool_name:
toolName:
description: "The name of the tool used to collect and compute the coverage criteria."
type: string
criteria:
type: array
items:
$ref: "#/$defs/CoverageCriterion"
required: ["tool_name","criteria"]
required: ["toolName","criteria"]

CoverageCriterion:
type: object
Expand Down
1 change: 1 addition & 0 deletions web-report/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/assets/icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Web Fuzzing Commons" />
<title>WFC Reports</title>
</head>
<body>
Expand Down
11 changes: 7 additions & 4 deletions web-report/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
"type": "module",
"scripts": {
"dev": "vite",
"generate": "json2ts ../src/main/resources/wfc/schemas/report.yaml src/types/GeneratedTypes.tsx",
"generate": "json2ts ../src/main/resources/wfc/schemas/report.yaml src/types/GeneratedTypes.tsx && ts-to-zod src/types/GeneratedTypes.tsx src/types/GeneratedTypesZod.ts",
"build": "tsc -b && vite build",
"installAndBuild": "yarn install && yarn generate && vitest --no-watch && tsc -b && vite build",
"installAndBuild": "yarn install && yarn generate && vitest --no-watch && tsc -b && vite build && yarn copyRunFiles",
"copyRunFiles": "cpx webreport.bat ../target/classes/webreport && cpx webreport.command ../target/classes/webreport && cpx webreport.py ../target/classes/webreport && cpx src-e2e/static/robots.txt ../target/classes/webreport",
"lint": "eslint .",
"preview": "vite preview",
"debug": "vite build && cpx \"src-e2e/static/*\" ../target/classes/webreport && vite preview",
"debug": "vite build && cpx src-e2e/static/* ../target/classes/webreport && vite preview",
"test": "vitest"
},
"dependencies": {
Expand All @@ -31,7 +32,8 @@
"recharts": "^2.15.1",
"tailwind-merge": "^3.0.2",
"tailwindcss": "^4.0.14",
"tailwindcss-animate": "^1.0.7"
"tailwindcss-animate": "^1.0.7",
"zod": "^3.25.67"
},
"devDependencies": {
"@eslint/js": "^9.21.0",
Expand All @@ -51,6 +53,7 @@
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^15.15.0",
"happy-dom": "^17.4.7",
"ts-to-zod": "^3.15.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.24.1",
"vite": "^6.2.0",
Expand Down
32 changes: 16 additions & 16 deletions web-report/src-e2e/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {resolve} from "path";
import {readFileSync} from "fs";
import {vi} from "vitest";
import App from "../src/App";
import {fetchFileContent, getFaultCounts} from "@/lib/utils";
import {fetchFileContent, getFaultCounts} from "../src/lib/utils";

// Read the report.json file
const reportJsonPath = resolve(__dirname, './static/report.json');
Expand Down Expand Up @@ -68,34 +68,34 @@ describe('App test', () => {
render(<App />);
expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByTestId('header-creation-date')).toContainHTML(new Date(reportData.creation_time).toUTCString());
expect(screen.getByTestId('header-tool-name-version')).toContainHTML(`${reportData.tool_name}`);
expect(screen.getByTestId('header-tool-name-version')).toContainHTML(`${reportData.tool_version}`);
expect(screen.getByTestId('header-schema-version')).toContainHTML(reportData.schema_version);
expect(screen.getByTestId('header-creation-date')).toContainHTML(new Date(reportData.creationTime).toUTCString());
expect(screen.getByTestId('header-tool-name-version')).toContainHTML(`${reportData.toolName}`);
expect(screen.getByTestId('header-tool-name-version')).toContainHTML(`${reportData.toolVersion}`);
expect(screen.getByTestId('header-schema-version')).toContainHTML(reportData.schemaVersion);
});
});

it('check rest report', async () => {
render(<App />);
expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument();
const total = reportData.problem_details.rest.endpoint_ids.length;
const total_http_calls = reportData.problem_details.rest.total_http_calls;
const total = reportData.problemDetails.rest.endpointIds.length;
const totalHttpCalls = reportData.problemDetails.rest.totalHttpCalls;

await waitFor(() => {
expect(screen.getByTestId('rest-report-endpoint')).toContainHTML(`${total}`);
expect(screen.getByTestId('rest-report-http-calls')).toContainHTML(`${total_http_calls}`);
expect(screen.getByTestId('rest-report-http-calls')).toContainHTML(`${totalHttpCalls}`);
});

});

it('check generated tests', async () => {
render(<App />);
expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument();
const total_tests = reportData.total_tests;
const total_test_files = reportData.test_file_paths.length;
const totalTests = reportData.totalTests;
const totalTestFiles = reportData.testFilePaths.length;
await waitFor(() => {
expect(screen.getByTestId('generated-tests-total-tests')).toContainHTML(`${total_tests}`);
expect(screen.getByTestId('generated-tests-total-test-files')).toContainHTML(`${total_test_files}`);
expect(screen.getByTestId('generated-tests-total-tests')).toContainHTML(`${totalTests}`);
expect(screen.getByTestId('generated-tests-total-test-files')).toContainHTML(`${totalTestFiles}`);
});
});

Expand Down Expand Up @@ -125,7 +125,7 @@ describe('App test', () => {

await waitFor(() => {
// check if the endpoints are displayed
reportData.problem_details.rest.endpoint_ids.forEach((endpoint: string) => {
reportData.problemDetails.rest.endpointIds.forEach((endpoint: string) => {
// const testId = convertEndpointToTestId(endpoint);
expect(screen.getByTestId(endpoint)).toBeInTheDocument();
});
Expand All @@ -135,11 +135,11 @@ describe('App test', () => {
it('check faults component', async () => {
render(<App />);
expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument();
const total_faults = reportData.faults.total_number;
const faultCounts = getFaultCounts(reportData.faults.found_faults);
const totalFaults = reportData.faults.totalNumber;
const faultCounts = getFaultCounts(reportData.faults.foundFaults);

await waitFor(() => {
expect(screen.getByTestId('faults-component-total-faults')).toContainHTML(`${total_faults}`);
expect(screen.getByTestId('faults-component-total-faults')).toContainHTML(`${totalFaults}`);
expect(screen.getByTestId('faults-component-fault-counts')).toContainHTML(faultCounts.length.toString());
});
});
Expand Down
Loading