test: add release v2 browser QA campaign
This commit is contained in:
1 parent
f57a660088
commit
ec95d18245
83 files changed
+20922
-19
No files matched your search
@@ -26,10 +26,21 @@ const getDevelopmentServiceAliases = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const getDistDir = () => {
|
||||
const qaDistDir = process.env.HOMARR_QA_NEXT_DIST_DIR;
|
||||
if (!qaDistDir) return ".next";
|
||||
if (!/^\.next-qa\/slot-[1-3]$/u.test(qaDistDir)) {
|
||||
throw new Error("HOMARR_QA_NEXT_DIST_DIR must identify .next-qa/slot-1, slot-2, or slot-3");
|
||||
}
|
||||
return qaDistDir;
|
||||
};
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
// Next previews otherwise create agent instruction files in the application
|
||||
// directory during development.
|
||||
agentRules: false,
|
||||
// Release-v2 QA runs multiple isolated development servers from one worktree.
|
||||
distDir: getDistDir(),
|
||||
env: {
|
||||
HOMARR_VERSION: process.env.HOMARR_VERSION ?? "unknown",
|
||||
},
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// @vitest-environment jsdom
|
||||
|
||||
import { act, StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { Analytics } from "./analytics";
|
||||
|
||||
const postHogMock = vi.hoisted(() => {
|
||||
let resolveImport: (() => void) | undefined;
|
||||
const importGate = new Promise<void>((resolve) => {
|
||||
resolveImport = resolve;
|
||||
});
|
||||
|
||||
return {
|
||||
importGate,
|
||||
init: vi.fn(),
|
||||
releaseImport: () => resolveImport?.(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("posthog-js", async () => {
|
||||
await postHogMock.importGate;
|
||||
return { default: { init: postHogMock.init } };
|
||||
});
|
||||
|
||||
const host = document.createElement("div");
|
||||
const root = createRoot(host);
|
||||
|
||||
afterEach(() => {
|
||||
act(() => root.unmount());
|
||||
});
|
||||
|
||||
describe("Analytics", () => {
|
||||
it("deduplicates Strict Mode initialization and retries after a failure", async () => {
|
||||
const initializationError = new Error("initialization failed");
|
||||
const consoleError = vi.spyOn(console, "error").mockImplementation(() => undefined);
|
||||
postHogMock.init.mockImplementationOnce(() => {
|
||||
throw initializationError;
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<Analytics enabled />
|
||||
</StrictMode>,
|
||||
);
|
||||
});
|
||||
|
||||
postHogMock.releaseImport();
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(postHogMock.init).toHaveBeenCalledOnce();
|
||||
expect(consoleError).toHaveBeenCalledWith("PostHog initialization failed", initializationError);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<Analytics enabled={false} />
|
||||
</StrictMode>,
|
||||
);
|
||||
});
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<Analytics enabled />
|
||||
</StrictMode>,
|
||||
);
|
||||
});
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(postHogMock.init).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
expect(consoleError).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
@@ -5,19 +5,36 @@ import { useEffect } from "react";
|
||||
const POSTHOG_KEY = "phc_vYBmGWNbRshvfeC7EHfeSmUm2pD2Neg5nGqzJuGvS8Hs";
|
||||
const POSTHOG_HOST = "https://hog.homarr.dev";
|
||||
|
||||
let postHogInitialization: Promise<void> | undefined;
|
||||
|
||||
const initializePostHog = () => {
|
||||
if (postHogInitialization) return;
|
||||
|
||||
const initializationAttempt = import("posthog-js").then(({ default: posthog }) => {
|
||||
posthog.init(POSTHOG_KEY, {
|
||||
api_host: POSTHOG_HOST,
|
||||
capture_pageview: false,
|
||||
capture_pageleave: false,
|
||||
autocapture: false,
|
||||
persistence: "memory",
|
||||
});
|
||||
});
|
||||
|
||||
postHogInitialization = initializationAttempt;
|
||||
void initializationAttempt.catch((error: unknown) => {
|
||||
if (postHogInitialization === initializationAttempt) {
|
||||
postHogInitialization = undefined;
|
||||
}
|
||||
|
||||
console.error("PostHog initialization failed", error);
|
||||
});
|
||||
};
|
||||
|
||||
export const Analytics = ({ enabled }: { enabled: boolean }) => {
|
||||
useEffect(() => {
|
||||
if (!enabled) return;
|
||||
|
||||
void import("posthog-js").then(({ default: posthog }) => {
|
||||
posthog.init(POSTHOG_KEY, {
|
||||
api_host: POSTHOG_HOST,
|
||||
capture_pageview: false,
|
||||
capture_pageleave: false,
|
||||
autocapture: false,
|
||||
persistence: "memory",
|
||||
});
|
||||
});
|
||||
initializePostHog();
|
||||
}, [enabled]);
|
||||
|
||||
return null;
|
||||
|
||||
Reference in new issue
Block a user