Add demo banner star-repo CTA analytics and fix CI formatting (#183)
* add star cta * feat: track demo banner star repo clicks * chore: format docs-site json for biome ci
This commit is contained in:
parent
ddf5130915
commit
16fdb425d8
@ -4,9 +4,7 @@
|
|||||||
{
|
{
|
||||||
"type": "category",
|
"type": "category",
|
||||||
"label": "Getting Started",
|
"label": "Getting Started",
|
||||||
"items": [
|
"items": ["getting-started/self-hosting"]
|
||||||
"getting-started/self-hosting"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "category",
|
"type": "category",
|
||||||
@ -58,17 +56,12 @@
|
|||||||
{
|
{
|
||||||
"type": "category",
|
"type": "category",
|
||||||
"label": "Troubleshooting",
|
"label": "Troubleshooting",
|
||||||
"items": [
|
"items": ["troubleshooting/common-problems"]
|
||||||
"troubleshooting/common-problems"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "category",
|
"type": "category",
|
||||||
"label": "Reference / FAQ",
|
"label": "Reference / FAQ",
|
||||||
"items": [
|
"items": ["reference/faq", "reference/documentation-style-guide"]
|
||||||
"reference/faq",
|
|
||||||
"reference/documentation-style-guide"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1 @@
|
|||||||
[
|
["0.1.22", "0.1.21", "0.1.20"]
|
||||||
"0.1.22",
|
|
||||||
"0.1.21",
|
|
||||||
"0.1.20"
|
|
||||||
]
|
|
||||||
|
|||||||
116
orchestrator/src/client/App.test.tsx
Normal file
116
orchestrator/src/client/App.test.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { fireEvent, render, screen } from "@testing-library/react";
|
||||||
|
import type React from "react";
|
||||||
|
import { MemoryRouter } from "react-router-dom";
|
||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import { trackEvent } from "@/lib/analytics";
|
||||||
|
import { App } from "./App";
|
||||||
|
import { useDemoInfo } from "./hooks/useDemoInfo";
|
||||||
|
|
||||||
|
vi.mock("./hooks/useDemoInfo", () => ({
|
||||||
|
useDemoInfo: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@/lib/analytics", () => ({
|
||||||
|
trackEvent: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("react-transition-group", () => ({
|
||||||
|
SwitchTransition: ({ children }: { children: React.ReactNode }) => children,
|
||||||
|
CSSTransition: ({ children }: { children: React.ReactNode }) => children,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@/components/ui/sonner", () => ({
|
||||||
|
Toaster: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./components/BasicAuthPrompt", () => ({
|
||||||
|
BasicAuthPrompt: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./components/OnboardingGate", () => ({
|
||||||
|
OnboardingGate: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./pages/GmailOauthCallbackPage", () => ({
|
||||||
|
GmailOauthCallbackPage: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./pages/HomePage", () => ({
|
||||||
|
HomePage: () => <div>overview</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./pages/InProgressBoardPage", () => ({
|
||||||
|
InProgressBoardPage: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./pages/JobPage", () => ({
|
||||||
|
JobPage: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./pages/OrchestratorPage", () => ({
|
||||||
|
OrchestratorPage: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./pages/SettingsPage", () => ({
|
||||||
|
SettingsPage: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./pages/TrackingInboxPage", () => ({
|
||||||
|
TrackingInboxPage: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("./pages/VisaSponsorsPage", () => ({
|
||||||
|
VisaSponsorsPage: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe("App demo banner", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows a Star repo link in demo mode and tracks click", () => {
|
||||||
|
vi.mocked(useDemoInfo).mockReturnValue({
|
||||||
|
demoMode: true,
|
||||||
|
resetCadenceHours: 6,
|
||||||
|
lastResetAt: null,
|
||||||
|
nextResetAt: null,
|
||||||
|
baselineVersion: null,
|
||||||
|
baselineName: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
render(
|
||||||
|
<MemoryRouter initialEntries={["/overview"]}>
|
||||||
|
<App />
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const link = screen.getByRole("link", { name: /star .*repo/i });
|
||||||
|
expect(link).toHaveAttribute(
|
||||||
|
"href",
|
||||||
|
"https://github.com/DaKheera47/job-ops",
|
||||||
|
);
|
||||||
|
fireEvent.click(link);
|
||||||
|
expect(trackEvent).toHaveBeenCalledWith("star_repo_click", {
|
||||||
|
location: "demo_mode_banner",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not render the demo banner CTA when demo mode is disabled", () => {
|
||||||
|
vi.mocked(useDemoInfo).mockReturnValue({
|
||||||
|
demoMode: false,
|
||||||
|
resetCadenceHours: 6,
|
||||||
|
lastResetAt: null,
|
||||||
|
nextResetAt: null,
|
||||||
|
baselineVersion: null,
|
||||||
|
baselineName: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
render(
|
||||||
|
<MemoryRouter initialEntries={["/overview"]}>
|
||||||
|
<App />
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.queryByRole("link", { name: /star .*repo/i })).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -7,6 +7,7 @@ import { Navigate, Route, Routes, useLocation } from "react-router-dom";
|
|||||||
import { CSSTransition, SwitchTransition } from "react-transition-group";
|
import { CSSTransition, SwitchTransition } from "react-transition-group";
|
||||||
|
|
||||||
import { Toaster } from "@/components/ui/sonner";
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
|
import { trackEvent } from "@/lib/analytics";
|
||||||
import { BasicAuthPrompt } from "./components/BasicAuthPrompt";
|
import { BasicAuthPrompt } from "./components/BasicAuthPrompt";
|
||||||
import { OnboardingGate } from "./components/OnboardingGate";
|
import { OnboardingGate } from "./components/OnboardingGate";
|
||||||
import { useDemoInfo } from "./hooks/useDemoInfo";
|
import { useDemoInfo } from "./hooks/useDemoInfo";
|
||||||
@ -58,7 +59,19 @@ export const App: React.FC = () => {
|
|||||||
{demoInfo?.demoMode && (
|
{demoInfo?.demoMode && (
|
||||||
<div className="w-full border-b border-amber-400/50 bg-amber-500/20 px-4 py-2 text-center text-xs text-amber-100 backdrop-blur">
|
<div className="w-full border-b border-amber-400/50 bg-amber-500/20 px-4 py-2 text-center text-xs text-amber-100 backdrop-blur">
|
||||||
Demo mode: integrations are simulated and data resets every{" "}
|
Demo mode: integrations are simulated and data resets every{" "}
|
||||||
{demoInfo.resetCadenceHours} hours.
|
{demoInfo.resetCadenceHours} hours.{" "}
|
||||||
|
<a
|
||||||
|
className="font-semibold underline underline-offset-2 hover:text-amber-50"
|
||||||
|
href="https://github.com/DaKheera47/job-ops"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
onClick={() =>
|
||||||
|
trackEvent("star_repo_click", { location: "demo_mode_banner" })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Star the repo on GitHub
|
||||||
|
</a>
|
||||||
|
.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user