Skip to content

Merge long going React Migration Branch to master #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 72 commits into from
Jun 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
a857bad
Move code to legacy folder and create new react folder next to it
l-1squared Feb 24, 2023
45fd586
Move code to legacy folder and create new react folder next to it
l-1squared Feb 24, 2023
fd848c4
Add sidebar
fudler Oct 20, 2023
916b6d5
Add contents of sidebar
fudler Oct 20, 2023
4331c21
Extract sidebar to own method
fudler Oct 20, 2023
8690c93
Integrate MenuBar into Scenario Overview
fudler Oct 20, 2023
c1fe2bc
Fix variable heights
fudler Jan 19, 2024
2751040
Fix menu bar
fudler Jan 19, 2024
24f20b8
Fix menu bar
fudler Jan 19, 2024
6585932
Include review comments
fudler Feb 2, 2024
cf3c7b6
Include review comments
fudler Feb 16, 2024
242f1d9
Provide Readme for Workshop
fudler Feb 16, 2024
45c0f28
Provide items to work on
fudler Feb 16, 2024
4f999d7
Add react-router-dom and basic routing example
marcus-aemilius Mar 1, 2024
80f755e
Changed Scenario UI structure
Mar 1, 2024
70a59bd
Show multiple scenarios
Mar 1, 2024
b17baf8
code format
Mar 1, 2024
70624bb
Add a complete JGiven Report
l-1squared Mar 1, 2024
3ae5da0
Single expansion logic
Mar 1, 2024
3c125c6
small fix
Mar 1, 2024
26986d4
Use url parameters for link to scenarios filtered by status
marcus-aemilius Mar 1, 2024
441407e
Added prettier
marcus-aemilius Mar 1, 2024
c3aa9db
Fix jgiven report json
l-1squared Mar 1, 2024
ba4e6dd
some statistics fixed
Mar 1, 2024
af602e5
Extend gitignore
marcus-aemilius Mar 1, 2024
bb900f1
Move styling to own file
marcus-aemilius Mar 1, 2024
a0860e6
Remove accidentally pushed dummy data
marcus-aemilius Mar 1, 2024
43bb347
introduce filter
l-1squared Mar 1, 2024
e569ce3
overhaueld new report model
Mar 1, 2024
bca41ba
Fix tests
marcus-aemilius Mar 1, 2024
66cc767
Make test compile
marcus-aemilius Mar 1, 2024
4e68f5d
force Json to be JsonReport
l-1squared Mar 1, 2024
ca450fb
fixed statistics
Mar 1, 2024
c967384
Moved icon button styling to separate file and increased button size
marcus-aemilius Mar 1, 2024
a13a448
Ran npm audit fix
marcus-aemilius Mar 1, 2024
a4e94e8
make as sample tag file available in a repository
l-1squared Mar 1, 2024
88dd331
number format change
Mar 1, 2024
331ea7a
Use onClick-properties to pass callbacks and avoid usage of built-in …
marcus-aemilius Mar 1, 2024
bef0810
better status filter
l-1squared Mar 1, 2024
fa25fc5
fix compile errors
l-1squared Mar 1, 2024
dd70b20
Restructured Scenario Accordion
Mar 1, 2024
ca093c1
move sample reports into sample data
l-1squared Mar 1, 2024
83b3a92
Test status filter
l-1squared Mar 1, 2024
8bb4fda
Added Iteration over Scenarios
Mar 1, 2024
d5c5f3b
Try to use filter function
marcus-aemilius Mar 1, 2024
f3542c5
expand report filter to accept several values
l-1squared Mar 1, 2024
a24c95a
filter returns scenario model array
l-1squared Mar 1, 2024
f4d5771
repository now has a get all scenarios method
l-1squared Mar 1, 2024
d7dc86d
Introduce type-safe hook for filters
marcus-aemilius Mar 1, 2024
9701742
fixed scenarios
Mar 1, 2024
76c3f5d
imroved scenarios
Mar 1, 2024
46b8d92
improved time display
Mar 1, 2024
9cb3028
Fix typo
fudler Mar 1, 2024
dc9323b
removed unnecessary condition
Mar 1, 2024
d3f12f7
Add basic test for ScenarioOverview
marcus-aemilius Mar 1, 2024
aba6e16
Refactored Scenario component
May 3, 2024
fa4ca88
Fixed formatting
May 3, 2024
6efe47f
removed unused variable
Jun 14, 2024
7feb1da
created subdirectory for tests
Jun 14, 2024
d1df2f7
Covered `ScenarioStep` with tests
Jun 14, 2024
9657cc7
Covered `ScenarioCase` with tests
Jun 14, 2024
2606d90
Overhauled scenario tests
Jun 14, 2024
3b5b1ed
Added tests for `StatisticsBreadcrumbs`
Aug 26, 2024
ac069e2
Covered `ScenarioHead` with tests
Jun 14, 2024
d521988
Code style fixes
Jun 14, 2024
2c0c496
skipped failing tests
Jun 14, 2024
77e6fe5
resolved npm audit vulnerability warnings
Aug 23, 2024
27efbe2
extracted statistics logic
Aug 23, 2024
6d1f13e
added functionality tests for `StatisticBreadcrumbs`
Sep 20, 2024
adfe2c4
repaired DonutChart functionality
Sep 20, 2024
1471cf2
Minor fixes
Jun 20, 2025
932dec7
Removed skipped tests
Jun 24, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
3 changes: 0 additions & 3 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37,103 changes: 16,520 additions & 20,583 deletions new/package-lock.json

Large diffs are not rendered by default.

52 changes: 20 additions & 32 deletions new/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,35 @@
"name": "new",
"version": "0.1.0",
"private": true,
"devDependencies": {
"@amcharts/amcharts5": "^5.3.7",
"babel-jest": "^27.4.2",
"babel-preset-react-app": "^10.0.1",
"eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.1",
"identity-obj-proxy": "^3.0.0",
"jest": "^27.4.3",
"jest-watch-typeahead": "^1.0.0",
"parcel": "^2.6.2",
"process": "^0.11.10"
},
"dependencies": {
"@cubejs-client/core": "^0.31.0",
"@devexpress/dx-react-chart-material-ui": "^4.0.3",
"@emotion/styled": "^11.10.6",
"@mui/icons-material": "^5.11.11",
"@mui/material": "^5.11.10",
"@mui/x-data-grid": "^5.17.25",
"@syncfusion/ej2-react-charts": "^20.4.53",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.15.7",
"@mui/material": "^5.15.7",
"@mui/x-data-grid": "^6.19.3",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^22.13.11",
"@types/node": "^16.18.3",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"amcharts": "^3.14.5",
"chart.js": "^4.2.1",
"i18next": "^22.4.10",
"chart.js": "^4.4.1",
"i18next": "^23.8.2",
"react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0",
"react-donut-chart": "^1.3.3",
"react-i18next": "^12.2.0",
"react-scripts": "5.0.1",
"react-i18next": "^14.0.1",
"react-router-dom": "^6.22.2",
"typescript": "^4.9.3",
"utility-types": "^3.10.0",
"web-vitals": "^2.1.4"
"web-vitals": "^2.1.4",
"nth-check": "^2.1.1"
},
"scripts": {
"start": "parcel serve src/index.html",
"build": "parcel build src/index.html",
"test": "tsc && jest",
"clean": "rm -rf dist .parcel-cache"
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"format": "prettier --write ."
},
"prettier": {
"printWidth": 100,
Expand Down Expand Up @@ -85,5 +69,9 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"react-scripts": "5.0.1",
"prettier": "3.2.5"
}
}
9 changes: 0 additions & 9 deletions new/src/App.test.tsx

This file was deleted.

23 changes: 5 additions & 18 deletions new/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
import "./App.css";
import ReportModel, { ReportStatistics } from "./reportModel";
import ReportModel from "./reportModel";
import * as guaranteedStateScenario from "./sampleData/GuaranteedStateTestScenario.json";
import { SingleScenarioView } from "./components/Scenarios/SingleScenarioView";

export const statistics: ReportStatistics[] = [
{
numClasses: 3,
numScenarios: 5,
numFailedScenarios: 2,
numCases: 3,
numFailedCases: 3,
numSteps: 10,
durationInNanos: 12345678910,
numPendingScenarios: 0,
numSuccessfulScenarios: 3
}
];
import { ScenarioOverview } from "./components/Scenarios/ScenarioOverview";

const guaranteedStateReport: ReportModel = guaranteedStateScenario as unknown as ReportModel;

function App() {
return (
<div className="App" aria-label="App">
<SingleScenarioView
<ScenarioOverview
title={"Mein Titel"}
description={"Meine Description"}
reportName={guaranteedStateReport.name}
scenario={guaranteedStateReport.scenarios[0]}
/>
</div>
);
Expand Down
52 changes: 52 additions & 0 deletions new/src/ReportFilter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { repository } from "./repository";
import { filterByStatus } from "./ReportFilter";
import { ScenarioStatusFilter } from "./components/ScenarioOverview/ScenarioCollectionHead";
import { createSampleScenario } from "./components/Scenarios/__test__/scenarioTestData";

describe("Report filter status filter", () => {
const fullReport = {
tagFile: { tagTypeMap: {}, tags: {} },
scenarios: [
{
className: "com.tngtech.jgiven.junit5.JUnit5ExecutorTest",
name: "J Unit 5 Executor",
scenarios: [
createSampleScenario({ executionStatus: "SUCCESS" }),
createSampleScenario({ executionStatus: "FAILED" })
]
},
{
className: "com.tngtech.jgiven.tests.TestScenarios",
name: "Test Scenarios",
scenarios: [createSampleScenario({ executionStatus: "FAILED" })]
}
]
};
test("should filter by status", () => {
jest.spyOn(repository, "getReport").mockReturnValue(fullReport);

expect(filterByStatus(ScenarioStatusFilter.SUCCESS)).toEqual([
fullReport.scenarios[0].scenarios[0]
]);
});

test("should ignore undefined status", () => {
jest.spyOn(repository, "getReport").mockReturnValue(fullReport);

expect(filterByStatus(ScenarioStatusFilter.SUCCESS, undefined)).toEqual([
fullReport.scenarios[0].scenarios[0]
]);
});

test("should return the full report if no status is provided", () => {
jest.spyOn(repository, "getReport").mockReturnValue(fullReport);

expect(filterByStatus()).toEqual(fullReport.scenarios.flatMap(s => s.scenarios));
});

test("should return the full report if null is provided", () => {
jest.spyOn(repository, "getReport").mockReturnValue(fullReport);

expect(filterByStatus(undefined)).toEqual(fullReport.scenarios.flatMap(s => s.scenarios));
});
});
35 changes: 35 additions & 0 deletions new/src/ReportFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { repository } from "./repository";
import ReportModel, { ScenarioModel } from "./reportModel";
import { ScenarioStatusFilter } from "./components/ScenarioOverview/ScenarioCollectionHead";

export function filterByStatus(
...statusParameter: (ScenarioStatusFilter | undefined)[]
): ScenarioModel[] {
const fullReport = repository.getReport();
const status = statusParameter
.filter(status => status !== undefined)
.map(s => s as ScenarioStatusFilter);

const filteredReports =
status.length === 0
? fullReport.scenarios
: filterReportByScenarioStatus(fullReport.scenarios, ...status);

return filteredReports.flatMap(report => report.scenarios);
}

function filterReportByScenarioStatus(reports: ReportModel[], ...status: ScenarioStatusFilter[]) {
const filteredReports = [];
for (const report of reports) {
const filteredScenarios = report.scenarios.filter(scenario =>
(status as string[]).includes(scenario.executionStatus)
);
if (filteredScenarios.length > 0) {
filteredReports.push({
...report,
scenarios: filteredScenarios
});
}
}
return filteredReports;
}
75 changes: 59 additions & 16 deletions new/src/components/ScenarioOverview/DonutChart.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
import { ReportStatistics } from "../../reportModel";
import { ArcElement, Chart as ChartJS, Legend, Tooltip } from "chart.js";
import { ArcElement, BubbleDataPoint, Chart as ChartJS, Legend, Point, Tooltip } from "chart.js";
import { Doughnut } from "react-chartjs-2";
import { useRef } from "react";
import { ChartJSOrUndefined } from "react-chartjs-2/dist/types";
import { useFilters } from "../../hooks/useFilters";
import { ScenarioStatusFilter } from "./ScenarioCollectionHead";

export function createReportCircle(props: { statistic: ReportStatistics }) {
export interface DonutChartProps {
statistic: ReportStatistics;
}

export function DonutChart(props: DonutChartProps) {
const successLabel = "Successful:";
const failedLabel = "Failed:";
ChartJS.register(ArcElement, Tooltip, Legend);

const { statistic } = props;

const { setUrlSearchParams } = useFilters();

const chartRef =
useRef<
ChartJSOrUndefined<
"doughnut",
(number | [number, number] | Point | BubbleDataPoint | null)[],
unknown
>
>(null);

const width = 240; // set default width to 100 if none is provided via props
const height = 120; // set default height to 100 if none is provided via props

const data = {
labels: ["Successful:", "Failed:"],
labels: [successLabel, failedLabel],
datasets: [
{
data: [props.statistic.numSuccessfulScenarios, props.statistic.numFailedScenarios],
data: [statistic.numSuccessfulScenarios, statistic.numFailedScenarios],
backgroundColor: ["rgba(60, 179, 113)", "rgba(255, 0, 0)"],
borderWidth: 1,
onClick: (event: MouseEvent, elements: any[], chart: any) => {
if (elements.length === 0) {
return; // user did not click on a chart element
}
const label = chart.data.labels[elements[0].index];
if (label === "Successful") {
window.location.href = "/successful";
} else if (label === "Failed") {
window.location.href = "/failed";
}
},
hoverBackgroundColor: ["rgba(60,179,113,0.63)", "rgba(255,20,20,0.63)"]
}
]
Expand Down Expand Up @@ -53,5 +65,36 @@ export function createReportCircle(props: { statistic: ReportStatistics }) {
}
};

return <Doughnut data={data} width={width} height={height} options={options} />;
const handleClick = (event: React.MouseEvent<HTMLCanvasElement>) => {
const chart = chartRef.current;
if (chart == null) {
return;
}

const clickedElementIndex = chart.getElementsAtEventForMode(
event.nativeEvent,
"nearest",
{ intersect: true },
false
)[0].index;

const label = chart.data.labels?.at(clickedElementIndex);

if (label === successLabel) {
setUrlSearchParams({ status: ScenarioStatusFilter.SUCCESS });
} else if (label === failedLabel) {
setUrlSearchParams({ status: ScenarioStatusFilter.FAILED });
}
};

return (
<Doughnut
ref={chartRef}
data={data}
width={width}
height={height}
options={options}
onClick={handleClick}
/>
);
}
Loading