122 lines
4.7 KiB
TypeScript
122 lines
4.7 KiB
TypeScript
import React from 'react';
|
|
import {fireEvent, queryAllByRole, render, screen, waitFor} from '@testing-library/react'
|
|
import {MockedProvider} from '@apollo/client/testing';
|
|
import {MemoryRouter} from 'react-router-dom';
|
|
import QuestionList from "../components/QuestionList";
|
|
import {SnackbarProvider} from "notistack";
|
|
import {getAllQuestionsMock, questionNodesMock} from "../backend/queries/question.mock";
|
|
import {getAllCategoriesMock} from "../backend/queries/category.mock";
|
|
import {editQuestionMock} from "../backend/mutations/question.mock";
|
|
import {getDeleteIconPath, getEditIconPath} from "./test-helper";
|
|
|
|
|
|
function renderQuestionList() {
|
|
return render(
|
|
<MockedProvider mocks={[...getAllQuestionsMock, ...getAllCategoriesMock, ...editQuestionMock]}>
|
|
<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;
|
|
}
|
|
|
|
// sorry, I found no better way to find a specific icon button...
|
|
const queryAllEditIconsButtons = (container?: HTMLElement): Array<HTMLElement> => {
|
|
return (container ? queryAllByRole(container, "button") : screen.queryAllByRole("button"))
|
|
.filter(button => button.innerHTML.includes("svg") && button.innerHTML.includes(getEditIconPath()));
|
|
}
|
|
|
|
// sorry, I found no better way to find a specific icon button...
|
|
const queryAllDeleteIconsButtons = (container?: HTMLElement): Array<HTMLElement> => {
|
|
return (container ? queryAllByRole(container, "button") : screen.queryAllByRole("button"))
|
|
.filter(button => button.innerHTML.includes("svg") && button.innerHTML.includes(getDeleteIconPath()));
|
|
}
|
|
|
|
const expandAccordionAndGetIconButtons = async (accordion: HTMLElement): Promise<{ editIconButton: HTMLElement, deleteIconButton: HTMLElement }> => {
|
|
let editIconsButtons = queryAllDeleteIconsButtons();
|
|
let deleteIconsButtons = queryAllEditIconsButtons();
|
|
expect(editIconsButtons).toHaveLength(0);
|
|
expect(deleteIconsButtons).toHaveLength(0);
|
|
fireEvent.click(accordion);
|
|
await waitFor(() => {
|
|
editIconsButtons = queryAllEditIconsButtons();
|
|
deleteIconsButtons = queryAllDeleteIconsButtons();
|
|
expect(editIconsButtons).toHaveLength(1);
|
|
expect(deleteIconsButtons).toHaveLength(1);
|
|
})
|
|
return {
|
|
editIconButton: editIconsButtons[0],
|
|
deleteIconButton: deleteIconsButtons[0]
|
|
};
|
|
}
|
|
|
|
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(queryAllEditIconsButtons()).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(queryAllEditIconsButtons()).toHaveLength(0)
|
|
});
|
|
});
|
|
|
|
test('enables editing a question title', async () => {
|
|
renderQuestionList();
|
|
|
|
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();
|
|
})
|
|
const confirmButton = screen.getByRole("button", {name: /Speichern/});
|
|
|
|
// call backend and assert apollo cache update
|
|
fireEvent.click(confirmButton);
|
|
await waitFor(() => {
|
|
expect(screen.queryByText(/Frage bearbeiten/)).toBeNull();
|
|
expect(screen.queryByText(/New title for Question 1/)).not.toBeNull()
|
|
})
|
|
});
|
|
});
|