feat: test case detail dialog
This commit is contained in:
@@ -252,6 +252,8 @@
|
||||
"no_cases_found": "No cases found",
|
||||
"are_you_sure_leave": "Are you sure you want to leave the page?",
|
||||
"type": "Type",
|
||||
"test_detail": "Test detail",
|
||||
"steps": "Steps",
|
||||
"preconditions": "Preconditions",
|
||||
"expected_result": "Expected result",
|
||||
"details_of_the_step": "Details of the step",
|
||||
|
||||
@@ -254,6 +254,7 @@
|
||||
"are_you_sure_leave": "ページを離れてもよろしいですか",
|
||||
"type": "タイプ",
|
||||
"test_detail": "テスト詳細",
|
||||
"steps": "ステップ",
|
||||
"preconditions": "前提条件",
|
||||
"expected_result": "期待結果",
|
||||
"details_of_the_step": "ステップ詳細",
|
||||
|
||||
@@ -39,6 +39,7 @@ import { useTheme } from 'next-themes';
|
||||
import { useFormGuard } from '@/utils/formGuard';
|
||||
import { PriorityMessages } from '@/types/priority';
|
||||
import { RunStatusMessages, TestRunCaseStatusMessages } from '@/types/status';
|
||||
import { TestTypeMessages } from '@/types/testType';
|
||||
|
||||
const defaultTestRun = {
|
||||
id: 0,
|
||||
@@ -58,6 +59,7 @@ type Props = {
|
||||
runStatusMessages: RunStatusMessages;
|
||||
testRunCaseStatusMessages: TestRunCaseStatusMessages;
|
||||
priorityMessages: PriorityMessages;
|
||||
testTypeMessages: TestTypeMessages;
|
||||
locale: string;
|
||||
};
|
||||
|
||||
@@ -68,6 +70,7 @@ export default function RunEditor({
|
||||
runStatusMessages,
|
||||
testRunCaseStatusMessages,
|
||||
priorityMessages,
|
||||
testTypeMessages,
|
||||
locale,
|
||||
}: Props) {
|
||||
const context = useContext(TokenContext);
|
||||
@@ -333,6 +336,7 @@ export default function RunEditor({
|
||||
messages={messages}
|
||||
testRunCaseStatusMessages={testRunCaseStatusMessages}
|
||||
priorityMessages={priorityMessages}
|
||||
testTypeMessages={testTypeMessages}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,31 +1,84 @@
|
||||
import { Button, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@nextui-org/react';
|
||||
import { useState, useEffect, useContext } from 'react';
|
||||
import { Button, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Avatar, Textarea } from '@nextui-org/react';
|
||||
import { testTypes, templates } from '@/config/selection';
|
||||
import { RunMessages } from '@/types/run';
|
||||
import { CaseType } from '@/types/case';
|
||||
import { CaseType, StepType } from '@/types/case';
|
||||
import { PriorityMessages } from '@/types/priority';
|
||||
import TestCasePriority from '@/components/TestCasePriority';
|
||||
import { TokenContext } from '@/utils/TokenProvider';
|
||||
import { fetchCase } from '@/utils/caseControl';
|
||||
import { TestTypeMessages } from '@/types/testType';
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
testCase: CaseType;
|
||||
caseId: number;
|
||||
onCancel: () => void;
|
||||
onChangeStatus: (changeCaseId: number, status: number) => {};
|
||||
messages: RunMessages;
|
||||
testTypeMessages: TestTypeMessages;
|
||||
priorityMessages: PriorityMessages;
|
||||
};
|
||||
|
||||
export default function showTestCaseDetailDialog({
|
||||
const defaultTestCase = {
|
||||
id: 0,
|
||||
title: '',
|
||||
state: 0,
|
||||
priority: 0,
|
||||
type: 0,
|
||||
automationStatus: 0,
|
||||
description: '',
|
||||
template: 0,
|
||||
preConditions: '',
|
||||
expectedResults: '',
|
||||
folderId: 0,
|
||||
};
|
||||
|
||||
export default function TestCaseDetailDialog({
|
||||
isOpen,
|
||||
testCase,
|
||||
caseId,
|
||||
onCancel,
|
||||
onChangeStatus,
|
||||
messages,
|
||||
testTypeMessages,
|
||||
priorityMessages,
|
||||
}: Props) {
|
||||
const context = useContext(TokenContext);
|
||||
const [testCase, setTestCase] = useState<CaseType>(defaultTestCase);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchDataEffect() {
|
||||
if (!context.isSignedIn()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!caseId || caseId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await fetchCase(context.token.access_token, Number(caseId));
|
||||
if (data.Steps && data.Steps.length > 0) {
|
||||
data.Steps.sort((a: StepType, b: StepType) => {
|
||||
const stepNoA = a.caseSteps.stepNo;
|
||||
const stepNoB = b.caseSteps.stepNo;
|
||||
return stepNoA - stepNoB;
|
||||
});
|
||||
}
|
||||
|
||||
setTestCase(data);
|
||||
} catch (error: any) {
|
||||
console.error('Error in effect:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
fetchDataEffect();
|
||||
}, [context, caseId]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
size="3xl"
|
||||
size="5xl"
|
||||
scrollBehavior="outside"
|
||||
onOpenChange={() => {
|
||||
onCancel();
|
||||
}}
|
||||
@@ -48,40 +101,55 @@ export default function showTestCaseDetailDialog({
|
||||
|
||||
<div className="w-1/2">
|
||||
<p className={'font-bold'}>{messages.type}</p>
|
||||
<div>{messages[testTypes[testCase.type].uid]}</div>
|
||||
<div>{testTypeMessages[testTypes[testCase.type].uid]}</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalBody>
|
||||
<ModalBody>
|
||||
{templates[testCase.template].uid === 'text' ? (
|
||||
<>
|
||||
<p className={'font-bold mt-2'}>{messages.testDetail}</p>
|
||||
<div className="flex my-2">
|
||||
<div className="w-1/2">
|
||||
<p className={'font-bold'}>{messages.preconditions}</p>
|
||||
<div>{testCase.preConditions}</div>
|
||||
</div>
|
||||
|
||||
<div className="w-1/2">
|
||||
<p className={'font-bold'}>{messages.expectedResult}</p>
|
||||
<div>{testCase.expectedResults}</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex my-2">
|
||||
{testCase.Steps &&
|
||||
testCase.Steps.map((step, index) => (
|
||||
<>
|
||||
<div className="w-1/2">
|
||||
<p className={'font-bold'}>{messages.preconditions}</p>
|
||||
<div>{step.step}</div>
|
||||
</div>
|
||||
|
||||
<div className="w-1/2">
|
||||
<p className={'font-bold'}>{messages.expectedResult}</p>
|
||||
<div>{step.result}</div>
|
||||
</div>
|
||||
</>
|
||||
))}
|
||||
) : (
|
||||
<>
|
||||
<p className={'font-bold mt-2'}>{messages.steps}</p>
|
||||
{testCase.Steps &&
|
||||
testCase.Steps.map((step) => (
|
||||
<div key={step.id} className="flex items-center my-1">
|
||||
<Avatar className="me-2" size="sm" name={step.caseSteps.stepNo.toString()} />
|
||||
<div key={step.id} className="grow flex gap-2">
|
||||
<div className="w-1/2">
|
||||
<Textarea
|
||||
isReadOnly
|
||||
size="sm"
|
||||
variant="flat"
|
||||
label={messages.detailsOfTheStep}
|
||||
value={step.step}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-1/2">
|
||||
<Textarea
|
||||
isReadOnly
|
||||
size="sm"
|
||||
variant="flat"
|
||||
label={messages.expectedResult}
|
||||
value={step.result}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
|
||||
@@ -32,7 +32,8 @@ import { RunMessages } from '@/types/run';
|
||||
import TestCaseDetailDialog from './TestCaseDetailDialog';
|
||||
import { PriorityMessages } from '@/types/priority';
|
||||
import TestCasePriority from '@/components/TestCasePriority';
|
||||
import { TestRunCaseStatusMessages } from '@/types/testRunCaseStatus';
|
||||
import { TestTypeMessages } from '@/types/testType';
|
||||
import { TestRunCaseStatusMessages } from '@/types/status';
|
||||
|
||||
type Props = {
|
||||
cases: CaseType[];
|
||||
@@ -45,6 +46,7 @@ type Props = {
|
||||
messages: RunMessages;
|
||||
testRunCaseStatusMessages: TestRunCaseStatusMessages;
|
||||
priorityMessages: PriorityMessages;
|
||||
testTypeMessages: TestTypeMessages;
|
||||
};
|
||||
|
||||
export default function TestCaseSelector({
|
||||
@@ -57,6 +59,7 @@ export default function TestCaseSelector({
|
||||
onExcludeCase,
|
||||
messages,
|
||||
testRunCaseStatusMessages,
|
||||
testTypeMessages,
|
||||
priorityMessages,
|
||||
}: Props) {
|
||||
const headerColumns = [
|
||||
@@ -138,7 +141,7 @@ export default function TestCaseSelector({
|
||||
size="sm"
|
||||
variant="light"
|
||||
className="data-[hover=true]:bg-transparent"
|
||||
onPress={() => showTestCaseDetailDialog(testCase)}
|
||||
onPress={() => showTestCaseDetailDialog(testCase.id)}
|
||||
>
|
||||
<span className={NextUiLinkClasses}>{cellValue}</span>
|
||||
</Button>
|
||||
@@ -244,22 +247,10 @@ export default function TestCaseSelector({
|
||||
|
||||
// Test Case Detail
|
||||
const [isTestCaseDetailDialogOpen, setIsTestCaseDetailDialogOpen] = useState(false);
|
||||
const [showingTestCase, setShowingTestCase] = useState<CaseType>({
|
||||
id: 0,
|
||||
title: '',
|
||||
state: 0,
|
||||
priority: 0,
|
||||
type: 0,
|
||||
automationStatus: 0,
|
||||
description: '',
|
||||
template: 0,
|
||||
preConditions: '',
|
||||
expectedResults: '',
|
||||
folderId: 0,
|
||||
});
|
||||
const showTestCaseDetailDialog = (showTestCase: CaseType) => {
|
||||
const [showingTestCaseId, setShowingTestCaseId] = useState<number>(0);
|
||||
const showTestCaseDetailDialog = (showTestCaseId: number) => {
|
||||
setIsTestCaseDetailDialogOpen(true);
|
||||
setShowingTestCase(showTestCase);
|
||||
setShowingTestCaseId(showTestCaseId);
|
||||
};
|
||||
const hideTestCaseDetailDialog = () => {
|
||||
setIsTestCaseDetailDialogOpen(false);
|
||||
@@ -302,11 +293,12 @@ export default function TestCaseSelector({
|
||||
|
||||
<TestCaseDetailDialog
|
||||
isOpen={isTestCaseDetailDialogOpen}
|
||||
testCase={showingTestCase}
|
||||
caseId={showingTestCaseId}
|
||||
onCancel={hideTestCaseDetailDialog}
|
||||
onChangeStatus={(showingCaseId, newStatus) => onChangeStatus(showingCaseId, newStatus)}
|
||||
messages={messages}
|
||||
priorityMessages={priorityMessages}
|
||||
testTypeMessages={testTypeMessages}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useTranslations } from 'next-intl';
|
||||
import { RunMessages } from '@/types/run';
|
||||
import { PriorityMessages } from '@/types/priority';
|
||||
import { RunStatusMessages, TestRunCaseStatusMessages } from '@/types/status';
|
||||
import { TestTypeMessages } from '@/types/testType';
|
||||
|
||||
export default function Page({ params }: { params: { projectId: string; runId: string; locale: string } }) {
|
||||
const t = useTranslations('Run');
|
||||
@@ -26,6 +27,8 @@ export default function Page({ params }: { params: { projectId: string; runId: s
|
||||
noCasesFound: t('no_cases_found'),
|
||||
areYouSureLeave: t('are_you_sure_leave'),
|
||||
type: t('type'),
|
||||
testDetail: t('test_detail'),
|
||||
steps: t('steps'),
|
||||
preconditions: t('preconditions'),
|
||||
expectedResult: t('expected_result'),
|
||||
detailsOfTheStep: t('details_of_the_step'),
|
||||
@@ -59,6 +62,23 @@ export default function Page({ params }: { params: { projectId: string; runId: s
|
||||
low: pt('low'),
|
||||
};
|
||||
|
||||
const tt = useTranslations('Type');
|
||||
const testTypeMessages: TestTypeMessages = {
|
||||
other: tt('other'),
|
||||
security: tt('security'),
|
||||
performance: tt('performance'),
|
||||
accessibility: tt('accessibility'),
|
||||
functional: tt('functional'),
|
||||
acceptance: tt('acceptance'),
|
||||
usability: tt('usability'),
|
||||
smokeSanity: tt('smoke_sanity'),
|
||||
compatibility: tt('compatibility'),
|
||||
destructive: tt('destructive'),
|
||||
regression: tt('regression'),
|
||||
automated: tt('automated'),
|
||||
manual: tt('manual'),
|
||||
};
|
||||
|
||||
return (
|
||||
<RunEditor
|
||||
projectId={params.projectId}
|
||||
@@ -67,6 +87,7 @@ export default function Page({ params }: { params: { projectId: string; runId: s
|
||||
runStatusMessages={runStatusMessages}
|
||||
testRunCaseStatusMessages={testRunCaseStatusMessages}
|
||||
priorityMessages={priorityMessages}
|
||||
testTypeMessages={testTypeMessages}
|
||||
locale={params.locale}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -59,20 +59,9 @@ type RunMessages = {
|
||||
title: string;
|
||||
pleaseEnter: string;
|
||||
description: string;
|
||||
new: string;
|
||||
inProgress: string;
|
||||
underReview: string;
|
||||
rejected: string;
|
||||
done: string;
|
||||
closed: string;
|
||||
priority: string;
|
||||
status: string;
|
||||
actions: string;
|
||||
untested: string;
|
||||
passed: string;
|
||||
failed: string;
|
||||
retest: string;
|
||||
skipped: string;
|
||||
selectTestCase: string;
|
||||
testCaseSelection: string;
|
||||
includeInRun: string;
|
||||
@@ -80,6 +69,8 @@ type RunMessages = {
|
||||
noCasesFound: string;
|
||||
areYouSureLeave: string;
|
||||
type: string;
|
||||
testDetail: string;
|
||||
steps: string;
|
||||
preconditions: string;
|
||||
expectedResult: string;
|
||||
detailsOfTheStep: string;
|
||||
|
||||
Reference in New Issue
Block a user