Skip to content

Add a filter option to the conformance page #199

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 4 commits into from
Jul 6, 2025
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
4 changes: 2 additions & 2 deletions src/components/HomepageFeatures/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Heading from "@theme/Heading";
type FeatureItem = {
title: string;
Svg: React.ComponentType<React.ComponentProps<"svg">>;
description: JSX.Element;
description: React.ReactNode;
};

const FeatureList: FeatureItem[] = [
Expand Down Expand Up @@ -52,7 +52,7 @@ function Feature({ title, description }: FeatureItem) {
);
}

export default function HomepageFeatures(): JSX.Element {
export default function HomepageFeatures(): React.ReactNode {
return (
<section className={styles.features}>
<div className="container">
Expand Down
4 changes: 3 additions & 1 deletion src/components/conformance/HeroBanner/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ interface BannerProps {
focusItems: VersionItem[];
}

export default function ConformanceHeroBanner(props: BannerProps): JSX.Element {
export default function ConformanceHeroBanner(
props: BannerProps,
): React.ReactNode {
return (
<div className={styles.bannerSection}>
{props.focusItems.map((item) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
TestResult,
SuiteResult,
ConformanceState,
FilterOption,
} from "@site/src/components/conformance/types";
import Heading from "@theme/Heading";
import styles from "./styles.module.css";
Expand All @@ -16,7 +17,7 @@ type TestsGridProps = {
selectTest: (string) => void;
};

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

Expand All @@ -32,6 +33,7 @@ export default function TestsGrid(props: TestsGridProps): JSX.Element {
<Grid
tests={props.suite.tests}
esFlag={props.state.ecmaScriptVersion}
filterOption={props.state.filterOption}
selectTest={props.selectTest}
setHoverValue={(name) => setHoverName(name)}
/>
Expand All @@ -44,16 +46,31 @@ export default function TestsGrid(props: TestsGridProps): JSX.Element {
type GridProps = {
tests: TestResult[];
esFlag: string | null;
filterOption: FilterOption;
selectTest: (test: string) => void;
setHoverValue: (test: string | undefined) => void;
};

function Grid(props: GridProps): JSX.Element {
function applyFilter(filter: FilterOption, outcome: TestOutcome): boolean {
switch (filter) {
case FilterOption.Passed:
return outcome == TestOutcome.Passed;
case FilterOption.Ignored:
return outcome == TestOutcome.Ignored;
case FilterOption.Failed:
return outcome == TestOutcome.Failed || outcome == TestOutcome.Panic;
default:
return true;
}
}

function Grid(props: GridProps): React.ReactNode {
return (
<>
{props.esFlag
? props.tests
.filter((test) => test.edition <= SpecEdition[props.esFlag])
.filter((test) => applyFilter(props.filterOption, test.result))
.map((test) => {
return (
<GridItem
Expand All @@ -64,16 +81,18 @@ function Grid(props: GridProps): JSX.Element {
/>
);
})
: props.tests.map((test) => {
return (
<GridItem
key={test.strict ? test.name + "-strict" : test.name}
test={test}
selectTest={props.selectTest}
setHoverValue={props.setHoverValue}
/>
);
})}
: props.tests
.filter((test) => applyFilter(props.filterOption, test.result))
.map((test) => {
return (
<GridItem
key={test.strict ? test.name + "-strict" : test.name}
test={test}
selectTest={props.selectTest}
setHoverValue={props.setHoverValue}
/>
);
})}
</>
);
}
Expand All @@ -84,7 +103,7 @@ type GridItemProps = {
setHoverValue: (test: string | undefined) => void;
};

function GridItem(props: GridItemProps): JSX.Element {
function GridItem(props: GridItemProps): React.ReactNode {
let testResult: string;
switch (props.test.result) {
case TestOutcome.Passed:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type TestViewerProps = {
backToGrid: () => void;
};

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

// path constants
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ type SuiteDataProps = {
setSelectedTest: (string) => void;
};

export default function SuiteDataContainer(props: SuiteDataProps): JSX.Element {
export default function SuiteDataContainer(
props: SuiteDataProps,
): React.ReactNode {
// Set the user's selected test to be displayed in the ViewPort.
const selectTest = (testName: string) => {
props.setSelectedTest(testName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ type SuiteDisplayProps = {
setSelectedTest: (string) => void;
};

export default function SuiteDisplay(props: SuiteDisplayProps): JSX.Element {
export default function SuiteDisplay(
props: SuiteDisplayProps,
): React.ReactNode {
return (
<div className={styles.suiteDisplay}>
{props.currentSuite.suites ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import {
ConformanceState,
FilterOption,
SortOption,
SuiteResult,
TestStats,
Expand All @@ -15,7 +16,7 @@ type SelectorProps = {
navigateToSuite: (string) => void;
};

export default function SuiteSelector(props: SelectorProps): JSX.Element {
export default function SuiteSelector(props: SelectorProps): React.ReactNode {
const option: SortOption[] = availableSortingOptions.filter(
(v) => v.id === props.state.sortOption,
);
Expand All @@ -35,6 +36,7 @@ export default function SuiteSelector(props: SelectorProps): JSX.Element {
key={suite.name}
suite={suite}
esFlag={props.state.ecmaScriptVersion}
filterOption={props.state.filterOption ?? FilterOption.None}
navigateToSuite={props.navigateToSuite}
/>
);
Expand All @@ -46,10 +48,11 @@ export default function SuiteSelector(props: SelectorProps): JSX.Element {
type SuiteItemProps = {
suite: SuiteResult;
esFlag: string | null;
filterOption: FilterOption;
navigateToSuite: (string) => void;
};

function SuiteItem(props: SuiteItemProps): JSX.Element {
function SuiteItem(props: SuiteItemProps): React.ReactNode {
return (
<div
className={styles.suiteCard}
Expand All @@ -64,26 +67,48 @@ function SuiteItem(props: SuiteItemProps): JSX.Element {
? (props.suite.versionedStats?.[props.esFlag] ?? props.suite.stats)
: props.suite.stats
}
filterOption={props.filterOption}
/>
</div>
);
}

function SuiteStatistics(props): JSX.Element {
type StatProps = {
testResults: TestStats;
filterOption: FilterOption;
};

function SuiteStatistics({
testResults,
filterOption,
}: StatProps): React.ReactNode {
const [filter, setFilter] = React.useState(filterOption);

React.useEffect(() => {
setFilter(filterOption);
}, [filterOption]);

let passed =
filter == FilterOption.None || filter == FilterOption.Passed
? testResults.passed
: 0;

let ignored =
filter == FilterOption.None || filter == FilterOption.Ignored
? testResults.ignored
: 0;

let failed =
filter == FilterOption.None || filter == FilterOption.Failed
? `${testResults.total - testResults.passed - testResults.ignored} (${testResults.panic}\u26A0)`
: 0;

return (
<div className={styles.suiteCardResults}>
<p>
<span style={{ color: "var(--ifm-color-success)" }}>
{props.testResults.passed}{" "}
</span>
/{" "}
<span style={{ color: "var(--ifm-color-warning)" }}>
{props.testResults.ignored}{" "}
</span>
/{" "}
<span
style={{ color: "var(--ifm-color-danger)" }}
>{`${props.testResults.total - props.testResults.passed - props.testResults.ignored} (${props.testResults.panic}\u26A0)`}</span>
<span style={{ color: "var(--ifm-color-success)" }}>{passed} </span>/{" "}
<span style={{ color: "var(--ifm-color-warning)" }}>{ignored} </span>/{" "}
<span style={{ color: "var(--ifm-color-danger)" }}>{failed}</span>
</p>
</div>
);
Expand Down
32 changes: 29 additions & 3 deletions src/components/conformance/ResultsDisplay/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
VersionItem,
SuiteResult,
ConformanceState,
FilterOption,
} from "@site/src/components/conformance/types";
import ResultNavigation from "./nav";
import {
Expand All @@ -20,14 +21,13 @@ type ResultsProps = {
state: ConformanceState;
};

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

// Refs
const activeResults = React.useRef<undefined | ResultInfo>();
const activeResults = React.useRef<undefined | ResultInfo>(undefined);

// History handling
const history = useHistory<ConformanceState>();
Expand Down Expand Up @@ -103,6 +103,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
newPath,
props.state.ecmaScriptVersion,
props.state.sortOption,
props.state.filterOption,
),
);
};
Expand All @@ -119,6 +120,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
slicedPath,
props.state.ecmaScriptVersion,
props.state.sortOption,
props.state.filterOption,
),
);
};
Expand All @@ -137,6 +139,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
props.state.testPath,
nulledFlag,
props.state.sortOption,
props.state.filterOption,
),
);
};
Expand All @@ -154,6 +157,27 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
props.state.testPath,
props.state.ecmaScriptVersion,
option,
props.state.filterOption,
),
);
};

// Sets the filter option.
//
// This filters the tests shown in the selection cards and tests grid
const setFilterOption = (option: string) => {
pushStateToHistory(
createSearchParams(
props.state.version,
props.state.testPath,
props.state.selectedTest,
),
createState(
props.state.version,
props.state.testPath,
props.state.ecmaScriptVersion,
props.state.sortOption,
option as FilterOption,
),
);
};
Expand All @@ -167,6 +191,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
props.state.testPath,
props.state.ecmaScriptVersion,
props.state.sortOption,
props.state.filterOption,
test,
),
);
Expand All @@ -189,6 +214,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element {
sliceNavToIndex={sliceNavToIndex}
setEcmaScriptFlag={setEcmaScriptFlag}
setSortOption={setSortOption}
setFilterOption={setFilterOption}
/>
{currentSuite ? (
<SuiteDisplay
Expand Down
Loading