Skip to content

Commit 8539f4f

Browse files
authored
fixes api key access for postcode search (#37)
* Add working unit tests * fixes api key access for postcode search
1 parent ad6e5dd commit 8539f4f

File tree

5 files changed

+104
-51
lines changed

5 files changed

+104
-51
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { render } from '@testing-library/react';
2+
import CardGrid from '@/components/layout/CardGrid';
3+
4+
describe('CardGrid', () => {
5+
it('renders children inside a grid', () => {
6+
const { container } = render(
7+
<CardGrid>
8+
<p>child</p>
9+
</CardGrid>
10+
);
11+
const grid = container.firstChild as HTMLElement;
12+
expect(grid.className).toContain('grid');
13+
expect(grid.textContent).toContain('child');
14+
});
15+
16+
it('uses single column layout when singleColumn is true', () => {
17+
const { container } = render(
18+
<CardGrid singleColumn>
19+
<p>item</p>
20+
</CardGrid>
21+
);
22+
const grid = container.firstChild as HTMLElement;
23+
expect(grid.className).toContain('grid-cols-1');
24+
expect(grid.className).toContain('max-w-screen-md');
25+
});
26+
});
Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,54 @@
1-
// __tests__/components/FilterPanel.test.tsx
1+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
2+
import FilterPanel from '@/components/FindHelp/FilterPanel';
3+
4+
function setup(selectedCategory = '', selectedSubCategory = '') {
5+
const setCategory = jest.fn();
6+
const setSub = jest.fn();
7+
const utils = render(
8+
<FilterPanel
9+
selectedCategory={selectedCategory}
10+
selectedSubCategory={selectedSubCategory}
11+
setSelectedCategory={setCategory}
12+
setSelectedSubCategory={setSub}
13+
/>
14+
);
15+
return { setCategory, setSub, ...utils };
16+
}
217

318
describe('FilterPanel', () => {
4-
it('skipped pending tests', () => {
5-
expect(true).toBe(true);
19+
it('renders category dropdown with options', () => {
20+
setup();
21+
const select = screen.getByLabelText('Category:');
22+
expect(select).toBeInTheDocument();
23+
// Check a known category from the data file
24+
expect(screen.getByRole('option', { name: /Food/i })).toBeInTheDocument();
625
});
726

8-
// TODO: Fix role matching for category dropdown
9-
// it('renders category dropdown with options after fetch', async () => {
10-
// ...
11-
// });
27+
it('updates category and subcategory selections', async () => {
28+
const { setCategory, setSub, rerender } = setup();
29+
const categorySelect = screen.getByLabelText('Category:');
30+
31+
fireEvent.change(categorySelect, { target: { value: 'foodbank' } });
32+
33+
await waitFor(() => expect(setCategory).toHaveBeenCalledWith('foodbank'));
1234

13-
// TODO: Investigate multiple matches on 'category' label
14-
// it('calls onFilterChange with correct values when category changes', async () => {
15-
// ...
16-
// });
35+
rerender(
36+
<FilterPanel
37+
selectedCategory="foodbank"
38+
selectedSubCategory=""
39+
setSelectedCategory={setCategory}
40+
setSelectedSubCategory={setSub}
41+
/>
42+
);
1743

18-
// TODO: Same as above — too many category matches
19-
// it('shows subcategory options when a category is selected', async () => {
20-
// ...
21-
// });
44+
const subSelect = screen.getByLabelText('Subcategory:');
45+
expect(subSelect).not.toBeDisabled();
46+
47+
await waitFor(() =>
48+
expect(screen.getByRole('option', { name: /Food Banks/i })).toBeInTheDocument()
49+
);
50+
51+
fireEvent.change(subSelect, { target: { value: 'general' } });
52+
expect(setSub).toHaveBeenCalledWith('general');
53+
});
2254
});
Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,27 @@
1-
import { render, screen } from '@testing-library/react';
1+
import { render } from '@testing-library/react';
22
import GoogleMap from '@/components/MapComponent/GoogleMap';
33

4-
const mockPins = [
4+
type Marker = { id: string; lat: number; lng: number; title: string; icon?: string };
5+
6+
const mockMarkers: Marker[] = [
57
{ id: '1', lat: 53.1, lng: -0.5, title: 'Test Pin 1' },
68
{ id: '2', lat: 53.2, lng: -0.6, title: 'Test Pin 2', icon: 'http://example.com/icon.png' },
79
];
810

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

11-
// Stub window.google before each test
1213
beforeEach(() => {
1314
(window as any).google = {
1415
maps: {
15-
Map: class {
16-
setCenter = jest.fn();
17-
setZoom = jest.fn();
18-
},
19-
marker: {
20-
AdvancedMarkerElement: class {
21-
map = null;
22-
constructor(args: any) {
23-
Object.assign(this, args);
24-
}
25-
},
26-
},
16+
Map: jest.fn().mockImplementation(function () {}),
17+
Marker: jest.fn().mockImplementation(function () {
18+
this.setMap = jest.fn();
19+
this.addListener = jest.fn();
20+
}),
21+
InfoWindow: jest.fn().mockImplementation(function () {
22+
this.open = jest.fn();
23+
this.close = jest.fn();
24+
}),
2725
},
2826
};
2927
});
@@ -33,21 +31,18 @@ afterEach(() => {
3331
});
3432

3533
describe('GoogleMap', () => {
36-
// it('renders without crashing', () => {
37-
// render(<GoogleMap pins={mockPins} center={mockCenter} zoom={10} />);
38-
// expect(screen.getByRole('region')).toBeInTheDocument(); // container div
39-
// });
34+
it('renders map container', () => {
35+
const { container } = render(<GoogleMap markers={mockMarkers} center={mockCenter} />);
36+
expect(container.querySelector('div')).toBeInTheDocument();
37+
});
4038

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

4644
it('creates markers using Google Maps API', () => {
47-
render(<GoogleMap pins={mockPins} center={mockCenter} zoom={10} />);
48-
const AdvancedMarkerElement = (window as any).google.maps.marker.AdvancedMarkerElement;
49-
50-
// There should be at least one marker created
51-
expect(AdvancedMarkerElement).toBeDefined();
45+
render(<GoogleMap markers={mockMarkers} center={mockCenter} />);
46+
expect((window as any).google.maps.Marker).toHaveBeenCalledTimes(mockMarkers.length);
5247
});
5348
});

__tests__/components/ServiceCard.test.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ describe('ServiceCard', () => {
3030
expect(screen.getByText(/Subcategory: dentist/i)).toBeInTheDocument();
3131
});
3232

33-
// it('renders client group tags and opening times', () => {
34-
// render(<ServiceCard service={mockService} />);
35-
// expect(screen.getByText('age-18+')).toBeInTheDocument();
36-
// expect(screen.getByText('rough-sleepers')).toBeInTheDocument();
37-
// expect(screen.getByText('Monday: 09:00 - 17:00')).toBeInTheDocument();
38-
// expect(screen.getByText('Wednesday: 09:00 - 17:00')).toBeInTheDocument();
39-
// });
33+
it('renders client group tags and opening times', () => {
34+
render(<ServiceCard service={mockService} />);
35+
expect(screen.getByText('age-18+')).toBeInTheDocument();
36+
expect(screen.getByText('rough-sleepers')).toBeInTheDocument();
37+
expect(screen.getByText('Monday: 09:00 17:00')).toBeInTheDocument();
38+
expect(screen.getByText('Wednesday: 09:00 17:00')).toBeInTheDocument();
39+
});
4040
});

src/app/api/geocode/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export async function GET(req: NextRequest) {
1212
});
1313
}
1414

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

1818
if (!apiKey) {

0 commit comments

Comments
 (0)