Files
pleno-vue/tests/unit/connectivity-issue.spec.js
Jeppe Bundgaard 0fa2284e89 Add connectivity issue handling logic and tests
- Add `ConnectivityIssue.vue` component for displaying server connection issues.
- Implement polling logic with retry intervals to check server health.
- Update i18n with new connectivity issue messages.
- Add unit tests to cover connectivity failure and recovery scenarios.
- Update test suite for breadth of coverage, including router contract and timer cleanup.
2026-05-28 18:11:21 +02:00

114 lines
3.2 KiB
JavaScript

// @vitest-environment jsdom
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { enableAutoUnmount } from "@vue/test-utils";
import { mountWithApp } from "./helpers/mountWithApp.js";
const mocks = vi.hoisted(() => ({
pingApiServer: vi.fn(),
}));
vi.mock("@/services/apiHealth.js", () => ({
pingApiServer: mocks.pingApiServer,
}));
import ConnectivityIssue from "@/views/errors/ConnectivityIssue.vue";
enableAutoUnmount(afterEach);
const messages = {
en: {
connectivity: {
title: "Connectivity issue",
subtitle: "Check your connection",
description: "Waiting for the server",
retry_in: "Retrying in {seconds} seconds",
retry_now: "Retrying now",
retry: "Retry",
footer: "Contact support",
},
},
};
const mountConnectivityIssue = () =>
mountWithApp(ConnectivityIssue, {
messages,
slots: {
default: '<div data-testid="app-content">App content</div>',
},
global: {
stubs: {
BIcon: true,
},
},
});
const flushPromises = async () => {
await Promise.resolve();
await Promise.resolve();
};
describe("ConnectivityIssue", () => {
beforeEach(() => {
mocks.pingApiServer.mockReset();
vi.spyOn(console, "error").mockImplementation(() => {});
});
afterEach(() => {
vi.useRealTimers();
vi.restoreAllMocks();
});
it("shows content after a healthy ping without continuing to poll", async () => {
vi.useFakeTimers();
mocks.pingApiServer.mockResolvedValue({ ok: true, status: 200, error: null });
const wrapper = mountConnectivityIssue();
await flushPromises();
expect(wrapper.find('[data-testid="app-content"]').exists()).toBe(true);
expect(wrapper.find('[data-testid="connectivity-issue"]').exists()).toBe(false);
await vi.advanceTimersByTimeAsync(20_000);
expect(mocks.pingApiServer).toHaveBeenCalledTimes(1);
});
it("retries after a failed ping and stops retrying once the API is healthy", async () => {
vi.useFakeTimers();
mocks.pingApiServer
.mockResolvedValueOnce({ ok: false, status: 500, error: null })
.mockResolvedValueOnce({ ok: true, status: 200, error: null });
const wrapper = mountConnectivityIssue();
await flushPromises();
expect(wrapper.find('[data-testid="connectivity-issue"]').exists()).toBe(true);
expect(wrapper.find('[data-testid="app-content"]').exists()).toBe(false);
await vi.advanceTimersByTimeAsync(5_000);
await flushPromises();
expect(mocks.pingApiServer).toHaveBeenCalledTimes(2);
expect(wrapper.find('[data-testid="app-content"]').exists()).toBe(true);
expect(wrapper.find('[data-testid="connectivity-issue"]').exists()).toBe(false);
await vi.advanceTimersByTimeAsync(10_000);
expect(mocks.pingApiServer).toHaveBeenCalledTimes(2);
});
it("clears pending retry work when unmounted", async () => {
vi.useFakeTimers();
mocks.pingApiServer.mockResolvedValue({ ok: false, status: 500, error: null });
const wrapper = mountConnectivityIssue();
await flushPromises();
wrapper.unmount();
await vi.advanceTimersByTimeAsync(5_000);
expect(mocks.pingApiServer).toHaveBeenCalledTimes(1);
});
});