refactor: update websocket context to use structured data and lazy load components

- Changed websocket context to use `lastData` instead of `lastMessage` for better type safety and clarity.
- Updated components to handle the new websocket data structure, including `DashCommand`, `Header`, `ServerDetail`, and various chart components.
- Introduced lazy loading for `NotFound`, `ServerDetail`, and `NetworkChart` components to improve performance.
- Added skeleton loading states for `ServerDetail` to enhance user experience during data fetching.
- Updated tests to reflect changes in websocket data handling and component structure.
This commit is contained in:
hamster1963
2026-06-20 00:48:30 +08:00
parent f2b13da7b1
commit 03977c4b4d
20 changed files with 225 additions and 147 deletions
+12 -14
View File
@@ -94,7 +94,7 @@ function renderServerPage(
{ withStatusControl = false } = {},
) {
const defaultWebsocketValue: WebSocketContextType = {
lastMessage: null,
lastData: null,
connected: false,
messageHistory: [],
reconnect: vi.fn(),
@@ -118,10 +118,8 @@ function renderServerPage(
function websocketPayload(servers: NezhaServer[]) {
return {
data: JSON.stringify({
now: Date.parse("2025-01-01T00:00:20.000Z"),
servers,
}),
now: Date.parse("2025-01-01T00:00:20.000Z"),
servers,
};
}
@@ -153,7 +151,7 @@ describe("Servers page", () => {
it("renders websocket loading and processing states", () => {
const { rerender } = renderServerPage({
connected: false,
lastMessage: null,
lastData: null,
});
expect(screen.getByText("info.websocketConnecting")).toBeInTheDocument();
@@ -163,7 +161,7 @@ describe("Servers page", () => {
<StatusProvider>
<WebSocketContext.Provider
value={{
lastMessage: null,
lastData: null,
connected: true,
messageHistory: [],
reconnect: vi.fn(),
@@ -190,7 +188,7 @@ describe("Servers page", () => {
renderServerPage({
connected: true,
lastMessage: websocketPayload([online, offline]),
lastData: websocketPayload([online, offline]),
});
expect(screen.getByTestId("server-overview")).toHaveTextContent("2:1:1");
@@ -215,7 +213,7 @@ describe("Servers page", () => {
renderServerPage({
connected: true,
lastMessage: websocketPayload([online, offline]),
lastData: websocketPayload([online, offline]),
});
await user.click(await screen.findByTestId("group-Edge"));
@@ -240,7 +238,7 @@ describe("Servers page", () => {
renderServerPage({
connected: true,
lastMessage: websocketPayload([lowCpu, highCpu]),
lastData: websocketPayload([lowCpu, highCpu]),
});
await user.selectOptions(screen.getByLabelText("Sort metric"), "cpu");
@@ -264,7 +262,7 @@ describe("Servers page", () => {
renderServerPage({
connected: true,
lastMessage: websocketPayload([onlineAlpha, offlineZeta]),
lastData: websocketPayload([onlineAlpha, offlineZeta]),
});
expect(screen.getByLabelText("Toggle sort direction")).toBeDisabled();
@@ -306,7 +304,7 @@ describe("Servers page", () => {
const { container } = renderServerPage({
connected: true,
lastMessage: websocketPayload([online, offline]),
lastData: websocketPayload([online, offline]),
});
await waitFor(() => {
@@ -340,7 +338,7 @@ describe("Servers page", () => {
renderServerPage({
connected: true,
lastMessage: websocketPayload([online]),
lastData: websocketPayload([online]),
});
expect(screen.getByTestId("server-card")).toHaveTextContent("alpha");
@@ -364,7 +362,7 @@ describe("Servers page", () => {
renderServerPage(
{
connected: true,
lastMessage: websocketPayload([online, offline]),
lastData: websocketPayload([online, offline]),
},
{ withStatusControl: true },
);
+5 -2
View File
@@ -109,10 +109,13 @@ describe("ServerDetail", () => {
expect(screen.getByTestId("detail-overview")).toHaveTextContent("7");
expect(screen.getByTestId("detail-chart")).toHaveTextContent("7");
expect(screen.getByTestId("network-chart")).toHaveTextContent("7:false");
expect(screen.queryByTestId("network-chart")).not.toBeInTheDocument();
await user.click(screen.getByRole("button", { name: "Network" }));
expect(screen.getByTestId("network-chart")).toHaveTextContent("7:true");
expect(await screen.findByTestId("network-chart")).toHaveTextContent(
"7:true",
);
expect(screen.queryByTestId("detail-chart")).not.toBeInTheDocument();
});
it("redirects when route params are missing", async () => {