Skip to main content
Glama
population.test.ts4.27 kB
import { describe, it, expect, vi, beforeEach } from "vitest"; import { analyzePopulation } from "../tools/population.js"; // API 모킹 vi.mock("../api/kakao-api.js", () => ({ kakaoApi: { getCoordinates: vi.fn(), }, })); vi.mock("../api/semas-api.js", () => ({ semasApi: { getStoresByRadius: vi.fn(), }, })); import { kakaoApi } from "../api/kakao-api.js"; import { semasApi } from "../api/semas-api.js"; describe("analyzePopulation", () => { beforeEach(() => { vi.clearAllMocks(); }); it("should return error when location not found", async () => { vi.mocked(kakaoApi.getCoordinates).mockResolvedValue(null); const result = await analyzePopulation("존재하지않는장소"); expect(result.success).toBe(false); expect(result.error?.code).toBe("LOCATION_NOT_FOUND"); }); it("should analyze known area (강남역) successfully", async () => { // 강남역은 알려진 상권이므로 좌표 조회 필요 없음 const result = await analyzePopulation("강남역"); expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.data?.location.name).toBe("강남역"); expect(result.data?.population.total).toBeGreaterThan(0); }); it("should include time distribution", async () => { const result = await analyzePopulation("홍대입구"); expect(result.success).toBe(true); expect(result.data?.timeDistribution).toBeDefined(); expect(result.data?.timeDistribution.morning).toBeGreaterThanOrEqual(0); expect(result.data?.timeDistribution.lunch).toBeGreaterThanOrEqual(0); expect(result.data?.timeDistribution.afternoon).toBeGreaterThanOrEqual(0); expect(result.data?.timeDistribution.evening).toBeGreaterThanOrEqual(0); expect(result.data?.timeDistribution.night).toBeGreaterThanOrEqual(0); }); it("should include age distribution", async () => { const result = await analyzePopulation("신촌"); expect(result.success).toBe(true); expect(result.data?.ageDistribution).toBeDefined(); // 대학가는 20대 비율이 높아야 함 expect(result.data?.ageDistribution.twenties).toBeGreaterThan(20); }); it("should calculate business fit when business type provided", async () => { const result = await analyzePopulation("강남역", "카페"); expect(result.success).toBe(true); expect(result.data?.businessFit).toBeDefined(); expect(result.data?.businessFit?.score).toBeGreaterThanOrEqual(0); expect(result.data?.businessFit?.score).toBeLessThanOrEqual(100); }); it("should include SEMAS real-time data when available", async () => { vi.mocked(kakaoApi.getCoordinates).mockResolvedValue({ lat: 37.556, lng: 126.924, }); vi.mocked(semasApi.getStoresByRadius).mockResolvedValue({ stores: [ { bizesNm: "테스트1", indsLclsNm: "음식" } as never, { bizesNm: "테스트2", indsLclsNm: "음식" } as never, { bizesNm: "테스트3", indsLclsNm: "소매" } as never, ], totalCount: 100, }); const result = await analyzePopulation("홍대입구", undefined, 500); expect(result.success).toBe(true); // SEMAS 데이터가 있으면 인사이트에 상권 데이터 표시 expect(result.data?.insights.some(i => i.includes("상권") || i.includes("업소"))).toBe(true); }); it("should infer area type for unknown locations", async () => { vi.mocked(kakaoApi.getCoordinates).mockResolvedValue({ lat: 37.5, lng: 127.0, }); vi.mocked(semasApi.getStoresByRadius).mockResolvedValue({ stores: [], totalCount: 0, }); const result = await analyzePopulation("테스트역"); expect(result.success).toBe(true); // 역이 포함된 이름은 역세권으로 추론되거나 특성이 있어야 함 expect(result.data?.characteristics).toBeDefined(); expect(result.data?.characteristics.length).toBeGreaterThan(0); }); it("should include gender ratio", async () => { const result = await analyzePopulation("명동"); expect(result.success).toBe(true); expect(result.data?.genderRatio).toBeDefined(); const genderRatio = result.data!.genderRatio; expect(genderRatio.male + genderRatio.female).toBe(100); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/re171113-byte/startup-helper-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server