Files
duty-teller/webapp/js/contactHtml.test.js
Nikolay Tatarinov 0d28123d0b
All checks were successful
CI / lint-and-test (push) Successful in 35s
Docker Build and Release / build-and-push (push) Successful in 51s
Docker Build and Release / release (push) Successful in 8s
feat: enhance current duty display with remaining time and improved contact links
- Added a new message key for displaying remaining time until the end of the shift in both English and Russian.
- Updated the current duty card to show remaining time with a formatted string.
- Enhanced the contact links to support block layout with icons for phone and Telegram, improving visual presentation.
- Implemented a new utility function to calculate remaining time until the end of the shift.
- Added unit tests for the new functionality, ensuring accurate time calculations and proper rendering of contact links.
2026-03-02 19:04:30 +03:00

177 lines
6.7 KiB
JavaScript

/**
* Unit tests for contactHtml (formatPhoneDisplay, buildContactLinksHtml).
*/
import { describe, it, expect } from "vitest";
import { formatPhoneDisplay, buildContactLinksHtml } from "./contactHtml.js";
describe("formatPhoneDisplay", () => {
it("formats 11-digit number starting with 7", () => {
expect(formatPhoneDisplay("79146522209")).toBe("+7 914 652-22-09");
expect(formatPhoneDisplay("+79146522209")).toBe("+7 914 652-22-09");
});
it("formats 11-digit number starting with 8", () => {
expect(formatPhoneDisplay("89146522209")).toBe("+7 914 652-22-09");
});
it("formats 10-digit number as Russian", () => {
expect(formatPhoneDisplay("9146522209")).toBe("+7 914 652-22-09");
});
it("returns empty string for null or empty", () => {
expect(formatPhoneDisplay(null)).toBe("");
expect(formatPhoneDisplay("")).toBe("");
expect(formatPhoneDisplay(" ")).toBe("");
});
it("strips non-digits before formatting", () => {
expect(formatPhoneDisplay("+7 (914) 652-22-09")).toBe("+7 914 652-22-09");
});
it("returns digits as-is for non-10/11 length", () => {
expect(formatPhoneDisplay("123")).toBe("123");
expect(formatPhoneDisplay("12345678901")).toBe("12345678901");
});
});
describe("buildContactLinksHtml", () => {
const baseOptions = { classPrefix: "test-contact", showLabels: true, separator: " " };
it("returns empty string when phone and username are missing", () => {
expect(buildContactLinksHtml("en", null, null, baseOptions)).toBe("");
expect(buildContactLinksHtml("en", undefined, undefined, baseOptions)).toBe("");
expect(buildContactLinksHtml("en", "", "", baseOptions)).toBe("");
expect(buildContactLinksHtml("en", " ", " ", baseOptions)).toBe("");
});
it("renders phone only with label and tel: link", () => {
const html = buildContactLinksHtml("en", "+79991234567", null, baseOptions);
expect(html).toContain("test-contact-row");
expect(html).toContain('href="tel:');
expect(html).toContain("+79991234567");
expect(html).toContain("Phone");
expect(html).not.toContain("t.me");
});
it("displays phone formatted for Russian numbers", () => {
const html = buildContactLinksHtml("en", "79146522209", null, baseOptions);
expect(html).toContain("+7 914 652-22-09");
expect(html).toContain('href="tel:79146522209"');
});
it("renders username only with label and t.me link", () => {
const html = buildContactLinksHtml("en", null, "alice_dev", baseOptions);
expect(html).toContain("test-contact-row");
expect(html).toContain("https://t.me/");
expect(html).toContain("alice_dev");
expect(html).toContain("@alice_dev");
expect(html).toContain("Telegram");
expect(html).not.toContain("tel:");
});
it("renders both phone and username with labels", () => {
const html = buildContactLinksHtml("en", "+79001112233", "bob", baseOptions);
expect(html).toContain("test-contact-row");
expect(html).toContain("tel:");
expect(html).toContain("+79001112233");
expect(html).toContain("+7 900 111-22-33");
expect(html).toContain("t.me");
expect(html).toContain("@bob");
expect(html).toContain("Phone");
expect(html).toContain("Telegram");
});
it("strips leading @ from username and displays with @", () => {
const html = buildContactLinksHtml("en", null, "@alice", baseOptions);
expect(html).toContain("https://t.me/alice");
expect(html).toContain("@alice");
expect(html).not.toContain("@@");
});
it("handles multiple leading @ in username", () => {
const html = buildContactLinksHtml("en", null, "@@@user", baseOptions);
expect(html).toContain("https://t.me/user");
expect(html).toContain("@user");
});
it("escapes special characters in phone href; display uses formatted digits only", () => {
const html = buildContactLinksHtml("en", '+7 999 "1" <2>', null, baseOptions);
expect(html).toContain("&quot;");
expect(html).toContain("&lt;");
expect(html).toContain("tel:");
expect(html).toContain("799912");
expect(html).not.toContain("<2>");
expect(html).not.toContain('"1"');
});
it("uses custom separator when showLabels is false", () => {
const html = buildContactLinksHtml("en", "+7999", "u1", {
classPrefix: "duty-contact",
showLabels: false,
separator: " · "
});
expect(html).toContain(" · ");
expect(html).not.toContain("Phone");
expect(html).not.toContain("Telegram");
expect(html).toContain("duty-contact-row");
expect(html).toContain("duty-contact-link");
});
it("uses Russian labels when lang is ru", () => {
const html = buildContactLinksHtml("ru", "+7999", null, baseOptions);
expect(html).toContain("Телефон");
const htmlTg = buildContactLinksHtml("ru", null, "u", baseOptions);
expect(htmlTg).toContain("Telegram");
});
it("uses default showLabels true and separator space when options omit them", () => {
const html = buildContactLinksHtml("en", "+7999", "u", {
classPrefix: "minimal",
});
expect(html).toContain("Phone");
expect(html).toContain("Telegram");
expect(html).toContain("minimal-row");
expect(html).not.toContain(" · ");
});
describe("layout: block", () => {
it("renders phone as block with icon and formatted number", () => {
const html = buildContactLinksHtml("en", "79146522209", null, {
classPrefix: "current-duty-contact",
layout: "block",
});
expect(html).toContain("current-duty-contact-row--blocks");
expect(html).toContain("current-duty-contact-block");
expect(html).toContain("current-duty-contact-block--phone");
expect(html).toContain("+7 914 652-22-09");
expect(html).toContain("tel:");
expect(html).toContain("<svg");
expect(html).not.toContain("Phone");
});
it("renders telegram as block with icon and @username", () => {
const html = buildContactLinksHtml("en", null, "alice_dev", {
classPrefix: "current-duty-contact",
layout: "block",
});
expect(html).toContain("current-duty-contact-block--telegram");
expect(html).toContain("https://t.me/");
expect(html).toContain("@alice_dev");
expect(html).toContain("<svg");
expect(html).not.toContain("Telegram");
});
it("renders both phone and telegram as stacked blocks", () => {
const html = buildContactLinksHtml("en", "+79001112233", "bob", {
classPrefix: "current-duty-contact",
layout: "block",
});
expect(html).toContain("current-duty-contact-block--phone");
expect(html).toContain("current-duty-contact-block--telegram");
expect(html).toContain("+7 900 111-22-33");
expect(html).toContain("@bob");
});
});
});