mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 16:09:05 +00:00
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
339 lines
11 KiB
TypeScript
339 lines
11 KiB
TypeScript
import { describe, it, expect, afterEach } from "vitest";
|
|
import { mount, VueWrapper } from "@vue/test-utils";
|
|
import { createStore } from "vuex";
|
|
import CustomDateTimePicker from "@/components/CustomDateTimePicker.vue";
|
|
|
|
describe("CustomDateTimePicker.vue", () => {
|
|
let wrapper: VueWrapper;
|
|
|
|
afterEach(() => {
|
|
if (wrapper) {
|
|
wrapper.unmount();
|
|
}
|
|
});
|
|
|
|
const createWrapper = (props = {}, storeState = {}) => {
|
|
const currentStore = createStore({
|
|
state: {
|
|
theme: "light",
|
|
...storeState,
|
|
},
|
|
mutations: {},
|
|
actions: {},
|
|
});
|
|
|
|
return mount(CustomDateTimePicker, {
|
|
props,
|
|
global: {
|
|
plugins: [currentStore],
|
|
stubs: {},
|
|
},
|
|
});
|
|
};
|
|
|
|
describe("Component Setup and Props", () => {
|
|
it("renders with default props", () => {
|
|
wrapper = createWrapper();
|
|
expect(wrapper.exists()).toBe(true);
|
|
});
|
|
|
|
it("accepts modelValue prop", () => {
|
|
wrapper = createWrapper({ modelValue: "5m" });
|
|
expect(wrapper.props("modelValue")).toBe("5m");
|
|
});
|
|
|
|
it("accepts isFirstEntry prop", () => {
|
|
wrapper = createWrapper({ isFirstEntry: true });
|
|
expect(wrapper.props("isFirstEntry")).toBe(true);
|
|
});
|
|
|
|
it("accepts changeStyle prop", () => {
|
|
wrapper = createWrapper({ changeStyle: true });
|
|
expect(wrapper.props("changeStyle")).toBe(true);
|
|
});
|
|
|
|
it("has correct default values for changeStyle", () => {
|
|
wrapper = createWrapper();
|
|
expect(wrapper.props("changeStyle")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("Fixed-length units only", () => {
|
|
const periodValues = (vm: any) => ({
|
|
rows: vm.relativePeriods.map((p: any) => p.value),
|
|
select: vm.relativePeriodsSelect.map((p: any) => p.value),
|
|
});
|
|
|
|
it("offers the month unit by default", () => {
|
|
wrapper = createWrapper({ modelValue: "1d" });
|
|
const { rows, select } = periodValues(wrapper.vm);
|
|
expect(rows).toContain("M");
|
|
expect(select).toContain("M");
|
|
});
|
|
|
|
it("leaves the month unit out when excludeMonths is set", () => {
|
|
wrapper = createWrapper({ modelValue: "1d", excludeMonths: true });
|
|
const { rows, select } = periodValues(wrapper.vm);
|
|
expect(rows).not.toContain("M");
|
|
expect(select).not.toContain("M");
|
|
expect(rows).toEqual(expect.arrayContaining(["m", "h", "d", "w"]));
|
|
expect(select).toEqual(expect.arrayContaining(["m", "h", "d", "w"]));
|
|
});
|
|
});
|
|
|
|
describe("Model Value Handling", () => {
|
|
it("parses modelValue correctly on initialization", () => {
|
|
wrapper = createWrapper({ modelValue: "10m" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.picker.data.selectedDate.relative.value).toBe(10);
|
|
expect(vm.picker.data.selectedDate.relative.period).toBe("m");
|
|
});
|
|
|
|
it("handles different period formats", () => {
|
|
wrapper = createWrapper({ modelValue: "2h" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.picker.data.selectedDate.relative.value).toBe(2);
|
|
expect(vm.picker.data.selectedDate.relative.period).toBe("h");
|
|
});
|
|
|
|
it("handles days format", () => {
|
|
wrapper = createWrapper({ modelValue: "7d" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.picker.data.selectedDate.relative.value).toBe(7);
|
|
expect(vm.picker.data.selectedDate.relative.period).toBe("d");
|
|
});
|
|
|
|
it("handles weeks format", () => {
|
|
wrapper = createWrapper({ modelValue: "2w" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.picker.data.selectedDate.relative.value).toBe(2);
|
|
expect(vm.picker.data.selectedDate.relative.period).toBe("w");
|
|
});
|
|
|
|
it("handles months format", () => {
|
|
wrapper = createWrapper({ modelValue: "3M" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.picker.data.selectedDate.relative.value).toBe(3);
|
|
expect(vm.picker.data.selectedDate.relative.period).toBe("M");
|
|
});
|
|
});
|
|
|
|
describe("Display Functions", () => {
|
|
it("getDisplayValue returns correct format", () => {
|
|
wrapper = createWrapper({ modelValue: "5m" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.getDisplayValue()).toBe("5 Minutes ago");
|
|
});
|
|
|
|
it("getTrimmedDisplayValue returns correct format", () => {
|
|
wrapper = createWrapper({ modelValue: "5m" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.getTrimmedDisplayValue()).toBe("Past 5 Minutes");
|
|
});
|
|
|
|
it("getDisplayValue works with hours", () => {
|
|
wrapper = createWrapper({ modelValue: "2h" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.getDisplayValue()).toBe("2 Hours ago");
|
|
});
|
|
|
|
it("getTrimmedDisplayValue works with days", () => {
|
|
wrapper = createWrapper({ modelValue: "3d" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.getTrimmedDisplayValue()).toBe("Past 3 Days");
|
|
});
|
|
});
|
|
|
|
describe("Period Label Functions", () => {
|
|
it("getPeriodLabelFromValue returns correct labels", () => {
|
|
wrapper = createWrapper();
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.getPeriodLabelFromValue("s")).toBe("Seconds");
|
|
expect(vm.getPeriodLabelFromValue("m")).toBe("Minutes");
|
|
expect(vm.getPeriodLabelFromValue("h")).toBe("Hours");
|
|
expect(vm.getPeriodLabelFromValue("d")).toBe("Days");
|
|
expect(vm.getPeriodLabelFromValue("w")).toBe("Weeks");
|
|
expect(vm.getPeriodLabelFromValue("M")).toBe("Months");
|
|
});
|
|
|
|
it("getPeriodLabelFromValue returns default for invalid period", () => {
|
|
wrapper = createWrapper();
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.getPeriodLabelFromValue("x")).toBe("Minutes");
|
|
});
|
|
|
|
it("getPeriodLabel returns current period label", () => {
|
|
wrapper = createWrapper({ modelValue: "5h" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.getPeriodLabel()).toBe("Hours");
|
|
});
|
|
});
|
|
|
|
describe("Selection Functions", () => {
|
|
it("isSelected returns true for matching values", () => {
|
|
wrapper = createWrapper({ modelValue: "5m" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.isSelected(5, "m")).toBe(true);
|
|
expect(vm.isSelected(10, "m")).toBe(false);
|
|
expect(vm.isSelected(5, "h")).toBe(false);
|
|
});
|
|
|
|
it("isSelected compares value strictly by type", () => {
|
|
wrapper = createWrapper({ modelValue: "15s" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
// picker value is stored as a number, so only a numeric argument matches.
|
|
expect(vm.isSelected(15, "s")).toBe(true);
|
|
expect(vm.isSelected("15", "s")).toBe(false); // strict equality: string !== number
|
|
});
|
|
});
|
|
|
|
describe("Event Emission", () => {
|
|
it("emits update:modelValue when setRelativeDate is called", async () => {
|
|
wrapper = createWrapper();
|
|
const vm = wrapper.vm as any;
|
|
|
|
const period = { value: "h", label: "Hours" };
|
|
vm.setRelativeDate(period, 2);
|
|
|
|
expect(wrapper.emitted("update:modelValue")).toBeTruthy();
|
|
expect(wrapper.emitted("update:modelValue")?.[0]).toEqual(["2h"]);
|
|
});
|
|
|
|
it("emits correct value for different periods", async () => {
|
|
wrapper = createWrapper();
|
|
const vm = wrapper.vm as any;
|
|
|
|
const periodDays = { value: "d", label: "Days" };
|
|
vm.setRelativeDate(periodDays, 7);
|
|
|
|
expect(wrapper.emitted("update:modelValue")?.[0]).toEqual(["7d"]);
|
|
});
|
|
|
|
it("emits update:modelValue when updateCustomPeriod is called", () => {
|
|
wrapper = createWrapper({ modelValue: "5m" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
vm.updateCustomPeriod("h");
|
|
|
|
expect(wrapper.emitted("update:modelValue")).toBeTruthy();
|
|
expect(wrapper.emitted("update:modelValue")?.[0]).toEqual(["5h"]);
|
|
});
|
|
});
|
|
|
|
describe("Theme and Styling", () => {
|
|
it("computedClass returns semantic surface class for dark theme", () => {
|
|
wrapper = createWrapper({ changeStyle: true }, { theme: "dark" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.computedClass).toBe("bg-surface-base!");
|
|
});
|
|
|
|
it("computedClass returns semantic surface class for light theme", () => {
|
|
wrapper = createWrapper({ changeStyle: true }, { theme: "light" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.computedClass).toBe("bg-surface-base!");
|
|
});
|
|
|
|
it("computedClass returns empty string when changeStyle is false", () => {
|
|
wrapper = createWrapper({ changeStyle: false }, { theme: "dark" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.computedClass).toBe("");
|
|
});
|
|
});
|
|
|
|
describe("Reactive Data Updates", () => {
|
|
it("updates picker data when setRelativeDate is called", () => {
|
|
wrapper = createWrapper();
|
|
const vm = wrapper.vm as any;
|
|
|
|
const period = { value: "s", label: "Seconds" };
|
|
vm.setRelativeDate(period, 30);
|
|
|
|
expect(vm.picker.data.selectedDate.relative.value).toBe(30);
|
|
expect(vm.picker.data.selectedDate.relative.period).toBe("s");
|
|
expect(vm.picker.data.selectedDate.relative.label).toBe("Seconds");
|
|
});
|
|
|
|
it("updates label when updateCustomPeriod is called", () => {
|
|
wrapper = createWrapper({ modelValue: "10m" });
|
|
const vm = wrapper.vm as any;
|
|
|
|
vm.updateCustomPeriod("d");
|
|
|
|
expect(vm.picker.data.selectedDate.relative.label).toBe("Days");
|
|
});
|
|
});
|
|
|
|
describe("Menu State Management", () => {
|
|
it("initializes with showMenu false", () => {
|
|
wrapper = createWrapper();
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.picker.showMenu).toBe(false);
|
|
});
|
|
|
|
it("has correct activeTab default", () => {
|
|
wrapper = createWrapper();
|
|
const vm = wrapper.vm as any;
|
|
|
|
expect(vm.picker.activeTab).toBe("relative");
|
|
});
|
|
});
|
|
|
|
describe("Edge Cases", () => {
|
|
it("handles null modelValue gracefully", () => {
|
|
wrapper = createWrapper({ modelValue: null });
|
|
expect(wrapper.exists()).toBe(true);
|
|
});
|
|
|
|
it("handles empty modelValue gracefully", () => {
|
|
wrapper = createWrapper({ modelValue: "" });
|
|
expect(wrapper.exists()).toBe(true);
|
|
});
|
|
|
|
it("handles undefined modelValue gracefully", () => {
|
|
wrapper = createWrapper({ modelValue: undefined });
|
|
expect(wrapper.exists()).toBe(true);
|
|
});
|
|
|
|
it("handles malformed modelValue", () => {
|
|
// Parsing is null-guarded, so a value with no digits must not crash.
|
|
expect(() => {
|
|
wrapper = createWrapper({ modelValue: "invalid" });
|
|
}).not.toThrow();
|
|
|
|
const vm = wrapper.vm as any;
|
|
// No numeric part -> NaN; the alphabetic part is captured as the period.
|
|
expect(Number.isNaN(vm.picker.data.selectedDate.relative.value)).toBe(true);
|
|
expect(vm.picker.data.selectedDate.relative.period).toBe("invalid");
|
|
});
|
|
|
|
it("setRelativeDate with zero value", () => {
|
|
wrapper = createWrapper();
|
|
const vm = wrapper.vm as any;
|
|
|
|
const period = { value: "m", label: "Minutes" };
|
|
vm.setRelativeDate(period, 0);
|
|
|
|
expect(vm.picker.data.selectedDate.relative.value).toBe(0);
|
|
expect(wrapper.emitted("update:modelValue")?.[0]).toEqual(["0m"]);
|
|
});
|
|
});
|
|
});
|