From 51e2ecdec89011a12fdf48e447eb38f3fd8e212b Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Tue, 17 Feb 2026 11:24:59 -0800 Subject: [PATCH] =?UTF-8?q?test(telemetry):=20Phase=203=20regression=20tes?= =?UTF-8?q?ts=20=E2=80=94=20UpdateClusterSchema,=20ClusterStatusEnum,=20ex?= =?UTF-8?q?tractClientIp=20(614=E2=86=92624=20tests)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/telemetry/routes.ts | 2 +- .../src/modules/telemetry/telemetry.test.ts | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/services/platform-service/src/modules/telemetry/routes.ts b/services/platform-service/src/modules/telemetry/routes.ts index db829211..8036f655 100644 --- a/services/platform-service/src/modules/telemetry/routes.ts +++ b/services/platform-service/src/modules/telemetry/routes.ts @@ -209,7 +209,7 @@ async function lookupGeo(ip: string): Promise { } } -function extractClientIp(req: { +export function extractClientIp(req: { headers: Record; ip?: string; }): string { diff --git a/services/platform-service/src/modules/telemetry/telemetry.test.ts b/services/platform-service/src/modules/telemetry/telemetry.test.ts index 3a6787c1..5a49cfdb 100644 --- a/services/platform-service/src/modules/telemetry/telemetry.test.ts +++ b/services/platform-service/src/modules/telemetry/telemetry.test.ts @@ -20,7 +20,9 @@ import { policyMatchesContext, mergePolicies, checkRateLimit, + extractClientIp, } from './routes.js'; +import { UpdateClusterSchema, ClusterStatusEnum } from './types.js'; // ─── Minimal valid event for reuse ────────────────────────────────── @@ -673,3 +675,76 @@ describe('checkRateLimit', () => { expect(checkRateLimit(id1, 20)).toBe(false); // id1 exceeded }); }); + +// ─── UpdateClusterSchema ───────────────────────────────────────── + +describe('UpdateClusterSchema', () => { + it('accepts valid status values', () => { + for (const status of ['open', 'resolved', 'ignored']) { + const result = UpdateClusterSchema.safeParse({ status }); + expect(result.success).toBe(true); + } + }); + + it('rejects invalid status', () => { + const result = UpdateClusterSchema.safeParse({ status: 'deleted' }); + expect(result.success).toBe(false); + }); + + it('rejects missing status', () => { + const result = UpdateClusterSchema.safeParse({}); + expect(result.success).toBe(false); + }); +}); + +// ─── ClusterStatusEnum ─────────────────────────────────────────── + +describe('ClusterStatusEnum', () => { + it('defines exactly three values', () => { + expect(ClusterStatusEnum.options).toEqual(['open', 'resolved', 'ignored']); + }); +}); + +// ─── extractClientIp ───────────────────────────────────────────── + +describe('extractClientIp', () => { + it('extracts first IP from X-Forwarded-For string', () => { + expect( + extractClientIp({ + headers: { 'x-forwarded-for': '1.2.3.4, 10.0.0.1, 172.16.0.1' }, + }) + ).toBe('1.2.3.4'); + }); + + it('extracts from X-Forwarded-For array', () => { + expect( + extractClientIp({ + headers: { 'x-forwarded-for': ['5.6.7.8, 10.0.0.1'] }, + }) + ).toBe('5.6.7.8'); + }); + + it('falls back to req.ip when no X-Forwarded-For', () => { + expect(extractClientIp({ headers: {}, ip: '192.168.1.1' })).toBe('192.168.1.1'); + }); + + it('returns empty string when no IP available', () => { + expect(extractClientIp({ headers: {} })).toBe(''); + }); + + it('trims whitespace from X-Forwarded-For', () => { + expect( + extractClientIp({ + headers: { 'x-forwarded-for': ' 9.8.7.6 , 10.0.0.1' }, + }) + ).toBe('9.8.7.6'); + }); + + it('handles single IP in X-Forwarded-For (no comma)', () => { + expect( + extractClientIp({ + headers: { 'x-forwarded-for': '203.0.113.50' }, + }) + ).toBe('203.0.113.50'); + }); +});