147 lines
5.2 KiB
TypeScript
147 lines
5.2 KiB
TypeScript
import { render, screen, waitFor } from "@testing-library/react"
|
|
import userEvent from "@testing-library/user-event"
|
|
import { MemoryRouter } from "react-router-dom"
|
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
|
import { ChannelsPage } from "./ChannelsPage"
|
|
import { AuthProvider } from "@/auth/AuthContext"
|
|
import { api } from "@/api/client"
|
|
import { vi, beforeEach, test, expect } from "vitest"
|
|
import type { Channel } from "@/api/types"
|
|
|
|
const PROJECT_ID = "p1"
|
|
const channels: Channel[] = [
|
|
{ id: "c1", type: "telegram", config: { chat_id: "123456" }, enabled: true },
|
|
{ id: "c2", type: "webhook", config: { url: "https://hooks.example.com/x" }, enabled: false },
|
|
]
|
|
|
|
function renderPage() {
|
|
const qc = new QueryClient()
|
|
return render(
|
|
<QueryClientProvider client={qc}>
|
|
<AuthProvider>
|
|
<MemoryRouter initialEntries={["/channels"]}>
|
|
<ChannelsPage />
|
|
</MemoryRouter>
|
|
</AuthProvider>
|
|
</QueryClientProvider>,
|
|
)
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.restoreAllMocks()
|
|
vi.spyOn(api.auth, "me").mockResolvedValue({
|
|
user: { id: "u1", email: "a@b.com" },
|
|
project: { id: PROJECT_ID, name: "Default" },
|
|
})
|
|
vi.spyOn(api, "listChannels").mockResolvedValue(channels)
|
|
})
|
|
|
|
test("отрисовывает список каналов без секрета", async () => {
|
|
renderPage()
|
|
|
|
expect(await screen.findByText("telegram")).toBeInTheDocument()
|
|
expect(screen.getByText("webhook")).toBeInTheDocument()
|
|
expect(screen.getByText(/123456/)).toBeInTheDocument()
|
|
expect(screen.getByText(/hooks\.example\.com/)).toBeInTheDocument()
|
|
|
|
expect(document.body.textContent).not.toMatch(/bot_token/i)
|
|
expect(screen.queryByDisplayValue(/123456/)).not.toBeInTheDocument()
|
|
})
|
|
|
|
test("создание telegram-канала собирает config.chat_id + secret=bot_token", async () => {
|
|
const createSpy = vi.spyOn(api, "createChannel").mockResolvedValue({
|
|
id: "c3", type: "telegram", config: { chat_id: "999" }, enabled: true,
|
|
})
|
|
const user = userEvent.setup()
|
|
renderPage()
|
|
|
|
await screen.findByText("telegram")
|
|
|
|
await user.click(screen.getByRole("combobox", { name: /тип канала/i }))
|
|
await user.click(await screen.findByRole("option", { name: /telegram/i }))
|
|
|
|
await user.type(screen.getByLabelText(/chat id/i), "999")
|
|
await user.type(screen.getByLabelText(/bot token/i), "SECRET_TOKEN")
|
|
await user.click(screen.getByRole("button", { name: /добавить канал/i }))
|
|
|
|
await waitFor(() =>
|
|
expect(createSpy).toHaveBeenCalledWith(PROJECT_ID, {
|
|
type: "telegram",
|
|
config: { chat_id: "999" },
|
|
secret: "SECRET_TOKEN",
|
|
}),
|
|
)
|
|
|
|
expect(document.body.textContent).not.toMatch(/SECRET_TOKEN/)
|
|
})
|
|
|
|
test("создание webhook-канала собирает config.url без секрета", async () => {
|
|
const createSpy = vi.spyOn(api, "createChannel").mockResolvedValue({
|
|
id: "c4", type: "webhook", config: { url: "https://hooks.example.com/y" }, enabled: true,
|
|
})
|
|
const user = userEvent.setup()
|
|
renderPage()
|
|
|
|
await screen.findByText("telegram")
|
|
|
|
await user.click(screen.getByRole("combobox", { name: /тип канала/i }))
|
|
await user.click(await screen.findByRole("option", { name: /webhook/i }))
|
|
|
|
await user.type(screen.getByLabelText(/url/i), "https://hooks.example.com/y")
|
|
await user.click(screen.getByRole("button", { name: /добавить канал/i }))
|
|
|
|
await waitFor(() =>
|
|
expect(createSpy).toHaveBeenCalledWith(PROJECT_ID, {
|
|
type: "webhook",
|
|
config: { url: "https://hooks.example.com/y" },
|
|
secret: "",
|
|
}),
|
|
)
|
|
})
|
|
|
|
test("удаление канала вызывает api.deleteChannel", async () => {
|
|
const deleteSpy = vi.spyOn(api, "deleteChannel").mockResolvedValue(undefined)
|
|
vi.spyOn(window, "confirm").mockReturnValue(true)
|
|
const user = userEvent.setup()
|
|
renderPage()
|
|
|
|
await screen.findByText("telegram")
|
|
|
|
await user.click(screen.getByRole("button", { name: /удалить канал telegram/i }))
|
|
|
|
await waitFor(() => expect(deleteSpy).toHaveBeenCalledWith(PROJECT_ID, "c1"))
|
|
})
|
|
|
|
test("кнопка «Тест» вызывает api.testChannel", async () => {
|
|
const testSpy = vi.spyOn(api, "testChannel").mockResolvedValue({ status: "ok" })
|
|
const user = userEvent.setup()
|
|
renderPage()
|
|
|
|
await screen.findByText("telegram")
|
|
|
|
const testButtons = screen.getAllByRole("button", { name: /тест/i })
|
|
await user.click(testButtons[0])
|
|
|
|
await waitFor(() => expect(testSpy).toHaveBeenCalledWith(PROJECT_ID, "c1"))
|
|
})
|
|
|
|
test("ошибка тест-отправки отображается как alert", async () => {
|
|
vi.spyOn(api, "testChannel").mockRejectedValue(new Error("Канал не отвечает"))
|
|
const user = userEvent.setup()
|
|
renderPage()
|
|
|
|
await screen.findByText("telegram")
|
|
|
|
const testButtons = screen.getAllByRole("button", { name: /тест/i })
|
|
await user.click(testButtons[0])
|
|
|
|
expect(await screen.findByRole("alert")).toHaveTextContent("Канал не отвечает")
|
|
})
|
|
|
|
test("пустое состояние при отсутствии каналов", async () => {
|
|
vi.spyOn(api, "listChannels").mockResolvedValue([])
|
|
renderPage()
|
|
|
|
expect(await screen.findByText(/каналов пока нет/i)).toBeInTheDocument()
|
|
})
|