diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 030e62a..814b48f 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -157,6 +157,7 @@ C4A47DA92B85F82100ADC637 /* ChangePasswordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DA82B85F82100ADC637 /* ChangePasswordView.swift */; }; C4A47DAD2B85FCCD00ADC637 /* CustomUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DAC2B85FCCD00ADC637 /* CustomUser.swift */; }; C4A47DB32B86387500ADC637 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DB22B86387500ADC637 /* AccountView.swift */; }; + C4AD83612DAE5EBF00022F97 /* ServerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AD83602DAE5EBF00022F97 /* ServerStateTests.swift */; }; C4B3A1552C2581DA0078EAA8 /* Patcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B3A1542C2581DA0078EAA8 /* Patcher.swift */; }; C4C01D982C481C0C0059087C /* CapsuleViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C01D972C481C0C0059087C /* CapsuleViewModifier.swift */; }; C4C33F762C9B1ED4006316DE /* CodingContainer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C33F752C9B1EC5006316DE /* CodingContainer+Extensions.swift */; }; @@ -1123,6 +1124,7 @@ C4A47DA82B85F82100ADC637 /* ChangePasswordView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangePasswordView.swift; sourceTree = ""; }; C4A47DAC2B85FCCD00ADC637 /* CustomUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomUser.swift; sourceTree = ""; }; C4A47DB22B86387500ADC637 /* AccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountView.swift; sourceTree = ""; }; + C4AD83602DAE5EBF00022F97 /* ServerStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerStateTests.swift; sourceTree = ""; }; C4B3A1542C2581DA0078EAA8 /* Patcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Patcher.swift; sourceTree = ""; }; C4C01D972C481C0C0059087C /* CapsuleViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapsuleViewModifier.swift; sourceTree = ""; }; C4C33F752C9B1EC5006316DE /* CodingContainer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CodingContainer+Extensions.swift"; sourceTree = ""; }; @@ -1542,6 +1544,7 @@ C425D4112B6D249E002A7B48 /* PadelClubTests.swift */, C49EF0412BE23BF50077B5AA /* PaymentTests.swift */, C411C9C22BEBA453003017AD /* ServerDataTests.swift */, + C4AD83602DAE5EBF00022F97 /* ServerStateTests.swift */, C411C9C82BF219CB003017AD /* UserDataTests.swift */, C411C9CF2BF38F41003017AD /* TokenExemptionTests.swift */, C4D477982CB6704C0077713D /* SynchronizationTests.swift */, @@ -2885,6 +2888,7 @@ C49EF0422BE23BF50077B5AA /* PaymentTests.swift in Sources */, C4D477992CB6704C0077713D /* SynchronizationTests.swift in Sources */, C425D4122B6D249E002A7B48 /* PadelClubTests.swift in Sources */, + C4AD83612DAE5EBF00022F97 /* ServerStateTests.swift in Sources */, C411C9C92BF219CB003017AD /* UserDataTests.swift in Sources */, C411C9C32BEBA453003017AD /* ServerDataTests.swift in Sources */, ); diff --git a/PadelClub/Data/Club.swift b/PadelClub/Data/Club.swift index c24cf26..80aff9b 100644 --- a/PadelClub/Data/Club.swift +++ b/PadelClub/Data/Club.swift @@ -31,12 +31,12 @@ final class Club: BaseClub { DataStore.shared.courts.filter { $0.club == self.id }.sorted(by: \.index) } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { let customizedCourts = self.customizedCourts for customizedCourt in customizedCourts { - customizedCourt.deleteDependencies() + customizedCourt.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - DataStore.shared.courts.deleteDependencies(customizedCourts) + DataStore.shared.courts.deleteDependencies(customizedCourts, shouldBeSynchronized: shouldBeSynchronized) } } diff --git a/PadelClub/Data/Court.swift b/PadelClub/Data/Court.swift index a1a7a7b..21aeca5 100644 --- a/PadelClub/Data/Court.swift +++ b/PadelClub/Data/Court.swift @@ -52,7 +52,7 @@ final class Court: BaseCourt { Store.main.findById(club) } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { } } diff --git a/PadelClub/Data/DateInterval.swift b/PadelClub/Data/DateInterval.swift index 94db947..4bdb0f3 100644 --- a/PadelClub/Data/DateInterval.swift +++ b/PadelClub/Data/DateInterval.swift @@ -57,7 +57,7 @@ final class DateInterval: BaseDateInterval { date <= startDate && date <= endDate && date >= startDate && date >= endDate } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { } // enum CodingKeys: String, CodingKey { diff --git a/PadelClub/Data/DrawLog.swift b/PadelClub/Data/DrawLog.swift index a0be6e3..67afe85 100644 --- a/PadelClub/Data/DrawLog.swift +++ b/PadelClub/Data/DrawLog.swift @@ -74,7 +74,7 @@ final class DrawLog: BaseDrawLog, SideStorable { return TournamentLibrary.shared.store(tournamentId: self.tournament) } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { } } diff --git a/PadelClub/Data/Event.swift b/PadelClub/Data/Event.swift index ed3d6e4..ff0bad4 100644 --- a/PadelClub/Data/Event.swift +++ b/PadelClub/Data/Event.swift @@ -25,19 +25,19 @@ final class Event: BaseEvent { super.init() } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { let tournaments = self.tournaments for tournament in tournaments { - tournament.deleteDependencies() + tournament.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - DataStore.shared.tournaments.deleteDependencies(tournaments) + DataStore.shared.tournaments.deleteDependencies(tournaments, shouldBeSynchronized: shouldBeSynchronized) let courtsUnavailabilities = self.courtsUnavailability for courtsUnavailability in courtsUnavailabilities { - courtsUnavailability.deleteDependencies() + courtsUnavailability.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - DataStore.shared.dateIntervals.deleteDependencies(courtsUnavailabilities) + DataStore.shared.dateIntervals.deleteDependencies(courtsUnavailabilities, shouldBeSynchronized: shouldBeSynchronized) } // MARK: - Computed dependencies diff --git a/PadelClub/Data/GroupStage.swift b/PadelClub/Data/GroupStage.swift index c515b98..f4c7c83 100644 --- a/PadelClub/Data/GroupStage.swift +++ b/PadelClub/Data/GroupStage.swift @@ -599,12 +599,12 @@ final class GroupStage: BaseGroupStage, SideStorable { return teams(true).firstIndex(of: team) } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { let matches = self._matches() for match in matches { - match.deleteDependencies() + match.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - self.tournamentStore?.matches.deleteDependencies(matches) + self.tournamentStore?.matches.deleteDependencies(matches, shouldBeSynchronized: shouldBeSynchronized) } // init(from decoder: Decoder) throws { diff --git a/PadelClub/Data/Match.swift b/PadelClub/Data/Match.swift index e747bea..abc9c4a 100644 --- a/PadelClub/Data/Match.swift +++ b/PadelClub/Data/Match.swift @@ -70,12 +70,12 @@ final class Match: BaseMatch, SideStorable { // MARK: - - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { let teamScores = self.teamScores for teamScore in teamScores { - teamScore.deleteDependencies() + teamScore.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - self.tournamentStore?.teamScores.deleteDependencies(teamScores) + self.tournamentStore?.teamScores.deleteDependencies(teamScores, shouldBeSynchronized: shouldBeSynchronized) } func indexInRound(in matches: [Match]? = nil) -> Int { diff --git a/PadelClub/Data/Round.swift b/PadelClub/Data/Round.swift index e3a7b90..d8c53f8 100644 --- a/PadelClub/Data/Round.swift +++ b/PadelClub/Data/Round.swift @@ -711,20 +711,20 @@ defer { self.tournamentStore?.matches.addOrUpdate(contentOfs: playedMatches) } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { let matches = self._matches() for match in matches { - match.deleteDependencies() + match.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - self.tournamentStore?.matches.deleteDependencies(matches) + self.tournamentStore?.matches.deleteDependencies(matches, shouldBeSynchronized: shouldBeSynchronized) let loserRounds = self.loserRounds() for round in loserRounds { - round.deleteDependencies() + round.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - self.tournamentStore?.rounds.deleteDependencies(loserRounds) + self.tournamentStore?.rounds.deleteDependencies(loserRounds, shouldBeSynchronized: shouldBeSynchronized) } // enum CodingKeys: String, CodingKey { diff --git a/PadelClub/Data/TeamRegistration.swift b/PadelClub/Data/TeamRegistration.swift index 62954c7..e57a927 100644 --- a/PadelClub/Data/TeamRegistration.swift +++ b/PadelClub/Data/TeamRegistration.swift @@ -116,18 +116,18 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable { tournamentStore.teamScores.delete(contentOfs: ts) } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { let unsortedPlayers = unsortedPlayers() for player in unsortedPlayers { - player.deleteDependencies() + player.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - self.tournamentStore?.playerRegistrations.deleteDependencies(unsortedPlayers) + self.tournamentStore?.playerRegistrations.deleteDependencies(unsortedPlayers, shouldBeSynchronized: shouldBeSynchronized) let teamScores = teamScores() for teamScore in teamScores { - teamScore.deleteDependencies() + teamScore.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - self.tournamentStore?.teamScores.deleteDependencies(teamScores) + self.tournamentStore?.teamScores.deleteDependencies(teamScores, shouldBeSynchronized: shouldBeSynchronized) } func hasArrived(isHere: Bool = false) { diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 6c82b89..3881a9c 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -124,32 +124,32 @@ final class Tournament: BaseTournament { return TournamentLibrary.shared.store(tournamentId: self.id) } - override func deleteDependencies() { + override func deleteDependencies(shouldBeSynchronized: Bool) { guard let store = self.tournamentStore else { return } let drawLogs = Array(store.drawLogs) for drawLog in drawLogs { - drawLog.deleteDependencies() + drawLog.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - store.drawLogs.deleteDependencies(drawLogs) + store.drawLogs.deleteDependencies(drawLogs, shouldBeSynchronized: shouldBeSynchronized) let teams = Array(store.teamRegistrations) for team in teams { - team.deleteDependencies() + team.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - store.teamRegistrations.deleteDependencies(teams) + store.teamRegistrations.deleteDependencies(teams, shouldBeSynchronized: shouldBeSynchronized) let groups = Array(store.groupStages) for group in groups { - group.deleteDependencies() + group.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - store.groupStages.deleteDependencies(groups) + store.groupStages.deleteDependencies(groups, shouldBeSynchronized: shouldBeSynchronized) let rounds = Array(store.rounds) for round in rounds { - round.deleteDependencies() + round.deleteDependencies(shouldBeSynchronized: shouldBeSynchronized) } - store.rounds.deleteDependencies(rounds) + store.rounds.deleteDependencies(rounds, shouldBeSynchronized: shouldBeSynchronized) store.matchSchedulers.deleteDependencies(self._matchSchedulers()) @@ -2394,9 +2394,9 @@ defer { guard shouldRefreshTeams(forced: forced), refreshInProgress == false, enableOnlineRegistration, hasEnded() == false else { return } refreshInProgress = true do { - try await self.tournamentStore?.playerRegistrations.loadDataFromServerIfAllowed(clear: true) - try await self.tournamentStore?.teamScores.loadDataFromServerIfAllowed(clear: true) - try await self.tournamentStore?.teamRegistrations.loadDataFromServerIfAllowed(clear: true) +// try await self.tournamentStore?.playerRegistrations.loadDataFromServerIfAllowed(clear: true) +// try await self.tournamentStore?.teamScores.loadDataFromServerIfAllowed(clear: true) +// try await self.tournamentStore?.teamRegistrations.loadDataFromServerIfAllowed(clear: true) refreshInProgress = false lastTeamRefresh = Date() } catch { diff --git a/PadelClub/Views/Tournament/TournamentView.swift b/PadelClub/Views/Tournament/TournamentView.swift index 9aa834c..1efed36 100644 --- a/PadelClub/Views/Tournament/TournamentView.swift +++ b/PadelClub/Views/Tournament/TournamentView.swift @@ -268,9 +268,9 @@ struct TournamentView: View { Label("Imprimer", systemImage: "printer") } -// NavigationLink(value: Screen.share) { -// Label("Partager", systemImage: "square.and.arrow.up") -// } + NavigationLink(value: Screen.share) { + Label("Partager", systemImage: "square.and.arrow.up") + } Divider() diff --git a/PadelClub/Views/User/ShareModelView.swift b/PadelClub/Views/User/ShareModelView.swift index c281ccd..119b62e 100644 --- a/PadelClub/Views/User/ShareModelView.swift +++ b/PadelClub/Views/User/ShareModelView.swift @@ -70,7 +70,7 @@ struct ShareModelView : View { .listStyle(PlainListStyle()) .navigationTitle("Partage") } else { - ContentUnavailableView("Si vous souhaitez partager votre tournoi avec d'autres utilisateurs, veuillez contacter notre support", image: "person.crop.circle.badge.xmark") + ContentUnavailableView("Si vous souhaitez partager votre tournoi avec d'autres utilisateurs, veuillez contacter notre support", systemImage: "person.crop.circle.badge.xmark") } }.onAppear { diff --git a/PadelClubTests/ServerDataTests.swift b/PadelClubTests/ServerDataTests.swift index dcc0837..42f3c90 100644 --- a/PadelClubTests/ServerDataTests.swift +++ b/PadelClubTests/ServerDataTests.swift @@ -435,7 +435,7 @@ final class ServerDataTests: XCTestCase { let transactionId = UInt64.random(in: 0...100000) let quantity = Int.random(in: 0...10) - let purchase: Purchase = Purchase(user: userId, transactionId: transactionId, purchaseDate: Date(), productId: "app.padelclub.productId", quantity: quantity, revocationDate: Date(), expirationDate: Date()) + let purchase: Purchase = Purchase(transactionId: transactionId, user: userId, purchaseDate: Date(), productId: "app.padelclub.productId", quantity: quantity, revocationDate: Date(), expirationDate: Date()) if let p: Purchase = try await StoreCenter.main.service().post(purchase) { diff --git a/PadelClubTests/ServerStateTests.swift b/PadelClubTests/ServerStateTests.swift new file mode 100644 index 0000000..1661991 --- /dev/null +++ b/PadelClubTests/ServerStateTests.swift @@ -0,0 +1,66 @@ +// +// ServerStateTests.swift +// PadelClubTests +// +// Created by Laurent Morvillier on 15/04/2025. +// + + +import Testing +import LeStorage +@testable import PadelClub + +struct ServerStateTests { + + let username: String = "sync" + let password: String = "sync123" + + var user: CustomUser? = nil + + init() { + StoreCenter.main.configureURLs(secureScheme: false, domain: "127.0.0.1:8000") + } + + @Test func synchronizationTest() async throws { + + _ = try await self.login() + try await StoreCenter.main.synchronizeLastUpdates() + + } + + @Test func createTournament() async throws { + + let user = try await self.login() + + // Cleanup + try DataStore.shared.events.deleteAll() + + try await DataStore.shared.events.loadDataFromServerIfAllowed(clear: true) + #expect(DataStore.shared.events.count == 0) + + try await DataStore.shared.tournaments.loadDataFromServerIfAllowed(clear: true) + #expect(DataStore.shared.tournaments.count == 0) + + // Create + let event: Event = Event(creator: user.id, club: nil, name: "test") + DataStore.shared.events.addOrUpdate(instance: event) + + let tournament: Tournament = Tournament.fake() + tournament.event = event.id + DataStore.shared.tournaments.addOrUpdate(instance: tournament) + + // Test server content + try await DataStore.shared.events.loadDataFromServerIfAllowed(clear: true) + #expect(DataStore.shared.events.count == 1) + + try await DataStore.shared.tournaments.loadDataFromServerIfAllowed(clear: true) + #expect(DataStore.shared.tournaments.count == 1) + + } + + func login() async throws -> CustomUser { + let user: CustomUser = try await StoreCenter.main.service().login(username: self.username, password: self.password) + return user + } + +} diff --git a/PadelClubTests/SynchronizationTests.swift b/PadelClubTests/SynchronizationTests.swift index 8d35757..2d8b0b9 100644 --- a/PadelClubTests/SynchronizationTests.swift +++ b/PadelClubTests/SynchronizationTests.swift @@ -30,4 +30,8 @@ struct SynchronizationTests { return user } + + + + }