kandimat/redaktions-app/src/integration-tests/question-list.integration.test.tsx
2021-03-30 17:57:28 +02:00

175 lines
5.6 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 QuestionList from "../components/QuestionList";
import { SnackbarProvider } from "notistack";
import {
getAllQuestionsMock,
getQuestionByIdMock,
questionNodesMock,
} from "../backend/queries/question.mock";
import { getAllCategoriesMock } from "../backend/queries/category.mock";
import {
addQuestionMock,
deleteQuestionMock,
editQuestionMock,
} from "../backend/mutations/question.mock";
import {
expandAccordionAndGetIconButtons,
queryAllAddIconButtons,
queryAllEditIconButtons,
} from "./test-helper";
function renderQuestionList(additionalMocks?: Array<MockedResponse>) {
const initialMocks = [
...getAllQuestionsMock,
...getQuestionByIdMock,
...getAllCategoriesMock,
];
const allMocks = additionalMocks
? [...initialMocks, ...additionalMocks]
: initialMocks;
return render(
<MockedProvider mocks={allMocks}>
<MemoryRouter>
<SnackbarProvider>
<QuestionList />
</SnackbarProvider>
</MemoryRouter>
</MockedProvider>
);
}
const waitForInitialQuestionsToRender = async (): Promise<
Array<HTMLElement>
> => {
const numberOfQuestionsInMockQuery = questionNodesMock.length;
let questionCards: Array<HTMLElement> = [];
await waitFor(() => {
questionCards = screen.queryAllByRole("button", {
name: /Question [1-3]\?/,
});
expect(questionCards.length).toEqual(numberOfQuestionsInMockQuery);
});
return questionCards;
};
describe("The QuestionList", () => {
test("displays the existing questions, but not the details of it", async () => {
renderQuestionList();
const questionCards = await waitForInitialQuestionsToRender();
questionCards.forEach((card) => {
expect(card.innerHTML).toMatch(/Question [1-3]\?/);
});
expect(questionCards[0].innerHTML).toMatch(/Category 1/);
expect(queryAllEditIconButtons()).toHaveLength(0);
});
test("enables toggling details on each question", async () => {
renderQuestionList();
// Initial state: Every question card is not expanded
const questionCards = await waitForInitialQuestionsToRender();
// Expand first question card
await expandAccordionAndGetIconButtons(questionCards[0]);
// Shrink first question card again
fireEvent.click(questionCards[0]);
await waitFor(() => {
expect(queryAllEditIconButtons()).toHaveLength(0);
});
});
test("enables editing a question title", async () => {
renderQuestionList(editQuestionMock);
const questionCards = await waitForInitialQuestionsToRender();
const { editIconButton } = await expandAccordionAndGetIconButtons(
questionCards[0]
);
// open edit dialog
expect(screen.queryByText(/Frage bearbeiten/)).toBeNull();
fireEvent.click(editIconButton);
await waitFor(() => {
expect(screen.queryByText(/Frage bearbeiten/)).not.toBeNull();
});
// change question title
const questionTitleField = screen.getByDisplayValue(/Question 1/);
fireEvent.change(questionTitleField, {
target: { value: "New title for Question 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(/Frage bearbeiten/)).toBeNull();
expect(screen.queryByText(/New title for Question 1/)).not.toBeNull();
});
});
test("enables adding a question", async () => {
renderQuestionList(addQuestionMock);
await waitForInitialQuestionsToRender();
// open add dialog
const dialogIdentifier = /Neue Frage erstellen/;
expect(screen.queryByText(dialogIdentifier)).toBeNull();
const addButton = queryAllAddIconButtons()[0];
fireEvent.click(addButton);
await waitFor(() => {
expect(screen.queryByText(dialogIdentifier)).not.toBeNull();
});
// change question title
const questionTitleField = screen.getByLabelText(/Zusammenfassung/);
fireEvent.change(questionTitleField, {
target: { value: "New question?" },
});
await waitFor(() => {
expect(screen.queryByDisplayValue(/New question/)).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 question/)).not.toBeNull();
});
});
test("enables deleting a question", async () => {
renderQuestionList(deleteQuestionMock);
const questionCards = await waitForInitialQuestionsToRender();
expect(screen.queryByText(/Question 2/)).not.toBeNull();
const { deleteIconButton } = await expandAccordionAndGetIconButtons(
questionCards[1]
);
// open delete confirmation dialog
expect(screen.queryByText(/Frage löschen/)).toBeNull();
fireEvent.click(deleteIconButton);
await waitFor(() => {
expect(screen.queryByText(/Frage 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(/Frage löschen/)).toBeNull();
expect(screen.queryByText(/Question 2/)).toBeNull();
});
});
});