feat: update language support and enhance API functionality
- Changed the default language in `index.html` from Russian to English, updating the title and button aria-labels for improved accessibility. - Refactored the `buildFetchOptions` function in `api.js` to include an optional external abort signal, enhancing request management. - Updated `fetchDuties` and `fetchCalendarEvents` to support request cancellation using the new abort signal, improving error handling. - Added unit tests for the API functions to ensure proper functionality, including handling of 403 errors and request cancellations. - Enhanced CSS styles for duty markers to improve visual consistency. - Removed unused code and improved the overall structure of the JavaScript files for better maintainability.
This commit is contained in:
159
webapp/js/dateUtils.test.js
Normal file
159
webapp/js/dateUtils.test.js
Normal file
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Unit tests for dateUtils: localDateString, dutyOverlapsLocalDay,
|
||||
* dutyOverlapsLocalRange, getMonday, formatHHMM.
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
localDateString,
|
||||
dutyOverlapsLocalDay,
|
||||
dutyOverlapsLocalRange,
|
||||
getMonday,
|
||||
formatHHMM,
|
||||
} from "./dateUtils.js";
|
||||
|
||||
describe("localDateString", () => {
|
||||
it("formats date as YYYY-MM-DD", () => {
|
||||
const d = new Date(2025, 0, 15);
|
||||
expect(localDateString(d)).toBe("2025-01-15");
|
||||
});
|
||||
|
||||
it("pads month and day with zero", () => {
|
||||
expect(localDateString(new Date(2025, 0, 5))).toBe("2025-01-05");
|
||||
expect(localDateString(new Date(2025, 8, 9))).toBe("2025-09-09");
|
||||
});
|
||||
|
||||
it("handles December and year boundary", () => {
|
||||
expect(localDateString(new Date(2024, 11, 31))).toBe("2024-12-31");
|
||||
});
|
||||
});
|
||||
|
||||
describe("dutyOverlapsLocalDay", () => {
|
||||
it("returns true when duty spans the whole day", () => {
|
||||
const d = {
|
||||
start_at: "2025-02-25T00:00:00Z",
|
||||
end_at: "2025-02-25T23:59:59Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalDay(d, "2025-02-25")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true when duty overlaps part of the day", () => {
|
||||
const d = {
|
||||
start_at: "2025-02-25T09:00:00Z",
|
||||
end_at: "2025-02-25T14:00:00Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalDay(d, "2025-02-25")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true when duty continues from previous day", () => {
|
||||
const d = {
|
||||
start_at: "2025-02-24T22:00:00Z",
|
||||
end_at: "2025-02-25T06:00:00Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalDay(d, "2025-02-25")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when duty ends before the day", () => {
|
||||
const d = {
|
||||
start_at: "2025-02-24T09:00:00Z",
|
||||
end_at: "2025-02-24T18:00:00Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalDay(d, "2025-02-25")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when duty starts after the day", () => {
|
||||
const d = {
|
||||
start_at: "2025-02-26T09:00:00Z",
|
||||
end_at: "2025-02-26T18:00:00Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalDay(d, "2025-02-25")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("dutyOverlapsLocalRange", () => {
|
||||
it("returns true when duty overlaps the range", () => {
|
||||
const d = {
|
||||
start_at: "2025-02-24T12:00:00Z",
|
||||
end_at: "2025-02-26T12:00:00Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalRange(d, "2025-02-25", "2025-02-28")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true when duty is entirely inside the range", () => {
|
||||
const d = {
|
||||
start_at: "2025-02-26T09:00:00Z",
|
||||
end_at: "2025-02-26T18:00:00Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalRange(d, "2025-02-25", "2025-02-28")).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when duty ends before range start", () => {
|
||||
const d = {
|
||||
start_at: "2025-02-20T09:00:00Z",
|
||||
end_at: "2025-02-22T18:00:00Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalRange(d, "2025-02-25", "2025-02-28")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when duty starts after range end", () => {
|
||||
const d = {
|
||||
start_at: "2025-03-01T09:00:00Z",
|
||||
end_at: "2025-03-01T18:00:00Z",
|
||||
};
|
||||
expect(dutyOverlapsLocalRange(d, "2025-02-25", "2025-02-28")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getMonday", () => {
|
||||
it("returns same day when date is Monday", () => {
|
||||
const monday = new Date(2025, 0, 6); // 6 Jan 2025 is Monday
|
||||
const result = getMonday(monday);
|
||||
expect(result.getFullYear()).toBe(2025);
|
||||
expect(result.getMonth()).toBe(0);
|
||||
expect(result.getDate()).toBe(6);
|
||||
expect(result.getDay()).toBe(1);
|
||||
});
|
||||
|
||||
it("returns previous Monday for Wednesday", () => {
|
||||
const wed = new Date(2025, 0, 8);
|
||||
const result = getMonday(wed);
|
||||
expect(result.getDay()).toBe(1);
|
||||
expect(result.getDate()).toBe(6);
|
||||
});
|
||||
|
||||
it("returns Monday of same week for Sunday", () => {
|
||||
const sun = new Date(2025, 0, 12);
|
||||
const result = getMonday(sun);
|
||||
expect(result.getDay()).toBe(1);
|
||||
expect(result.getDate()).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatHHMM", () => {
|
||||
it("formats ISO string as HH:MM in local time", () => {
|
||||
const s = "2025-02-25T14:30:00Z";
|
||||
const result = formatHHMM(s);
|
||||
expect(result).toMatch(/^\d{2}:\d{2}$/);
|
||||
const d = new Date(s);
|
||||
const expected = (d.getHours() < 10 ? "0" : "") + d.getHours() + ":" + (d.getMinutes() < 10 ? "0" : "") + d.getMinutes();
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
|
||||
it("returns empty string for null", () => {
|
||||
expect(formatHHMM(null)).toBe("");
|
||||
});
|
||||
|
||||
it("returns empty string for undefined", () => {
|
||||
expect(formatHHMM(undefined)).toBe("");
|
||||
});
|
||||
|
||||
it("returns empty string for empty string", () => {
|
||||
expect(formatHHMM("")).toBe("");
|
||||
});
|
||||
|
||||
it("pads hours and minutes with zero", () => {
|
||||
const s = "2025-02-25T09:05:00Z";
|
||||
const result = formatHHMM(s);
|
||||
expect(result).toMatch(/^\d{2}:\d{2}$/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user