diff --git a/native/ios/MatchLiveTv.xcodeproj/project.pbxproj b/native/ios/MatchLiveTv.xcodeproj/project.pbxproj index 35face1..81d39ea 100644 --- a/native/ios/MatchLiveTv.xcodeproj/project.pbxproj +++ b/native/ios/MatchLiveTv.xcodeproj/project.pbxproj @@ -677,11 +677,11 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 37; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_API_BASE_URL = "$(API_BASE_URL)"; IPHONEOS_DEPLOYMENT_TARGET = 16.6; - MARKETING_VERSION = 2.0.12; + MARKETING_VERSION = 2.0.13; PRODUCT_BUNDLE_IDENTIFIER = "com.matchlivetv.match-live-tv.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -698,7 +698,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 37; DEVELOPMENT_TEAM = S8Q9TWBRG5; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = MatchLiveTv/Resources/Info.plist; @@ -709,7 +709,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.12; + MARKETING_VERSION = 2.0.13; PRODUCT_BUNDLE_IDENTIFIER = "com.matchlivetv.match-live-tv"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -727,7 +727,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 37; DEVELOPMENT_TEAM = S8Q9TWBRG5; ENABLE_TESTABILITY = YES; GENERATE_INFOPLIST_FILE = NO; @@ -739,7 +739,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.12; + MARKETING_VERSION = 2.0.13; PRODUCT_BUNDLE_IDENTIFIER = "com.matchlivetv.match-live-tv"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -756,11 +756,11 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 37; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_API_BASE_URL = "$(API_BASE_URL)"; IPHONEOS_DEPLOYMENT_TARGET = 16.6; - MARKETING_VERSION = 2.0.12; + MARKETING_VERSION = 2.0.13; PRODUCT_BUNDLE_IDENTIFIER = "com.matchlivetv.match-live-tv.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -775,11 +775,11 @@ buildSettings = { CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 37; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_API_BASE_URL = "$(API_BASE_URL)"; IPHONEOS_DEPLOYMENT_TARGET = 16.6; - MARKETING_VERSION = 2.0.12; + MARKETING_VERSION = 2.0.13; PRODUCT_BUNDLE_IDENTIFIER = "com.matchlivetv.match-live-tv.uitests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -794,11 +794,11 @@ buildSettings = { CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 37; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_API_BASE_URL = "$(API_BASE_URL)"; IPHONEOS_DEPLOYMENT_TARGET = 16.6; - MARKETING_VERSION = 2.0.12; + MARKETING_VERSION = 2.0.13; PRODUCT_BUNDLE_IDENTIFIER = "com.matchlivetv.match-live-tv.uitests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; diff --git a/native/ios/MatchLiveTv/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon.png b/native/ios/MatchLiveTv/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon.png index a625fdf..7aead6f 100644 Binary files a/native/ios/MatchLiveTv/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon.png and b/native/ios/MatchLiveTv/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon.png differ diff --git a/native/ios/MatchLiveTv/Resources/Info.plist b/native/ios/MatchLiveTv/Resources/Info.plist index 04a65da..e474af1 100644 --- a/native/ios/MatchLiveTv/Resources/Info.plist +++ b/native/ios/MatchLiveTv/Resources/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.0.12 + 2.0.13 CFBundleURLTypes @@ -32,7 +32,7 @@ CFBundleVersion - 35 + 37 LSRequiresIPhoneOS NSCameraUsageDescription diff --git a/native/ios/MatchLiveTvTests/ApiInstantTests.swift b/native/ios/MatchLiveTvTests/ApiInstantTests.swift index f6d7c3b..119e302 100644 --- a/native/ios/MatchLiveTvTests/ApiInstantTests.swift +++ b/native/ios/MatchLiveTvTests/ApiInstantTests.swift @@ -1,7 +1,45 @@ import XCTest +@testable import MatchLiveTv -/// Smoke test eseguibile senza @testable import (validazione logica pura). +/// Logica calendario/API reale + smoke parser (RTMP/overlay) senza dipendenze di rete. final class ApiInstantTests: XCTestCase { + func testParseApiInstantRailsOffsetWithMillis() { + let now = iso("2026-06-06T16:00:00Z") + XCTAssertTrue(ApiInstant.isScheduledOnCalendar("2026-06-06T20:00:00.000+02:00", now: now)) + } + + func testIsScheduledOnCalendarKeepsThisMorningAfterKickoff() { + let kickoff = "2026-09-06T07:00:00Z" + let now = iso("2026-09-06T08:30:00Z") + XCTAssertTrue(ApiInstant.isScheduledOnCalendar(kickoff, now: now)) + XCTAssertFalse(ApiInstant.isScheduledFuture(kickoff, now: now)) + } + + func testIsScheduledOnCalendarHidesYesterday() { + let yesterday = "2026-09-05T10:00:00Z" + let now = iso("2026-09-06T08:30:00Z") + XCTAssertFalse(ApiInstant.isScheduledOnCalendar(yesterday, now: now)) + } + + func testConcurrentStreamForbiddenShowsApiMessage() { + let body = """ + {"error":"Hai già una diretta in corso con questo account. Chiudila prima di avviarne un’altra.","error_code":"user_concurrent_stream"} + """ + XCTAssertEqual( + APIError.http(403, body).errorDescription, + "Hai già una diretta in corso con questo account. Chiudila prima di avviarne un’altra." + ) + } + + private func iso(_ value: String) -> Date { + let f = ISO8601DateFormatter() + f.formatOptions = [.withInternetDateTime] + guard let date = f.date(from: value) else { + XCTFail("Data ISO non valida: \(value)") + return Date() + } + return date + } func testOverlayKindMapping() { XCTAssertEqual(OverlayKindMapping.fromApi("basket"), "basket") XCTAssertEqual(OverlayKindMapping.fromApi("none"), "none") diff --git a/native/ios/MatchLiveTvTests/MatchScoringRulesTests.swift b/native/ios/MatchLiveTvTests/MatchScoringRulesTests.swift index 498001b..1f19614 100644 --- a/native/ios/MatchLiveTvTests/MatchScoringRulesTests.swift +++ b/native/ios/MatchLiveTvTests/MatchScoringRulesTests.swift @@ -121,6 +121,65 @@ final class MatchScoringRulesTests: XCTestCase { } } +final class MatchHubCalendarTests: XCTestCase { + func testHubKeepsMatchAfterKickoffSameDay() { + let now = iso("2026-09-06T08:30:00Z") + let match = hubMatch(scheduledAt: "2026-09-06T07:00:00Z") + XCTAssertTrue(MatchHubFilter.coachHubVisible(match, now: now)) + XCTAssertTrue(MatchHubFilter.isOnCalendar(match, now: now)) + XCTAssertFalse(MatchHubFilter.isScheduledFuture(match, now: now)) + } + + func testHubHidesYesterdayMatch() { + let now = iso("2026-09-06T08:30:00Z") + let match = hubMatch(scheduledAt: "2026-09-05T10:00:00Z") + XCTAssertFalse(MatchHubFilter.coachHubVisible(match, now: now)) + } + + func testHubRespectsApiCoachHubVisibleFalse() { + let now = iso("2026-09-06T08:30:00Z") + let match = hubMatch(scheduledAt: "2026-09-06T07:00:00Z", coachHubVisible: false) + XCTAssertFalse(MatchHubFilter.coachHubVisible(match, now: now)) + } + + private func iso(_ value: String) -> Date { + let f = ISO8601DateFormatter() + f.formatOptions = [.withInternetDateTime] + return f.date(from: value)! + } + + private func hubMatch(scheduledAt: String?, coachHubVisible: Bool? = nil) -> Match { + Match( + id: "match-hub", + teamId: "team-1", + teamName: "Team MLTV", + opponentName: "Team Guest", + location: nil, + scheduledAt: scheduledAt, + sportKey: "pallavolo", + sportLabel: "Pallavolo", + boardType: "volley", + overlayKind: "volley", + effectiveOverlayKind: "volley", + setsToWin: 3, + category: nil, + scoringRules: nil, + activeSessionId: nil, + activeSessionStatus: nil, + streamCompleted: false, + coachHubVisible: coachHubVisible, + homePrimaryColor: "#FF2D2D", + homeSecondaryColor: nil, + homeLogoUrl: nil, + opponentPrimaryColor: "#1E3A8A", + opponentLogoUrl: nil, + effectiveCoverUrl: nil, + coverSource: "default", + customCoverEnabled: false + ) + } +} + final class ScoreboardOverlayTests: XCTestCase { func testScoreboardColumnsAfterSetClosed() { let score = ScoreState( diff --git a/native/ios/generate_xcodeproj.py b/native/ios/generate_xcodeproj.py index b8ef250..0d754af 100755 --- a/native/ios/generate_xcodeproj.py +++ b/native/ios/generate_xcodeproj.py @@ -96,7 +96,7 @@ lines += [ app_settings = """ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 37; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = MatchLiveTv/Resources/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 16.0; @@ -107,7 +107,7 @@ app_settings = """ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.12; + MARKETING_VERSION = 2.0.13; PRODUCT_BUNDLE_IDENTIFIER = com.matchlivetv.match-live-tv; PRODUCT_NAME = "$(TARGET_NAME)"; API_BASE_URL = "https://www.matchlivetv.it"; @@ -122,10 +122,10 @@ app_debug_settings = app_settings + """ test_settings = """ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 37; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.0; - MARKETING_VERSION = 2.0.12; + MARKETING_VERSION = 2.0.13; PRODUCT_BUNDLE_IDENTIFIER = com.matchlivetv.match-live-tv.tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos;