Skip to content

Commit

Permalink
fix(SILVA-536): fixing missing notification when no param provided (#461
Browse files Browse the repository at this point in the history
)
  • Loading branch information
paulushcgcj authored Nov 13, 2024
1 parent 5e350e0 commit cdee258
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// src/__test__/components/SilvicultureSearch/Openings/OpeningsSearchBar.test.tsx

import React from "react";
import { render, screen } from "@testing-library/react";
import { render, screen, act } from "@testing-library/react";
import "@testing-library/jest-dom";
import OpeningsSearchBar from "../../../../components/SilvicultureSearch/Openings/OpeningsSearchBar";
import { vi } from "vitest";
Expand Down Expand Up @@ -36,7 +36,7 @@ describe("OpeningsSearchBar", () => {
expect(searchInput).toBeInTheDocument();
});

it("should call the onSearchClick function when the search button is clicked", () => {
it("should call the onSearchClick function when the search button is clicked", async () => {
// Create a mock function to pass as a prop
const onSearchClick = vi.fn();

Expand All @@ -48,7 +48,7 @@ describe("OpeningsSearchBar", () => {

// Click the search button
const searchButton = screen.getAllByRole("button", { name: "Search" })[1];
searchButton.click();
await act(async () => searchButton.click());

// Check if the onSearchClick function was called
expect(onSearchClick).toHaveBeenCalled();
Expand Down Expand Up @@ -119,4 +119,25 @@ describe("OpeningsSearchBar", () => {
const dNoneElement = screen.getByText('+2');
expect(dNoneElement).toBeInTheDocument();
});

it("should show inline notification when no filter provided", async () => {
// Create a mock function to pass as a prop
const onSearchClick = vi.fn();

const {container, getByText} = render(
<QueryClientProvider client={queryClient}>
<OpeningsSearchBar onSearchClick={onSearchClick} showNoFilterNotification={true} />
</QueryClientProvider>
);

// Click the search button
const searchButton = screen.getAllByRole("button", { name: "Search" })[1];
await act(async () => searchButton.click());

// Check if the onSearchClick function was called
expect(onSearchClick).toHaveBeenCalled();

expect(getByText("Missing at least one criteria to search")).toBeInTheDocument();

});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React from 'react';
import { render, screen, act, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';
import OpeningSearchTab from '../../../../components/SilvicultureSearch/Openings/OpeningsSearchTab';
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';
import { OpeningsSearchProvider, useOpeningsSearch } from "../../../../contexts/search/OpeningsSearch";
import { useOpeningsQuery } from "../../../../services/queries/search/openingQueries";
import { BrowserRouter } from 'react-router-dom';
import { NotificationProvider } from '../../../../contexts/NotificationProvider';
import PaginationProvider from '../../../../contexts/PaginationProvider';

const data = [{
id: '114207',
openingId: '114207',
fileId: 'TFL47',
cuttingPermit: '12S',
timberMark: '47/12S',
cutBlock: '12-69',
grossAreaHa: '12.9',
status: 'Free growing',
category: 'FTML',
disturbanceStart: '-',
createdAt: '2022-10-27',
orgUnit: 'DCC - Cariboo chilcotin natural resources',
lastViewed: '2022-10-27'
}];

vi.mock("../../../../services/queries/search/openingQueries", async () => {
const actual = await vi.importActual<typeof import("../../../../services/queries/search/openingQueries")>("../../../../services/queries/search/openingQueries");
return {
...actual,
useOpeningsQuery: vi.fn(),
};
});

describe('OpeningSearchTab', () => {
const queryClient = new QueryClient(); // here's the problem

beforeEach(() => {
vi.clearAllMocks();
});

it('should render without crashing', () => {
(useOpeningsQuery as vi.Mock).mockReturnValue({ data: [], isLoading: false });
const { getByText} = render(
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<PaginationProvider>
<OpeningsSearchProvider>
<NotificationProvider>
<OpeningSearchTab />
</NotificationProvider>
</OpeningsSearchProvider>
</PaginationProvider>
</QueryClientProvider>
</BrowserRouter>
);
expect(getByText('Advanced Search')).toBeInTheDocument();
});

it('should display the empty state', () => {
(useOpeningsQuery as vi.Mock).mockReturnValue({ data: [], isLoading: false });
const { getByText} = render(
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<PaginationProvider>
<OpeningsSearchProvider>
<NotificationProvider>
<OpeningSearchTab />
</NotificationProvider>
</OpeningsSearchProvider>
</PaginationProvider>
</QueryClientProvider>
</BrowserRouter>
);
expect(screen.getByText('Nothing to show yet')).toBeInTheDocument();
});

it('should have a search input field', () => {
(useOpeningsQuery as vi.Mock).mockReturnValue({ data: [], isLoading: false });
render(
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<PaginationProvider>
<OpeningsSearchProvider>
<NotificationProvider>
<OpeningSearchTab />
</NotificationProvider>
</OpeningsSearchProvider>
</PaginationProvider>
</QueryClientProvider>
</BrowserRouter>
);
expect(screen.getByPlaceholderText('Search by opening ID, opening number, timber mark or file ID')).toBeInTheDocument();
});

it('should display search results when search is performed', async () => {
(useOpeningsQuery as vi.Mock).mockReturnValue({ data, isFetching: false });

const { container } = render(
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<PaginationProvider>
<OpeningsSearchProvider>
<NotificationProvider>
<OpeningSearchTab />
</NotificationProvider>
</OpeningsSearchProvider>
</PaginationProvider>
</QueryClientProvider>
</BrowserRouter>
);
const searchInput = screen.getByPlaceholderText('Search by opening ID, opening number, timber mark or file ID') as HTMLInputElement;
await act(async () => userEvent.type(searchInput, 'test'));
await act(async () => (await screen.findByTestId('search-button')).click());
await act(async () => await screen.findByText('Actions'));
});

it('should display a message when no results are found', async () => {
(useOpeningsQuery as vi.Mock).mockReturnValue({ data: [], isLoading: false });

render(
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<PaginationProvider>
<OpeningsSearchProvider>
<NotificationProvider>
<OpeningSearchTab />
</NotificationProvider>
</OpeningsSearchProvider>
</PaginationProvider>
</QueryClientProvider>
</BrowserRouter>
);
const searchInput = screen.getByPlaceholderText('Search by opening ID, opening number, timber mark or file ID');
await act(async () => await userEvent.type(searchInput, 'potato'));
await act(async () => (await screen.findByTestId('search-button')).click());
expect(screen.getByText('Results not found')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
@use '@bcgov-nr/nr-theme/design-tokens/variables.scss' as vars;
@use '@bcgov-nr/nr-theme/design-tokens/colors.scss' as colors;
@use '@carbon/type';

.ddbbgg{
border: solid 1px pink !important;
}
.openings-searchbar-container{
padding: 32px 32px;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import React, { useEffect, useState } from "react";
import "./OpeningsSearchBar.scss";
import { Search, Button, FlexGrid, Row, Column, DismissibleTag } from "@carbon/react";
import { Search, Button, FlexGrid, Row, Column, DismissibleTag, InlineNotification } from "@carbon/react";
import * as Icons from "@carbon/icons-react";
import AdvancedSearchDropdown from "../AdvancedSearchDropdown";
import SearchFilterBar from "../SearchFilterBar";
import { useOpeningsSearch } from "../../../../contexts/search/OpeningsSearch";
import { countActiveFilters } from "../../../../utils/searchUtils";

interface IOpeningsSearchBar {
onSearchClick: Function;
onSearchClick: () => void;
showNoFilterNotification?: boolean;
}

const OpeningsSearchBar: React.FC<IOpeningsSearchBar> = ({
onSearchClick
onSearchClick,
showNoFilterNotification = false
}) => {
const [isOpen, setIsOpen] = useState<boolean>(false);
const [showFilters, setShowFilters] = useState<boolean>(false);
Expand Down Expand Up @@ -52,8 +54,19 @@ const OpeningsSearchBar: React.FC<IOpeningsSearchBar> = ({
<div>
<div>
<FlexGrid className="openings-searchbar-container">
{showNoFilterNotification && (
<Row>
<Column lg={8} xl={6} max={10} className="p-0 mb-2 mb-lg-0">
<Column lg={14} className="p-0 pb-3">
<InlineNotification
className="mw-100 w-100"
title="Missing at least one criteria to search"
subtitle="Please, start searching for an opening ID, opening number, timber mark, file ID or apply advanced search criteria"
lowContrast={true} />
</Column>
</Row>
)}
<Row>
<Column lg={8} xl={6} max={10} className="p-0 mb-2 mb-lg-0">
<Search
size="md"
placeholder="Search by opening ID, opening number, timber mark or file ID"
Expand Down Expand Up @@ -109,6 +122,7 @@ const OpeningsSearchBar: React.FC<IOpeningsSearchBar> = ({
<Column lg={0} className="p-0 mt-2">
<Button
className="search-button ms-xl-2"
data-testid="search-button"
renderIcon={Icons.Search}
type="button"
size="md"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const OpeningsSearchTab: React.FC = () => {
const [searchParams, setSearchParams] = useState<Record<string, any>>({});
const [finalParams, setFinalParams] = useState<Record<string, any>>({}); // Store params for query after search
const [isSearchTriggered, setIsSearchTriggered] = useState<boolean>(false); // Trigger state for search
const [isNoFilterSearch, setIsNoFilterSearch] = useState<boolean>(false); // Handles the notification for no filters applied
const { currentPage, itemsPerPage } = useContext(PaginationContext);

const [headers, setHeaders] = useState<ITableHeader[]>(columns);
Expand All @@ -35,11 +36,18 @@ const OpeningsSearchTab: React.FC = () => {
setFiltersApplied(!filtersApplied);
};

const hasFilters = countActiveFilters(filters) > 0 || searchTerm.length > 0;


const handleSearch = () => {
toggleFiltersApplied();
setFiltersApplied(true); // Set filters as applied to show results
setFinalParams({...searchParams, ...filters, page: currentPage, perPage: itemsPerPage }); // Only update finalParams on search
setIsSearchTriggered(true); // Trigger the search
setIsNoFilterSearch(!hasFilters);

if(hasFilters){
toggleFiltersApplied();
setFiltersApplied(true); // Set filters as applied to show results
setFinalParams({...searchParams, ...filters, page: currentPage, perPage: itemsPerPage }); // Only update finalParams on search
setIsSearchTriggered(true); // Trigger the search
}
};

const handleFiltersChanged = () => {
Expand Down Expand Up @@ -116,6 +124,7 @@ const OpeningsSearchTab: React.FC = () => {
<>
<div className="container-fluid p-0 pb-5 align-content-center">
<OpeningsSearchBar
showNoFilterNotification={isNoFilterSearch}
onSearchClick={handleSearch}
/>
{showSpatial ? (
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/TruncatedText/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const TruncatedText: React.FC<{text: string, maxLength?: number, parentWidth?: n
align="bottom-left"
autoAlign
>
<span>{truncated}</span>
<span aria-label={text}>{truncated}</span>
</Tooltip>;
}

Expand Down

0 comments on commit cdee258

Please sign in to comment.