145 lines
5.3 KiB
TypeScript
145 lines
5.3 KiB
TypeScript
import React from 'react';
|
|
import {fireEvent, render, screen, waitFor} from '@testing-library/react'
|
|
import {MockedProvider, MockedResponse} from '@apollo/client/testing';
|
|
import {MemoryRouter} from 'react-router-dom';
|
|
import CategoryList from "../components/CategoryList";
|
|
import {SnackbarProvider} from "notistack";
|
|
import {categoryNodesMock, getAllCategoriesMock} from "../backend/queries/category.mock";
|
|
import {addCategoryMock, deleteCategoryMock, editCategoryMock} from "../backend/mutations/category.mock";
|
|
import {expandAccordionAndGetIconButtons, queryAllAddIconButtons, queryAllEditIconButtons} from "./test-helper";
|
|
|
|
|
|
describe('The CategoryList', () => {
|
|
test('displays the existing categories, but not the details of it', async () => {
|
|
renderCategoryList();
|
|
|
|
const categoryCards = await waitForInitialCategoriesToRender()
|
|
categoryCards.forEach(card => {
|
|
expect(card.innerHTML).toMatch(/Category [1-2]/)
|
|
})
|
|
expect(queryAllEditIconButtons()).toHaveLength(0)
|
|
});
|
|
|
|
test('enables toggling details on each category', async () => {
|
|
renderCategoryList();
|
|
|
|
// Initial state: Every category card is not expanded
|
|
const categoryCards = await waitForInitialCategoriesToRender()
|
|
|
|
// Expand first category card
|
|
await expandAccordionAndGetIconButtons(categoryCards[0])
|
|
|
|
// Shrink first category card again
|
|
fireEvent.click(categoryCards[0])
|
|
await waitFor(() => {
|
|
expect(queryAllEditIconButtons()).toHaveLength(0)
|
|
});
|
|
});
|
|
|
|
test('enables editing a category title', async () => {
|
|
renderCategoryList(editCategoryMock);
|
|
|
|
const categoryCards = await waitForInitialCategoriesToRender();
|
|
const {editIconButton} = await expandAccordionAndGetIconButtons(categoryCards[0]);
|
|
|
|
// open edit dialog
|
|
expect(screen.queryByText(/Kategorie bearbeiten/)).toBeNull();
|
|
fireEvent.click(editIconButton);
|
|
await waitFor(() => {
|
|
expect(screen.queryByText(/Kategorie bearbeiten/)).not.toBeNull();
|
|
})
|
|
|
|
// change category title
|
|
const categoryTitleField = screen.getByDisplayValue(/Category 1/);
|
|
fireEvent.change(categoryTitleField, {target: {value: "New title for Category 1"}});
|
|
await waitFor(() => {
|
|
expect(screen.queryByDisplayValue(/New title for /)).not.toBeNull();
|
|
})
|
|
|
|
// call backend and assert apollo cache update
|
|
const confirmButton = screen.getByRole("button", {name: /Speichern/});
|
|
fireEvent.click(confirmButton);
|
|
await waitFor(() => {
|
|
expect(screen.queryByText(/Kategorie bearbeiten/)).toBeNull();
|
|
expect(screen.queryByText(/New title for Category 1/)).not.toBeNull()
|
|
})
|
|
});
|
|
|
|
test('enables adding a category', async () => {
|
|
renderCategoryList(addCategoryMock);
|
|
await waitForInitialCategoriesToRender();
|
|
|
|
// open add dialog
|
|
const dialogIdentifier = /Neue Kategorie erstellen/;
|
|
expect(screen.queryByText(dialogIdentifier)).toBeNull();
|
|
const addButton = queryAllAddIconButtons()[0];
|
|
fireEvent.click(addButton);
|
|
await waitFor(() => {
|
|
expect(screen.queryByText(dialogIdentifier)).not.toBeNull();
|
|
})
|
|
|
|
// change category title
|
|
const categoryTitleField = screen.getByLabelText(/Zusammenfassung/);
|
|
fireEvent.change(categoryTitleField, {target: {value: "New category"}});
|
|
await waitFor(() => {
|
|
expect(screen.queryByDisplayValue(/New category/)).not.toBeNull();
|
|
})
|
|
|
|
// call backend and assert apollo cache update
|
|
const confirmButton = screen.getByRole("button", {name: /Erstellen/});
|
|
fireEvent.click(confirmButton);
|
|
await waitFor(() => {
|
|
expect(screen.queryByText(dialogIdentifier)).toBeNull();
|
|
expect(screen.queryByText(/New category/)).not.toBeNull()
|
|
})
|
|
});
|
|
|
|
test('enables deleting a category', async () => {
|
|
renderCategoryList(deleteCategoryMock);
|
|
|
|
const categoryCards = await waitForInitialCategoriesToRender();
|
|
expect(screen.queryByText(/Category 2/)).not.toBeNull();
|
|
const {deleteIconButton} = await expandAccordionAndGetIconButtons(categoryCards[1]);
|
|
|
|
// open delete confirmation dialog
|
|
expect(screen.queryByText(/Kategorie löschen/)).toBeNull();
|
|
fireEvent.click(deleteIconButton);
|
|
await waitFor(() => {
|
|
expect(screen.queryByText(/Kategorie löschen/)).not.toBeNull();
|
|
})
|
|
|
|
// call backend and assert apollo cache update
|
|
const confirmButton = screen.getByRole("button", {name: /Löschen/});
|
|
fireEvent.click(confirmButton);
|
|
await waitFor(() => {
|
|
expect(screen.queryByText(/Kategorie löschen/)).toBeNull();
|
|
expect(screen.queryByText(/Category 2/)).toBeNull();
|
|
})
|
|
});
|
|
});
|
|
|
|
function renderCategoryList(additionalMocks?: Array<MockedResponse>) {
|
|
const initialMocks = [...getAllCategoriesMock];
|
|
const allMocks = additionalMocks ? [...initialMocks, ...additionalMocks] : initialMocks
|
|
return render(
|
|
<MockedProvider mocks={allMocks}>
|
|
<MemoryRouter>
|
|
<SnackbarProvider>
|
|
<CategoryList/>
|
|
</SnackbarProvider>
|
|
</MemoryRouter>
|
|
</MockedProvider>
|
|
);
|
|
}
|
|
|
|
const waitForInitialCategoriesToRender = async (): Promise<Array<HTMLElement>> => {
|
|
const numberOfCategoriesInMockQuery = categoryNodesMock.length;
|
|
let categoryCards: Array<HTMLElement> = [];
|
|
await waitFor(() => {
|
|
categoryCards = screen.queryAllByRole("button", {name: /Category [1-2]/})
|
|
expect(categoryCards.length).toEqual(numberOfCategoriesInMockQuery);
|
|
});
|
|
return categoryCards;
|
|
}
|
|
|