- 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.
177 lines
6.7 KiB
JavaScript
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(""");
|
|
expect(html).toContain("<");
|
|
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");
|
|
});
|
|
});
|
|
});
|