feat: added logic to search test cases by title and description (#337)

This commit is contained in:
Matheus Santana
2025-11-15 06:21:30 -03:00
committed by GitHub
parent 068e077805
commit 7db464e28b
10 changed files with 44 additions and 36 deletions

View File

@@ -223,6 +223,7 @@
"no_cases_found": "No test cases found",
"case_title": "Test Case Title",
"case_description": "Test Case Description",
"case_title_or_description": "Test case title or description",
"create": "Create",
"please_enter": "Please enter test case title",
"filter": "Filter",

View File

@@ -223,6 +223,7 @@
"no_cases_found": "テストケースがありません",
"case_title": "テストケースタイトル",
"case_description": "テストケース詳細",
"case_title_or_description": "テストケースのタイトルまたは説明",
"create": "作成",
"please_enter": "テストケースタイトルを入力してください",
"filter": "フィルター",

View File

@@ -223,6 +223,7 @@
"no_cases_found": "Nenhum caso de teste encontrado",
"case_title": "Título do Caso de Teste",
"case_description": "Descrição do Caso de Teste",
"case_title_or_description": "Título ou descrição do caso de teste",
"create": "Criar",
"please_enter": "Por favor, insira o título do caso de teste",
"filter": "Filtrar",

View File

@@ -34,7 +34,7 @@ export default function CasesPane({
}: Props) {
const [cases, setCases] = useState<CaseType[]>([]);
const [isCaseDialogOpen, setIsCaseDialogOpen] = useState(false);
const [titleFilter, setTitleFilter] = useState('');
const [searchFilter, setSearchFilter] = useState('');
const [priorityFilter, setPriorityFilter] = useState<number[]>([]);
const [typeFilter, setTypeFilter] = useState<number[]>([]);
const [tagFilter, setTagFilter] = useState<number[]>([]);
@@ -45,13 +45,13 @@ export default function CasesPane({
const router = useRouter();
const searchParams = useSearchParams();
const updateUrlParams = (updates: { title?: string; priority?: number[]; type?: number[]; tag?: number[] }) => {
const updateUrlParams = (updates: { search?: string; priority?: number[]; type?: number[]; tag?: number[] }) => {
const currentParams = new URLSearchParams(searchParams.toString());
if (updates.title) {
currentParams.set('title', updates.title);
if (updates.search) {
currentParams.set('search', updates.search);
} else {
currentParams.delete('title');
currentParams.delete('search');
}
if (updates.priority && updates.priority.length > 0) {
@@ -80,12 +80,12 @@ export default function CasesPane({
async function fetchDataEffect() {
if (!context.isSignedIn()) return;
const titleParam = searchParams.get('title') || '';
const searchParam = searchParams.get('search') || '';
const priorityParam = parseQueryParam(searchParams.get('priority'));
const typeParam = parseQueryParam(searchParams.get('type'));
const tagParam = parseQueryParam(searchParams.get('tag'));
setTitleFilter(titleParam);
setSearchFilter(searchParam);
setPriorityFilter(priorityParam);
setTypeFilter(typeParam);
setTagFilter(tagParam);
@@ -94,7 +94,7 @@ export default function CasesPane({
const data = await fetchCases(
context.token.access_token,
Number(folderId),
titleParam || undefined,
searchParam || undefined,
priorityParam.length > 0 ? priorityParam : undefined,
typeParam.length > 0 ? typeParam : undefined,
tagParam.length > 0 ? tagParam : undefined
@@ -143,12 +143,12 @@ export default function CasesPane({
await exportCases(context.token.access_token, Number(folderId), type);
};
const handleFilterChange = (title: string, priorities: number[], types: number[], tag: number[]) => {
setTitleFilter(title);
const handleFilterChange = (search: string, priorities: number[], types: number[], tag: number[]) => {
setSearchFilter(search);
setPriorityFilter(priorities);
setTypeFilter(types);
setTagFilter(tag);
updateUrlParams({ title: title, priority: priorities, type: types, tag: tag });
updateUrlParams({ search: search, priority: priorities, type: types, tag: tag });
};
// **************************************************************************
@@ -186,7 +186,7 @@ export default function CasesPane({
onDeleteCases={onDeleteCases}
onExportCases={onExportCases}
onFilterChange={handleFilterChange}
activeTitleFilter={titleFilter}
activeSearchFilter={searchFilter}
activePriorityFilters={priorityFilter}
activeTypeFilters={typeFilter}
activeTagFilters={tagFilter}

View File

@@ -23,12 +23,12 @@ type TestCaseFilterProps = {
messages: CasesMessages;
priorityMessages: PriorityMessages;
testTypeMessages: TestTypeMessages;
activeTitleFilter: string;
activeSearchFilter: string;
activePriorityFilters: number[];
activeTypeFilters: number[];
activeTagFilters: number[];
projectId: string;
onFilterChange: (title: string, priorities: number[], types: number[], tags: number[]) => void;
onFilterChange: (search: string, priorities: number[], types: number[], tags: number[]) => void;
};
type Tag = Pick<TagType, 'id' | 'name'>;
@@ -37,7 +37,7 @@ export default function TestCaseFilter({
messages,
priorityMessages,
testTypeMessages,
activeTitleFilter,
activeSearchFilter,
activePriorityFilters,
activeTypeFilters,
activeTagFilters,
@@ -45,7 +45,7 @@ export default function TestCaseFilter({
projectId,
}: TestCaseFilterProps) {
const tokenContext = useContext(TokenContext);
const [title, setTitle] = useState<string>('');
const [search, setSearch] = useState<string>('');
const [selectedPriorities, setSelectedPriorities] = useState<Selection>(new Set([]));
const [selectedTypes, setSelectedTypes] = useState<Selection>(new Set([]));
const [selectedTags, setSelectedTags] = useState<Selection>(new Set([]));
@@ -74,8 +74,8 @@ export default function TestCaseFilter({
}, [activeTagFilters]);
useEffect(() => {
setTitle(activeTitleFilter);
}, [activeTitleFilter]);
setSearch(activeSearchFilter);
}, [activeSearchFilter]);
useEffect(() => {
if (activePriorityFilters.length > 0) {
@@ -125,7 +125,7 @@ export default function TestCaseFilter({
.filter((id) => !isNaN(id));
}
onFilterChange(title, priorityIndices, typeIndices, tagIds);
onFilterChange(search, priorityIndices, typeIndices, tagIds);
};
const handleClearFilter = () => {
@@ -137,7 +137,7 @@ export default function TestCaseFilter({
return (
<div className="p-3">
<div className="mb-3 space-y-1">
<h3 className="text-default-500 text-small">{messages.caseTitle}</h3>
<h3 className="text-default-500 text-small">{messages.caseTitleOrDescription}</h3>
<Input
variant="bordered"
classNames={{
@@ -148,8 +148,8 @@ export default function TestCaseFilter({
size="sm"
startContent={<SearchIcon size={18} />}
type="search"
value={title}
onValueChange={setTitle}
value={search}
onValueChange={setSearch}
maxLength={100}
/>
</div>

View File

@@ -47,7 +47,7 @@ type Props = {
onDeleteCases: (caseIds: number[]) => void;
onExportCases: (type: string) => void;
onFilterChange: (query: string, priorities: number[], types: number[], tag: number[]) => void;
activeTitleFilter: string;
activeSearchFilter: string;
activePriorityFilters: number[];
activeTypeFilters: number[];
activeTagFilters: number[];
@@ -66,7 +66,7 @@ export default function TestCaseTable({
onDeleteCases,
onExportCases,
onFilterChange,
activeTitleFilter,
activeSearchFilter,
activePriorityFilters,
activeTypeFilters,
activeTagFilters,
@@ -105,7 +105,7 @@ export default function TestCaseTable({
>
{highlightSearchTerm({
text: cellValue as string,
searchTerm: activeTitleFilter,
searchTerm: activeSearchFilter,
})}
</Link>
);
@@ -147,7 +147,7 @@ export default function TestCaseTable({
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[activeTitleFilter]
[activeSearchFilter]
);
// **************************************************************************
@@ -155,7 +155,7 @@ export default function TestCaseTable({
// **************************************************************************
const [showFilter, setShowFilter] = useState(false);
const activeFilterNum =
(activeTitleFilter ? 1 : 0) + activePriorityFilters.length + activeTypeFilters.length + activeTagFilters.length;
(activeSearchFilter ? 1 : 0) + activePriorityFilters.length + activeTypeFilters.length + activeTagFilters.length;
// **************************************************************************
// select test case
@@ -318,7 +318,7 @@ export default function TestCaseTable({
messages={messages}
priorityMessages={priorityMessages}
testTypeMessages={testTypeMessages}
activeTitleFilter={activeTitleFilter}
activeSearchFilter={activeSearchFilter}
activePriorityFilters={activePriorityFilters}
activeTypeFilters={activeTypeFilters}
activeTagFilters={activeTagFilters}

View File

@@ -31,6 +31,7 @@ export default function Page({ params }: { params: { projectId: string; folderId
noCasesFound: t('no_cases_found'),
caseTitle: t('case_title'),
caseDescription: t('case_description'),
caseTitleOrDescription: t('case_title_or_description'),
create: t('create'),
pleaseEnter: t('please_enter'),
apply: t('apply'),

View File

@@ -79,6 +79,7 @@ type CasesMessages = {
noCasesFound: string;
caseTitle: string;
caseDescription: string;
caseTitleOrDescription: string;
create: string;
pleaseEnter: string;
filter: string;

View File

@@ -29,15 +29,15 @@ async function fetchCase(jwt: string, caseId: number) {
async function fetchCases(
jwt: string,
folderId: number,
title?: string,
search?: string,
priority?: number[],
type?: number[],
tag?: number[]
) {
const queryParams = [`folderId=${folderId}`];
if (title) {
queryParams.push(`title=${title}`);
if (search) {
queryParams.push(`search=${search}`);
}
if (priority && priority.length > 0) {