import { describe, expect, it } from 'vitest'; import { DiscoveryListener } from '../src/main/discovery'; import { Announcer, broadcastAddresses } from '../src/server/discovery'; import { MAX_PLAYERS, PROTOCOL_VERSION } from '../src/shared/constants'; import { isAnnouncement, type Announcement } from '../src/shared/protocol'; const announcement: Announcement = { magic: 'goutermageddon', serverId: 'test-server', name: 'Goûter de test', mapId: 'gateau-etages', players: 2, maxPlayers: MAX_PLAYERS, phase: 'lobby', version: PROTOCOL_VERSION, port: 47100, }; describe('LAN discovery', () => { it('validates announcements', () => { expect(isAnnouncement(announcement)).toBe(true); expect(isAnnouncement({ ...announcement, magic: 'other-game' })).toBe(false); expect(isAnnouncement({ ...announcement, phase: 'nope' })).toBe(false); }); it('always announces on loopback and the limited broadcast', () => { expect(broadcastAddresses()).toEqual(expect.arrayContaining(['127.0.0.1', '255.255.255.255'])); }); it('a listener hears an announcer on the same machine, once, with its address', async () => { const listener = new DiscoveryListener(); listener.start((err) => { throw err; }); const announcer = new Announcer(() => announcement); announcer.start(); await new Promise((r) => setTimeout(r, 400)); const games = listener.list(); announcer.stop(); listener.stop(); expect(games).toHaveLength(1); expect(games[0]).toMatchObject({ serverId: 'test-server', name: 'Goûter de test', players: 2, port: 47100 }); expect(games[0].address).toMatch(/^\d+\.\d+\.\d+\.\d+$/); }); });