Skip to content

Commit 079088b

Browse files
authored
Merge pull request #11 from supabase-community/feat/test-closest-region
feat: test closest region logic
2 parents 970af72 + c524661 commit 079088b

File tree

3 files changed

+73
-19
lines changed

3 files changed

+73
-19
lines changed

packages/mcp-server-supabase/src/regions.test.ts

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ import { describe, expect, it } from 'vitest';
22
import {
33
EARTH_RADIUS,
44
getClosestAwsRegion,
5+
getCountryCode,
56
getCountryCoordinates,
67
getDistance,
8+
TRACE_URL,
79
} from './regions.js';
10+
import { http, HttpResponse } from 'msw';
11+
import { setupServer } from 'msw/node';
12+
13+
const COUNTRY_CODE = 'US';
814

915
describe('getDistance', () => {
1016
it('should return 0 for the same coordinates', () => {
@@ -61,37 +67,55 @@ describe('getDistance', () => {
6167
});
6268

6369
describe('getClosestRegion', () => {
64-
it('should find the closest AWS region to a specific location', async () => {
70+
it('should find the closest AWS region to a specific location', () => {
6571
const tokyo = { lat: 35.6762, lng: 139.6503 };
66-
const result = await getClosestAwsRegion(tokyo);
72+
const result = getClosestAwsRegion(tokyo);
6773
expect(result.code).toBe('ap-northeast-1'); // Tokyo region
6874
});
6975

70-
it('should find the correct AWS region for European location', async () => {
76+
it('should find the correct AWS region for European location', () => {
7177
const london = { lat: 51.5074, lng: -0.1278 };
72-
const result = await getClosestAwsRegion(london);
78+
const result = getClosestAwsRegion(london);
7379
expect(result.code).toBe('eu-west-2'); // London region
7480
});
7581

76-
it('should find the correct AWS region for US West Coast location', async () => {
82+
it('should find the correct AWS region for US West Coast location', () => {
7783
const sanFrancisco = { lat: 37.7749, lng: -122.4194 };
78-
const result = await getClosestAwsRegion(sanFrancisco);
84+
const result = getClosestAwsRegion(sanFrancisco);
7985
expect(result.code).toBe('us-west-1'); // North California region
8086
});
8187

82-
it('should find the correct AWS region for Sydney location', async () => {
88+
it('should find the correct AWS region for Sydney location', () => {
8389
const sydney = { lat: -33.8688, lng: 151.2093 };
84-
const result = await getClosestAwsRegion(sydney);
90+
const result = getClosestAwsRegion(sydney);
8591
expect(result.code).toBe('ap-southeast-2'); // Sydney region
8692
});
8793

88-
it('should find the correct AWS region for a location in South America', async () => {
94+
it('should find the correct AWS region for a location in South America', () => {
8995
const saoPaulo = { lat: -23.5505, lng: -46.6333 };
90-
const result = await getClosestAwsRegion(saoPaulo);
96+
const result = getClosestAwsRegion(saoPaulo);
9197
expect(result.code).toBe('sa-east-1'); // São Paulo region
9298
});
9399
});
94100

101+
describe('getCountryCode', () => {
102+
const handlers = [
103+
http.get(TRACE_URL, () => {
104+
return HttpResponse.text(
105+
`fl=123abc\nvisit_scheme=https\nloc=${COUNTRY_CODE}\ntls=TLSv1.3\nhttp=http/2`
106+
);
107+
}),
108+
];
109+
110+
const server = setupServer(...handlers);
111+
server.listen({ onUnhandledRequest: 'error' });
112+
113+
it('should return the correct country code for a given location', async () => {
114+
const code = await getCountryCode();
115+
expect(code).toEqual(COUNTRY_CODE);
116+
});
117+
});
118+
95119
describe('getCountryCoordinates', () => {
96120
it('should throw an error for an invalid country code', async () => {
97121
const invalidCountryCode = 'INVALID_CODE';

packages/mcp-server-supabase/src/regions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type Location = {
1212
};
1313

1414
export const EARTH_RADIUS = 6371; // in kilometers
15+
export const TRACE_URL = 'https://www.cloudflare.com/cdn-cgi/trace';
1516

1617
export const COUNTRY_COORDINATES = {
1718
AF: { lat: 33, lng: 65 },
@@ -387,7 +388,7 @@ export function getClosestAwsRegion(location: Location) {
387388
* Fetches the user's country code based on their IP address.
388389
*/
389390
export async function getCountryCode() {
390-
const response = await fetch('https://www.cloudflare.com/cdn-cgi/trace');
391+
const response = await fetch(TRACE_URL);
391392
const data = await response.text();
392393
const info = parseKeyValueList(data);
393394
const countryCode = info['loc'];

packages/mcp-server-supabase/src/server.test.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { beforeEach, describe, expect, test } from 'vitest';
1212
import { z } from 'zod';
1313
import { version } from '../package.json';
1414
import type { components } from './management-api/types';
15+
import { TRACE_URL } from './regions.js';
1516
import { createSupabaseMcpServer } from './server.js';
1617

1718
type Project = components['schemas']['V1ProjectWithDatabaseResponse'];
@@ -23,6 +24,8 @@ const MCP_SERVER_VERSION = version;
2324
const MCP_CLIENT_NAME = 'test-client';
2425
const MCP_CLIENT_VERSION = '0.1.0';
2526
const ACCESS_TOKEN = 'dummy-token';
27+
const COUNTRY_CODE = 'US';
28+
const CLOSEST_REGION = 'us-east-2';
2629

2730
const mockOrgs: Organization[] = [
2831
{ id: 'org-1', name: 'Org 1' },
@@ -91,6 +94,12 @@ beforeEach(() => {
9194

9295
// Mock the management API
9396
const handlers = [
97+
http.get(TRACE_URL, () => {
98+
return HttpResponse.text(
99+
`fl=123abc\nvisit_scheme=https\nloc=${COUNTRY_CODE}\ntls=TLSv1.3\nhttp=http/2`
100+
);
101+
}),
102+
94103
http.all('*', ({ request }) => {
95104
const authHeader = request.headers.get('Authorization');
96105

@@ -230,14 +239,7 @@ beforeEach(() => {
230239
];
231240

232241
const server = setupServer(...handlers);
233-
234-
server.listen({
235-
onUnhandledRequest: (request) => {
236-
throw new Error(
237-
`No request handler found for ${request.method} ${request.url}`
238-
);
239-
},
240-
});
242+
server.listen({ onUnhandledRequest: 'error' });
241243
});
242244

243245
type SetupOptions = {
@@ -387,6 +389,33 @@ describe('tools', () => {
387389
});
388390
});
389391

392+
test('create project chooses closest region when undefined', async () => {
393+
const { callTool } = await setup();
394+
395+
const newProject = {
396+
name: 'New Project',
397+
organization_id: mockOrgs[0]!.id,
398+
db_pass: 'dummy-password',
399+
};
400+
401+
const result = await callTool({
402+
name: 'create_project',
403+
arguments: newProject,
404+
});
405+
406+
const { db_pass, ...projectInfo } = newProject;
407+
408+
expect(result).toEqual({
409+
...projectInfo,
410+
id: expect.stringMatching(/^project-\d+$/),
411+
created_at: expect.stringMatching(
412+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/
413+
),
414+
status: 'UNKNOWN',
415+
region: CLOSEST_REGION,
416+
});
417+
});
418+
390419
test('get project url', async () => {
391420
const { callTool } = await setup();
392421
const project = mockProjects[0]!;

0 commit comments

Comments
 (0)