Files
MeshChatX/tests/frontend/Performance.test.js
Sudo-Ivan e2586e9052
Some checks failed
CI / test-backend (push) Successful in 32s
CI / lint (push) Failing after 2m12s
CI / build-frontend (pull_request) Successful in 1m38s
Build and Publish Docker Image / build (pull_request) Has been skipped
CI / test-backend (pull_request) Successful in 24s
OSV-Scanner PR Scan / scan-pr (pull_request) Successful in 53s
CI / test-lang (pull_request) Successful in 1m15s
CI / lint (pull_request) Failing after 5m8s
CI / build-frontend (push) Successful in 9m46s
CI / test-lang (push) Successful in 9m48s
Tests / test (push) Successful in 13m32s
Tests / test (pull_request) Successful in 11m23s
Build Test / Build and Test (push) Successful in 15m56s
Build and Publish Docker Image / build-dev (pull_request) Successful in 13m42s
Build Test / Build and Test (pull_request) Successful in 16m9s
feat(tests): add comprehensive telemetry and interface tests
- Introduced new test files for telemetry functionality, including integration, fuzzing, and extended tests to ensure robustness and performance.
- Added tests for parsing LXMF display names and telemetry data, addressing potential bugs and ensuring correct handling of various input formats.
- Implemented performance tests for the InterfacesPage component, validating rendering efficiency with a large number of discovered interfaces.
- Enhanced existing tests for markdown rendering and link utilities to cover additional edge cases and improve stability.
2026-01-07 19:22:00 -06:00

183 lines
6.0 KiB
JavaScript

import { mount } from "@vue/test-utils";
import { describe, it, expect, vi } from "vitest";
import MessagesSidebar from "../../meshchatx/src/frontend/components/messages/MessagesSidebar.vue";
import ConversationViewer from "../../meshchatx/src/frontend/components/messages/ConversationViewer.vue";
// Mock dependencies
vi.mock("../../meshchatx/src/frontend/js/GlobalState", () => ({
default: {
config: { theme: "light", banished_effect_enabled: false },
blockedDestinations: [],
},
}));
vi.mock("../../meshchatx/src/frontend/js/Utils", () => ({
default: {
formatTimeAgo: () => "1 hour ago",
formatBytes: () => "1 KB",
formatDestinationHash: (h) => h,
escapeHtml: (t) =>
t.replace(
/[&<>"']/g,
(m) =>
({
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#039;",
})[m]
),
},
}));
vi.mock("../../meshchatx/src/frontend/js/WebSocketConnection", () => ({
default: {
on: vi.fn(),
off: vi.fn(),
send: vi.fn(),
},
}));
vi.mock("../../meshchatx/src/frontend/js/GlobalEmitter", () => ({
default: {
on: vi.fn(),
off: vi.fn(),
emit: vi.fn(),
},
}));
// Mock axios
global.axios = {
get: vi.fn(() => Promise.resolve({ data: {} })),
post: vi.fn(() => Promise.resolve({ data: {} })),
patch: vi.fn(() => Promise.resolve({ data: {} })),
};
window.axios = global.axios;
// Mock localStorage
const localStorageMock = {
getItem: vi.fn(() => null),
setItem: vi.fn(),
clear: vi.fn(),
};
global.localStorage = localStorageMock;
// Mock MaterialDesignIcon
const MaterialDesignIcon = {
template: '<div class="mdi"></div>',
props: ["iconName"],
};
describe("UI Performance and Memory Tests", () => {
const getMemoryUsage = () => {
if (global.process && process.memoryUsage) {
return process.memoryUsage().heapUsed / (1024 * 1024);
}
return 0;
};
it("renders MessagesSidebar with 2000 conversations quickly and tracks memory", async () => {
const numConvs = 2000;
const conversations = Array.from({ length: numConvs }, (_, i) => ({
destination_hash: `hash_${i}`.padEnd(32, "0"),
display_name: `Peer ${i}`,
updated_at: new Date().toISOString(),
latest_message_preview: `Latest message from peer ${i}`,
is_unread: i % 10 === 0,
failed_messages_count: i % 50 === 0 ? 1 : 0,
}));
const startMem = getMemoryUsage();
const start = performance.now();
const wrapper = mount(MessagesSidebar, {
props: {
conversations,
peers: {},
selectedDestinationHash: "",
isLoading: false,
isLoadingMore: false,
hasMoreConversations: false,
},
global: {
components: {
MaterialDesignIcon,
LxmfUserIcon: { template: '<div class="lxmf-icon"></div>' },
},
mocks: { $t: (key) => key },
},
});
const end = performance.now();
const endMem = getMemoryUsage();
const renderTime = end - start;
const memGrowth = endMem - startMem;
console.log(
`Rendered ${numConvs} conversations in ${renderTime.toFixed(2)}ms, Memory growth: ${memGrowth.toFixed(2)}MB`
);
expect(wrapper.findAll(".conversation-item").length).toBe(numConvs);
expect(renderTime).toBeLessThan(5000);
expect(memGrowth).toBeLessThan(200); // Adjusted for JSDOM/Node.js overhead with 2000 items
});
it("measures performance of data updates in ConversationViewer", async () => {
const numMsgs = 1000;
const myLxmfAddressHash = "my_hash";
const selectedPeer = {
destination_hash: "peer_hash",
display_name: "Peer Name",
};
const wrapper = mount(ConversationViewer, {
props: {
myLxmfAddressHash,
selectedPeer,
conversations: [selectedPeer],
config: { theme: "light", lxmf_address_hash: myLxmfAddressHash },
},
global: {
components: {
MaterialDesignIcon,
ConversationDropDownMenu: { template: "<div></div>" },
SendMessageButton: { template: "<div></div>" },
IconButton: { template: "<button></button>" },
AddImageButton: { template: "<div></div>" },
AddAudioButton: { template: "<div></div>" },
PaperMessageModal: { template: "<div></div>" },
},
mocks: {
$t: (key) => key,
$i18n: { locale: "en" },
},
},
});
const chatItems = Array.from({ length: numMsgs }, (_, i) => ({
type: "lxmf_message",
is_outbound: i % 2 === 0,
lxmf_message: {
hash: `msg_${i}`.padEnd(32, "0"),
source_hash: i % 2 === 0 ? myLxmfAddressHash : "peer_hash",
destination_hash: i % 2 === 0 ? "peer_hash" : myLxmfAddressHash,
content: `Message content ${i}.`.repeat(5),
created_at: new Date().toISOString(),
state: "delivered",
method: "direct",
progress: 1.0,
delivery_attempts: 1,
id: i,
},
}));
const start = performance.now();
await wrapper.setData({ chatItems });
const end = performance.now();
console.log(`Updated 1000 messages in ConversationViewer in ${(end - start).toFixed(2)}ms`);
expect(end - start).toBeLessThan(3000);
});
});