fix: preserve committed room results
This commit is contained in:
1 parent
184052fbce
commit
d0190bc11f
2 files changed
+95
-18
No files matched your search
@@ -236,6 +236,7 @@ beforeEach(() => {
|
|||||||
testState.auditEntries = [];
|
testState.auditEntries = [];
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
testState.rconSend.mockResolvedValue(true);
|
testState.rconSend.mockResolvedValue(true);
|
||||||
|
testState.revalidate.mockImplementation(() => undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("legacy room actions through the Hotel mutation service", () => {
|
describe("legacy room actions through the Hotel mutation service", () => {
|
||||||
@@ -449,6 +450,70 @@ describe("legacy room actions through the Hotel mutation service", () => {
|
|||||||
expect(revalidatePath).toHaveBeenCalledWith("/admin/rooms");
|
expect(revalidatePath).toHaveBeenCalledWith("/admin/rooms");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
[
|
||||||
|
"item update",
|
||||||
|
() => {
|
||||||
|
testState.selectRows = [[itemRow()]];
|
||||||
|
return updateRoomItem({ roomId: 7, itemId: 11, x: 4 });
|
||||||
|
},
|
||||||
|
"/admin/rooms/7/furni",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"item delete",
|
||||||
|
() => {
|
||||||
|
testState.selectRows = [[itemRow()]];
|
||||||
|
return deleteRoomItem({ roomId: 7, itemId: 11 });
|
||||||
|
},
|
||||||
|
"/admin/rooms/7/furni",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"bulk item delete",
|
||||||
|
() => {
|
||||||
|
testState.selectRows = [[itemRow()]];
|
||||||
|
return bulkDeleteRoomItems({ roomId: 7, itemIds: [11] });
|
||||||
|
},
|
||||||
|
"/admin/rooms/7/furni",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"room update",
|
||||||
|
() => {
|
||||||
|
testState.selectRows = [[roomRow()]];
|
||||||
|
return updateRoom({ id: 7, name: "After" });
|
||||||
|
},
|
||||||
|
"/admin/rooms/7",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"room delete",
|
||||||
|
() => {
|
||||||
|
testState.selectRows = [[roomRow()]];
|
||||||
|
return deleteRoom({ id: 7 });
|
||||||
|
},
|
||||||
|
"/admin/rooms",
|
||||||
|
],
|
||||||
|
])(
|
||||||
|
"reports committed %s with refresh-needed context when revalidation fails",
|
||||||
|
async (_name, invoke, path) => {
|
||||||
|
testState.revalidate.mockImplementation(() => {
|
||||||
|
throw new Error("cache unavailable");
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await invoke();
|
||||||
|
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
ok: true,
|
||||||
|
data: {
|
||||||
|
committed: true,
|
||||||
|
refreshNeeded: true,
|
||||||
|
warning: expect.stringMatching(/saved.*refresh/i),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(testState.committedWrites).toHaveLength(1);
|
||||||
|
expect(testState.auditEntries).toHaveLength(1);
|
||||||
|
expect(revalidatePath).toHaveBeenCalledWith(path);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
it("rejects invalid runtime actions before RCON delivery", async () => {
|
it("rejects invalid runtime actions before RCON delivery", async () => {
|
||||||
const result = await roomRconAction({ roomId: 7, action: "explode" });
|
const result = await roomRconAction({ roomId: 7, action: "explode" });
|
||||||
expectFailure(result, /invalid/i);
|
expectFailure(result, /invalid/i);
|
||||||
|
|||||||
+30
-18
@@ -58,17 +58,32 @@ function notifyBestEffort(payload: Parameters<typeof notify>[0]): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function revalidateCommittedPath(path: string): ActionResult {
|
||||||
|
try {
|
||||||
|
revalidatePath(path);
|
||||||
|
return actionOk();
|
||||||
|
} catch {
|
||||||
|
return actionOk({
|
||||||
|
committed: true,
|
||||||
|
refreshNeeded: true,
|
||||||
|
warning:
|
||||||
|
"Changes were saved, but the page could not refresh automatically. Refresh the page before trying the action again.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function updateRoomItem(
|
export async function updateRoomItem(
|
||||||
payload: Record<string, unknown>,
|
payload: Record<string, unknown>,
|
||||||
): Promise<ActionResult> {
|
): Promise<ActionResult> {
|
||||||
const staff = await requirePermission(PERMS.ROOMS_EDIT);
|
const staff = await requirePermission(PERMS.ROOMS_EDIT);
|
||||||
try {
|
try {
|
||||||
await executeLegacyHotelMutation(staff, "room-item.update", payload);
|
await executeLegacyHotelMutation(staff, "room-item.update", payload);
|
||||||
revalidatePath(`/admin/rooms/${String(payload.roomId)}/furni`);
|
|
||||||
return actionOk();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return actionFailure(error);
|
return actionFailure(error);
|
||||||
}
|
}
|
||||||
|
return revalidateCommittedPath(
|
||||||
|
`/admin/rooms/${String(payload.roomId)}/furni`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function bulkDeleteRoomItems(payload: {
|
export async function bulkDeleteRoomItems(payload: {
|
||||||
@@ -78,11 +93,10 @@ export async function bulkDeleteRoomItems(payload: {
|
|||||||
const staff = await requirePermission(PERMS.ROOMS_EDIT);
|
const staff = await requirePermission(PERMS.ROOMS_EDIT);
|
||||||
try {
|
try {
|
||||||
await executeLegacyHotelMutation(staff, "room-item.bulk-delete", payload);
|
await executeLegacyHotelMutation(staff, "room-item.bulk-delete", payload);
|
||||||
revalidatePath(`/admin/rooms/${payload.roomId}/furni`);
|
|
||||||
return actionOk();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return actionFailure(error);
|
return actionFailure(error);
|
||||||
}
|
}
|
||||||
|
return revalidateCommittedPath(`/admin/rooms/${payload.roomId}/furni`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteRoomItem(payload: {
|
export async function deleteRoomItem(payload: {
|
||||||
@@ -92,11 +106,10 @@ export async function deleteRoomItem(payload: {
|
|||||||
const staff = await requirePermission(PERMS.ROOMS_EDIT);
|
const staff = await requirePermission(PERMS.ROOMS_EDIT);
|
||||||
try {
|
try {
|
||||||
await executeLegacyHotelMutation(staff, "room-item.delete", payload);
|
await executeLegacyHotelMutation(staff, "room-item.delete", payload);
|
||||||
revalidatePath(`/admin/rooms/${payload.roomId}/furni`);
|
|
||||||
return actionOk();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return actionFailure(error);
|
return actionFailure(error);
|
||||||
}
|
}
|
||||||
|
return revalidateCommittedPath(`/admin/rooms/${payload.roomId}/furni`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function roomRconAction(payload: {
|
export async function roomRconAction(payload: {
|
||||||
@@ -124,25 +137,25 @@ export async function deleteRoom(payload: {
|
|||||||
id: number;
|
id: number;
|
||||||
}): Promise<ActionResult> {
|
}): Promise<ActionResult> {
|
||||||
const staff = await requirePermission(PERMS.ROOMS_DELETE);
|
const staff = await requirePermission(PERMS.ROOMS_DELETE);
|
||||||
|
let target = `#${payload.id}`;
|
||||||
try {
|
try {
|
||||||
const snapshot = await executeLegacyHotelMutation(
|
const snapshot = await executeLegacyHotelMutation(
|
||||||
staff,
|
staff,
|
||||||
"room.delete",
|
"room.delete",
|
||||||
payload,
|
payload,
|
||||||
);
|
);
|
||||||
notifyBestEffort({
|
if (typeof snapshot.before?.name === "string") {
|
||||||
action: "room_delete",
|
target = snapshot.before.name;
|
||||||
actor: staff.username,
|
}
|
||||||
target:
|
|
||||||
typeof snapshot.before?.name === "string"
|
|
||||||
? snapshot.before.name
|
|
||||||
: `#${payload.id}`,
|
|
||||||
});
|
|
||||||
revalidatePath("/admin/rooms");
|
|
||||||
return actionOk();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return actionFailure(error);
|
return actionFailure(error);
|
||||||
}
|
}
|
||||||
|
notifyBestEffort({
|
||||||
|
action: "room_delete",
|
||||||
|
actor: staff.username,
|
||||||
|
target,
|
||||||
|
});
|
||||||
|
return revalidateCommittedPath("/admin/rooms");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateRoom(payload: {
|
export async function updateRoom(payload: {
|
||||||
@@ -155,9 +168,8 @@ export async function updateRoom(payload: {
|
|||||||
const staff = await requirePermission(PERMS.ROOMS_EDIT);
|
const staff = await requirePermission(PERMS.ROOMS_EDIT);
|
||||||
try {
|
try {
|
||||||
await executeLegacyHotelMutation(staff, "room.update", payload);
|
await executeLegacyHotelMutation(staff, "room.update", payload);
|
||||||
revalidatePath(`/admin/rooms/${payload.id}`);
|
|
||||||
return actionOk();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return actionFailure(error);
|
return actionFailure(error);
|
||||||
}
|
}
|
||||||
|
return revalidateCommittedPath(`/admin/rooms/${payload.id}`);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user