Skip to content

Commit

Permalink
Adding test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
karevn committed Oct 7, 2021
1 parent e06f7ab commit 8b8ff4f
Show file tree
Hide file tree
Showing 34 changed files with 815 additions and 452 deletions.
1 change: 1 addition & 0 deletions ui/src/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import '../src/index.css';
import 'tailwindcss/tailwind.css';

export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
Expand Down
16 changes: 8 additions & 8 deletions ui/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,20 @@
},
"devDependencies": {
"@craco/craco": "^6.3.0",
"@storybook/addon-actions": "^6.3.8",
"@storybook/addon-essentials": "^6.3.8",
"@storybook/addon-links": "^6.3.8",
"@storybook/addon-actions": "^6.3.10",
"@storybook/addon-essentials": "^6.3.10",
"@storybook/addon-links": "^6.3.10",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/builder-webpack5": "^6.3.8",
"@storybook/manager-webpack5": "^6.3.8",
"@storybook/node-logger": "^6.3.8",
"@storybook/react": "^6.3.8",
"@storybook/builder-webpack5": "^6.3.10",
"@storybook/manager-webpack5": "^6.3.10",
"@storybook/node-logger": "^6.3.10",
"@storybook/react": "^6.3.10",
"@types/react-router": "^5.1.16",
"autoprefixer": "^9",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"prettier": "^2.4.0",
"storybook": "^6.3.8",
"storybook": "^6.3.10",
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"typescript": "^4.4.3"
}
Expand Down
4 changes: 3 additions & 1 deletion ui/src/src/App.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, { Component } from "react";
import "tailwindcss/tailwind.css";
import "./App.css";
import Header from "./common/Header";
import Main from "./common/Main";
import Footer from "./common/Footer";
import "./App.css";

import { library } from "@fortawesome/fontawesome-svg-core";
import { faStroopwafel } from "@fortawesome/free-solid-svg-icons";
import { RecoilRoot } from "recoil";
Expand Down
4 changes: 2 additions & 2 deletions ui/src/src/components/suite/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ const Form = ({ initialValues, initialFocus, onSubmit, onCancel, ...other }: For
<Formik initialValues={initialValues} validationSchema={schema} onSubmit={onSubmit}>
{({ values, errors, handleSubmit, handleChange, handleBlur }) => (
<form onSubmit={handleSubmit} {...other}>
<h3 className="uppercase font-medium text-base text-neutral-fade2 mt-3 mb-5">Save a new test case</h3>
<h3 className="uppercase font-medium text-base text-neutral-fade2 mt-3 mb-5">Save a new test suite</h3>
<p className="text-base text-neutral mb-4">
Your new test suite requires a name. Please choose something meaningful and easy to remember.
</p>
<label htmlFor="name" className={clsx("block mb-2", captionClasses)}>
<label htmlFor="name" className={clsx("block mb-2 font-medium", captionClasses)}>
Suite name
</label>
<TextInput
Expand Down
34 changes: 34 additions & 0 deletions ui/src/src/components/testcase/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useRef } from "react";
import { ExistingAttribute, FakeAttribute } from "../../domain";
import Dialog from "../ui/Dialog";
import Form, { FormValues } from "./Form";

export type SuiteDialogProps = {
onCancel: VoidFunction;
onSubmit: (values: FormValues) => void;
attributes: (FakeAttribute | ExistingAttribute)[];
};

const TestCaseDialog = ({ onCancel, onSubmit, attributes, ...other }: SuiteDialogProps) => {
const firstElementRef = useRef<HTMLInputElement>(null);
const initialValues: FormValues = {
attributes: [],
name: "",
description: "",
};
return (
<Dialog open onClose={onCancel} className="max-w-xl w-full" onOverlayClick={onCancel} {...other}>
<Dialog.Close onClick={onCancel} />
<Form
initialValues={initialValues}
onSubmit={onSubmit}
onCancel={onCancel}
className="p-8"
initialFocus={firstElementRef}
attributes={attributes}
/>
</Dialog>
);
};

export default TestCaseDialog;
71 changes: 71 additions & 0 deletions ui/src/src/components/testcase/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Formik } from "formik";
import { OKCancelFooter } from "../ui/Dialog";
import TextInput from "../ui/TextInput";
import * as Yup from "yup";
import FieldError from "../ui/FieldError";
import clsx from "clsx";
import { captionClasses } from "../ui/typography";
import { FormHTMLAttributes, Ref } from "react";
import { ExistingAttribute, FakeAttribute } from "../../domain";
import Attributes from "../ui/Attributes";
import { FilterValue } from "../ui/Attribute";
const schema = Yup.object().shape({
name: Yup.string().required("Please give this test case a name"),
});

export type FormValues = {
name: string;
description: string;
attributes: FilterValue[];
};

export type FormProps = Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"> & {
initialValues: FormValues;
initialFocus?: Ref<HTMLInputElement>;
onSubmit: (values: FormValues) => void;
onCancel: VoidFunction;
attributes: (ExistingAttribute | FakeAttribute)[];
};

const Form = ({ initialValues, initialFocus, onSubmit, onCancel, attributes, ...other }: FormProps) => (
<Formik initialValues={initialValues} validationSchema={schema} onSubmit={onSubmit}>
{({ values, errors, handleSubmit, handleChange, handleBlur, setFieldValue }) => (
<form onSubmit={handleSubmit} {...other}>
<h3 className="uppercase font-medium text-base text-neutral-fade2 mt-3 mb-5">Create a new test case</h3>
<label htmlFor="name" className={clsx("block mb-2 font-medium", captionClasses)}>
Test case name
</label>
<TextInput
ref={initialFocus}
name="name"
className="block w-full"
placeholder="Suite name"
value={values.name}
onChange={handleChange}
/>
<FieldError>{errors.name}</FieldError>
<label htmlFor="description" className={clsx("block mb-2 font-medium mt-8", captionClasses)}>
Description
</label>
<TextInput
name="description"
className="block w-full"
placeholder="Description"
value={values.description}
onChange={handleChange}
/>
<label className={clsx("block mb-2 font-medium mt-8", captionClasses)}>Attributes</label>
<Attributes
attributes={attributes}
value={values.attributes}
onChange={value => setFieldValue("attributes", value)}
addLinkContent="Add attribute"
className="flex-col"
/>
<OKCancelFooter OKText="Save" OKType="submit" onCancelClick={onCancel} className="pt-8" />
</form>
)}
</Formik>
);

export default Form;
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ export type FilterValue = {
values: string[];
};

export type FilterProps = {
export type AttributeProps = {
value: FilterValue;
onChange: (value: FilterValue) => void;
attributes: (ExistingAttribute | FakeAttribute)[];
onRemoveClick: EventHandler<MouseEvent>;
disabled?: boolean;
};
const Filter = ({ value, onChange, attributes, onRemoveClick, disabled }: FilterProps) => {

const Attribute = ({ value, onChange, attributes, onRemoveClick, disabled }: AttributeProps) => {
const selectedAttribute = useMemo(
() => attributes.find(attribute => attribute.id === value?.attribute),
[attributes, value],
Expand Down Expand Up @@ -48,15 +49,15 @@ const Filter = ({ value, onChange, attributes, onRemoveClick, disabled }: Filter
return (
<div
className={clsx(
"inline-flex items-center gap-2 flex-nowrap pl-3",
"inline-flex items-center gap-2 pl-2.5",
inputBorderClasses,
inputBackgroundClasses,
inputTextClasses,
)}
>
<CustomListbox
disabled={disabled}
className="flex-grow flex-shrink-0"
className="flex-grow flex-shrink"
buttonClassName="pl-1"
value={value?.attribute}
onChange={handleAttributeChange}
Expand All @@ -77,7 +78,7 @@ const Filter = ({ value, onChange, attributes, onRemoveClick, disabled }: Filter
<span className="font-semibold">{selectedValues.length > 1 ? "in" : "="}</span>
<CustomListbox
disabled={disabled}
className="flex-grow flex-shrink-0"
className="flex-grow flex-shrink"
buttonClassName="pl-1"
value={selectedValues as any}
onChange={handleValueChange}
Expand Down Expand Up @@ -113,4 +114,4 @@ const Filter = ({ value, onChange, attributes, onRemoveClick, disabled }: Filter
</div>
);
};
export default Filter;
export default Attribute;
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import Filter, { FilterValue } from "./Filter";
import Attribute, { FilterValue } from "./Attribute";
import PlusCircleIcon from "@heroicons/react/solid/PlusCircleIcon";
import { ExistingAttribute, FakeAttribute } from "../../domain";
import clsx from "clsx";
import { ReactNode } from "react";

export type FiltersProps = {
export type AttributesProps = {
attributes: (ExistingAttribute | FakeAttribute)[];
value: FilterValue[];
onChange: (value: FilterValue[]) => void;
disabled?: boolean;
className?: string;
addLinkContent: ReactNode;
};
const Filters = ({ attributes, value, onChange, disabled }: FiltersProps) => {

const Attributes = ({ attributes, value, onChange, disabled, className, addLinkContent }: AttributesProps) => {
const handleFilterChange = (index: number) => (newValue: FilterValue) =>
onChange(value.map((filter, i) => (i === index ? newValue : filter)));
const handleRemoveFilterClick = (index: number) => () =>
onChange(value.map((filter, i) => (i === index ? undefined : filter)!).filter(Boolean));
const handleAddFilterClick = () => onChange([...value, { attribute: undefined, values: [] }]);
return (
<div className="flex flex-wrap gap-3">
<div className={clsx("flex flex-wrap gap-3", className)}>
{value.map((filter, index) => (
<Filter
<Attribute
disabled={disabled}
key={index}
value={filter}
Expand All @@ -30,12 +35,13 @@ const Filters = ({ attributes, value, onChange, disabled }: FiltersProps) => {
className="flex items-center text-base text-primary gap-1 focus:outline-focus"
onClick={handleAddFilterClick}
disabled={disabled}
type="button"
>
<PlusCircleIcon className="w-5 h-5" />
<span>Add filter</span>
<span>{addLinkContent}</span>
</button>
</div>
);
};

export default Filters;
export default Attributes;
6 changes: 3 additions & 3 deletions ui/src/src/components/ui/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import clsx from "clsx";
import { ButtonHTMLAttributes } from "react";
import { focusClasses } from "./focus";

export const baseClasses = "duration-200 font-semibold ";
export const baseClasses = "duration-200 font-medium";

const Button = ({ className, ...other }: ButtonHTMLAttributes<HTMLButtonElement>) => (
<button className={clsx(className, baseClasses)} {...other} />
Expand All @@ -24,8 +24,8 @@ Button.Transparent = Transparent;

export const linkTextClasses = "text-base";
export const linkClasses = "pl-3 pr-3 rounded-md";
export const linkNeutralClasses = "text-neutral-fade1 hover:text-neutral";
export const linkPrimaryClasses = "text-base text-primary hover:text-primary-hover";
export const linkNeutralClasses = "text-neutral-fade2 hover:text-neutral";
export const linkPrimaryClasses = "text-primary hover:text-primary-hover";
const Link = ({ className, ...other }: ButtonHTMLAttributes<HTMLButtonElement>) => (
<button className={clsx(className, baseClasses, linkTextClasses, focusClasses, linkClasses)} {...other} />
);
Expand Down
31 changes: 20 additions & 11 deletions ui/src/src/components/ui/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,30 @@ const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(
({ checked, indeterminate, className, onClick, iconClassName, disabled, ...other }, ref) => (
<button
ref={ref}
className={clsx("border-2 rounded-md w-6 h-6", focusClasses, className, { "opacity-60": disabled })}
className={clsx("border-2 rounded-md w-6 h-6 flex-shrink-0 relative", focusClasses, className, {
"opacity-60": disabled,
})}
onClick={disabled ? undefined : onClick}
{...other}
>
{indeterminate ? (
<svg viewBox="0 0 24 24" className="w-5 h-5 fill-current">
<rect fill="current" width="16" height="16" x="4" y="4" rx="3" ry="3"></rect>
</svg>
) : (
<CheckIcon
className={clsx("w-5 h-5 stroke-current block duration-200 transition-opacity", iconClassName, {
<svg
viewBox="0 0 24 24"
className={clsx("w-6 h-6 fill-current absolute top-0 left-0 duration-200 transition-opacity", {
"opacity-0": !indeterminate,
})}
>
<rect fill="current" width="16" height="16" x="2" y="2" rx="3" ry="3"></rect>
</svg>

<CheckIcon
className={clsx(
"w-5 h-5 stroke-current block duration-200 transition-opacity absolute top-0 left-0",
iconClassName,
{
"opacity-0": !checked,
})}
/>
)}
},
)}
/>
</button>
),
);
Expand Down
6 changes: 3 additions & 3 deletions ui/src/src/components/ui/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import XCircleIcon from "@heroicons/react/outline/XCircleIcon";
import clsx from "clsx";
import { ButtonHTMLAttributes, EventHandler, MouseEvent, PropsWithChildren } from "react";
import { useLayoutEffect } from "react";
import Button from "./Button";
import Button, { linkNeutralClasses } from "./Button";
import { focusClasses } from "./focus";

export type DialogProps = PropsWithChildren<{
Expand All @@ -28,7 +28,7 @@ const Dialog = ({ children, className, onOverlayClick, onClose, ...other }: Dial
className="text-neutral z-20 inset-0 fixed flex items-center justify-center overflow-y-auto font-sans"
onClose={onClose}
>
<div className="flex items-center justify-center min-h-screen">
<div className="flex items-center justify-center min-h-screen w-full">
<HeadlessDialog.Overlay
className="z-10 absolute opacity-80 bg-white w-screen h-screen"
onClick={onOverlayClick}
Expand Down Expand Up @@ -78,7 +78,7 @@ export const OKCancelFooter = ({
<Button.Primary onClick={onOKClick} type={OKType} className="pl-8 pr-8">
{OKText}
</Button.Primary>
<Button.Link onClick={onCancelClick} type={cancelType}>
<Button.Link className={linkNeutralClasses} onClick={onCancelClick} type={cancelType}>
{cancelText}
</Button.Link>
</div>
Expand Down
12 changes: 10 additions & 2 deletions ui/src/src/components/ui/ListBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { inputBorderClasses, inputLayoutClasses, inputTextClasses } from "./inpu
import { focusClasses } from "./focus";
import { PropsWithChildren, ReactNode } from "react";

const Placeholder = ({ children }: PropsWithChildren<{}>) => <span className="text-neutral-fade2">{children}</span>;
const Placeholder = ({ children }: PropsWithChildren<{}>) => (
<span className="text-neutral-fade2 whitespace-nowrap">{children}</span>
);

export type BasicListboxProps<TValue> = PropsWithChildren<{
label?: ReactNode;
Expand Down Expand Up @@ -35,7 +37,13 @@ export function BasicListbox<TValue>({
className={clsx(className, "relative", "flex")}
>
<HeadlessListBox.Button
className={clsx("flex items-center gap-1", buttonClassName, inputTextClasses, inputLayoutClasses, focusClasses)}
className={clsx(
"flex flex-grow items-center gap-1",
buttonClassName,
inputTextClasses,
inputLayoutClasses,
focusClasses,
)}
>
<span className="flex-grow">{label}</span>
<SelectorIcon className="w-4 h-4 text-neutral-fade2 hover:text-neutral-fade1 transition-colors duration-200" />
Expand Down
2 changes: 1 addition & 1 deletion ui/src/src/components/ui/typography.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const captionClasses = "uppercase text-sm font-medium text-neutral-fade2";
export const captionClasses = "uppercase text-sm font-normal text-neutral-fade2 tracking-wider";
Loading

0 comments on commit 8b8ff4f

Please sign in to comment.