import { describe, expect, it } from 'vitest'; import { parseInfoLine, parsePlayerCount } from '../../src/lib/server/integrations/rcon.js'; describe('parsePlayerCount', () => { it('counts rows after --- --- separator (status dialect)', () => { const body = [ 'print', 'map: mp_kino', 'num score ping guid name', '--- ----- ---- -------- ----', ' 0 12 45 abc123def456 joe', ' 1 0 72 xyz789abc123 jill', ' 2 999 30 111222333444 kade' ].join('\n'); expect(parsePlayerCount(body)).toBe(3); }); it('returns 0 when the scoreboard has no rows', () => { const body = [ 'print', 'map: mp_ascension', 'num score ping guid name', '--- ----- ---- -------- ----', '' ].join('\n'); expect(parsePlayerCount(body)).toBe(0); }); it('counts non-blank lines after the info line (statusResponse dialect)', () => { const body = [ 'statusResponse', '\\mapname\\mp_kino\\g_gametype\\zom\\sv_maxclients\\4', '10 45 "joe"', '0 72 "jill"' ].join('\n'); expect(parsePlayerCount(body)).toBe(2); }); it('returns null on malformed payloads with no separator or info line', () => { expect(parsePlayerCount('nonsense body\nno structure here')).toBeNull(); }); }); describe('parseInfoLine', () => { it('splits \\key\\value pairs from an info string', () => { const body = [ 'statusResponse', '\\mapname\\mp_kino\\g_gametype\\zom\\sv_maxclients\\4' ].join('\n'); const info = parseInfoLine(body); expect(info.mapname).toBe('mp_kino'); expect(info.g_gametype).toBe('zom'); expect(info.sv_maxclients).toBe('4'); }); it('returns empty object when no info line is present', () => { expect(parseInfoLine('nothing here')).toEqual({}); }); });