210 lines
6.2 KiB
JavaScript
210 lines
6.2 KiB
JavaScript
// @vitest-environment jsdom
|
|
import { defineComponent } from "vue";
|
|
import { mount } from "@vue/test-utils";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
vi.mock("vue-i18n", async (importOriginal) => {
|
|
const actual = await importOriginal();
|
|
|
|
return {
|
|
...actual,
|
|
useI18n: () => ({
|
|
t: (value) => value,
|
|
}),
|
|
};
|
|
});
|
|
|
|
vi.mock("@/components/session/token/SessionUser.vue", () => ({
|
|
SessionUser: {
|
|
objects: {
|
|
global: {
|
|
language: {
|
|
date_from: "From",
|
|
date_to: "To",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}));
|
|
|
|
import { formatLocalDateOnly } from "@/services/dateOnly.js";
|
|
import PaginationDisplayTemplateDate from "@/components/displays/pagination/templates/PaginationDisplayTemplateDate.vue";
|
|
import PaginationDisplayTemplateDates from "@/components/displays/pagination/templates/PaginationDisplayTemplateDates.vue";
|
|
import { dateFunctions } from "@/components/displays/pagination/PaginationDisplayDates.vue";
|
|
|
|
const PaginationDisplayItemColumnStub = defineComponent({
|
|
name: "PaginationDisplayItemColumn",
|
|
props: {
|
|
label: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
},
|
|
template: "<div><slot name='control' /></div>",
|
|
});
|
|
|
|
const BuefyDateFieldStub = defineComponent({
|
|
name: "BuefyDateField",
|
|
props: {
|
|
modelValue: {
|
|
type: Date,
|
|
default: null,
|
|
},
|
|
dataTestid: {
|
|
type: String,
|
|
default: "pagination-date-picker",
|
|
},
|
|
placeholder: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
},
|
|
emits: ["update:modelValue", "change"],
|
|
methods: {
|
|
format(value) {
|
|
return value instanceof Date ? formatLocalDateOnly(value) : "";
|
|
},
|
|
parse(value) {
|
|
const [year, month, day] = String(value).split("-").map(Number);
|
|
return new Date(year, month - 1, day);
|
|
},
|
|
update(value) {
|
|
const nextDate = this.parse(value);
|
|
this.$emit("update:modelValue", nextDate);
|
|
this.$emit("change", nextDate);
|
|
},
|
|
},
|
|
template:
|
|
"<input :data-testid='dataTestid' :placeholder='placeholder' :value='format(modelValue)' @input='update($event.target.value)' />",
|
|
});
|
|
|
|
const globalStubs = {
|
|
PaginationDisplayItemColumn: PaginationDisplayItemColumnStub,
|
|
BuefyDateField: BuefyDateFieldStub,
|
|
};
|
|
|
|
describe("pagination date selection", () => {
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it("renders Date model values as the same local date", () => {
|
|
const wrapper = mount(PaginationDisplayTemplateDate, {
|
|
props: {
|
|
label: "Date",
|
|
modelValue: new Date(2026, 2, 31, 0, 0, 0, 0),
|
|
},
|
|
global: {
|
|
stubs: globalStubs,
|
|
},
|
|
});
|
|
|
|
expect(wrapper.get("[data-testid='pagination-date-picker']").element.value).toBe("2026-03-31");
|
|
});
|
|
|
|
it("emits the clicked input date as the same local date", async () => {
|
|
const wrapper = mount(PaginationDisplayTemplateDate, {
|
|
props: {
|
|
label: "Date",
|
|
modelValue: new Date(2026, 2, 1, 0, 0, 0, 0),
|
|
},
|
|
global: {
|
|
stubs: globalStubs,
|
|
},
|
|
});
|
|
|
|
await wrapper.get("[data-testid='pagination-date-picker']").setValue("2026-03-31");
|
|
|
|
const emittedDate = wrapper.emitted("update:date")?.at(-1)?.[0];
|
|
expect(formatLocalDateOnly(emittedDate)).toBe("2026-03-31");
|
|
});
|
|
|
|
it("uses the real first day of the month for month presets", () => {
|
|
const firstDay = dateFunctions.datePresetFunctions.month.firstDayOfMonth(new Date(2026, 4, 15, 12, 0, 0, 0));
|
|
|
|
expect(formatLocalDateOnly(firstDay)).toBe("2026-05-01");
|
|
expect(firstDay.getHours()).toBe(0);
|
|
expect(firstDay.getMinutes()).toBe(0);
|
|
});
|
|
|
|
it("emits both start and end updates from the paired date selector", async () => {
|
|
const wrapper = mount(PaginationDisplayTemplateDates, {
|
|
props: {
|
|
startDate: new Date(2026, 2, 1, 0, 0, 0, 0),
|
|
endDate: new Date(2026, 2, 31, 0, 0, 0, 0),
|
|
},
|
|
global: {
|
|
stubs: globalStubs,
|
|
},
|
|
});
|
|
|
|
const inputs = wrapper.findAll("[data-testid='pagination-date-picker']");
|
|
await inputs[0].setValue("2026-04-01");
|
|
await inputs[1].setValue("2026-04-30");
|
|
|
|
expect(formatLocalDateOnly(wrapper.emitted("update:startDate")?.at(-1)?.[0])).toBe("2026-04-01");
|
|
expect(formatLocalDateOnly(wrapper.emitted("update:endDate")?.at(-1)?.[0])).toBe("2026-04-30");
|
|
});
|
|
|
|
it("passes date placeholders to the paired date selector inputs", () => {
|
|
const wrapper = mount(PaginationDisplayTemplateDates, {
|
|
props: {
|
|
startDate: new Date(2026, 2, 1, 0, 0, 0, 0),
|
|
endDate: new Date(2026, 2, 31, 0, 0, 0, 0),
|
|
},
|
|
global: {
|
|
stubs: globalStubs,
|
|
},
|
|
});
|
|
|
|
const inputs = wrapper.findAll("[data-testid='pagination-date-picker']");
|
|
|
|
expect(inputs).toHaveLength(2);
|
|
expect(inputs[0].attributes("placeholder")).toBe("--.--.----");
|
|
expect(inputs[1].attributes("placeholder")).toBe("--.--.----");
|
|
});
|
|
|
|
it("builds preset ranges from the current date when clicked", async () => {
|
|
vi.useFakeTimers();
|
|
vi.setSystemTime(new Date("2026-05-04T10:00:00.000Z"));
|
|
|
|
const wrapper = mount(PaginationDisplayTemplateDates, {
|
|
props: {
|
|
startDate: new Date(2026, 2, 1, 0, 0, 0, 0),
|
|
endDate: new Date(2026, 2, 31, 0, 0, 0, 0),
|
|
},
|
|
global: {
|
|
stubs: globalStubs,
|
|
},
|
|
});
|
|
|
|
const thisMonthButton = wrapper.findAll("button").find((button) => button.text() === "global.text.this_month");
|
|
expect(thisMonthButton).toBeTruthy();
|
|
|
|
await thisMonthButton.trigger("click");
|
|
|
|
expect(formatLocalDateOnly(wrapper.emitted("update:startDate")?.at(-1)?.[0])).toBe("2026-05-01");
|
|
expect(formatLocalDateOnly(wrapper.emitted("update:endDate")?.at(-1)?.[0])).toBe("2026-05-31");
|
|
});
|
|
|
|
it("marks the matching preset as selected", () => {
|
|
vi.useFakeTimers();
|
|
vi.setSystemTime(new Date("2026-05-04T10:00:00.000Z"));
|
|
|
|
const wrapper = mount(PaginationDisplayTemplateDates, {
|
|
props: {
|
|
startDate: new Date(2026, 4, 4, 0, 0, 0, 0),
|
|
endDate: new Date(2026, 4, 4, 23, 59, 59, 999),
|
|
},
|
|
global: {
|
|
stubs: globalStubs,
|
|
},
|
|
});
|
|
|
|
const todayButton = wrapper.findAll("button").find((button) => button.text() === "global.text.today");
|
|
|
|
expect(todayButton).toBeTruthy();
|
|
expect(todayButton.classes()).toContain("is-link");
|
|
});
|
|
});
|