/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ import {MemoryRouter, Route, Switch} from "react-router-dom"; import {render, screen, within} from "@testing-library/react"; import * as React from "react"; import Tasks, {Task} from "../views/Tasks"; import Actions, {Action} from "../views/Actions"; import {server} from "./mocks/server"; import {PathParams, ResponseResolver, rest, RestContext, RestRequest} from "msw"; import userEvent from "@testing-library/user-event"; import TaskDetail from "../views/TaskDetail"; const mockTasksList: Task[] = [ { name: "task1", taskId: "id1", description: "task 1 description", }, { name: "task2", taskId: "id2", description: "task 2 description", }, { name: "task3", taskId: "id3", description: "task 3 description", }, ] function getApiToken() { return "" //no need for api token in these tests } function renderTasksPage() { return render( ()} /> ()} /> ()} /> ) } function tasksApi() { return { returnsTasks: (tasks: Task[]) => { server.use( rest.get("/tasks", (request, response, context) => { return response( context.status(200), context.json(tasks) ) }) ) }, returnsTasksAfterDelay: (tasks: Task[], msDelay: number) => { server.use( rest.get("/tasks", (request, response, context) => { return response( context.delay(msDelay), context.status(200), context.json(tasks) ) }) ) }, returnsResponse: (resolver: ResponseResolver>, RestContext>) => { server.use( rest.get("/tasks", (request, response, context) => { return resolver(request, response, context); }) ) } } } async function tasksHaveLoaded() { //'taskname-panel' is included on all task panels as a testId await screen.findAllByTestId(/.*-panel/); } describe('ListTasks Page', ()=> { test('loads', async ()=> { renderTasksPage() expect(screen.getByRole('heading', {name:/Tasks/i})).toBeInTheDocument() }) test('displays all tasks', async ()=> { tasksApi().returnsTasks(mockTasksList); renderTasksPage() await tasksHaveLoaded() expect(screen.getByText(/task1/)).toBeInTheDocument() expect(screen.getByText(/task2/)).toBeInTheDocument() expect(screen.getByText(/task3/)).toBeInTheDocument() }) test('search bar filters tasks correctly', async ()=> { tasksApi().returnsTasks(mockTasksList); renderTasksPage() await tasksHaveLoaded() const searchBar = screen.getByRole('textbox') await userEvent.type(searchBar, "task1"); expect(screen.queryByText(/task1/)).toBeInTheDocument() expect(screen.queryByText(/task2/)).not.toBeInTheDocument() expect(screen.queryByText(/task3/)).not.toBeInTheDocument() }) test('search filter is case insensitive', async ()=> { tasksApi().returnsTasks(mockTasksList) renderTasksPage() await tasksHaveLoaded() const searchBar = screen.getByRole('textbox') await userEvent.type(searchBar, "tASk1"); expect(screen.queryByText(/task1/)).toBeInTheDocument() }) test('search filter performs partial matching', async ()=> { tasksApi().returnsTasks([{name: "ATaskWithAVeryVeryVeryLongName", taskId: "id", description: "description"}]) renderTasksPage() await tasksHaveLoaded() const searchBar = screen.getByRole('textbox') await userEvent.type(searchBar, "longname"); expect(screen.queryByText(/ATaskWithAVeryVeryVeryLongName/)).toBeInTheDocument() }) test('initial task sort order is ascending by name', async()=> { tasksApi().returnsTasks(mockTasksList) renderTasksPage() await tasksHaveLoaded() const tasks = screen.getAllByTestId(/.*-panel/); const task1Panel = screen.getByTestId(/task1-panel/); const task2Panel = screen.getByTestId(/task2-panel/); expect(tasks.indexOf(task1Panel)).toBeLessThan(tasks.indexOf(task2Panel)) screen.debug() }) test('user can select task sort order', async()=> { tasksApi().returnsTasks(mockTasksList) renderTasksPage() await tasksHaveLoaded() const task1Panel = screen.getByTestId(/task1-panel/); const task2Panel = screen.getByTestId(/task2-panel/); const sortOrderSelector = screen.getByRole('combobox') const ascOrderSortOption = within(sortOrderSelector).getByRole('option', {name: /a-z/i}); const descOrderSortOption = within(sortOrderSelector).getByRole('option', {name: /z-a/i}); await userEvent.selectOptions(sortOrderSelector, descOrderSortOption) //confirm descending sort order let tasks = screen.getAllByTestId(/.*-panel/); expect(tasks.indexOf(task1Panel)).toBeGreaterThan(tasks.indexOf(task2Panel)) await userEvent.selectOptions(sortOrderSelector, ascOrderSortOption) //confirm ascending sort order (user can switch back and forth tasks = screen.getAllByTestId(/.*-panel/); expect(tasks.indexOf(task1Panel)).toBeLessThan(tasks.indexOf(task2Panel)) }) test('each task has own details button', async ()=> { tasksApi().returnsTasks(mockTasksList) renderTasksPage() await tasksHaveLoaded() screen.getAllByTestId(/.*-panel/).forEach(task => { expect(within(task).queryByRole('button', {name:/detail/i})).toBeInTheDocument() }); }) test('get start button opens action select page', async ()=> { renderTasksPage() const getStartedButton = screen.getByRole('button', {name: /get started/i}) await userEvent.click(getStartedButton) expect(screen.queryByRole('heading', {name: /action catalog/i})).toBeInTheDocument() }) test('click task detail button opens correct details page', async ()=> { tasksApi().returnsTasks([{ name: "task1", taskId: "task1id", description: "task 1 description", },]) //necessary for taskdetails page server.use( rest.get("/tasks/task1id", (request, response, context) => { return response( context.status(200), context.json({ taskId: "task1id", name: "task1", }) ) }) ) renderTasksPage() await tasksHaveLoaded() const action1Panel = screen.getByTestId(/task1-panel/) const action1DetailsBtn = within(action1Panel).getByRole('button', {name:/detail/i}) await userEvent.click(action1DetailsBtn); expect(await screen.findByRole('heading', {name: /task detail/i})).toBeInTheDocument() expect(await screen.findByRole('heading', {name: /task1/i})).toBeInTheDocument() //requires refactoring of taskDetails to be testable }) test('shows error when tasks fail to load', async ()=> { tasksApi().returnsResponse((request, response, context) => { return response( context.status(500), context.json({ message: 'Error loading Actions' }) ) }) renderTasksPage(); expect(await screen.findByRole('alert')).toBeInTheDocument() }) test('shows loading bar while tasks are loading', async ()=> { tasksApi().returnsTasksAfterDelay(mockTasksList, 500) renderTasksPage() expect(await screen.findByRole('progressbar')).toBeInTheDocument() }) test('does not show loading bar when tasks have finished loading', async ()=> { tasksApi().returnsTasks(mockTasksList) renderTasksPage() await tasksHaveLoaded() expect(screen.queryByRole('progressbar')).not.toBeInTheDocument() }) })