Skip to content

Commit 31d8f01

Browse files
test(worker): assert full upstream fetch args in worker tests
Agent-Logs-Url: https://github.com/richardthe3rd/cambridge-beer-festival-app/sessions/0c00ccf3-adc6-477f-818c-0327541020c6 Co-authored-by: richardthe3rd <573334+richardthe3rd@users.noreply.github.com>
1 parent da23570 commit 31d8f01

2 files changed

Lines changed: 31 additions & 20 deletions

File tree

cloudflare-worker/test/beverage-types.test.js

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:
33
import worker from '../worker.js';
44

55
const UPSTREAM = 'https://data.cambridgebeerfestival.com';
6+
const DIRECTORY_FETCH_INIT = {
7+
headers: {
8+
'User-Agent': 'Cambridge-Beer-Festival-App-Proxy/1.0',
9+
},
10+
};
611

712
async function fetchWorker(path, origin = 'https://cambeerfestival.app') {
813
const request = new Request(`https://worker.example.com${path}`, {
@@ -51,7 +56,7 @@ describe('available_beverage_types endpoint', () => {
5156
const data = await response.json();
5257
expect(data.festival_id).toBe('cbf2025');
5358
expect(data.available_beverage_types).toEqual(['beer', 'cider', 'mead', 'perry']);
54-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
59+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
5560
});
5661

5762
it('returns types sorted alphabetically', async () => {
@@ -63,7 +68,7 @@ describe('available_beverage_types endpoint', () => {
6368
const response = await fetchWorker('/cbf2025/available_beverage_types.json');
6469
const data = await response.json();
6570
expect(data.available_beverage_types).toEqual(['apple-juice', 'beer', 'wine']);
66-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
71+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
6772
});
6873

6974
it('filters out available_beverage_types.json from results', async () => {
@@ -76,7 +81,7 @@ describe('available_beverage_types endpoint', () => {
7681
const data = await response.json();
7782
expect(data.available_beverage_types).toEqual(['beer', 'cider']);
7883
expect(data.available_beverage_types).not.toContain('available_beverage_types');
79-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
84+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
8085
});
8186

8287
it('returns empty array when no JSON files found', async () => {
@@ -88,7 +93,7 @@ describe('available_beverage_types endpoint', () => {
8893
const response = await fetchWorker('/cbf2025/available_beverage_types.json');
8994
const data = await response.json();
9095
expect(data.available_beverage_types).toEqual([]);
91-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
96+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
9297
});
9398

9499
it('returns 404 when festival not found upstream', async () => {
@@ -100,7 +105,7 @@ describe('available_beverage_types endpoint', () => {
100105
const data = await response.json();
101106
expect(data.error).toBe('Festival not found');
102107
expect(data.festival_id).toBe('nonexistent');
103-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/nonexistent/`, expect.anything());
108+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/nonexistent/`, DIRECTORY_FETCH_INIT);
104109
});
105110

106111
it('returns 500 when upstream fetch fails', async () => {
@@ -111,7 +116,7 @@ describe('available_beverage_types endpoint', () => {
111116

112117
const data = await response.json();
113118
expect(data.error).toBe('Failed to fetch beverage types');
114-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
119+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
115120
});
116121

117122
it('includes CORS headers on 500 error', async () => {
@@ -120,7 +125,7 @@ describe('available_beverage_types endpoint', () => {
120125
const response = await fetchWorker('/cbf2025/available_beverage_types.json');
121126
expect(response.headers.get('Access-Control-Allow-Origin'))
122127
.toBe('https://cambeerfestival.app');
123-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
128+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
124129
});
125130

126131
it('includes CORS headers on success', async () => {
@@ -132,7 +137,7 @@ describe('available_beverage_types endpoint', () => {
132137
const response = await fetchWorker('/cbf2025/available_beverage_types.json');
133138
expect(response.headers.get('Access-Control-Allow-Origin'))
134139
.toBe('https://cambeerfestival.app');
135-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
140+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
136141
});
137142

138143
it('includes CORS headers on 404', async () => {
@@ -141,7 +146,7 @@ describe('available_beverage_types endpoint', () => {
141146
const response = await fetchWorker('/nonexistent/available_beverage_types.json');
142147
expect(response.headers.get('Access-Control-Allow-Origin'))
143148
.toBe('https://cambeerfestival.app');
144-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/nonexistent/`, expect.anything());
149+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/nonexistent/`, DIRECTORY_FETCH_INIT);
145150
});
146151

147152
it('sets Cache-Control to 1 hour on success', async () => {
@@ -152,7 +157,7 @@ describe('available_beverage_types endpoint', () => {
152157

153158
const response = await fetchWorker('/cbf2025/available_beverage_types.json');
154159
expect(response.headers.get('Cache-Control')).toBe('public, max-age=3600');
155-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
160+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
156161
});
157162

158163
it('includes timestamp in response', async () => {
@@ -165,7 +170,7 @@ describe('available_beverage_types endpoint', () => {
165170
const data = await response.json();
166171
expect(data.timestamp).toBeDefined();
167172
expect(new Date(data.timestamp).toISOString()).toBe(data.timestamp);
168-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
173+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
169174
});
170175

171176
it('handles hyphenated beverage type names', async () => {
@@ -179,6 +184,6 @@ describe('available_beverage_types endpoint', () => {
179184
expect(data.available_beverage_types).toEqual([
180185
'apple-juice', 'international-beer', 'low-no',
181186
]);
182-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, expect.anything());
187+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/`, DIRECTORY_FETCH_INIT);
183188
});
184189
});

cloudflare-worker/test/proxy.test.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:
33
import worker from '../worker.js';
44

55
const UPSTREAM = 'https://data.cambridgebeerfestival.com';
6+
const PROXY_FETCH_INIT = {
7+
method: 'GET',
8+
headers: {
9+
'User-Agent': 'Cambridge-Beer-Festival-App-Proxy/1.0',
10+
},
11+
};
612

713
async function fetchWorker(path, origin = 'https://cambeerfestival.app') {
814
const request = new Request(`https://worker.example.com${path}`, {
@@ -60,7 +66,7 @@ describe('upstream proxy', () => {
6066

6167
const data = await response.json();
6268
expect(data).toEqual([{ name: 'Test Brewery', products: [] }]);
63-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, expect.anything());
69+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, PROXY_FETCH_INIT);
6470
});
6571

6672
it('adds charset=utf-8 to JSON responses missing it', async () => {
@@ -72,7 +78,7 @@ describe('upstream proxy', () => {
7278
const response = await fetchWorker('/cbf2025/beer.json');
7379
expect(response.headers.get('Content-Type'))
7480
.toBe('application/json; charset=utf-8');
75-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, expect.anything());
81+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, PROXY_FETCH_INIT);
7682
});
7783

7884
it('preserves charset if already present in upstream response', async () => {
@@ -84,7 +90,7 @@ describe('upstream proxy', () => {
8490
const response = await fetchWorker('/cbf2025/beer.json');
8591
expect(response.headers.get('Content-Type'))
8692
.toBe('application/json; charset=utf-8');
87-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, expect.anything());
93+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, PROXY_FETCH_INIT);
8894
});
8995

9096
it('includes CORS headers on proxied responses', async () => {
@@ -97,15 +103,15 @@ describe('upstream proxy', () => {
97103
expect(response.headers.get('Access-Control-Allow-Origin'))
98104
.toBe('https://cambeerfestival.app');
99105
expect(response.headers.get('Vary')).toBe('Origin');
100-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, expect.anything());
106+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, PROXY_FETCH_INIT);
101107
});
102108

103109
it('passes through upstream error status codes', async () => {
104110
mockFetch.mockResolvedValueOnce(new Response('Not Found', { status: 404 }));
105111

106112
const response = await fetchWorker('/cbf2025/nonexistent.json');
107113
expect(response.status).toBe(404);
108-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/nonexistent.json`, expect.anything());
114+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/nonexistent.json`, PROXY_FETCH_INIT);
109115
});
110116

111117
it('returns 502 when upstream fetch fails', async () => {
@@ -117,7 +123,7 @@ describe('upstream proxy', () => {
117123
const data = await response.json();
118124
expect(data.error).toBe('Proxy error');
119125
expect(data.message).toBeDefined();
120-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, expect.anything());
126+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, PROXY_FETCH_INIT);
121127
});
122128

123129
it('returns 502 with CORS headers on proxy error', async () => {
@@ -127,7 +133,7 @@ describe('upstream proxy', () => {
127133
expect(response.status).toBe(502);
128134
expect(response.headers.get('Access-Control-Allow-Origin'))
129135
.toBe('https://cambeerfestival.app');
130-
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, expect.anything());
136+
expect(mockFetch).toHaveBeenCalledWith(`${UPSTREAM}/cbf2025/beer.json`, PROXY_FETCH_INIT);
131137
});
132138

133139
it('preserves query string when proxying', async () => {
@@ -140,7 +146,7 @@ describe('upstream proxy', () => {
140146
expect(response.status).toBe(200);
141147
expect(mockFetch).toHaveBeenCalledWith(
142148
`${UPSTREAM}/cbf2025/beer.json?v=2`,
143-
expect.anything(),
149+
PROXY_FETCH_INIT,
144150
);
145151
});
146152
});

0 commit comments

Comments
 (0)