test case editor with steps template
This commit is contained in:
@@ -7,8 +7,11 @@ import {
|
|||||||
SelectItem,
|
SelectItem,
|
||||||
Chip,
|
Chip,
|
||||||
Button,
|
Button,
|
||||||
|
Divider,
|
||||||
} from "@nextui-org/react";
|
} from "@nextui-org/react";
|
||||||
import { priorities, testTypes } from "@/config/selection";
|
import { ArrowUpFromLine } from "lucide-react";
|
||||||
|
import { priorities, testTypes, templates } from "@/config/selection";
|
||||||
|
import StepsEditor from "./steps-editor";
|
||||||
import Config from "@/config/config";
|
import Config from "@/config/config";
|
||||||
const apiServer = Config.apiServer;
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
@@ -26,6 +29,22 @@ type CaseType = {
|
|||||||
folderId: number;
|
folderId: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type CaseStepType = {
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
CaseId: number;
|
||||||
|
StepId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type StepType = {
|
||||||
|
id: number;
|
||||||
|
step: string;
|
||||||
|
result: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
caseSteps: CaseStepType;
|
||||||
|
};
|
||||||
|
|
||||||
const defaultTestCase = {
|
const defaultTestCase = {
|
||||||
id: 0,
|
id: 0,
|
||||||
title: "",
|
title: "",
|
||||||
@@ -103,7 +122,7 @@ export default function Page({
|
|||||||
async function fetchDataEffect() {
|
async function fetchDataEffect() {
|
||||||
try {
|
try {
|
||||||
const data = await fetchCase(url);
|
const data = await fetchCase(url);
|
||||||
console.log(data)
|
console.log(data);
|
||||||
setTestCase(data);
|
setTestCase(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error in effect:", error.message);
|
console.error("Error in effect:", error.message);
|
||||||
@@ -115,6 +134,7 @@ export default function Page({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
|
<h6>Basic</h6>
|
||||||
<Input
|
<Input
|
||||||
size="sm"
|
size="sm"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -126,6 +146,7 @@ export default function Page({
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setTestCase({ ...testCase, title: e.target.value });
|
setTestCase({ ...testCase, title: e.target.value });
|
||||||
}}
|
}}
|
||||||
|
className="mt-3"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Textarea
|
<Textarea
|
||||||
@@ -194,6 +215,35 @@ export default function Page({
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Select
|
||||||
|
size="sm"
|
||||||
|
variant="bordered"
|
||||||
|
selectedKeys={[templates[testCase.template].uid]}
|
||||||
|
onSelectionChange={(e) => {
|
||||||
|
const selectedUid = e.anchorKey;
|
||||||
|
const index = templates.findIndex(
|
||||||
|
(template) => template.uid === selectedUid
|
||||||
|
);
|
||||||
|
setTestCase({ ...testCase, template: index });
|
||||||
|
}}
|
||||||
|
label="template"
|
||||||
|
className="mt-3 max-w-xs"
|
||||||
|
>
|
||||||
|
{templates.map((template, index) => (
|
||||||
|
<SelectItem key={template.uid} value={index}>
|
||||||
|
{template.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider className="my-6" />
|
||||||
|
|
||||||
|
{templates[testCase.template].name === "Text" ? (
|
||||||
|
<div>
|
||||||
|
<h6>Test Detail</h6>
|
||||||
|
<div className="flex">
|
||||||
<Textarea
|
<Textarea
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="bordered"
|
variant="bordered"
|
||||||
@@ -203,10 +253,11 @@ export default function Page({
|
|||||||
onValueChange={(changeValue) => {
|
onValueChange={(changeValue) => {
|
||||||
setTestCase({ ...testCase, preConditions: changeValue });
|
setTestCase({ ...testCase, preConditions: changeValue });
|
||||||
}}
|
}}
|
||||||
className="mt-3"
|
className="mt-3 pe-1"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Textarea
|
<Textarea
|
||||||
|
size="sm"
|
||||||
variant="bordered"
|
variant="bordered"
|
||||||
label="ExpectedResults"
|
label="ExpectedResults"
|
||||||
placeholder="ExpectedResults"
|
placeholder="ExpectedResults"
|
||||||
@@ -214,10 +265,45 @@ export default function Page({
|
|||||||
onValueChange={(changeValue) => {
|
onValueChange={(changeValue) => {
|
||||||
setTestCase({ ...testCase, expectedResults: changeValue });
|
setTestCase({ ...testCase, expectedResults: changeValue });
|
||||||
}}
|
}}
|
||||||
className="mt-3"
|
className="mt-3 ps-1"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<h6>Steps</h6>
|
||||||
|
<StepsEditor
|
||||||
|
steps={testCase.Steps}
|
||||||
|
onStepUpdate={() => {}}
|
||||||
|
onStepPlus={() => {}}
|
||||||
|
onStepDelete={() => {}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="mt-3">
|
<Divider className="my-6" />
|
||||||
|
|
||||||
|
<h6>Attachments</h6>
|
||||||
|
<div className="flex items-center justify-center w-96 mt-3">
|
||||||
|
<label
|
||||||
|
htmlFor="dropzone-file"
|
||||||
|
className="flex flex-col items-center justify-center w-full h-32 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600"
|
||||||
|
>
|
||||||
|
<div className="flex flex-col items-center justify-center pt-5 pb-6">
|
||||||
|
<ArrowUpFromLine />
|
||||||
|
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
<span className="font-semibold">Click to upload</span> or drag and
|
||||||
|
drop
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
Max. file size: 50 MB
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<input id="dropzone-file" type="file" className="hidden" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6">
|
||||||
<Button color="primary" onPress={() => updateCase(testCase)}>
|
<Button color="primary" onPress={() => updateCase(testCase)}>
|
||||||
Update
|
Update
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import { Textarea, Button } from "@nextui-org/react";
|
||||||
|
import { StepType } from "./page";
|
||||||
|
import { Plus, Trash } from "lucide-react";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
steps: StepType[];
|
||||||
|
onStepUpdate: (stepId: number, step: StepType) => void;
|
||||||
|
onStepPlus: () => void;
|
||||||
|
onStepDelete: (stepId: number) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function StepsEditor({
|
||||||
|
steps,
|
||||||
|
onStepUpdate,
|
||||||
|
onStepPlus,
|
||||||
|
onStepDelete,
|
||||||
|
}: Props) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{steps.map((step, index) => (
|
||||||
|
<div key={index} className="flex">
|
||||||
|
<Textarea
|
||||||
|
size="sm"
|
||||||
|
variant="bordered"
|
||||||
|
label="Details of the step"
|
||||||
|
placeholder="Details of the step"
|
||||||
|
value={step.step}
|
||||||
|
onValueChange={(changeValue) => {
|
||||||
|
onStepUpdate(step.id, { ...step, step: changeValue });
|
||||||
|
}}
|
||||||
|
className="mt-3 me-1"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Textarea
|
||||||
|
size="sm"
|
||||||
|
variant="bordered"
|
||||||
|
label="Expected Result"
|
||||||
|
placeholder="Expected Result"
|
||||||
|
value={step.result}
|
||||||
|
onValueChange={(changeValue) => {
|
||||||
|
onStepUpdate(step.id, { ...step, result: changeValue });
|
||||||
|
}}
|
||||||
|
className="mt-3 ms-1"
|
||||||
|
/>
|
||||||
|
<div className="mt-3 ms-1">
|
||||||
|
<Button
|
||||||
|
isIconOnly
|
||||||
|
size="sm"
|
||||||
|
className="bg-transparent rounded-full"
|
||||||
|
onPress={() => onStepDelete(step.id)}
|
||||||
|
>
|
||||||
|
<Trash size={16} />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
isIconOnly
|
||||||
|
size="sm"
|
||||||
|
className="bg-transparent rounded-full"
|
||||||
|
onPress={onStepPlus}
|
||||||
|
>
|
||||||
|
<Plus size={16} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user