Ok lets use a shared helper for the widget field mutation

This commit is contained in:
shamoon
2026-08-21 12:33:35 -07:00
parent e87b790353
commit d91d30ed27
6 changed files with 53 additions and 15 deletions
+12
View File
@@ -0,0 +1,12 @@
export default function withWidgetFields(service, defaultFields, maxFields = 4) {
const configuredFields = service.widget.fields;
const fields = (configuredFields?.length ? configuredFields : defaultFields).slice(0, maxFields);
return {
...service,
widget: {
...service.widget,
fields,
},
};
}
+27
View File
@@ -0,0 +1,27 @@
import { describe, expect, it } from "vitest";
import withWidgetFields from "./widget-fields";
describe("utils/widget-fields", () => {
it("applies defaults without modifying the service", () => {
const service = { name: "Example", widget: { type: "example" } };
const normalizedService = withWidgetFields(service, ["one", "two"]);
expect(normalizedService).toEqual({
name: "Example",
widget: { type: "example", fields: ["one", "two"] },
});
expect(service).toEqual({ name: "Example", widget: { type: "example" } });
});
it("copies and limits configured fields", () => {
const service = { widget: { type: "example", fields: ["one", "two", "three"] } };
const normalizedService = withWidgetFields(service, ["default"], 2);
expect(normalizedService.widget.fields).toEqual(["one", "two"]);
expect(normalizedService.widget.fields).not.toBe(service.widget.fields);
expect(service.widget.fields).toEqual(["one", "two", "three"]);
});
});
+4 -7
View File
@@ -3,19 +3,16 @@ import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next/pages"; import { useTranslation } from "next-i18next/pages";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
const MAX_FIELDS = 4; const MAX_FIELDS = 4;
const DEFAULT_FIELDS = ["running", "stopped", "total", "image_updates"];
export default function Component({ service }) { export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, DEFAULT_FIELDS, MAX_FIELDS);
const { widget } = service; const { widget } = service;
if (!widget.fields) {
widget.fields = ["running", "stopped", "total", "image_updates"];
} else if (widget.fields.length > MAX_FIELDS) {
widget.fields = widget.fields.slice(0, MAX_FIELDS);
}
const envNotSet = widget.env == null || widget.env === ""; const envNotSet = widget.env == null || widget.env === "";
const { data: containers, error: containersError } = useWidgetAPI(widget, envNotSet ? "" : "containers"); const { data: containers, error: containersError } = useWidgetAPI(widget, envNotSet ? "" : "containers");
+1
View File
@@ -66,6 +66,7 @@ describe("widgets/arcane/component", () => {
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
// sliced to first four entries // sliced to first four entries
expect(service.widget.fields).toEqual(["running", "stopped", "total", "images", "images_unused"]);
expect(container.querySelectorAll(".service-block")).toHaveLength(4); expect(container.querySelectorAll(".service-block")).toHaveLength(4);
expect(screen.getByText("docker.running")).toBeInTheDocument(); expect(screen.getByText("docker.running")).toBeInTheDocument();
expect(screen.getByText("dockhand.stopped")).toBeInTheDocument(); expect(screen.getByText("dockhand.stopped")).toBeInTheDocument();
+4 -7
View File
@@ -3,19 +3,16 @@ import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next/pages"; import { useTranslation } from "next-i18next/pages";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
const MAX_FIELDS = 4; const MAX_FIELDS = 4;
const DEFAULT_FIELDS = ["running", "total", "cpu", "memory"];
export default function Component({ service }) { export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, DEFAULT_FIELDS, MAX_FIELDS);
const { widget } = service; const { widget } = service;
if (!widget.fields) {
widget.fields = ["running", "total", "cpu", "memory"];
} else if (widget.fields.length > MAX_FIELDS) {
widget.fields = widget.fields.slice(0, MAX_FIELDS);
}
const { data: stats, error: statsError } = useWidgetAPI(widget, "dashboard/stats"); const { data: stats, error: statsError } = useWidgetAPI(widget, "dashboard/stats");
if (statsError) { if (statsError) {
+5 -1
View File
@@ -22,7 +22,11 @@ describe("widgets/dockhand/component", () => {
const service = { widget: { type: "dockhand" } }; const service = { widget: { type: "dockhand" } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["running", "total", "cpu", "memory"]); expect(service.widget.fields).toBeUndefined();
expect(useWidgetAPI).toHaveBeenCalledWith(
{ type: "dockhand", fields: ["running", "total", "cpu", "memory"] },
"dashboard/stats",
);
expect(container.querySelectorAll(".service-block")).toHaveLength(4); expect(container.querySelectorAll(".service-block")).toHaveLength(4);
expect(screen.getByText("dockhand.running")).toBeInTheDocument(); expect(screen.getByText("dockhand.running")).toBeInTheDocument();
expect(screen.getByText("dockhand.total")).toBeInTheDocument(); expect(screen.getByText("dockhand.total")).toBeInTheDocument();