Files
duty-teller/webapp/js/currentDuty.test.js
Nikolay Tatarinov e3240d0981 feat: enhance duty information handling with contact details and current duty view
- Added `bot_username` to settings for dynamic retrieval of the bot's username.
- Implemented `_resolve_bot_username` function to fetch the bot's username if not set, improving user experience in group chats.
- Updated `DutyWithUser` schema to include optional `phone` and `username` fields for enhanced duty information.
- Enhanced API responses to include contact details for users, ensuring better communication.
- Introduced a new current duty view in the web app, displaying active duty information along with contact options.
- Updated CSS styles for better presentation of contact information in duty cards.
- Added unit tests to verify the inclusion of contact details in API responses and the functionality of the current duty view.
2026-03-02 16:09:08 +03:00

122 lines
3.9 KiB
JavaScript

/**
* Unit tests for currentDuty (findCurrentDuty, renderCurrentDutyContent, showCurrentDutyView).
*/
import { describe, it, expect, beforeAll, vi } from "vitest";
vi.mock("./api.js", () => ({
fetchDuties: vi.fn().mockResolvedValue([])
}));
import {
findCurrentDuty,
renderCurrentDutyContent
} from "./currentDuty.js";
describe("currentDuty", () => {
beforeAll(() => {
document.body.innerHTML =
'<div id="loading"></div>' +
'<div class="container">' +
'<div id="calendarSticky"></div>' +
'<div id="dutyList"></div>' +
'<div id="currentDutyView" class="current-duty-view hidden"></div>' +
"</div>";
});
describe("findCurrentDuty", () => {
it("returns duty when now is between start_at and end_at", () => {
const now = new Date();
const start = new Date(now);
start.setHours(start.getHours() - 1, 0, 0, 0);
const end = new Date(now);
end.setHours(end.getHours() + 1, 0, 0, 0);
const duties = [
{
event_type: "duty",
full_name: "Иванов",
start_at: start.toISOString(),
end_at: end.toISOString()
}
];
const duty = findCurrentDuty(duties);
expect(duty).not.toBeNull();
expect(duty.full_name).toBe("Иванов");
});
it("returns null when no duty overlaps current time", () => {
const duties = [
{
event_type: "duty",
full_name: "Past",
start_at: "2020-01-01T09:00:00Z",
end_at: "2020-01-01T17:00:00Z"
},
{
event_type: "duty",
full_name: "Future",
start_at: "2030-01-01T09:00:00Z",
end_at: "2030-01-01T17:00:00Z"
}
];
expect(findCurrentDuty(duties)).toBeNull();
});
});
describe("renderCurrentDutyContent", () => {
it("renders no-duty message and back button when duty is null", () => {
const html = renderCurrentDutyContent(null, "en");
expect(html).toContain("current-duty-card");
expect(html).toContain("Current Duty");
expect(html).toContain("No one is on duty right now");
expect(html).toContain("Back to calendar");
expect(html).toContain('data-action="back"');
});
it("renders duty card with name, shift, and back button when duty has no contacts", () => {
const duty = {
event_type: "duty",
full_name: "Иванов Иван",
start_at: "2025-03-02T06:00:00.000Z",
end_at: "2025-03-03T06:00:00.000Z"
};
const html = renderCurrentDutyContent(duty, "ru");
expect(html).toContain("Текущее дежурство");
expect(html).toContain("Иванов Иван");
expect(html).toContain("Смена");
expect(html).toContain("Назад к календарю");
expect(html).toContain('data-action="back"');
});
it("renders duty card with phone and Telegram links when present", () => {
const duty = {
event_type: "duty",
full_name: "Alice",
start_at: "2025-03-02T09:00:00",
end_at: "2025-03-02T17:00:00",
phone: "+7 900 123-45-67",
username: "alice_dev"
};
const html = renderCurrentDutyContent(duty, "en");
expect(html).toContain("Alice");
expect(html).toContain("current-duty-contact-row");
expect(html).toContain('href="tel:');
expect(html).toContain("+7 900 123-45-67");
expect(html).toContain("https://t.me/");
expect(html).toContain("alice_dev");
expect(html).toContain("Back to calendar");
});
});
describe("showCurrentDutyView", () => {
it("hides the global loading element when called", async () => {
vi.resetModules();
const { showCurrentDutyView } = await import("./currentDuty.js");
await showCurrentDutyView(() => {});
const loading = document.getElementById("loading");
expect(loading).not.toBeNull();
expect(loading.classList.contains("hidden")).toBe(true);
});
});
});