fix(activity): an old audit/log link opens its tab, times read relative, one name for admin actions
Seen in the browser, not in the page's own tests: the navigation provider rewrites a retired page id to `activity` before the page's chunk reads the URL, so `?page=audit` landed on the Runs tab. The retired-page map now carries the params that open the successor's part (`at`), and the provider writes them as it rewrites the page — on load and on Back alike. A list time is relative with the exact second on hover (the DESIGN copy rule); a run moved over from the audit log, whose start and end are one instant, shows no length instead of an invented "1 sec". The audit log is called "admin actions" everywhere it is named (the clear button and its confirm, the Configuration group, the cleanup job, which also prunes the run history its description left out).
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
// The activity page around its run and audit lists (the server-log tab has its own file): the view
|
||||
// is the URL — a link narrows the runs to one job, a status chip narrows them further; a run opens
|
||||
// to its log lines and an admin action to its request's, each a new history entry that Back undoes;
|
||||
// a link to the retired audit page opens the admin tab; the account filter reaches the quota tab; a
|
||||
// the account filter reaches the quota tab; a
|
||||
// failed read is an error with a retry, never an empty list.
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { act, cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
@@ -168,11 +168,10 @@ describe("Activity", () => {
|
||||
expect(screen.getByText("quotaExceeded")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("a link to the retired audit page opens the admin tab, and an action opens its request's lines", async () => {
|
||||
window.history.replaceState(null, "", "/?page=audit");
|
||||
it("the admin tab lists the actions, and an action opens its request's lines", async () => {
|
||||
window.history.replaceState(null, "", "/?page=activity&at=admin");
|
||||
renderPage();
|
||||
await waitFor(() => expect(screen.getByText("auditActions.scheduler_interval")).toBeTruthy());
|
||||
expect(url().get("page")).toBe("activity");
|
||||
expect(runsMock).not.toHaveBeenCalled();
|
||||
|
||||
fireEvent.click(rowButton(/auditActions\.scheduler_interval/));
|
||||
@@ -197,6 +196,24 @@ describe("Activity", () => {
|
||||
expect(Math.round(days)).toBe(30);
|
||||
});
|
||||
|
||||
// The runs moved over from the audit log kept one instant for start and end: their length is
|
||||
// unknown, and a "1 sec" would be invented.
|
||||
it("a run whose start and end are one instant has no length", async () => {
|
||||
window.history.replaceState(null, "", "/?page=activity");
|
||||
runsMock.mockResolvedValue(
|
||||
page([
|
||||
{ ...RUN, id: 1, status: "ok", error: null, finished_at: RUN.started_at, summary: "moved" },
|
||||
{ ...RUN, id: 2, status: "ok", error: null, summary: "timed" },
|
||||
]),
|
||||
);
|
||||
renderPage();
|
||||
await waitFor(() => expect(screen.getByText("moved")).toBeTruthy());
|
||||
const cells = (text: string) =>
|
||||
[...rowButton(new RegExp(text)).children].map((c) => c.textContent);
|
||||
expect(cells("moved")).toContain("—");
|
||||
expect(cells("timed")).not.toContain("—");
|
||||
});
|
||||
|
||||
it("a failed read is an error with a retry, not an empty list", async () => {
|
||||
window.history.replaceState(null, "", "/?page=activity");
|
||||
runsMock.mockRejectedValue(new Error("502"));
|
||||
|
||||
Reference in New Issue
Block a user