mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-03-31 10:25:42 +00:00
- Introduced new test files for BlockedPage, DropDownMenu, and Interface components to ensure proper rendering and functionality. - Enhanced existing tests for ConfirmDialog, MessagesSidebar, and NotificationBell, improving coverage and verifying UI behavior. - Added performance tests for LoadTimePerformance to measure loading times for large datasets in the PropagationNodesPage and MessagesSidebar. - Removed the deprecated InterfacesPage test file to streamline the test suite.
132 lines
4.9 KiB
JavaScript
132 lines
4.9 KiB
JavaScript
import { mount } from "@vue/test-utils";
|
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import Interface from "../../meshchatx/src/frontend/components/interfaces/Interface.vue";
|
|
|
|
vi.mock("../../meshchatx/src/frontend/js/DialogUtils", () => ({
|
|
default: { alert: vi.fn() },
|
|
}));
|
|
|
|
const defaultIface = {
|
|
_name: "Default Interface",
|
|
type: "AutoInterface",
|
|
enabled: true,
|
|
discoverable: true,
|
|
};
|
|
|
|
function mountInterface(props = {}, options = {}) {
|
|
return mount(Interface, {
|
|
props: { iface: { ...defaultIface, ...props }, isReticulumRunning: true },
|
|
global: {
|
|
mocks: { $t: (key) => key },
|
|
stubs: ["MaterialDesignIcon", "IconButton", "DropDownMenu", "DropDownMenuItem"],
|
|
},
|
|
...options,
|
|
});
|
|
}
|
|
|
|
describe("Interface.vue", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("renders interface name and type", () => {
|
|
const wrapper = mountInterface();
|
|
expect(wrapper.text()).toContain("Default Interface");
|
|
expect(wrapper.text()).toContain("AutoInterface");
|
|
});
|
|
|
|
it("emits disable when Disable button is clicked", async () => {
|
|
const wrapper = mountInterface();
|
|
const disableBtn = wrapper.find("button.secondary-chip");
|
|
await disableBtn.trigger("click");
|
|
expect(wrapper.emitted("disable")).toHaveLength(1);
|
|
});
|
|
|
|
it("emits enable when Enable button is clicked for disabled interface", async () => {
|
|
const wrapper = mountInterface({ enabled: false });
|
|
const enableBtn = wrapper.find("button.primary-chip");
|
|
await enableBtn.trigger("click");
|
|
expect(wrapper.emitted("enable")).toHaveLength(1);
|
|
});
|
|
|
|
it("has overflow containment classes on card and content", () => {
|
|
const wrapper = mountInterface();
|
|
const card = wrapper.find(".interface-card");
|
|
expect(card.classes()).toContain("min-w-0");
|
|
const contentArea = wrapper.find(".min-w-0.overflow-hidden");
|
|
expect(contentArea.exists()).toBe(true);
|
|
});
|
|
|
|
it("has break-words on description for long host:port", () => {
|
|
const wrapper = mountInterface({
|
|
_name: "RNS Testnet Amsterdam",
|
|
type: "TCPClientInterface",
|
|
target_host: "amsterdam.connect.reticulum.network",
|
|
target_port: 4965,
|
|
});
|
|
const desc = wrapper.find(".text-sm.text-gray-600");
|
|
expect(desc.classes()).toContain("break-words");
|
|
expect(desc.classes()).toContain("min-w-0");
|
|
});
|
|
|
|
it("has responsive layout classes for stacking on small screens", () => {
|
|
const wrapper = mountInterface();
|
|
const outer = wrapper.find(".flex.flex-col.sm\\:flex-row");
|
|
expect(outer.exists()).toBe(true);
|
|
});
|
|
|
|
it("renders without overflow when given very long name and description", () => {
|
|
const longName = "A".repeat(120);
|
|
const wrapper = mountInterface({
|
|
_name: longName,
|
|
type: "TCPClientInterface",
|
|
target_host: "very-long-hostname-that-could-overflow-on-mobile.example.reticulum.network",
|
|
target_port: 4242,
|
|
});
|
|
const card = wrapper.find(".interface-card");
|
|
expect(card.exists()).toBe(true);
|
|
const contentWrapper = wrapper.find(".flex-1.min-w-0.space-y-2");
|
|
expect(contentWrapper.exists()).toBe(true);
|
|
const nameEl = wrapper.find(".truncate.min-w-0");
|
|
expect(nameEl.exists()).toBe(true);
|
|
});
|
|
|
|
it("action buttons and dropdown have shrink-0 to prevent squashing", () => {
|
|
const wrapper = mountInterface();
|
|
const actionsCol = wrapper.find(".flex.flex-col.sm\\:flex-row.gap-2");
|
|
expect(actionsCol.classes()).toContain("sm:shrink-0");
|
|
const btn = wrapper.find("button.secondary-chip");
|
|
expect(btn.classes()).toContain("shrink-0");
|
|
});
|
|
|
|
it("detail-value has break-all for long addresses", () => {
|
|
const wrapper = mountInterface({
|
|
_name: "UDP Test",
|
|
type: "UDPInterface",
|
|
listen_ip: "0.0.0.0",
|
|
listen_port: 4242,
|
|
forward_ip: "192.168.1.100",
|
|
forward_port: 4242,
|
|
});
|
|
const detailValues = wrapper.findAll(".detail-value");
|
|
expect(detailValues.length).toBeGreaterThan(0);
|
|
detailValues.forEach((el) => {
|
|
expect(el.classes()).toContain("break-all");
|
|
expect(el.classes()).toContain("min-w-0");
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Interface.vue overflow at different viewports", () => {
|
|
it("card has min-w-0 so it can shrink in grid", () => {
|
|
const wrapper = mountInterface();
|
|
expect(wrapper.find(".interface-card").classes()).toContain("min-w-0");
|
|
});
|
|
|
|
it("icon and chips have shrink-0 so they do not collapse", () => {
|
|
const wrapper = mountInterface();
|
|
expect(wrapper.find(".interface-card__icon").classes()).toContain("shrink-0");
|
|
expect(wrapper.find(".type-chip").classes()).toContain("shrink-0");
|
|
});
|
|
});
|