Brings all of the develop branch's commits into master. ## What this contains The 9 commits on develop that landed in this round — all XL Vask-related UI fixes plus the 'visible primary-button hover state' visual-diff: - **PR #303** (TRU-5 / AUT-1) — style(AUT-1): visible primary-button hover state + visual diff - **PR #304** (TRU-10 / AUT-6) — fix(invoicing-period): propagate flagged wash start date to Selvvask view - **PR #305** (TRU-12 / AUT-8) — feat(xlvask): render friendly notice for 404 from /modules/xlvask/services/usage/orders - **PR #306** (TRU-9 / AUT-5) — i18n(test): lock in xlvask_review / xlvask_usage_log mirroring to the global v2 fallback - **PR #307** (TRU-13 / AUT-9) — i18n(xlvask_review): translate missing keys for no, sv, de, en - **PR #308** (TRU-15 / AUT-11) — test(e2e): add Playwright smoke test for XL Vask flag → Selvvash navigation - **PR #309** (TRU-11 / AUT-7) — feat(TRU-11): propagate department selector to Selvvask usage query - **PR #310** (TRU-19 / AUT-15) — test(TRU-19): lock self-serve program number range + button registry contract - **PR #311** (TRU-8 / AUT-4) — fix(invoicing-flag-list): explain empty XL Vask hover preview when flag context has no metadata ## Why The XL Vask integration bug surfaced from the user-reported message "XL Vask-registreringen er hverken ignoreret eller knyttet til en ordre i den valgte periode. doesn't show the wash." After dispatching 9 diagnostic + fix tasks and merging all 9 PRs into develop via the OpenSymphony orchestrator running against MiniMax M3, this PR is the canonical release to bring develop's accumulated changes into master. No new code in this PR — just the squash-merged output of the 9 source PRs combined into a single develop→master merge. ## Verification All 9 source PRs passed: - Required CI (Action Runners) - App Store Readiness - Quality lint/i18n/build/unit/e2e suites The required checks on this PR will run the same gate. ## Notes - The api repo has its own equivalent PR/merge — see CHANGELOG for that side. --------- Co-authored-by: Jeppe <jeppe@copenhagentruckwash.io> Co-authored-by: openhands <openhands@all-hands.dev>
92 lines
2.7 KiB
JavaScript
92 lines
2.7 KiB
JavaScript
// @vitest-environment jsdom
|
|
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import axios from "axios";
|
|
import { usePaginatedList } from "@/components/pagination/paginatedList.vue";
|
|
|
|
vi.mock("axios", () => ({
|
|
default: {
|
|
get: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
describe("paginatedList tracks the last error so consumers can detect 404", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
localStorage.clear();
|
|
localStorage.setItem("token", "test-token");
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it("exposes a reactive lastError ref and clears it on success", async () => {
|
|
axios.get.mockResolvedValueOnce({
|
|
data: { data: [{ id: 1 }], meta: { pagination: { page: 1, per_page: 100, total: 1 } } },
|
|
});
|
|
|
|
const list = usePaginatedList();
|
|
list.setEndpoint("/modules/xlvask/services/usage/orders", false);
|
|
expect(list.lastError.value).toBeNull();
|
|
|
|
await list.paginatedGetRequest();
|
|
|
|
expect(list.lastError.value).toBeNull();
|
|
});
|
|
|
|
it("captures the HTTP status of a failed request for the current endpoint", async () => {
|
|
axios.get.mockRejectedValueOnce({
|
|
response: { status: 404, data: { data: { message: "Not Found" } } },
|
|
message: "Request failed with status code 404",
|
|
});
|
|
|
|
const list = usePaginatedList();
|
|
list.setEndpoint("/modules/xlvask/services/usage/orders", false);
|
|
|
|
const result = await list.paginatedGetRequest();
|
|
|
|
expect(result).toBeNull();
|
|
expect(list.lastError.value).toEqual({
|
|
status: 404,
|
|
endpoint: "/modules/xlvask/services/usage/orders",
|
|
message: "Not Found",
|
|
});
|
|
});
|
|
|
|
it("resets lastError at the start of every request", async () => {
|
|
axios.get
|
|
.mockRejectedValueOnce({
|
|
response: { status: 500, data: { data: { message: "Server Error" } } },
|
|
message: "Request failed with status code 500",
|
|
})
|
|
.mockResolvedValueOnce({
|
|
data: { data: [], meta: { pagination: { page: 1, per_page: 100, total: 0 } } },
|
|
});
|
|
|
|
const list = usePaginatedList();
|
|
list.setEndpoint("/modules/xlvask/services/usage/orders", false);
|
|
|
|
await list.paginatedGetRequest();
|
|
expect(list.lastError.value?.status).toBe(500);
|
|
|
|
await list.paginatedGetRequest();
|
|
expect(list.lastError.value).toBeNull();
|
|
});
|
|
|
|
it("does not set lastError when the request was cancelled", async () => {
|
|
axios.get.mockRejectedValueOnce({
|
|
name: "CanceledError",
|
|
code: "ERR_CANCELED",
|
|
message: "canceled",
|
|
});
|
|
|
|
const list = usePaginatedList();
|
|
list.setEndpoint("/modules/xlvask/services/usage/orders", false);
|
|
|
|
await list.paginatedGetRequest();
|
|
|
|
expect(list.lastError.value).toBeNull();
|
|
});
|
|
});
|