discovery.test.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. import { describe, expect, it } from 'vitest';
  2. import { DiscoveryListener } from '../src/main/discovery';
  3. import { Announcer, broadcastAddresses } from '../src/server/discovery';
  4. import { MAX_PLAYERS, PROTOCOL_VERSION } from '../src/shared/constants';
  5. import { isAnnouncement, type Announcement } from '../src/shared/protocol';
  6. const announcement: Announcement = {
  7. magic: 'goutermageddon',
  8. serverId: 'test-server',
  9. name: 'Goûter de test',
  10. mapId: 'gateau-etages',
  11. players: 2,
  12. maxPlayers: MAX_PLAYERS,
  13. phase: 'lobby',
  14. version: PROTOCOL_VERSION,
  15. port: 47100,
  16. };
  17. describe('LAN discovery', () => {
  18. it('validates announcements', () => {
  19. expect(isAnnouncement(announcement)).toBe(true);
  20. expect(isAnnouncement({ ...announcement, magic: 'other-game' })).toBe(false);
  21. expect(isAnnouncement({ ...announcement, phase: 'nope' })).toBe(false);
  22. });
  23. it('always announces on loopback and the limited broadcast', () => {
  24. expect(broadcastAddresses()).toEqual(expect.arrayContaining(['127.0.0.1', '255.255.255.255']));
  25. });
  26. it('a listener hears an announcer on the same machine, once, with its address', async () => {
  27. const listener = new DiscoveryListener();
  28. listener.start((err) => {
  29. throw err;
  30. });
  31. const announcer = new Announcer(() => announcement);
  32. announcer.start();
  33. await new Promise((r) => setTimeout(r, 400));
  34. // Other games may be running on this machine or the LAN: only look at ours.
  35. const games = listener.list().filter((g) => g.serverId === 'test-server');
  36. announcer.stop();
  37. listener.stop();
  38. expect(games).toHaveLength(1);
  39. expect(games[0]).toMatchObject({ serverId: 'test-server', name: 'Goûter de test', players: 2, port: 47100 });
  40. expect(games[0].address).toMatch(/^\d+\.\d+\.\d+\.\d+$/);
  41. });
  42. });