import 'package:farolero/estado/estado_juego.dart'; import 'package:farolero/modelos/inicio_partida_multijugador.dart'; import 'package:farolero/modelos/jugador.dart'; import 'package:farolero/modelos/palabra.dart'; import 'package:farolero/modelos/partida.dart'; import 'package:farolero/modelos/snapshot_partida_online.dart'; import 'package:flutter_test/flutter_test.dart'; Partida _partidaConImpostores() => Partida( config: const ConfigPartida(numImpostores: 2), jugadores: [ Jugador(id: 'j1', nombre: 'Ana', esImpostor: true), Jugador(id: 'j2', nombre: 'Beto'), Jugador(id: 'j3', nombre: 'Cris', esImpostor: true), Jugador(id: 'j4', nombre: 'Dani'), ], palabraSecreta: 'Camión', categoriaReal: 'objetos', ); void main() { group('SnapshotPartidaOnline no filtra los roles', () { test('durante la partida no envía esImpostor de nadie', () { final json = SnapshotPartidaOnline.desdePartida( _partidaConImpostores(), fase: 'debate', ).toJson(); final jugadores = json['jugadoresTodos'] as List; for (final jugador in jugadores) { expect( (jugador as Map).containsKey('esImpostor'), isFalse, reason: 'el rol no puede viajar en el snapshot de fase', ); } expect(json.containsKey('impostores'), isFalse); expect(json.containsKey('palabraSecreta'), isFalse); }); test('al final de la partida sí revela roles y palabra', () { final json = SnapshotPartidaOnline.desdePartida( _partidaConImpostores(), fase: 'finPartida', revelarImpostores: true, revelarPalabra: true, ).toJson(); final jugadores = (json['jugadoresTodos'] as List) .cast>(); expect(jugadores.every((j) => j.containsKey('esImpostor')), isTrue); expect(json['impostores'], ['Ana', 'Cris']); expect(json['palabraSecreta'], 'Camión'); }); test('el snapshot de fase se reparsea sin marcar impostores', () { final snapshot = SnapshotPartidaOnline.fromJson( SnapshotPartidaOnline.desdePartida( _partidaConImpostores(), fase: 'votacion', ).toJson(), ); expect(snapshot.jugadores.any((j) => j.esImpostor), isFalse); expect(snapshot.revelarImpostores, isFalse); }); }); group('Los impostores se conocen entre ellos', () { final asignaciones = const [ AsignacionJugador( jugadorId: 'j1', nombre: 'Ana', clientId: 'host', endpointId: null, ), AsignacionJugador( jugadorId: 'j2', nombre: 'Beto', clientId: 'c2', endpointId: 'e2', ), AsignacionJugador( jugadorId: 'j3', nombre: 'Cris', clientId: 'c3', endpointId: 'e3', ), ]; const impostores = {'j1': true, 'j2': false, 'j3': true}; test('cada impostor recibe los nombres del resto, nunca el suyo', () { final payloads = InicioPartidaMultijugador.crearPayloadsPorCliente( asignaciones: asignaciones, palabraSecreta: 'Camión', categoria: 'objetos', impostoresPorJugadorId: impostores, impostoresSeConocen: true, ); expect(payloads['host']!.jugadores.single.companerosImpostores, ['Cris']); expect(payloads['c3']!.jugadores.single.companerosImpostores, ['Ana']); }); test('un jugador normal nunca recibe la lista', () { final payloads = InicioPartidaMultijugador.crearPayloadsPorCliente( asignaciones: asignaciones, palabraSecreta: 'Camión', categoria: 'objetos', impostoresPorJugadorId: impostores, impostoresSeConocen: true, ); expect(payloads['c2']!.jugadores.single.companerosImpostores, isNull); }); test('con la opción desactivada nadie recibe la lista', () { final payloads = InicioPartidaMultijugador.crearPayloadsPorCliente( asignaciones: asignaciones, palabraSecreta: 'Camión', categoria: 'objetos', impostoresPorJugadorId: impostores, impostoresSeConocen: false, ); for (final payload in payloads.values) { for (final jugador in payload.jugadores) { expect(jugador.companerosImpostores, isNull); } } }); test('la lista vacía sobrevive al viaje JSON y no se vuelve null', () { const jugador = JugadorInicioPartida( jugadorId: 'j1', nombre: 'Ana', esImpostor: true, palabra: null, companerosImpostores: [], ); final reparsed = JugadorInicioPartida.fromJson(jugador.toJson()); expect(reparsed.companerosImpostores, isEmpty); expect(reparsed.companerosImpostores, isNotNull); }); }); group('Pistas del banco de palabras', () { test('prioriza la pista de la palabra sobre la de la categoría', () { final banco = BancoPalabras( { 'objetos': ['Camión', 'Silla'], }, pistasPorCategoria: {'objetos': 'Objetos'}, pistasPorPalabra: {'Camión': 'Se conduce y transporta carga'}, ); expect(banco.pistaDePalabra('Camión'), 'Se conduce y transporta carga'); expect(banco.pistaDePalabra('Silla'), 'Objetos'); }); test('sin pista de palabra ni de categoría devuelve null', () { final banco = BancoPalabras({ 'objetos': ['Silla'], }); expect(banco.pistaDePalabra('Silla'), isNull); }); }); group('Tope de impostores', () { test('es el mismo en ambos modos de juego', () { expect(EstadoJuego.maxImpostoresPara(3), 1); expect(EstadoJuego.maxImpostoresPara(5), 1); expect(EstadoJuego.maxImpostoresPara(6), 2); expect(EstadoJuego.maxImpostoresPara(12), 4); expect(EstadoJuego.maxImpostoresPara(20), 4); }); }); group('Partida', () { test('la pista cae a la categoría cuando no se aporta una específica', () { final partida = Partida( config: const ConfigPartida(), jugadores: [Jugador(id: 'j1', nombre: 'Ana')], palabraSecreta: 'Camión', categoriaReal: 'objetos', ); expect(partida.pistaImpostor, 'objetos'); }); test('nombresImpostores lista solo a los impostores', () { expect(_partidaConImpostores().nombresImpostores, ['Ana', 'Cris']); }); }); }