Skip to content

Commit bcf6d32

Browse files
authored
Add a filter option to the conformance page (#199)
* Add a filter option to conformance page * npm run format * JSX.Element => React.ReactNode * Fix bug with filter not persisting when sortOption was selected
1 parent 66dedb3 commit bcf6d32

File tree

14 files changed

+176
-45
lines changed

14 files changed

+176
-45
lines changed

src/components/HomepageFeatures/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Heading from "@theme/Heading";
99
type FeatureItem = {
1010
title: string;
1111
Svg: React.ComponentType<React.ComponentProps<"svg">>;
12-
description: JSX.Element;
12+
description: React.ReactNode;
1313
};
1414

1515
const FeatureList: FeatureItem[] = [
@@ -52,7 +52,7 @@ function Feature({ title, description }: FeatureItem) {
5252
);
5353
}
5454

55-
export default function HomepageFeatures(): JSX.Element {
55+
export default function HomepageFeatures(): React.ReactNode {
5656
return (
5757
<section className={styles.features}>
5858
<div className="container">

src/components/conformance/HeroBanner/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ interface BannerProps {
1818
focusItems: VersionItem[];
1919
}
2020

21-
export default function ConformanceHeroBanner(props: BannerProps): JSX.Element {
21+
export default function ConformanceHeroBanner(
22+
props: BannerProps,
23+
): React.ReactNode {
2224
return (
2325
<div className={styles.bannerSection}>
2426
{props.focusItems.map((item) => {

src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestGrid/index.tsx

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
TestResult,
66
SuiteResult,
77
ConformanceState,
8+
FilterOption,
89
} from "@site/src/components/conformance/types";
910
import Heading from "@theme/Heading";
1011
import styles from "./styles.module.css";
@@ -16,7 +17,7 @@ type TestsGridProps = {
1617
selectTest: (string) => void;
1718
};
1819

19-
export default function TestsGrid(props: TestsGridProps): JSX.Element {
20+
export default function TestsGrid(props: TestsGridProps): React.ReactNode {
2021
const [hoverName, setHoverName] = React.useState<undefined | string>();
2122
const cardBodyClass = "card__body " + styles.gridStyle;
2223

@@ -32,6 +33,7 @@ export default function TestsGrid(props: TestsGridProps): JSX.Element {
3233
<Grid
3334
tests={props.suite.tests}
3435
esFlag={props.state.ecmaScriptVersion}
36+
filterOption={props.state.filterOption}
3537
selectTest={props.selectTest}
3638
setHoverValue={(name) => setHoverName(name)}
3739
/>
@@ -44,16 +46,31 @@ export default function TestsGrid(props: TestsGridProps): JSX.Element {
4446
type GridProps = {
4547
tests: TestResult[];
4648
esFlag: string | null;
49+
filterOption: FilterOption;
4750
selectTest: (test: string) => void;
4851
setHoverValue: (test: string | undefined) => void;
4952
};
5053

51-
function Grid(props: GridProps): JSX.Element {
54+
function applyFilter(filter: FilterOption, outcome: TestOutcome): boolean {
55+
switch (filter) {
56+
case FilterOption.Passed:
57+
return outcome == TestOutcome.Passed;
58+
case FilterOption.Ignored:
59+
return outcome == TestOutcome.Ignored;
60+
case FilterOption.Failed:
61+
return outcome == TestOutcome.Failed || outcome == TestOutcome.Panic;
62+
default:
63+
return true;
64+
}
65+
}
66+
67+
function Grid(props: GridProps): React.ReactNode {
5268
return (
5369
<>
5470
{props.esFlag
5571
? props.tests
5672
.filter((test) => test.edition <= SpecEdition[props.esFlag])
73+
.filter((test) => applyFilter(props.filterOption, test.result))
5774
.map((test) => {
5875
return (
5976
<GridItem
@@ -64,16 +81,18 @@ function Grid(props: GridProps): JSX.Element {
6481
/>
6582
);
6683
})
67-
: props.tests.map((test) => {
68-
return (
69-
<GridItem
70-
key={test.strict ? test.name + "-strict" : test.name}
71-
test={test}
72-
selectTest={props.selectTest}
73-
setHoverValue={props.setHoverValue}
74-
/>
75-
);
76-
})}
84+
: props.tests
85+
.filter((test) => applyFilter(props.filterOption, test.result))
86+
.map((test) => {
87+
return (
88+
<GridItem
89+
key={test.strict ? test.name + "-strict" : test.name}
90+
test={test}
91+
selectTest={props.selectTest}
92+
setHoverValue={props.setHoverValue}
93+
/>
94+
);
95+
})}
7796
</>
7897
);
7998
}
@@ -84,7 +103,7 @@ type GridItemProps = {
84103
setHoverValue: (test: string | undefined) => void;
85104
};
86105

87-
function GridItem(props: GridItemProps): JSX.Element {
106+
function GridItem(props: GridItemProps): React.ReactNode {
88107
let testResult: string;
89108
switch (props.test.result) {
90109
case TestOutcome.Passed:

src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestViewer/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type TestViewerProps = {
1010
backToGrid: () => void;
1111
};
1212

13-
export default function TestViewer(props: TestViewerProps): JSX.Element {
13+
export default function TestViewer(props: TestViewerProps): React.ReactNode {
1414
const [testContent, setTestContent] = React.useState<string | null>(null);
1515

1616
// path constants

src/components/conformance/ResultsDisplay/components/SuiteDataContainer/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ type SuiteDataProps = {
1515
setSelectedTest: (string) => void;
1616
};
1717

18-
export default function SuiteDataContainer(props: SuiteDataProps): JSX.Element {
18+
export default function SuiteDataContainer(
19+
props: SuiteDataProps,
20+
): React.ReactNode {
1921
// Set the user's selected test to be displayed in the ViewPort.
2022
const selectTest = (testName: string) => {
2123
props.setSelectedTest(testName);

src/components/conformance/ResultsDisplay/components/SuiteDisplay/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ type SuiteDisplayProps = {
1616
setSelectedTest: (string) => void;
1717
};
1818

19-
export default function SuiteDisplay(props: SuiteDisplayProps): JSX.Element {
19+
export default function SuiteDisplay(
20+
props: SuiteDisplayProps,
21+
): React.ReactNode {
2022
return (
2123
<div className={styles.suiteDisplay}>
2224
{props.currentSuite.suites ? (

src/components/conformance/ResultsDisplay/components/SuiteSelector/index.tsx

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from "react";
22
import {
33
ConformanceState,
4+
FilterOption,
45
SortOption,
56
SuiteResult,
67
TestStats,
@@ -15,7 +16,7 @@ type SelectorProps = {
1516
navigateToSuite: (string) => void;
1617
};
1718

18-
export default function SuiteSelector(props: SelectorProps): JSX.Element {
19+
export default function SuiteSelector(props: SelectorProps): React.ReactNode {
1920
const option: SortOption[] = availableSortingOptions.filter(
2021
(v) => v.id === props.state.sortOption,
2122
);
@@ -35,6 +36,7 @@ export default function SuiteSelector(props: SelectorProps): JSX.Element {
3536
key={suite.name}
3637
suite={suite}
3738
esFlag={props.state.ecmaScriptVersion}
39+
filterOption={props.state.filterOption ?? FilterOption.None}
3840
navigateToSuite={props.navigateToSuite}
3941
/>
4042
);
@@ -46,10 +48,11 @@ export default function SuiteSelector(props: SelectorProps): JSX.Element {
4648
type SuiteItemProps = {
4749
suite: SuiteResult;
4850
esFlag: string | null;
51+
filterOption: FilterOption;
4952
navigateToSuite: (string) => void;
5053
};
5154

52-
function SuiteItem(props: SuiteItemProps): JSX.Element {
55+
function SuiteItem(props: SuiteItemProps): React.ReactNode {
5356
return (
5457
<div
5558
className={styles.suiteCard}
@@ -64,26 +67,48 @@ function SuiteItem(props: SuiteItemProps): JSX.Element {
6467
? (props.suite.versionedStats?.[props.esFlag] ?? props.suite.stats)
6568
: props.suite.stats
6669
}
70+
filterOption={props.filterOption}
6771
/>
6872
</div>
6973
);
7074
}
7175

72-
function SuiteStatistics(props): JSX.Element {
76+
type StatProps = {
77+
testResults: TestStats;
78+
filterOption: FilterOption;
79+
};
80+
81+
function SuiteStatistics({
82+
testResults,
83+
filterOption,
84+
}: StatProps): React.ReactNode {
85+
const [filter, setFilter] = React.useState(filterOption);
86+
87+
React.useEffect(() => {
88+
setFilter(filterOption);
89+
}, [filterOption]);
90+
91+
let passed =
92+
filter == FilterOption.None || filter == FilterOption.Passed
93+
? testResults.passed
94+
: 0;
95+
96+
let ignored =
97+
filter == FilterOption.None || filter == FilterOption.Ignored
98+
? testResults.ignored
99+
: 0;
100+
101+
let failed =
102+
filter == FilterOption.None || filter == FilterOption.Failed
103+
? `${testResults.total - testResults.passed - testResults.ignored} (${testResults.panic}\u26A0)`
104+
: 0;
105+
73106
return (
74107
<div className={styles.suiteCardResults}>
75108
<p>
76-
<span style={{ color: "var(--ifm-color-success)" }}>
77-
{props.testResults.passed}{" "}
78-
</span>
79-
/{" "}
80-
<span style={{ color: "var(--ifm-color-warning)" }}>
81-
{props.testResults.ignored}{" "}
82-
</span>
83-
/{" "}
84-
<span
85-
style={{ color: "var(--ifm-color-danger)" }}
86-
>{`${props.testResults.total - props.testResults.passed - props.testResults.ignored} (${props.testResults.panic}\u26A0)`}</span>
109+
<span style={{ color: "var(--ifm-color-success)" }}>{passed} </span>/{" "}
110+
<span style={{ color: "var(--ifm-color-warning)" }}>{ignored} </span>/{" "}
111+
<span style={{ color: "var(--ifm-color-danger)" }}>{failed}</span>
87112
</p>
88113
</div>
89114
);

src/components/conformance/ResultsDisplay/index.tsx

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
VersionItem,
66
SuiteResult,
77
ConformanceState,
8+
FilterOption,
89
} from "@site/src/components/conformance/types";
910
import ResultNavigation from "./nav";
1011
import {
@@ -20,14 +21,13 @@ type ResultsProps = {
2021
state: ConformanceState;
2122
};
2223

23-
export default function ResultsDisplay(props: ResultsProps): JSX.Element {
24-
const location = useLocation<ConformanceState>();
24+
export default function ResultsDisplay(props: ResultsProps): React.ReactNode {
2525
const [currentSuite, setCurrentSuite] = React.useState<SuiteResult | null>(
2626
null,
2727
);
2828

2929
// Refs
30-
const activeResults = React.useRef<undefined | ResultInfo>();
30+
const activeResults = React.useRef<undefined | ResultInfo>(undefined);
3131

3232
// History handling
3333
const history = useHistory<ConformanceState>();
@@ -103,6 +103,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
103103
newPath,
104104
props.state.ecmaScriptVersion,
105105
props.state.sortOption,
106+
props.state.filterOption,
106107
),
107108
);
108109
};
@@ -119,6 +120,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
119120
slicedPath,
120121
props.state.ecmaScriptVersion,
121122
props.state.sortOption,
123+
props.state.filterOption,
122124
),
123125
);
124126
};
@@ -137,6 +139,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
137139
props.state.testPath,
138140
nulledFlag,
139141
props.state.sortOption,
142+
props.state.filterOption,
140143
),
141144
);
142145
};
@@ -154,6 +157,27 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
154157
props.state.testPath,
155158
props.state.ecmaScriptVersion,
156159
option,
160+
props.state.filterOption,
161+
),
162+
);
163+
};
164+
165+
// Sets the filter option.
166+
//
167+
// This filters the tests shown in the selection cards and tests grid
168+
const setFilterOption = (option: string) => {
169+
pushStateToHistory(
170+
createSearchParams(
171+
props.state.version,
172+
props.state.testPath,
173+
props.state.selectedTest,
174+
),
175+
createState(
176+
props.state.version,
177+
props.state.testPath,
178+
props.state.ecmaScriptVersion,
179+
props.state.sortOption,
180+
option as FilterOption,
157181
),
158182
);
159183
};
@@ -167,6 +191,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
167191
props.state.testPath,
168192
props.state.ecmaScriptVersion,
169193
props.state.sortOption,
194+
props.state.filterOption,
170195
test,
171196
),
172197
);
@@ -189,6 +214,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
189214
sliceNavToIndex={sliceNavToIndex}
190215
setEcmaScriptFlag={setEcmaScriptFlag}
191216
setSortOption={setSortOption}
217+
setFilterOption={setFilterOption}
192218
/>
193219
{currentSuite ? (
194220
<SuiteDisplay

0 commit comments

Comments
 (0)