diff --git a/dashboard/package.json b/dashboard/package.json index a373f6882f..439e4a6032 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -37,9 +37,16 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", - "test": "react-scripts test", + "test": "react-scripts test --coverage", "eject": "react-scripts eject" }, + "jest":{ + "transform": { + "^.+\\.[t|j]sx?$": "babel-jest" + }, + "transformIgnorePatterns":["node_modules/(?!@patternfly)/"] + } + , "eslintConfig": { "extends": [ "react-app", @@ -59,7 +66,10 @@ ] }, "devDependencies": { + "@babel/preset-env": "^7.17.10", + "babel-jest": "^28.1.0", "css-loader": "^6.7.1", + "jest": "^28.1.0", "less": "^4.1.2", "less-loader": "^10.2.0", "style-loader": "^3.3.1" diff --git a/dashboard/public/index.html b/dashboard/public/index.html index 896deda7e5..a386a682bc 100644 --- a/dashboard/public/index.html +++ b/dashboard/public/index.html @@ -30,7 +30,7 @@ Notice the use of %PUBLIC_URL% in the tags above. It will be replaced with the URL of the `public` folder during the build. Only files inside the `public` folder can be referenced from the HTML. - + Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. diff --git a/dashboard/src/App.js b/dashboard/src/App.js index 5301b7cce5..c9e3f58991 100644 --- a/dashboard/src/App.js +++ b/dashboard/src/App.js @@ -10,7 +10,7 @@ import MainLayout from 'modules/containers/MainLayout'; function App() { useEffect(() => { const faviconLogo = document.getElementById("favicon"); - faviconLogo.setAttribute("href", favicon); + faviconLogo?.setAttribute("href", favicon); }, []); return ( diff --git a/dashboard/src/App.test.js b/dashboard/src/App.test.js deleted file mode 100644 index 1f03afeece..0000000000 --- a/dashboard/src/App.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/dashboard/src/modules/components/AlertComponent/Alert.test.js b/dashboard/src/modules/components/AlertComponent/Alert.test.js new file mode 100644 index 0000000000..eeac933b88 --- /dev/null +++ b/dashboard/src/modules/components/AlertComponent/Alert.test.js @@ -0,0 +1,26 @@ +import { Provider } from "react-redux"; +import store from "store/store"; +import App from "../../../App"; +const { render, screen, fireEvent } = require("@testing-library/react"); +const AppWrapper = () => { + return ( + + + + ); +}; +test("Alert message is displayed on initial load", () => { + render(); + const alert = screen.getByText('Want to see your own data?'); + expect(alert).toBeInTheDocument(); +}); + +test("Alert message is closed on clicking close button", () => { + render(); + const alert = screen.getByText('Want to see your own data?'); + const closeButton = screen.getByRole("button", { + name: /close info alert/i, + }); + fireEvent.click(closeButton); + expect(alert).not.toBeVisible(); +}); diff --git a/dashboard/src/modules/components/DatePickerComponent/DatePicker.test.js b/dashboard/src/modules/components/DatePickerComponent/DatePicker.test.js new file mode 100644 index 0000000000..aa325e4ff9 --- /dev/null +++ b/dashboard/src/modules/components/DatePickerComponent/DatePicker.test.js @@ -0,0 +1,39 @@ +import { Provider } from "react-redux"; +import store from "store/store"; +import { MOCK_DATA } from "utils/mockData"; +import App from "../../../App"; +const { render, screen, fireEvent } = require("@testing-library/react"); +const AppWrapper = () => { + return ( + + + + ); +}; +jest.mock("utils/api", () => { + return { + get: () => ({ + data: MOCK_DATA, + status:200 + }), + }; +}); +test("data is filtered based on date range selected from date picker", async () => { + render(); + await screen.findByText("pbench_user_benchmark1"); + const datePickerInput = screen.getAllByPlaceholderText('YYYY-MM-DD'); + fireEvent.change(datePickerInput[0], { target: { value: "2022-02-16" } }); + fireEvent.change(datePickerInput[1], { target: { value: "2022-02-20" } }); + const updateBtn = screen.getByRole("button", { name: 'Update'}); + fireEvent.click(updateBtn); + const datasetNameOne = screen.queryByText("pbench_user_benchmark1"); + const datasetNameTwo = screen.queryByText("pbench_user_benchmark2"); + const datasetNameThree = screen.queryByText("pbench_user_benchmark3"); + const datasetNameFour = screen.queryByText("pbench_user_benchmark4"); + const datasetNameFive = screen.queryByText("pbench_user_benchmark5"); + expect(datasetNameOne).toBeInTheDocument(); + expect(datasetNameTwo).toBeInTheDocument(); + expect(datasetNameThree).toBeInTheDocument(); + expect(datasetNameFour).not.toBeInTheDocument(); + expect(datasetNameFive).not.toBeInTheDocument(); +}); diff --git a/dashboard/src/modules/components/TableComponent/Table.test.js b/dashboard/src/modules/components/TableComponent/Table.test.js new file mode 100644 index 0000000000..6c8474f57a --- /dev/null +++ b/dashboard/src/modules/components/TableComponent/Table.test.js @@ -0,0 +1,78 @@ +import { Provider } from "react-redux"; +import store from "store/store"; +import { MOCK_DATA } from "utils/mockData"; +import App from "../../../App"; +const { render, screen, fireEvent } = require("@testing-library/react"); +const AppWrapper = () => { + return ( + + + + ); +}; +jest.mock("utils/api", () => { + return { + get: () => ({ + data: MOCK_DATA, + status: 200, + }), + }; +}); +test("Page heading is displayed on initial load", async () => { + render(); + await screen.findByText("pbench_user_benchmark1"); + const heading = screen.getByRole("heading", { name: 'Results' }); + expect(heading).toBeInTheDocument(); +}); +test("data from API is displayed on initial load", async () => { + render(); + await screen.findByText("pbench_user_benchmark1"); + const datasetNameOne = screen.queryByText("pbench_user_benchmark1"); + const datasetNameTwo = screen.queryByText("pbench_user_benchmark2"); + const datasetNameThree = screen.queryByText("pbench_user_benchmark3"); + const datasetNameFour = screen.queryByText("pbench_user_benchmark4"); + const datasetNameFive = screen.queryByText("pbench_user_benchmark5"); + expect(datasetNameOne).toBeInTheDocument(); + expect(datasetNameTwo).toBeInTheDocument(); + expect(datasetNameThree).toBeInTheDocument(); + expect(datasetNameFour).toBeInTheDocument(); + expect(datasetNameFive).toBeInTheDocument(); +}); + +test("row is favorited after clicking on favorite icon", async () => { + render(); + await screen.findByText("pbench_user_benchmark1"); + const starBtn = screen.getAllByRole("button", { + name: 'Not starred', + }); + fireEvent.click(starBtn[0]); + fireEvent.click(starBtn[1]); + const favoriteBtn = screen.getByRole("button", { + name: 'see favorites button', + }); + fireEvent.click(favoriteBtn); + const datasetNameOne = screen.queryByText("pbench_user_benchmark1"); + const datasetNameTwo = screen.queryByText("pbench_user_benchmark2"); + const datasetNameThree = screen.queryByText("pbench_user_benchmark3"); + const datasetNameFour = screen.queryByText("pbench_user_benchmark4"); + const datasetNameFive = screen.queryByText("pbench_user_benchmark5"); + expect(datasetNameOne).toBeInTheDocument(); + expect(datasetNameTwo).toBeInTheDocument(); + expect(datasetNameThree).not.toBeInTheDocument(); + expect(datasetNameFour).not.toBeInTheDocument(); + expect(datasetNameFive).not.toBeInTheDocument(); +}); +test("data is filtered based on value in search box", async () => { + render(); + await screen.findByText("pbench_user_benchmark1"); + const searchBox = screen.getByPlaceholderText('Search Dataset'); + fireEvent.change(searchBox, { target: { value: "pbench_user_benchmark2" } }); + const searchBtn = screen.getByRole("button", { + name: 'searchButton', + }); + fireEvent.click(searchBtn); + const datasetNameTwo = screen.queryByText("pbench_user_benchmark2"); + const datasetNameThree = screen.queryByText("pbench_user_benchmark3"); + expect(datasetNameTwo).toBeInTheDocument(); + expect(datasetNameThree).not.toBeInTheDocument(); +}); diff --git a/dashboard/src/modules/components/TableComponent/common-components.jsx b/dashboard/src/modules/components/TableComponent/common-components.jsx index edb1c30c03..16d0f23bef 100644 --- a/dashboard/src/modules/components/TableComponent/common-components.jsx +++ b/dashboard/src/modules/components/TableComponent/common-components.jsx @@ -79,10 +79,10 @@ export const SearchBox = ({ setSearchKey(e)} > - diff --git a/dashboard/src/modules/components/TableComponent/index.jsx b/dashboard/src/modules/components/TableComponent/index.jsx index 69f1062d6d..8845d6fd89 100644 --- a/dashboard/src/modules/components/TableComponent/index.jsx +++ b/dashboard/src/modules/components/TableComponent/index.jsx @@ -26,11 +26,11 @@ import DatePickerWidget from "../DatePickerComponent"; import PathBreadCrumb from "../BreadCrumbComponent"; import { LoginHint, Heading, EmptyTable, SearchBox } from "./common-components"; import { getTodayMidnightUTCDate } from "utils/dateFunctions"; +import { bumpToDate } from "utils/dateFunctions"; let startDate = new Date(Date.UTC(1990, 10, 4)); -let endDate = getTodayMidnightUTCDate(); +let endDate = bumpToDate(getTodayMidnightUTCDate(),1); let datasetName = ""; -let dataArray = []; const TableWithFavorite = () => { const columnNames = { @@ -51,7 +51,7 @@ const TableWithFavorite = () => { dispatch(getFavoritedDatasets()); }, [dispatch]); - const { publicData, favoriteRepoNames } = useSelector( + const { publicData, favoriteRepoNames,tableData } = useSelector( (state) => state.datasetlist ); const setPublicData = (data) => { @@ -141,20 +141,17 @@ const TableWithFavorite = () => { - +
{ isSelected={isSelected === "datasetListButton"} onChange={handleButtonClick} className="datasetListButton" + aria-label="see dataset button" /> { isSelected={isSelected === "favoriteListButton"} onChange={handleButtonClick} className="favoriteListButton" + aria-label="see favorites button" /> diff --git a/dashboard/src/utils/mockData.js b/dashboard/src/utils/mockData.js new file mode 100644 index 0000000000..ec7e17b00e --- /dev/null +++ b/dashboard/src/utils/mockData.js @@ -0,0 +1,32 @@ +export const MOCK_DATA = [ + { + name: "pbench_user_benchmark1", + metadata: { + "dataset.created": "2022-02-16T13:21:29+00:00", + }, + }, + { + name: "pbench_user_benchmark2", + metadata: { + "dataset.created": "2022-02-18T13:21:29+00:00", + }, + }, + { + name: "pbench_user_benchmark3", + metadata: { + "dataset.created": "2022-02-20T13:21:29+00:00", + }, + }, + { + name: "pbench_user_benchmark4", + metadata: { + "dataset.created": "2022-02-25T13:21:29+00:00", + }, + }, + { + name: "pbench_user_benchmark5", + metadata: { + "dataset.created": "2022-03-08T13:21:29+00:00", + }, + }, +];