diff --git a/src/components/HomepageFeatures/index.tsx b/src/components/HomepageFeatures/index.tsx index c6ed438a..19be2150 100644 --- a/src/components/HomepageFeatures/index.tsx +++ b/src/components/HomepageFeatures/index.tsx @@ -9,7 +9,7 @@ import Heading from "@theme/Heading"; type FeatureItem = { title: string; Svg: React.ComponentType>; - description: JSX.Element; + description: React.ReactNode; }; const FeatureList: FeatureItem[] = [ @@ -52,7 +52,7 @@ function Feature({ title, description }: FeatureItem) { ); } -export default function HomepageFeatures(): JSX.Element { +export default function HomepageFeatures(): React.ReactNode { return (
diff --git a/src/components/conformance/HeroBanner/index.tsx b/src/components/conformance/HeroBanner/index.tsx index 2a47a713..aad13a2a 100644 --- a/src/components/conformance/HeroBanner/index.tsx +++ b/src/components/conformance/HeroBanner/index.tsx @@ -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 (
{props.focusItems.map((item) => { diff --git a/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestGrid/index.tsx b/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestGrid/index.tsx index 333fd14d..58650b53 100644 --- a/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestGrid/index.tsx +++ b/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestGrid/index.tsx @@ -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"; @@ -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(); const cardBodyClass = "card__body " + styles.gridStyle; @@ -32,6 +33,7 @@ export default function TestsGrid(props: TestsGridProps): JSX.Element { setHoverName(name)} /> @@ -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 ( ); }) - : props.tests.map((test) => { - return ( - - ); - })} + : props.tests + .filter((test) => applyFilter(props.filterOption, test.result)) + .map((test) => { + return ( + + ); + })} ); } @@ -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: diff --git a/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestViewer/index.tsx b/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestViewer/index.tsx index d6265d59..46de3903 100644 --- a/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestViewer/index.tsx +++ b/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/cards/TestViewer/index.tsx @@ -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(null); // path constants diff --git a/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/index.tsx b/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/index.tsx index 75068a6e..932000fa 100644 --- a/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/index.tsx +++ b/src/components/conformance/ResultsDisplay/components/SuiteDataContainer/index.tsx @@ -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); diff --git a/src/components/conformance/ResultsDisplay/components/SuiteDisplay/index.tsx b/src/components/conformance/ResultsDisplay/components/SuiteDisplay/index.tsx index 4e8997fb..877931a1 100644 --- a/src/components/conformance/ResultsDisplay/components/SuiteDisplay/index.tsx +++ b/src/components/conformance/ResultsDisplay/components/SuiteDisplay/index.tsx @@ -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 (
{props.currentSuite.suites ? ( diff --git a/src/components/conformance/ResultsDisplay/components/SuiteSelector/index.tsx b/src/components/conformance/ResultsDisplay/components/SuiteSelector/index.tsx index cb202ad8..46d03ba7 100644 --- a/src/components/conformance/ResultsDisplay/components/SuiteSelector/index.tsx +++ b/src/components/conformance/ResultsDisplay/components/SuiteSelector/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import { ConformanceState, + FilterOption, SortOption, SuiteResult, TestStats, @@ -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, ); @@ -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} /> ); @@ -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 (
); } -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 (

- - {props.testResults.passed}{" "} - - /{" "} - - {props.testResults.ignored}{" "} - - /{" "} - {`${props.testResults.total - props.testResults.passed - props.testResults.ignored} (${props.testResults.panic}\u26A0)`} + {passed} /{" "} + {ignored} /{" "} + {failed}

); diff --git a/src/components/conformance/ResultsDisplay/index.tsx b/src/components/conformance/ResultsDisplay/index.tsx index 040169af..d90d773f 100644 --- a/src/components/conformance/ResultsDisplay/index.tsx +++ b/src/components/conformance/ResultsDisplay/index.tsx @@ -5,6 +5,7 @@ import { VersionItem, SuiteResult, ConformanceState, + FilterOption, } from "@site/src/components/conformance/types"; import ResultNavigation from "./nav"; import { @@ -20,14 +21,13 @@ type ResultsProps = { state: ConformanceState; }; -export default function ResultsDisplay(props: ResultsProps): JSX.Element { - const location = useLocation(); +export default function ResultsDisplay(props: ResultsProps): React.ReactNode { const [currentSuite, setCurrentSuite] = React.useState( null, ); // Refs - const activeResults = React.useRef(); + const activeResults = React.useRef(undefined); // History handling const history = useHistory(); @@ -103,6 +103,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element { newPath, props.state.ecmaScriptVersion, props.state.sortOption, + props.state.filterOption, ), ); }; @@ -119,6 +120,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element { slicedPath, props.state.ecmaScriptVersion, props.state.sortOption, + props.state.filterOption, ), ); }; @@ -137,6 +139,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element { props.state.testPath, nulledFlag, props.state.sortOption, + props.state.filterOption, ), ); }; @@ -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, ), ); }; @@ -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, ), ); @@ -189,6 +214,7 @@ export default function ResultsDisplay(props: ResultsProps): JSX.Element { sliceNavToIndex={sliceNavToIndex} setEcmaScriptFlag={setEcmaScriptFlag} setSortOption={setSortOption} + setFilterOption={setFilterOption} /> {currentSuite ? ( void; setEcmaScriptFlag: (string) => void; setSortOption: (string) => void; + setFilterOption: (string) => void; }; -export default function ResultNavigation(props: ResultsNavProps): JSX.Element { +export default function ResultNavigation( + props: ResultsNavProps, +): React.ReactNode { return (
@@ -25,6 +28,10 @@ export default function ResultNavigation(props: ResultsNavProps): JSX.Element { sortValue={props.state.sortOption} setSortOption={props.setSortOption} /> +
void; }; -function BreadCrumbItem(props: BreadCrumbItemProps): JSX.Element { +function BreadCrumbItem(props: BreadCrumbItemProps): React.ReactNode { return (
  • void; }; -function EcmaScriptVersionDropdown(props: DropDownProps): JSX.Element { +function EcmaScriptVersionDropdown(props: DropDownProps): React.ReactNode { const [dropdownValue, setDropdownValue] = React.useState( props.esVersionValue ? props.esVersionValue : "", ); @@ -134,7 +141,7 @@ type SortProps = { setSortOption: (string) => void; }; -function SortingDropdown(props: SortProps): JSX.Element { +function SortingDropdown(props: SortProps): React.ReactNode { const [sortValue, setSortValue] = React.useState( props.sortValue ? props.sortValue : "alpha", ); @@ -168,3 +175,40 @@ function SortingDropdown(props: SortProps): JSX.Element {
  • ); } + +type FilterProps = { + filterOption: FilterOption; + setFilterOption: (string) => void; +}; + +function FilterDropdown(props: FilterProps): React.ReactNode { + const [filterValue, setFilterValue] = React.useState( + props.filterOption ?? FilterOption.None, + ); + + React.useEffect(() => { + setFilterValue(props.filterOption); + }, [props.filterOption]); + + const handlefilterSelection = (e) => { + setFilterValue(e.target.value); + props.setFilterOption(e.target.value); + }; + + return ( +
    + + Filter: + + +
    + ); +} diff --git a/src/components/conformance/VersionSelector/index.tsx b/src/components/conformance/VersionSelector/index.tsx index 2e3fe0da..259ee0fe 100644 --- a/src/components/conformance/VersionSelector/index.tsx +++ b/src/components/conformance/VersionSelector/index.tsx @@ -11,7 +11,7 @@ interface SelectorProps { availableVersions: VersionItem[]; } -export default function VersionSelector(props: SelectorProps): JSX.Element { +export default function VersionSelector(props: SelectorProps): React.ReactNode { return (
    {props.availableVersions.map((version) => { @@ -25,7 +25,7 @@ type VersionProps = { version: VersionItem; }; -function Version(props: VersionProps): JSX.Element { +function Version(props: VersionProps): React.ReactNode { const history = useHistory(); return ( diff --git a/src/components/conformance/index.tsx b/src/components/conformance/index.tsx index ec1c16f6..6f4f06dc 100644 --- a/src/components/conformance/index.tsx +++ b/src/components/conformance/index.tsx @@ -9,7 +9,7 @@ type ViewProps = { records: VersionItem[]; }; -export default function ConformanceView(props: ViewProps): JSX.Element { +export default function ConformanceView(props: ViewProps): React.ReactNode { return ( <> diff --git a/src/components/conformance/types.ts b/src/components/conformance/types.ts index 5824eb25..8d126965 100644 --- a/src/components/conformance/types.ts +++ b/src/components/conformance/types.ts @@ -7,6 +7,7 @@ export type ConformanceState = { testPath: string[]; ecmaScriptVersion: string | undefined; sortOption: string; + filterOption: FilterOption; selectedTest: string | undefined; }; @@ -27,6 +28,13 @@ export type SortOption = { callback: (a: SuiteResult, b: SuiteResult) => number; }; +export enum FilterOption { + None = "none", + Passed = "passed", + Failed = "failed", + Ignored = "ignored", +} + // The below types are specific to test result types. export type ResultInfo = { diff --git a/src/components/conformance/utils.ts b/src/components/conformance/utils.ts index 75903d36..33a2d30c 100644 --- a/src/components/conformance/utils.ts +++ b/src/components/conformance/utils.ts @@ -1,5 +1,6 @@ import { ConformanceState, + FilterOption, ResultInfo, SortOption, SpecEdition, @@ -69,6 +70,7 @@ export function createState( testPath?: string[], ecmaScriptVersion?: string, sortOption?: string, + filterOption?: FilterOption, selectedTest?: string, ): ConformanceState { testPath = testPath ? testPath : [version.tagName]; @@ -79,6 +81,7 @@ export function createState( testPath, ecmaScriptVersion, sortOption, + filterOption, selectedTest, }; } diff --git a/src/components/home/index.tsx b/src/components/home/index.tsx index 83ddb80e..7354dadd 100644 --- a/src/components/home/index.tsx +++ b/src/components/home/index.tsx @@ -36,7 +36,7 @@ function HomepageHeader() { ); } -export default function Home({ recentPosts }): JSX.Element { +export default function Home({ recentPosts }): React.ReactNode { const { siteConfig } = useDocusaurusContext(); return (