mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: add a Keep it free sponsor button to the top nav (#427)
Adds a prominent Keep it free sponsor button to the top nav, linking to https://github.com/sponsors/snapotter-hq. Solid orange pill on desktop (left of the avatar), orange heart icon on mobile. Opens in a new tab with rel=noopener noreferrer, so no referrer or user data leaks, and it adds no passive network activity (offline-mode compatible). Fires an opt-in, property-less sponsor_clicked analytics event. Adds sidebar.sponsor and a11y.sponsorLink across all 21 locales. Claude-Session: https://claude.ai/code/session_01DnYLLA5z4Uf1GDeEPENVgr
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { expect, test } from "./helpers";
|
||||
|
||||
const SPONSOR_URL = "https://github.com/sponsors/snapotter-hq";
|
||||
|
||||
test.describe("Sponsor button", () => {
|
||||
// Pin a desktop viewport so the full pill (with visible text) renders,
|
||||
// not the mobile icon-only form.
|
||||
test.use({ viewport: { width: 1280, height: 720 } });
|
||||
|
||||
test("top nav links to GitHub Sponsors with safe rel", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
|
||||
const link = page.locator(`a[href="${SPONSOR_URL}"]`);
|
||||
await expect(link).toBeVisible();
|
||||
await expect(link).toHaveAttribute("target", "_blank");
|
||||
await expect(link).toHaveAttribute("rel", "noopener noreferrer");
|
||||
await expect(link).toContainText(/keep it free/i);
|
||||
});
|
||||
});
|
||||
@@ -2,8 +2,8 @@ import { ANALYTICS_EVENTS } from "@snapotter/shared";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
describe("ANALYTICS_EVENTS", () => {
|
||||
it("has exactly 13 event keys", () => {
|
||||
expect(Object.keys(ANALYTICS_EVENTS)).toHaveLength(13);
|
||||
it("has exactly 14 event keys", () => {
|
||||
expect(Object.keys(ANALYTICS_EVENTS)).toHaveLength(14);
|
||||
});
|
||||
|
||||
it("contains the expected keys", () => {
|
||||
@@ -20,6 +20,7 @@ describe("ANALYTICS_EVENTS", () => {
|
||||
expect(ANALYTICS_EVENTS).toHaveProperty("AI_BUNDLE_PROMPTED");
|
||||
expect(ANALYTICS_EVENTS).toHaveProperty("BATCH_PROCESSED");
|
||||
expect(ANALYTICS_EVENTS).toHaveProperty("FEEDBACK_SUBMITTED");
|
||||
expect(ANALYTICS_EVENTS).toHaveProperty("SPONSOR_CLICKED");
|
||||
});
|
||||
|
||||
it("all event values are strings", () => {
|
||||
|
||||
Reference in New Issue
Block a user