Skip to content

Commit

Permalink
Replace example with proper report parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
barroco committed Aug 15, 2023
1 parent 72e7581 commit fc09dec
Show file tree
Hide file tree
Showing 8 changed files with 392 additions and 243 deletions.
2 changes: 2 additions & 0 deletions reports/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
"preview": "vite preview"
},
"dependencies": {
"jsonpath": "^1.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.15.0"
},
"devDependencies": {
"@types/jsonpath": "^0.2.0",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.0.0",
Expand Down
11 changes: 8 additions & 3 deletions reports/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@ import "./App.css";
function App() {
// FIXME use the report from the config
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const configuration = JSON.stringify((window as any)["interuss"]);
const configuration = JSON.parse((window as any)["interuss"] || "{}");
console.log("Configuration:", configuration);

const { report, nav } = useReport();
const { loading, report, nav } = useReport(configuration);
if (loading) {
return <div>Loading report...</div>;
}
if (!report) {
return <div>Report not found</div>;
}
const router = createBrowserRouter(nav);
return <RouterProvider router={router} />;
return <>
<RouterProvider router={router} />
</>;
}

export default App;
21 changes: 16 additions & 5 deletions reports/src/capability/CapabilityTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,33 @@ import {
Capability,
Check,
Requirement,
exampleReport,
} from "./capabilityTypes";

type CapabilityTableProps = {
capability?: Capability;
capability: Capability;
};

export const CheckLabel = ({name, docUrl} : {name: string, docUrl?: string}) => {
return docUrl ? <a href={docUrl}>{name}</a> : <>{name}</>
}

export const CheckRow = ({ check }: { check: Check }) => {
const separator = " :: "
const checkSource = <>
<CheckLabel {...check.scenario} />{separator}
<CheckLabel {...check.case} />{separator}
<CheckLabel {...check.step} />{separator}
<CheckLabel name={check.name} />
</>

return (
<tr>
<td>{check.name}</td>
<td>{checkSource}</td>
<td className={check.result === "pass" ? "pass" : "fail"}>
{check.result === "pass" ? "PASS" : "FAIL"}
</td>
<td>
<a href={check.detailLink}>Link</a>
<a href={check.detailsUrl}>Link</a>
</td>
</tr>
);
Expand Down Expand Up @@ -91,7 +102,7 @@ export const CapabilityRows = ({ capability }: { capability: Capability }) => {
};

export const CapabilityTable = ({
capability = exampleReport.capability,
capability
}: CapabilityTableProps) => {
return (
<>
Expand Down
131 changes: 17 additions & 114 deletions reports/src/capability/capabilityTypes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
type CapabilityResult = "pass" | "fail" | "missing";
type CheckResult = "pass" | "fail";
export type CheckResult = "pass" | "fail";

export type Check = {
result: CheckResult;
scenario: {
name: string;
docUrl: string;
}
case: {
name: string;
docUrl: string;
}
step: {
name: string;
docUrl: string;
}

name: string;
detailLink: string;
};
result: CheckResult
detailsUrl: string;
}

export type Requirement = {
name: string;
Expand All @@ -22,113 +35,3 @@ export type Capability = {
export type Report = {
capability: Capability;
};

export const exampleReport: Report = {
capability: {
name: "ASTM Service Provider",
result: "fail",
requirements: [
{
name: "astm.f3548.v21.GEN0310",
checks: [
{
name: "Nominal behavior :: Setup :: Clear",
result: "pass",
detailLink: "Link to test details",
},
{
name: "SP polling :: Poll :: Valid data",
result: "pass",
detailLink: "Link to test details",
},
],
},
{
name: "astm.f3548.v21.OPIN0030",
checks: [
{
name: "...",
result: "fail",
detailLink: "Link to test details",
},
{
name: "...",
result: "pass",
detailLink: "Link to test details",
},
],
},
{
name: "astm.f3548.v21.SDC0015",
checks: [
// Should display "Not tested"
],
},
{
name: "astm.f3548.v21.GEN0200",
checks: [
{
name: "...",
result: "pass",
detailLink: "Link to test details",
},
],
},
],
childCapabilities: [
{
name: "ASTM SP Operator ID Provider",
result: "pass",
requirements: [
{
name: "child 1",
checks: [
{
name: "Nominal behavior :: Setup :: Clear",
result: "pass",
detailLink: "Link to test details",
},
{
name: "SP polling :: Poll :: Valid data",
result: "pass",
detailLink: "Link to test details",
},
],
},
{
name: "child 2",
checks: [
{
name: "...",
result: "fail",
detailLink: "Link to test details",
},
{
name: "...",
result: "pass",
detailLink: "Link to test details",
},
],
},
{
name: "child 3",
checks: [
// Should display "Not tested"
],
},
{
name: "child 4",
checks: [
{
name: "...",
result: "pass",
detailLink: "Link to test details",
},
],
},
],
childCapabilities: [],
},
],
},
};
152 changes: 136 additions & 16 deletions reports/src/capability/reportParser.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,147 @@
import {
ReportsReportCheckedRequirement,
ReportsReportRequirementsCheckedConditionEvaluationReport,
ReportsReportTestRunReport,
ReportsReportTestSuiteActionReport,
ReportsReportTestSuiteReport,
} from "../types/TestRunReport";
import { Capability, Report, exampleReport } from "./capabilityTypes";

const parseTestSuite = (testSuite: ReportsReportTestSuiteActionReport) => {
console.log("Parse test suite", testSuite);
if (!testSuite.test_suite) return null;
const capabilities = testSuite.test_suite.capability_evaluations.map(
(c): Capability => ({
name: `${c.capability_id} - ${c.participant_id}`,
requirements: [],
childCapabilities: [],
result: c.verified ? "pass" : "fail",
import {
Capability,
Check,
CheckResult,
Report,
Requirement,
} from "./capabilityTypes";
import * as jp from "jsonpath";

const flattenChecks = (
r: ReportsReportCheckedRequirement,
root: ReportsReportTestSuiteActionReport
): Check[] => {
const expandCheck = (checkLocation: string, result: CheckResult): Check => {
const l = jp.parse(checkLocation);
const check = jp.value(root, jp.stringify(l));
const step = jp.value(root, jp.stringify(l.slice(0, -2)));
const _case = jp.value(root, jp.stringify(l.slice(0, -4)));
const scenario = jp.value(root, jp.stringify(l.slice(0, -6)));

return {
scenario: {
name: scenario.name,
docUrl: scenario.documentation_url,
},
case: {
name: _case.name,
docUrl: _case.documentation_url,
},
step: {
name: step.name,
docUrl: step.documentation_url,
},
name: check.name,
result,
detailsUrl: "", // TODO Add details page + navigation
};
};

const res = [
...r.passed_checks.map((c) => expandCheck(c, "pass")),

...r.failed_checks.map((c) => expandCheck(c, "fail")),
];
return res;
};

const flattenRequirements = (
requirementsChecked: ReportsReportRequirementsCheckedConditionEvaluationReport,
root: ReportsReportTestSuiteReport
): Requirement[] => {
return [
...requirementsChecked.passed_requirements.map((pr) => ({
name: pr.requirement_id,
checks: flattenChecks(pr, root),
})),

...requirementsChecked.failed_requirements.map((fr) => ({
name: fr.requirement_id,
checks: flattenChecks(fr, root),
})),

...requirementsChecked.untested_requirements.map((ur) => ({
name: ur,
checks: [],
})),
];
};

const getCapability = (
testSuite: ReportsReportTestSuiteReport
): Capability[] => {
return testSuite.capability_evaluations
.map((ce) => {
const c = ce.condition_evaluation;
if (c.requirements_checked) {
return {
name: ce.capability_id,
result: ce.verified ? "pass" : "fail",
requirements: flattenRequirements(c.requirements_checked, testSuite),
childCapabilities: [],
participant_id: ce.participant_id,
};
} else if (c.capability_verified) {
return {
name: ce.capability_id,
result: ce.verified ? "pass" : "fail",
requirements: [],
childCapabilities: [], // TODO: Add child capabilities
participant_id: ce.participant_id,
};
} else {
return null;
}
})
);
console.log("Parsed capbilities", capabilities);
.filter((x) => !!x) as Capability[];
};

const parseActions = (
node?: ReportsReportTestSuiteActionReport
): Capability[] => {
if (!node) return [];

try {
if (node.test_suite) {
return [
...getCapability(node.test_suite),
...node.test_suite.actions.map((a) => parseActions(a)),
].flat();
} else if (node.test_scenario) {
return [];
} else if (node.action_generator) {
return node.action_generator.actions
.map((a) => {
return parseActions(a);
})
.flat();
} else {
// TODO Improve
console.error("Unknown state");
return [];
}
} catch (err) {
console.error(err);
return [];
}
};

export const parseReport = (report: ReportsReportTestRunReport): Report => {
// FixMe: Actually parse the report
const startTime = new Date().getTime();
console.log("Input Report", report);
const parsed = parseTestSuite(report.report);
const parsed = {capability: parseActions(report.report)[0]};
console.log("Parsed report", parsed);
return exampleReport;
console.info(
"[performance] Report rendered in ",
new Date().getTime() - startTime,
"ms"
);
return parsed;
};
Loading

0 comments on commit fc09dec

Please sign in to comment.