Skip to content

Display all passing test cases upon valid schema #155

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
58 changes: 36 additions & 22 deletions app/components/Output/Output.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState } from "react";
import styles from "./Output.module.css";
import classnames from "classnames";
import { OutputResult } from "@/lib/types";
import FailedTestCasesWindow from "../TestCaseWindow/TestCaseWindow";
import TestCasesWindow from "../TestCaseWindow/TestCaseWindow";
import MyBtn from "../MyBtn";
import { InvalidSchemaError } from "@hyperjump/json-schema/draft-2020-12";
import { schemaUrl } from "@/lib/validators";
Expand All @@ -28,17 +28,17 @@ const SchemaError = ({ schemaPath }: { schemaPath: string }) => {
You are using invalid type or keyword in the schema. The type should be
one of the valid JSON Schema types. The valid types are:{" "}
{JSONSchemaTypes.map((t) => (
<>
<CodeSnippet key={t}>{t}</CodeSnippet>
<React.Fragment key={t}>
<CodeSnippet>{t}</CodeSnippet>
{", "}
</>
</React.Fragment>
))}
</>
);
const possibleFixes = [
"Check that the type specified is one of the valid JSON Schema types",
"Correct any typos in the type name",
<>
<React.Fragment key="link">
Ensure you are using valid keywords for the JSON Schema version you are
using. You can view all the JSON Schema keywords for the latest version{" "}
<Link
Expand All @@ -51,7 +51,7 @@ const SchemaError = ({ schemaPath }: { schemaPath: string }) => {
>
here
</Link>
</>,
</React.Fragment>,
];

return (
Expand Down Expand Up @@ -87,10 +87,9 @@ function Output({
}) {
let outputBodyContent;

if (outputResult.validityStatus == "neutral") {
if (outputResult.validityStatus === "neutral") {
outputBodyContent = (
<Flex dir="row" gap={1} paddingTop={2}>
{" "}
Please click the{" "}
<MyBtn variant="default" onClick={() => {}}>
validate
Expand All @@ -99,22 +98,37 @@ function Output({
output
</Flex>
);
} else if (outputResult.validityStatus == "valid") {
outputBodyContent = (
<div className={styles.valid}>
<b className={styles.validMessage}>Valid Schema!</b>
<span className={styles.validSmallMessage}>
Let&apos;s move on to the next step
</span>
</div>
);
} else if (outputResult.validityStatus == "syntaxError") {
} else if (outputResult.validityStatus === "valid") {
if (outputResult.testCaseResults && outputResult.totalTestCases) {
outputBodyContent = (
<div>
<div className={styles.valid}>
<b className={styles.validMessage}>Valid Schema!</b>
</div>
<TestCasesWindow
testCaseResult={outputResult.testCaseResults}
totalTestCases={outputResult.totalTestCases}
isValidSchema={true}
/>
</div>
);
} else {
outputBodyContent = (
<div className={styles.valid}>
<b className={styles.validMessage}>Valid Schema!</b>
<span className={styles.validSmallMessage}>
Let&apos;s move on to the next step
</span>
</div>
);
}
} else if (outputResult.validityStatus === "syntaxError") {
outputBodyContent = (
<div className={styles.invalid}>
<b>Syntax Error:</b> <code>{outputResult.errors as string}</code>
</div>
);
} else if (outputResult.validityStatus == "invalidSchema") {
} else if (outputResult.validityStatus === "invalidSchema") {
outputBodyContent = (
<div>
{(outputResult.errors as InvalidSchemaError).output.errors && (
Expand All @@ -128,19 +142,19 @@ function Output({
);
} else {
outputBodyContent = (
<FailedTestCasesWindow
<TestCasesWindow
testCaseResult={outputResult.testCaseResults!}
totalTestCases={outputResult.totalTestCases!}
isValidSchema={false}
/>
);
}

return (
<>
<div className={styles.header}>
<div className={styles.title}>Output </div>
<div className={styles.title}>Output</div>
</div>

<div className={classnames(styles.outputBody)}>
{outputBodyContent}
{outputResult.validityStatus !== "neutral" &&
Expand Down
76 changes: 52 additions & 24 deletions app/components/TestCaseWindow/TestCaseWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { TestCaseResult } from "@/lib/types";
import TestCaseTab from "../TestCaseTab";
import styles from "./TestCaseWindow.module.css";
import { useEffect, useMemo, useRef, useState } from "react";
import { Box, Flex, useColorMode } from "@chakra-ui/react";
import { Flex, useColorMode } from "@chakra-ui/react";
import CkChevronLeft from "@/app/styles/icons/CkChevronLeft";
import CkChevronRight from "@/app/styles/icons/CkChevronRight";
import cx from "classnames";
Expand Down Expand Up @@ -58,62 +58,87 @@ function TestCaseItem({
export default function TestCasesWindow({
testCaseResult,
totalTestCases,
isValidSchema = false,
}: {
testCaseResult: TestCaseResult[];
totalTestCases: number;
isValidSchema?: boolean;
}) {
const [activeTestCase, setActiveTestCase] = useState(0);
const testCasesTabWrapperRef = useRef<HTMLDivElement | null>(null);
const { colorMode } = useColorMode();

const scrollLeft = () => {
testCasesTabWrapperRef.current!.scrollLeft -= 100;
if (testCasesTabWrapperRef.current) {
testCasesTabWrapperRef.current.scrollLeft -= 100;
}
};

const scrollRight = () => {
testCasesTabWrapperRef.current!.scrollLeft += 100;
if (testCasesTabWrapperRef.current) {
testCasesTabWrapperRef.current.scrollLeft += 100;
}
};

const numberOfFailedTestCases = useMemo(
() => testCaseResult.filter((testCase) => !testCase.passed).length,
[testCaseResult],
);

const normalizedTestCaseResult = useMemo(() => {
if (isValidSchema) {
return testCaseResult.map((tc) => ({
...tc,
expected: true,
actual: true,
passed: true,
errors: undefined,
}));
}
return testCaseResult;
}, [testCaseResult, isValidSchema]);

const [isLeftDisabled, setIsLeftDisabled] = useState(true);
const [isRightDisabled, setIsRightDisabled] = useState(false);
const [scrollPosition, setScrollPosition] = useState(0);
const [areBothDisabled, setAreBothDisabled] = useState(false);

const handleScroll = () => {
const container = testCasesTabWrapperRef.current;
if (container) {
const newScrollPosition = container.scrollLeft;
const maxScroll = container.scrollWidth - container.clientWidth;
console.log(newScrollPosition, maxScroll);

setScrollPosition(newScrollPosition);
setIsLeftDisabled(newScrollPosition === 0);
setIsRightDisabled(Math.round(newScrollPosition + 1) >= maxScroll);
setIsRightDisabled(newScrollPosition >= maxScroll);
}
};

useEffect(() => {
const container = testCasesTabWrapperRef.current;
if (container) {
const newScrollPosition = container.scrollLeft;
const maxScroll = container.scrollWidth - container.clientWidth;
if (newScrollPosition === 0 && maxScroll === 0) {
setIsLeftDisabled(true);
setIsRightDisabled(true);
setAreBothDisabled(true);
} else {
container.addEventListener("scroll", handleScroll);
return () => container.removeEventListener("scroll", handleScroll);
}
setIsLeftDisabled(container.scrollLeft === 0);
setIsRightDisabled(maxScroll <= 0);
setAreBothDisabled(maxScroll <= 0);
container.addEventListener("scroll", handleScroll);
return () => container.removeEventListener("scroll", handleScroll);
}
}, []);
}, [normalizedTestCaseResult]);

if (!normalizedTestCaseResult || normalizedTestCaseResult.length === 0) {
return <div>No test cases available</div>;
}

return (
<div className={styles.TestCasesWindow}>
<div className={styles.TestCasesHeaderWrapper}>
<span className={styles.TestCasesHeader}>Invalid Schema!</span>
{/* Reverted to original "Invalid Schema!" for invalid case */}
{!isValidSchema && (
<span className={styles.TestCasesHeader}>Invalid Schema!</span>
)}
<span className={styles.TestCasesSubtitle}>
{numberOfFailedTestCases} out of {totalTestCases} test cases failed
{isValidSchema
? `All ${totalTestCases} test cases passed`
: `${numberOfFailedTestCases} out of ${totalTestCases} test cases failed`}
</span>
</div>
<Flex dir="row" gap={2}>
Expand All @@ -124,6 +149,8 @@ export default function TestCasesWindow({
styles.scrollButton,
isLeftDisabled ? styles.disabledScrollBtn : "",
)}
disabled={isLeftDisabled}
aria-label="Scroll left"
>
<CkChevronLeft colorMode={colorMode} />
</button>
Expand All @@ -133,13 +160,13 @@ export default function TestCasesWindow({
ref={testCasesTabWrapperRef}
>
<div className={styles.TestCasesTabs}>
{testCaseResult.map((_, i) => (
{normalizedTestCaseResult.map((_, i) => (
<TestCaseTab
key={i}
isActive={i === activeTestCase}
index={i}
setIsActive={setActiveTestCase}
passed={testCaseResult[i].passed}
passed={normalizedTestCaseResult[i].passed}
/>
))}
</div>
Expand All @@ -151,15 +178,16 @@ export default function TestCasesWindow({
styles.scrollButton,
isRightDisabled ? styles.disabledScrollBtn : "",
)}
disabled={isRightDisabled}
aria-label="Scroll right"
>
<CkChevronRight colorMode={colorMode} />
</button>
)}
</Flex>

<TestCaseItem
index={activeTestCase}
testCase={testCaseResult[activeTestCase]}
testCase={normalizedTestCaseResult[activeTestCase]}
/>
</div>
);
Expand Down