aegida-console / components / chat / chat-header.test.tsx
chat-header.test.tsx
Raw
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";

import { ChatHeader } from "@/components/chat/chat-header";
import type { QuotaState } from "@/hooks/use-chat";

const models = [{ id: "qwen", name: "Qwen", description: "Qwen" }];

afterEach(cleanup);

describe("ChatHeader quota", () => {
  it.each([
    [{ status: "loading" } as QuotaState, "Баланс…"],
    [{ status: "unavailable" } as QuotaState, "Баланс недоступен"],
    [
      {
        status: "ready",
        snapshot: snapshot({ availableTokens: null, unlimited: true }),
      } as QuotaState,
      "Без лимита",
    ],
  ])("renders the established %s label", (quota, label) => {
    renderHeader(quota);

    expect(screen.getByText(label)).toBeInTheDocument();
  });

  it("formats finite tokens and an optional UTC reset", () => {
    renderHeader({
      status: "ready",
      snapshot: snapshot({
        availableTokens: 42_000,
        resetsAt: "2026-08-08T00:00:00Z",
      }),
    });

    expect(screen.getByText(/42.000 токенов/)).toBeInTheDocument();
    expect(screen.getByText(/UTC/)).toContainElement(screen.getByRole("time"));
    expect(screen.getByRole("time")).toHaveAttribute(
      "datetime",
      "2026-08-08T00:00:00Z",
    );
  });
});

function renderHeader(quota: QuotaState) {
  return render(
    <ChatHeader
      modelId="qwen"
      models={models}
      onModelChange={vi.fn()}
      onOpenMenu={vi.fn()}
      quota={quota}
    />,
  );
}

function snapshot(
  overrides: Partial<{
    availableTokens: number | null;
    unlimited: boolean;
    exhausted: boolean;
    resetsAt: string | null;
  }> = {},
) {
  return {
    object: "aegida.quota" as const,
    model: "qwen",
    availableTokens: 42_000,
    unlimited: false,
    exhausted: false,
    resetsAt: null,
    asOf: "2026-08-07T12:00:00Z",
    ...overrides,
  };
}