fix(custom-widgets): address v2 merge review

This commit is contained in:
ajnart committed 2026-07-22 23:36:25 +02:00
1 parent 6aceb2fd1f
commit 48ce83806d
122 files changed
+8534 -1447

No files matched your search

+1 -6
View File
@@ -9,7 +9,6 @@ import {
useQueryClient,
} from "@tanstack/react-query";
import { CUSTOM_WIDGET_SCHEMA } from "@homarr/custom-widgets/core";
import type { HomarrCustomWidgetV2 } from "@homarr/custom-widgets/core";
import type {
@@ -34,7 +33,6 @@ import {
workshopScreenshotsSchema,
workshopUserSchema,
workshopVoteSchema,
WORKSHOP_CSS_SCHEMA,
} from "./schema";
export interface WorkshopListOptions {
@@ -458,9 +456,7 @@ export class WorkshopBackend {
workshopScreenshotsSchema.parse(screenshots);
const data = new FormData();
Object.entries(parsed).forEach(([key, value]) => data.set(key, typeof value === "string" ? value : String(value)));
data.set("widgetSchema", parsed.type === "customCss" ? WORKSHOP_CSS_SCHEMA : CUSTOM_WIDGET_SCHEMA);
data.set("author", this.currentUser?.id ?? "");
data.set("revision", "1");
screenshots.forEach((file) => data.append("screenshots", file));
try {
const result = await this.pocketBase.collection("submissions").create(data);
@@ -483,8 +479,7 @@ export class WorkshopBackend {
const data: Record<string, unknown> = {
...parsed,
widgetSchema: parsed.type === "customCss" ? WORKSHOP_CSS_SCHEMA : CUSTOM_WIDGET_SCHEMA,
revision: current.revision + 1,
expectedRevision: current.revision,
};
if (additions.length > 0) data["screenshots+"] = additions;
if (removals.length > 0) data["screenshots-"] = removals;
+33 -1
View File
@@ -3,6 +3,7 @@ import { beforeEach, describe, expect, expectTypeOf, test, vi } from "vitest";
const mocks = vi.hoisted(() => ({
autoCancellation: vi.fn(),
authWithOAuth2: vi.fn(),
create: vi.fn(),
getFullList: vi.fn(),
getList: vi.fn(),
update: vi.fn(),
@@ -47,11 +48,18 @@ import type { RecordService } from "pocketbase";
import { WorkshopBackend } from "./backend";
import type { WorkshopSubmissionRecord } from "./backend";
import * as workshopClient from "./client";
describe("WorkshopBackend", () => {
test("resolves the advertised client module", () => {
expect(workshopClient.WorkshopBackend).toBe(WorkshopBackend);
expect(workshopClient.validateWorkshopContent).toBeTypeOf("function");
});
beforeEach(() => {
mocks.autoCancellation.mockReset();
mocks.authWithOAuth2.mockReset();
mocks.create.mockReset();
mocks.getFullList.mockReset();
mocks.getList.mockReset();
mocks.update.mockReset();
@@ -82,6 +90,27 @@ describe("WorkshopBackend", () => {
expect(mocks.autoCancellation).toHaveBeenCalledWith(false);
});
test("leaves schema and initial revision ownership to PocketBase", async () => {
const client = new WorkshopBackend("https://workshop.example.com");
client.pocketBase.authStore.save("token", { id: "author-id" } as never);
mocks.create.mockResolvedValue({ id: "submission-id" });
vi.spyOn(client, "get").mockResolvedValue(listingRecord() as never);
await client.create({
type: "customCss",
title: "Dashboard theme",
description: "A theme",
content: ".dashboard { color: red; }",
changelog: "",
outdated: false,
});
const payload = mocks.create.mock.calls[0]?.[0] as FormData;
expect(payload.get("author")).toBe("author-id");
expect(payload.get("widgetSchema")).toBeNull();
expect(payload.get("revision")).toBeNull();
});
test("appends and removes screenshots without replacing retained files", async () => {
const client = new WorkshopBackend("https://workshop.example.com");
const current = {
@@ -113,9 +142,12 @@ describe("WorkshopBackend", () => {
expect.objectContaining({
"screenshots+": [addition],
"screenshots-": ["remove.png"],
revision: 3,
expectedRevision: 2,
}),
);
const payload = mocks.update.mock.calls[0]?.[1];
expect(payload).not.toHaveProperty("revision");
expect(payload).not.toHaveProperty("widgetSchema");
});
test("uses PocketBase filtering and pagination when the listing view is current", async () => {
+2
View File
@@ -0,0 +1,2 @@
export * from "./backend";
export * from "./schema";