components/frontend/src/App.test.js
import { act, fireEvent, render, screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import history from "history/browser"
import * as auth from "./api/auth"
import * as fetch_server_api from "./api/fetch_server_api"
import App from "./App"
import * as toast from "./widgets/toast"
function set_user_in_local_storage(session_expiration_datetime, email) {
localStorage.setItem("user", "admin")
localStorage.setItem("email", email ?? "admin@example.org")
localStorage.setItem("session_expiration_datetime", session_expiration_datetime)
}
beforeAll(() => {
global.EventSource = jest.fn(() => ({
addEventListener: jest.fn(),
close: jest.fn(),
}))
Object.defineProperty(window, "matchMedia", {
value: jest.fn().mockImplementation((_query) => ({
matches: false,
addEventListener: () => {
/* No implementation needed */
},
removeEventListener: () => {
/* No implementation needed */
},
})),
})
})
beforeEach(() => {
history.push("")
fetch_server_api.fetch_server_api = jest.fn().mockReturnValue({
then: jest.fn().mockReturnValue({ catch: jest.fn().mockReturnValue({ finally: jest.fn() }) }),
})
})
afterEach(() => {
jest.restoreAllMocks()
})
it("shows spinner", async () => {
render(<App />)
expect(screen.getAllByLabelText(/Loading/).length).toBe(1)
})
it("sets the user from local storage", () => {
set_user_in_local_storage("3000-02-23T22:00:50.945Z")
render(<App />)
expect(screen.getAllByText(/admin/).length).toBe(1)
expect(screen.getAllByAltText(/Avatar/).length).toBe(1)
})
it("does not set invalid email addresses", () => {
set_user_in_local_storage("3000-02-23T22:00:50.945Z", "admin at example.org")
render(<App />)
expect(screen.getAllByText(/admin/).length).toBe(1)
expect(screen.queryAllByAltText(/Avatar/).length).toBe(0)
})
it("resets the user when the session is expired on mount", () => {
set_user_in_local_storage("2000-02-23T22:00:50.945Z")
render(<App />)
expect(screen.queryAllByText(/admin/).length).toBe(0)
})
it("resets the user when the user clicks logout", async () => {
set_user_in_local_storage("3000-02-23T22:00:50.945Z")
auth.logout = jest.fn().mockResolvedValue({ ok: true })
render(<App />)
await act(async () => {
fireEvent.click(screen.getByText(/admin/))
})
await act(async () => {
fireEvent.click(screen.getByText(/Logout/))
})
expect(screen.queryAllByText(/admin/).length).toBe(0)
})
it("handles a date change", async () => {
render(<App />)
await userEvent.type(screen.getByPlaceholderText("YYYY-MM-DD"), "2020-03-13")
expect(screen.getAllByDisplayValue("2020-03-13").length).toBe(1)
})
it("handles a date change between two dates in the past", async () => {
history.push("/?report_date=2022-03-13")
render(<App />)
await userEvent.type(screen.getByPlaceholderText("YYYY-MM-DD"), "{Backspace}4")
expect(screen.getAllByDisplayValue("2022-03-14").length).toBe(1)
})
it("reads the report date query parameter", () => {
history.push("/?report_date=2020-03-13")
render(<App />)
expect(screen.getAllByDisplayValue("2020-03-13").length).toBe(1)
})
it("handles a date reset", async () => {
history.push("/?report_date=2020-03-13")
render(<App />)
await act(async () => {
fireEvent.click(screen.getByRole("button", { name: "Close" }))
})
expect(screen.queryAllByDisplayValue("2020-03-13").length).toBe(0)
})
it("handles the nr of measurements event source", async () => {
const eventSourceInstance = {
addEventListener: jest.fn(),
close: jest.fn(),
}
const eventListeners = {}
eventSourceInstance.addEventListener.mockImplementation((event, listener) => {
eventListeners[event] = listener
})
const showMessage = jest.spyOn(toast, "showMessage")
global.EventSource = jest.fn(() => eventSourceInstance)
render(<App />)
await act(async () => eventListeners["init"]({ data: 42 }))
expect(showMessage).toHaveBeenCalledWith(
"info",
"Not logged in",
"You are not logged in. Editing is not possible until you are.",
)
await act(async () => eventListeners["delta"]({ data: 42 }))
await act(async () => eventListeners["delta"]({ data: 43 }))
await act(async () => eventListeners["error"]())
expect(showMessage).toHaveBeenCalledWith(
"error",
"Server unreachable",
"Trying to reconnect to server...",
"reconnecting",
)
await act(async () => eventListeners["init"]({ data: 43 }))
expect(showMessage).toHaveBeenCalledWith("success", "Connected to server", "Successfully reconnected to server.")
})