Files
MatchLiveTv/native/ios/MatchLiveTvTests/ScoreControllerTests.swift
Emiliano Frascaro e20c2ae619 Accetta undo punteggio dalla regia sull'overlay iOS.
applyRemote ignorava aggiornamenti Action Cable con progressKey più basso, quindi il meno in regia non aggiornava il tabellone sullo stream.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-20 16:28:36 +02:00

162 lines
6.2 KiB
Swift

import XCTest
@testable import MatchLiveTv
@MainActor
final class ScoreControllerTests: XCTestCase {
func testBindNewSessionResetsScoreToZero() {
let controller = ScoreController(
scoreRepository: ScoreRepository(api: MatchLiveAPI()),
sessionCable: SessionCableService()
)
var previous = ScoreState()
previous.homePoints = 3
previous.awayPoints = 3
controller.bind(sessionId: "session-1", initial: previous)
XCTAssertEqual(controller.score.homePoints, 3)
controller.bind(sessionId: "session-2", initial: nil)
XCTAssertEqual(controller.score.homePoints, 0)
XCTAssertEqual(controller.score.awayPoints, 0)
}
func testBindNewSessionUsesServerInitialState() {
let controller = ScoreController(
scoreRepository: ScoreRepository(api: MatchLiveAPI()),
sessionCable: SessionCableService()
)
controller.bind(sessionId: "session-1", initial: ScoreState(homePoints: 2, awayPoints: 1))
var fresh = ScoreState()
fresh.homePoints = 1
fresh.awayPoints = 0
controller.bind(sessionId: "session-2", initial: fresh)
XCTAssertEqual(controller.score.homePoints, 1)
XCTAssertEqual(controller.score.awayPoints, 0)
}
func testIncrementHomeUpdatesPublishedScore() {
let controller = ScoreController(
scoreRepository: ScoreRepository(api: MatchLiveAPI()),
sessionCable: SessionCableService()
)
controller.bind(sessionId: "session-1", initial: ScoreState())
controller.incrementHome()
XCTAssertEqual(controller.score.homePoints, 1)
}
func testApplyBoardActionOptimisticThenConfirm() async {
let api = MatchLiveAPI()
let controller = ScoreController(
scoreRepository: ScoreRepository(api: api),
sessionCable: SessionCableService()
)
controller.bind(sessionId: "session-1", initial: ScoreState())
// Senza backend: fallisce e ripristina ma l'ottimistico deve almeno scattare durante la chiamata.
// Verifichiamo solo che applyOptimistic funzioni via applyAction locale.
controller.applyAction("home_point")
XCTAssertEqual(controller.score.homePoints, 1)
}
func testAdvancePeriodOptimisticUpdatesQuarter() {
let controller = ScoreController(
scoreRepository: ScoreRepository(api: MatchLiveAPI()),
sessionCable: SessionCableService()
)
var initial = ScoreState()
initial.boardType = "basket"
initial.period = 1
initial.periodLabel = "Q1"
controller.bind(sessionId: "session-1", initial: initial)
controller.applyAction("advance_period")
XCTAssertEqual(controller.score.period, 2)
XCTAssertEqual(controller.score.periodLabel, "Q2")
XCTAssertFalse(controller.score.clockRunning)
}
func testProgressKeyChangesWhenPeriodAdvances() {
var q1 = ScoreState(boardType: "basket", period: 1, periodLabel: "Q1", clockSecs: 600)
var q2 = ScoreState(boardType: "basket", period: 2, periodLabel: "Q2", clockSecs: 600)
q1.homePoints = 10
q1.awayPoints = 8
q2.homePoints = 10
q2.awayPoints = 8
XCTAssertGreaterThan(q2.progressKey(), q1.progressKey())
}
func testCableRemoteCancelsStaleLocalSync() {
let controller = ScoreController(
scoreRepository: ScoreRepository(api: MatchLiveAPI()),
sessionCable: SessionCableService()
)
var local = ScoreState(boardType: "basket", period: 1, periodLabel: "Q1")
local.homePoints = 5
local.awayPoints = 4
controller.bind(sessionId: "session-1", initial: local)
controller.applyAction("home_point")
var remote = ScoreState(boardType: "basket", period: 1, periodLabel: "Q1")
remote.homePoints = 6
remote.awayPoints = 7
controller.applyRemote(remote, source: .cable)
XCTAssertEqual(controller.score.homePoints, 6)
XCTAssertEqual(controller.score.awayPoints, 7)
}
func testCableAdvancePeriodUpdatesOverlayState() {
let controller = ScoreController(
scoreRepository: ScoreRepository(api: MatchLiveAPI()),
sessionCable: SessionCableService()
)
var local = ScoreState(boardType: "basket", period: 1, periodLabel: "Q1")
local.homePoints = 0
local.awayPoints = 4
controller.bind(sessionId: "session-1", initial: local)
var remote = ScoreState(boardType: "basket", period: 2, periodLabel: "Q2")
remote.homePoints = 0
remote.awayPoints = 4
controller.applyRemote(remote, source: .cable)
XCTAssertEqual(controller.score.periodLabel, "Q2")
XCTAssertEqual(controller.score.period, 2)
}
func testCableUndoFromRegiaAppliesLowerScore() {
let controller = ScoreController(
scoreRepository: ScoreRepository(api: MatchLiveAPI()),
sessionCable: SessionCableService()
)
var local = ScoreState(boardType: "basket", period: 2, periodLabel: "Q2")
local.homePoints = 6
local.awayPoints = 4
controller.bind(sessionId: "session-1", initial: local)
var remote = ScoreState(boardType: "basket", period: 2, periodLabel: "Q2")
remote.homePoints = 5
remote.awayPoints = 4
controller.applyRemote(remote, source: .cable)
XCTAssertEqual(controller.score.homePoints, 5)
XCTAssertEqual(controller.score.awayPoints, 4)
}
func testPollingUndoFromRegiaAppliesWhenNotSuppressing() {
let controller = ScoreController(
scoreRepository: ScoreRepository(api: MatchLiveAPI()),
sessionCable: SessionCableService()
)
var local = ScoreState(boardType: "basket")
local.homePoints = 6
local.awayPoints = 4
controller.bind(sessionId: "session-1", initial: local)
var remote = ScoreState(boardType: "basket")
remote.homePoints = 5
remote.awayPoints = 3
controller.applyRemote(remote, source: .polling)
XCTAssertEqual(controller.score.homePoints, 5)
XCTAssertEqual(controller.score.awayPoints, 3)
}
}