Skip to content
Merged
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
26 changes: 26 additions & 0 deletions __tests__/components/CardGrid.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { render } from '@testing-library/react';
import CardGrid from '@/components/layout/CardGrid';

describe('CardGrid', () => {
it('renders children inside a grid', () => {
const { container } = render(
<CardGrid>
<p>child</p>
</CardGrid>
);
const grid = container.firstChild as HTMLElement;
expect(grid.className).toContain('grid');
expect(grid.textContent).toContain('child');
});

it('uses single column layout when singleColumn is true', () => {
const { container } = render(
<CardGrid singleColumn>
<p>item</p>
</CardGrid>
);
const grid = container.firstChild as HTMLElement;
expect(grid.className).toContain('grid-cols-1');
expect(grid.className).toContain('max-w-screen-md');
});
});
62 changes: 47 additions & 15 deletions __tests__/components/FilterPanel.test.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,54 @@
// __tests__/components/FilterPanel.test.tsx
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import FilterPanel from '@/components/FindHelp/FilterPanel';

function setup(selectedCategory = '', selectedSubCategory = '') {
const setCategory = jest.fn();
const setSub = jest.fn();
const utils = render(
<FilterPanel
selectedCategory={selectedCategory}
selectedSubCategory={selectedSubCategory}
setSelectedCategory={setCategory}
setSelectedSubCategory={setSub}
/>
);
return { setCategory, setSub, ...utils };
}

describe('FilterPanel', () => {
it('skipped pending tests', () => {
expect(true).toBe(true);
it('renders category dropdown with options', () => {
setup();
const select = screen.getByLabelText('Category:');
expect(select).toBeInTheDocument();
// Check a known category from the data file
expect(screen.getByRole('option', { name: /Food/i })).toBeInTheDocument();
});

// TODO: Fix role matching for category dropdown
// it('renders category dropdown with options after fetch', async () => {
// ...
// });
it('updates category and subcategory selections', async () => {
const { setCategory, setSub, rerender } = setup();
const categorySelect = screen.getByLabelText('Category:');

fireEvent.change(categorySelect, { target: { value: 'foodbank' } });

await waitFor(() => expect(setCategory).toHaveBeenCalledWith('foodbank'));

// TODO: Investigate multiple matches on 'category' label
// it('calls onFilterChange with correct values when category changes', async () => {
// ...
// });
rerender(
<FilterPanel
selectedCategory="foodbank"
selectedSubCategory=""
setSelectedCategory={setCategory}
setSelectedSubCategory={setSub}
/>
);

// TODO: Same as above — too many category matches
// it('shows subcategory options when a category is selected', async () => {
// ...
// });
const subSelect = screen.getByLabelText('Subcategory:');
expect(subSelect).not.toBeDisabled();

await waitFor(() =>
expect(screen.getByRole('option', { name: /Food Banks/i })).toBeInTheDocument()
);

fireEvent.change(subSelect, { target: { value: 'general' } });
expect(setSub).toHaveBeenCalledWith('general');
});
});
51 changes: 23 additions & 28 deletions __tests__/components/GoogleMap.test.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
import { render, screen } from '@testing-library/react';
import { render } from '@testing-library/react';
import GoogleMap from '@/components/MapComponent/GoogleMap';

const mockPins = [
type Marker = { id: string; lat: number; lng: number; title: string; icon?: string };

const mockMarkers: Marker[] = [
{ id: '1', lat: 53.1, lng: -0.5, title: 'Test Pin 1' },
{ id: '2', lat: 53.2, lng: -0.6, title: 'Test Pin 2', icon: 'http://example.com/icon.png' },
];

const mockCenter = { lat: 53.1, lng: -0.5 };

// Stub window.google before each test
beforeEach(() => {
(window as any).google = {
maps: {
Map: class {
setCenter = jest.fn();
setZoom = jest.fn();
},
marker: {
AdvancedMarkerElement: class {
map = null;
constructor(args: any) {
Object.assign(this, args);
}
},
},
Map: jest.fn().mockImplementation(function () {}),
Marker: jest.fn().mockImplementation(function () {
this.setMap = jest.fn();
this.addListener = jest.fn();
}),
InfoWindow: jest.fn().mockImplementation(function () {
this.open = jest.fn();
this.close = jest.fn();
}),
},
};
});
Expand All @@ -33,21 +31,18 @@ afterEach(() => {
});

describe('GoogleMap', () => {
// it('renders without crashing', () => {
// render(<GoogleMap pins={mockPins} center={mockCenter} zoom={10} />);
// expect(screen.getByRole('region')).toBeInTheDocument(); // container div
// });
it('renders map container', () => {
const { container } = render(<GoogleMap markers={mockMarkers} center={mockCenter} />);
expect(container.querySelector('div')).toBeInTheDocument();
});

// it('displays loading spinner initially', () => {
// render(<GoogleMap pins={mockPins} center={mockCenter} zoom={10} />);
// expect(screen.getByRole('status')).toBeInTheDocument(); // spinner div
// });
it('initialises Google Maps when center provided', () => {
render(<GoogleMap markers={mockMarkers} center={mockCenter} />);
expect((window as any).google.maps.Map).toHaveBeenCalled();
});

it('creates markers using Google Maps API', () => {
render(<GoogleMap pins={mockPins} center={mockCenter} zoom={10} />);
const AdvancedMarkerElement = (window as any).google.maps.marker.AdvancedMarkerElement;

// There should be at least one marker created
expect(AdvancedMarkerElement).toBeDefined();
render(<GoogleMap markers={mockMarkers} center={mockCenter} />);
expect((window as any).google.maps.Marker).toHaveBeenCalledTimes(mockMarkers.length);
});
});
14 changes: 7 additions & 7 deletions __tests__/components/ServiceCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ describe('ServiceCard', () => {
expect(screen.getByText(/Subcategory: dentist/i)).toBeInTheDocument();
});

// it('renders client group tags and opening times', () => {
// render(<ServiceCard service={mockService} />);
// expect(screen.getByText('age-18+')).toBeInTheDocument();
// expect(screen.getByText('rough-sleepers')).toBeInTheDocument();
// expect(screen.getByText('Monday: 09:00 - 17:00')).toBeInTheDocument();
// expect(screen.getByText('Wednesday: 09:00 - 17:00')).toBeInTheDocument();
// });
it('renders client group tags and opening times', () => {
render(<ServiceCard service={mockService} />);
expect(screen.getByText('age-18+')).toBeInTheDocument();
expect(screen.getByText('rough-sleepers')).toBeInTheDocument();
expect(screen.getByText('Monday: 09:00 17:00')).toBeInTheDocument();
expect(screen.getByText('Wednesday: 09:00 17:00')).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion src/app/api/geocode/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function GET(req: NextRequest) {
});
}

const apiKey = process.env.GOOGLE_MAPS_API_KEY;
const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY;
console.log('Loaded server API key:', apiKey);

if (!apiKey) {
Expand Down