Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 61 additions & 5 deletions soroban-client/__tests__/components/Header.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import Header from '../../components/Header';
import { ThemeProvider } from '@/contexts/ThemeContext';
import { useWallet } from '@/contexts/WalletContext';

// Mock Wallet Context Hook
Expand All @@ -13,6 +14,33 @@ jest.mock('next/navigation', () => ({
}));

describe('Header Component', () => {
beforeEach(() => {
window.localStorage.clear();

Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query: string) => ({
matches: false,
media: query,
onchange: null,
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
addListener: jest.fn(),
removeListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});

document.documentElement.classList.remove('dark');
});

const renderHeader = () =>
render(
<ThemeProvider>
<Header />
</ThemeProvider>
);

it('renders navigation links properly', () => {
(useWallet as jest.Mock).mockReturnValue({
address: null,
Expand All @@ -27,7 +55,7 @@ describe('Header Component', () => {
signTransaction: jest.fn(),
});

render(<Header />);
renderHeader();

expect(screen.getByText('CrowdPass')).toBeInTheDocument();
// Home, Events, Analytics, and Create Events may appear multiple times (desktop + mobile)
Expand All @@ -36,6 +64,7 @@ describe('Header Component', () => {
expect(screen.getAllByText('Analytics').length).toBeGreaterThan(0);
expect(screen.getAllByText('Create Events').length).toBeGreaterThan(0);
expect(screen.getAllByText('Connect Freighter').length).toBeGreaterThan(0);
expect(screen.getAllByLabelText('Switch to dark mode').length).toBeGreaterThan(0);
});

it('displays Install Freighter if wallet is not installed', () => {
Expand All @@ -52,7 +81,7 @@ describe('Header Component', () => {
signTransaction: jest.fn(),
});

render(<Header />);
renderHeader();
// Select Wallet may appear multiple times (desktop + mobile)
expect(screen.getAllByText('Select Wallet').length).toBeGreaterThan(0);
});
Expand All @@ -74,15 +103,42 @@ describe('Header Component', () => {
signTransaction: jest.fn(),
});

render(<Header />);
renderHeader();
const formattedAddress = 'GBJ2...V2Y2';
// There are multiple address displays (desktop and mobile), so verify they exist
expect(screen.getAllByText(formattedAddress).length).toBeGreaterThan(0);

// Disconnect buttons may appear multiple times (desktop + mobile)
const disconnectBtns = screen.getAllByText('Disconnect');
expect(disconnectBtns.length).toBeGreaterThan(0);
fireEvent.click(disconnectBtns[0]);
expect(disconnectMock).toHaveBeenCalledTimes(1);
});

it('persists theme selection and toggles the root dark class', async () => {
(useWallet as jest.Mock).mockReturnValue({
address: null,
providerId: 'freighter',
providerName: 'Freighter',
availableProviders: [],
isConnected: false,
isInstalled: true,
connect: jest.fn(),
disconnect: jest.fn(),
setProviderId: jest.fn(),
signTransaction: jest.fn(),
});

renderHeader();

const toggleButtons = screen.getAllByLabelText('Switch to dark mode');
fireEvent.click(toggleButtons[0]);

await waitFor(() => {
expect(window.localStorage.getItem('crowdpass-theme')).toBe('dark');
expect(document.documentElement.classList.contains('dark')).toBe(true);
});

expect(screen.getAllByLabelText('Switch to light mode').length).toBeGreaterThan(0);
});
});
10 changes: 5 additions & 5 deletions soroban-client/app/[locale]/analytics/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import Header from "@/components/Header";

export default function AnalyticsPage() {
return (
<div className="min-h-screen bg-[#18181B] text-white">
<div className="min-h-screen bg-background text-foreground">
<AnalyticsPageView page="analytics" />
<Header />

<main className="mx-auto flex w-full max-w-7xl flex-col gap-10 px-4 pb-20 pt-36 sm:px-6">
<section className="rounded-[32px] border border-white/10 bg-[radial-gradient(circle_at_top_left,_rgba(255,87,34,0.18),_transparent_35%),linear-gradient(180deg,rgba(255,255,255,0.04),rgba(255,255,255,0.02))] p-8">
<p className="text-sm uppercase tracking-[0.4em] text-orange-200/70">
<section className="rounded-[32px] border border-zinc-200 bg-white/90 p-8 shadow-lg shadow-zinc-900/5 dark:border-white/10 dark:bg-[radial-gradient(circle_at_top_left,_rgba(255,87,34,0.18),_transparent_35%),linear-gradient(180deg,rgba(255,255,255,0.04),rgba(255,255,255,0.02))] dark:shadow-none">
<p className="text-sm uppercase tracking-[0.4em] text-orange-700 dark:text-orange-200/70">
Analytics
</p>
<h1 className="mt-3 max-w-3xl text-4xl font-semibold leading-tight sm:text-5xl">
<h1 className="mt-3 max-w-3xl text-4xl font-semibold leading-tight text-zinc-950 dark:text-white sm:text-5xl">
Organizer and platform insights in one dashboard
</h1>
<p className="mt-4 max-w-2xl text-base leading-7 text-zinc-300">
<p className="mt-4 max-w-2xl text-base leading-7 text-zinc-600 dark:text-zinc-300">
Track page views, wallet connections, batch ticket purchases, conversion
trends, and revenue signals without leaving the CrowdPass interface.
</p>
Expand Down
Loading
Loading