From cbdd0cb1d41a1c257d508de7f660d20139a57a79 Mon Sep 17 00:00:00 2001 From: Takeshi Kimata <117462761+kimatata@users.noreply.github.com> Date: Sun, 21 Jul 2024 10:44:41 +0900 Subject: [PATCH] feat: test case detail dialog --- frontend/messages/en.json | 22 ++++- frontend/messages/ja.json | 23 ++++- .../[folderId]/cases/[caseId]/page.tsx | 2 +- .../[projectId]/runs/[runId]/RunEditor.tsx | 2 +- .../runs/[runId]/TestCaseDetailDialog.tsx | 98 +++++++++++++++++++ .../runs/[runId]/TestCaseSelector.tsx | 50 +++++++++- .../[projectId]/runs/[runId]/page.tsx | 18 ++++ frontend/types/case.ts | 2 +- frontend/types/run.ts | 18 ++++ 9 files changed, 225 insertions(+), 10 deletions(-) create mode 100644 frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/TestCaseDetailDialog.tsx diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 92cf712..dcdadb9 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -201,12 +201,12 @@ "template": "Template", "test_detail": "Test detail", "preconditions": "Preconditions", + "expected_result": "Expected result", "step": "Step", "text": "Text", "steps": "Steps", "new_step": "New Step", "details_of_the_step": "Details of the step", - "expected_result": "Expected result", "delete_this_step": "Delete this step", "insert_step": "Insert step", "attachments": "Attachments", @@ -272,7 +272,25 @@ "include_in_run": "Include in run", "exclude_from_run": "Exclude from run", "no_cases_found": "No cases found", - "are_you_sure_leave": "Are you sure you want to leave the page?" + "are_you_sure_leave": "Are you sure you want to leave the page?", + "type": "Type", + "other": "Other", + "security": "Security", + "performance": "Performance", + "accessibility": "Accessibility", + "functional": "Functional", + "acceptance": "Acceptance", + "usability": "Usability", + "smoke_sanity": "Smoke&Sanity", + "compatibility": "Compatibility", + "destructive": "Destructive", + "regression": "Regression", + "automated": "Automated", + "manual": "Manual", + "preconditions": "Preconditions", + "expected_result": "Expected result", + "details_of_the_step": "Details of the step", + "close": "Close" }, "Members": { "member_management": "Member Management", diff --git a/frontend/messages/ja.json b/frontend/messages/ja.json index b12a4e0..e56f4e0 100644 --- a/frontend/messages/ja.json +++ b/frontend/messages/ja.json @@ -201,12 +201,12 @@ "template": "テンプレート", "test_detail": "テスト詳細", "preconditions": "前提条件", + "expected_result": "期待結果", "step": "ステップ", "text": "テキスト", "steps": "ステップ", "new_step": "新規ステップ", "details_of_the_step": "ステップ詳細", - "expected_result": "期待結果", "delete_this_step": "このステップを削除", "insert_step": "ステップを挿入", "attachments": "添付ファイル", @@ -272,7 +272,26 @@ "include_in_run": "テストランに含める", "exclude_from_run": "テストランから除外する", "no_cases_found": "テストケースが見つかりません", - "are_you_sure_leave": "ページを離れてもよろしいですか" + "are_you_sure_leave": "ページを離れてもよろしいですか", + "type": "タイプ", + "other": "その他", + "security": "セキュリティ", + "performance": "パフォーマンス", + "accessibility": "アクセシビリティ", + "functional": "機能", + "acceptance": "受け入れ", + "usability": "ユーザビリティ", + "smoke_sanity": "スモーク/サニティ", + "compatibility": "互換性", + "destructive": "破壊", + "regression": "回帰", + "automated": "自動", + "manual": "手動", + "test_detail": "テスト詳細", + "preconditions": "前提条件", + "expected_result": "期待結果", + "details_of_the_step": "ステップ詳細", + "close": "閉じる" }, "Members": { "member_management": "メンバー管理", diff --git a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/[caseId]/page.tsx b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/[caseId]/page.tsx index e859a4f..cbb9569 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/[caseId]/page.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/[caseId]/page.tsx @@ -43,12 +43,12 @@ export default function Page({ template: t('template'), testDetail: t('test_detail'), preconditions: t('preconditions'), + expectedResult: t('expected_result'), step: t('step'), text: t('text'), steps: t('steps'), newStep: t('new_step'), detailsOfTheStep: t('details_of_the_step'), - expectedResult: t('expected_result'), deleteThisStep: t('delete_this_step'), insertStep: t('insert_step'), attachments: t('attachments'), diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx index 6aa6947..731319f 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/RunEditor.tsx @@ -310,7 +310,7 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props) isDisabled={!context.isProjectReporter(Number(projectId))} selectedKeys={selectedKeys} onSelectionChange={setSelectedKeys} - onStatusChange={handleChangeStatus} + onChangeStatus={handleChangeStatus} onIncludeCase={(includeTestId) => handleIncludeExcludeCase(true, includeTestId)} onExcludeCase={(excludeCaseId) => handleIncludeExcludeCase(false, excludeCaseId)} messages={messages} diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/TestCaseDetailDialog.tsx b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/TestCaseDetailDialog.tsx new file mode 100644 index 0000000..90ca322 --- /dev/null +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/TestCaseDetailDialog.tsx @@ -0,0 +1,98 @@ +import { Button, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Chip, Divider } from '@nextui-org/react'; +import { RunMessages } from '@/types/run'; +import { CaseType } from '@/types/case'; +import { Circle } from 'lucide-react'; +import { priorities, testTypes, templates } from '@/config/selection'; + +type Props = { + isOpen: boolean; + testCase: CaseType; + onCancel: () => void; + onChangeStatus: (changeCaseId: number, status: number) => {}; + messages: RunMessages; +}; + +export default function showTestCaseDetailDialog({ isOpen, testCase, onCancel, onChangeStatus, messages }: Props) { + return ( + { + onCancel(); + }} + classNames={{ + header: 'border-b-[1px] border-[#e5e5e5]', + body: 'border-b-[1px] border-[#e5e5e5]', + }} + > + + {testCase.title} + +

{messages.description}

+
{testCase.description}
+ +
+
+

{messages.priority}

+ + } + variant="light" + > + {messages[priorities[testCase.priority].uid]} + +
+ +
+

{messages.type}

+
{messages[testTypes[testCase.type].uid]}
+
+
+
+ + {templates[testCase.template].uid === 'text' ? ( +
+
+

{messages.preconditions}

+
{testCase.preConditions}
+
+ +
+

{messages.expectedResult}

+
{testCase.expectedResults}
+
+
+ ) : ( +
+ {testCase.Steps && + testCase.Steps.map((step, index) => ( + <> +
+

{messages.preconditions}

+
{step.step}
+
+ +
+

{messages.expectedResult}

+
{step.result}
+
+ + ))} +
+ )} +
+ + + +
+
+ ); +} diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/TestCaseSelector.tsx b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/TestCaseSelector.tsx index 3d4eaa2..a1deb0c 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/TestCaseSelector.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/TestCaseSelector.tsx @@ -25,16 +25,18 @@ import { CircleX, CircleSlash2, } from 'lucide-react'; +import { NextUiLinkClasses } from '@/src/navigation'; import { priorities, testRunCaseStatus } from '@/config/selection'; import { CaseType } from '@/types/case'; import { RunMessages } from '@/types/run'; +import TestCaseDetailDialog from './TestCaseDetailDialog'; type Props = { cases: CaseType[]; isDisabled: boolean; selectedKeys: Selection; onSelectionChange: React.Dispatch>; - onStatusChange: (changeCaseId: number, status: number) => {}; + onChangeStatus: (changeCaseId: number, status: number) => {}; onIncludeCase: (includeCaseId: number) => {}; onExcludeCase: (excludeCaseId: number) => {}; messages: RunMessages; @@ -45,7 +47,7 @@ export default function TestCaseSelector({ isDisabled, selectedKeys, onSelectionChange, - onStatusChange, + onChangeStatus, onIncludeCase, onExcludeCase, messages, @@ -124,6 +126,17 @@ export default function TestCaseSelector({ const runStatus = testCase.RunCases && testCase.RunCases.length > 0 ? testCase.RunCases[0].status : 0; switch (columnKey) { + case 'title': + return ( + + ); case 'priority': return (
@@ -154,7 +167,7 @@ export default function TestCaseSelector({ onStatusChange(testCase.id, index)} + onPress={() => onChangeStatus(testCase.id, index)} > {messages[runCaseStatus.uid]} @@ -226,6 +239,29 @@ export default function TestCaseSelector({ onSelectionChange(keys); }; + // Test Case Detail + const [isTestCaseDetailDialogOpen, setIsTestCaseDetailDialogOpen] = useState(false); + const [showingTestCase, setShowingTestCase] = useState({ + id: 0, + title: '', + state: 0, + priority: 0, + type: 0, + automationStatus: 0, + description: '', + template: 0, + preConditions: '', + expectedResults: '', + folderId: 0, + }); + const showTestCaseDetailDialog = (showTestCase: CaseType) => { + setIsTestCaseDetailDialogOpen(true); + setShowingTestCase(showTestCase); + }; + const hideTestCaseDetailDialog = () => { + setIsTestCaseDetailDialogOpen(false); + }; + return ( <>
+ + onChangeStatus(showingCaseId, newStatus)} + messages={messages} + /> ); } diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/page.tsx b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/page.tsx index f53a060..b86c688 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/page.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/[runId]/page.tsx @@ -37,6 +37,24 @@ export default function Page({ params }: { params: { projectId: string; runId: s excludeFromRun: t('exclude_from_run'), noCasesFound: t('no_cases_found'), areYouSureLeave: t('are_you_sure_leave'), + type: t('type'), + other: t('other'), + security: t('security'), + performance: t('performance'), + accessibility: t('accessibility'), + functional: t('functional'), + acceptance: t('acceptance'), + usability: t('usability'), + smokeSanity: t('smoke_sanity'), + compatibility: t('compatibility'), + destructive: t('destructive'), + regression: t('regression'), + automated: t('automated'), + manual: t('manual'), + preconditions: t('preconditions'), + expectedResult: t('expected_result'), + detailsOfTheStep: t('details_of_the_step'), + close: t('close'), }; return ; diff --git a/frontend/types/case.ts b/frontend/types/case.ts index cdba0a8..ff945b6 100644 --- a/frontend/types/case.ts +++ b/frontend/types/case.ts @@ -123,12 +123,12 @@ type CaseMessages = { template: string; testDetail: string; preconditions: string; + expectedResult: string; step: string; text: string; steps: string; newStep: string; detailsOfTheStep: string; - expectedResult: string; deleteThisStep: string; insertStep: string; attachments: string; diff --git a/frontend/types/run.ts b/frontend/types/run.ts index 15285c7..93b72bf 100644 --- a/frontend/types/run.ts +++ b/frontend/types/run.ts @@ -83,6 +83,24 @@ type RunMessages = { excludeFromRun: string; noCasesFound: string; areYouSureLeave: string; + type: string; + other: string; + security: string; + performance: string; + accessibility: string; + functional: string; + acceptance: string; + usability: string; + smokeSanity: string; + compatibility: string; + destructive: string; + regression: string; + automated: string; + manual: string; + preconditions: string; + expectedResult: string; + detailsOfTheStep: string; + close: string; }; export type { RunType, RunCaseType, RunStatusCountType, ProgressSeriesType, RunsMessages, RunMessages };