diff --git a/PadelClubDataTests/PadelClubDataTests.swift b/PadelClubDataTests/PadelClubDataTests.swift index aa986c3..1bbd58f 100644 --- a/PadelClubDataTests/PadelClubDataTests.swift +++ b/PadelClubDataTests/PadelClubDataTests.swift @@ -41,7 +41,7 @@ struct PadelClubDataTests { // Cleanup let events = DataStore.shared.events - await DataStore.shared.events.deleteAsync(contentOfs: Array(events)) + try await DataStore.shared.events.deleteAsync(contentOfs: Array(events)) try await DataStore.shared.events.loadDataFromServerIfAllowed(clear: true) #expect(DataStore.shared.events.count == 0) @@ -51,11 +51,11 @@ struct PadelClubDataTests { // Create let event: Event = Event(creator: userId, club: nil, name: "test") - await DataStore.shared.events.addOrUpdateAsync(instance: event) + try await DataStore.shared.events.addOrUpdateAsync(instance: event) let tournament: Tournament = Tournament.fake() tournament.event = event.id - await DataStore.shared.tournaments.addOrUpdateAsync(instance: tournament) + try await DataStore.shared.tournaments.addOrUpdateAsync(instance: tournament) // Test server content try await DataStore.shared.events.loadDataFromServerIfAllowed(clear: true) @@ -86,7 +86,7 @@ struct PadelClubDataTests { secondStoreServer.tokenKeychain = MockKeychainStore(fileName: "token.json") let events = DataStore.shared.events - await DataStore.shared.events.deleteAsync(contentOfs: Array(events)) + try await DataStore.shared.events.deleteAsync(contentOfs: Array(events)) } diff --git a/PadelClubDataTests/SyncDataAccessTests.swift b/PadelClubDataTests/SyncDataAccessTests.swift index 0be87e5..08f9a77 100644 --- a/PadelClubDataTests/SyncDataAccessTests.swift +++ b/PadelClubDataTests/SyncDataAccessTests.swift @@ -65,7 +65,12 @@ struct SyncDataAccessTests { #expect(userId1 != userId2) } - @Test func testDataAccess() async throws { + /// In this test, the first user: + /// - creates an event and a tournament + /// - shares the tournament with a second user + /// - remove the sharing with the second user + /// We test that the data is properly received and removed upon the sharing actions + @Test func testTournamentSharing() async throws { guard let userId1 = StoreCenter.main.userId else { throw TestError.notAuthenticated @@ -81,11 +86,11 @@ struct SyncDataAccessTests { let tournamentColB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() if let dataAccessCollection = StoreCenter.main.dataAccessCollection { - await dataAccessCollection.deleteAsync(contentOfs: Array(dataAccessCollection)) + try await dataAccessCollection.deleteAsync(contentOfs: Array(dataAccessCollection)) } - await eventColA.deleteAsync(contentOfs: Array(eventColA)) - await tournamentColA.deleteAsync(contentOfs: Array(tournamentColA)) + try await eventColA.deleteAsync(contentOfs: Array(eventColA)) + try await tournamentColA.deleteAsync(contentOfs: Array(tournamentColA)) let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() @@ -94,9 +99,9 @@ struct SyncDataAccessTests { // Create let eventA = Event(creator: userId1) - await eventColA.addOrUpdateAsync(instance: eventA) + try await eventColA.addOrUpdateAsync(instance: eventA) let tournamentA = Tournament(event: eventA.id, name: "P100") - await tournamentColA.addOrUpdateAsync(instance: tournamentA) + try await tournamentColA.addOrUpdateAsync(instance: tournamentA) // Share with user2 try await StoreCenter.main.setAuthorizedUsersAsync(for: tournamentA, users: [userId2]) @@ -123,7 +128,134 @@ struct SyncDataAccessTests { #expect(dataAccesses.count == 0) } - // tester les shared data, les relationship add/remove shared/ou non + /// In this test, the first user: + /// - creates a club and 2 events in that club + /// - shares both events with a second user + /// - removes the sharing of 1 event + /// Here we want to test that the Club instance remains even if one event is removed from the second user + @Test func testSharedRelationship() async throws { + + guard let userId1 = StoreCenter.main.userId else { + throw TestError.notAuthenticated + } + guard let userId2 = self.secondStoreCenter.userId else { + throw TestError.notAuthenticated + } + + // Setup + let eventColA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() + let clubColA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() + let eventColB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() + let clubColB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() + + if let dataAccessCollection = StoreCenter.main.dataAccessCollection { + try await dataAccessCollection.deleteAsync(contentOfs: Array(dataAccessCollection)) + } + + try await eventColA.deleteAsync(contentOfs: Array(eventColA)) + try await clubColA.deleteAsync(contentOfs: Array(clubColA)) + + let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() + + #expect(eventColB.count == 0) + #expect(clubColB.count == 0) + + // Create + let clubA = Club(creator: userId1, name: "Club A", acronym: "CA") + try await clubColA.addOrUpdateAsync(instance: clubA) + + let event1A = Event(creator: userId1, club: clubA.id, name: "event 1") + let event2A = Event(creator: userId1, club: clubA.id, name: "event 2") + try await eventColA.addOrUpdateAsync(contentOfs: [event1A, event2A]) + + // Share with user2 + try await StoreCenter.main.setAuthorizedUsersAsync(for: event1A, users: [userId2]) + try await StoreCenter.main.setAuthorizedUsersAsync(for: event2A, users: [userId2]) + + var dataB = try await self.secondStoreCenter.testSynchronizeOnceAsync() + var syncDataB = try SyncData(data: dataB, storeCenter: self.secondStoreCenter) + + #expect(syncDataB.grants.count == 2) + + let clubGrants = syncDataB.grants.first { $0.type == Club.self } + let eventGrants = syncDataB.grants.first { $0.type == Event.self } + #expect(clubGrants?.items.count == 1) + #expect(eventGrants?.items.count == 2) + + #expect(eventColB.count == 2) + #expect(clubColB.count == 1) + + // Remove sharing from user2 + try await StoreCenter.main.setAuthorizedUsersAsync(for: event1A, users: []) + + dataB = try await self.secondStoreCenter.testSynchronizeOnceAsync() + syncDataB = try SyncData(data: dataB, storeCenter: self.secondStoreCenter) + #expect(syncDataB.revocations.count == 1) + #expect(syncDataB.revocationParents.count == 1) + + #expect(eventColB.count == 1) + #expect(clubColB.count == 1) // club remains because used in event2A + } + + /// In this test, the first user: + /// - creates one event and 2 clubs + /// - shares the event with a second user + /// - changes the club on the event + /// Here we want to test that the first Club is removed and the second one is received + @Test func testRelationshipChange() async throws { + + guard let userId1 = StoreCenter.main.userId else { + throw TestError.notAuthenticated + } + guard let userId2 = self.secondStoreCenter.userId else { + throw TestError.notAuthenticated + } + + // Setup + let eventColA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() + let clubColA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() + let eventColB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() + let clubColB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() + + if let dataAccessCollection = StoreCenter.main.dataAccessCollection { + try await dataAccessCollection.deleteAsync(contentOfs: Array(dataAccessCollection)) + } + + try await eventColA.deleteAsync(contentOfs: Array(eventColA)) + try await clubColA.deleteAsync(contentOfs: Array(clubColA)) + + let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() + + #expect(eventColB.count == 0) + #expect(clubColB.count == 0) + + // Create + let club1A = Club(creator: userId1, name: "Club 1", acronym: "C1") + try await clubColA.addOrUpdateAsync(instance: club1A) + let club2A = Club(creator: userId1, name: "Club 2", acronym: "C2") + try await clubColA.addOrUpdateAsync(instance: club2A) + + let eventA = Event(creator: userId1, club: club1A.id, name: "event 1") + try await eventColA.addOrUpdateAsync(instance: eventA) + + // Share with user2 + try await StoreCenter.main.setAuthorizedUsersAsync(for: eventA, users: [userId2]) + let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() + #expect(eventColB.count == 1) + #expect(clubColB.count == 1) + + // Change the club + eventA.club = club2A.id + try await eventColA.addOrUpdateAsync(instance: eventA) + let dataB = try await self.secondStoreCenter.testSynchronizeOnceAsync() + + let syncDataB = try SyncData(data: dataB, storeCenter: self.secondStoreCenter) + + #expect(syncDataB.sharedRelationshipSets.count == 1) + #expect(syncDataB.sharedRelationshipRemovals.count == 1) + + #expect(eventColB.first?.club == club2A.id) + } // trouver le moyen de tester les sous-Store et voir si on peut essayer de rendre ça propre sans passer par DataStore ou autre diff --git a/PadelClubDataTests/SynchronizationTests.swift b/PadelClubDataTests/SynchronizationTests.swift index 0ad34e3..45b8bf6 100644 --- a/PadelClubDataTests/SynchronizationTests.swift +++ b/PadelClubDataTests/SynchronizationTests.swift @@ -27,7 +27,7 @@ struct SynchronizationTests { FileManager.default.deleteDirectoryInDocuments(directoryName: "storage-2") self.secondStoreCenter = StoreCenter(directoryName: "storage-2") - self.secondStoreCenter.configureURLs(secureScheme: false, domain: "127.0.0.1:8000", webSockets: false) + self.secondStoreCenter.configureURLs(secureScheme: false, domain: "127.0.0.1:8000", webSockets: false, useSynchronization: true) self.secondStoreCenter.tokenKeychain = MockKeychainStore(fileName: "storage-2/token.json") self.secondStoreCenter.deviceKeychain = MockKeychainStore(fileName: "storage-2/device.json") try self.secondStoreCenter.deviceKeychain.add(value: UUID().uuidString) @@ -39,7 +39,7 @@ struct SynchronizationTests { try await self.login(storeCenter: self.secondStoreCenter) } - StoreCenter.main.configureURLs(secureScheme: false, domain: "127.0.0.1:8000", webSockets: false) + StoreCenter.main.configureURLs(secureScheme: false, domain: "127.0.0.1:8000", webSockets: false, useSynchronization: true) StoreCenter.main.tokenKeychain = MockKeychainStore(fileName: "storage/token.json") StoreCenter.main.deviceKeychain = MockKeychainStore(fileName: "storage/device.json") try StoreCenter.main.deviceKeychain.add(value: UUID().uuidString) @@ -75,7 +75,7 @@ struct SynchronizationTests { let eventCollection1: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() #expect(eventCollection1.hasLoaded == true) - await eventCollection1.deleteAsync(contentOfs: Array(eventCollection1)) + try await eventCollection1.deleteAsync(contentOfs: Array(eventCollection1)) let eventCollection2: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() #expect(eventCollection2.hasLoaded == true) @@ -86,7 +86,7 @@ struct SynchronizationTests { // Create let event: Event = Event(creator: userId, club: nil, name: "test") - await eventCollection1.addOrUpdateAsync(instance: event) + try await eventCollection1.addOrUpdateAsync(instance: event) let serverEvents: [Event] = try await StoreCenter.main.service().get() #expect(serverEvents.count == 1) @@ -118,13 +118,13 @@ struct SynchronizationTests { // Setup events collections let eventCollectionA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() - await eventCollectionA.deleteAsync(contentOfs: Array(eventCollectionA)) + try await eventCollectionA.deleteAsync(contentOfs: Array(eventCollectionA)) let eventCollectionB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() eventCollectionB.clear() // Setup clubs collections let clubCollectionA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() - await clubCollectionA.deleteAsync(contentOfs: Array(clubCollectionA)) + try await clubCollectionA.deleteAsync(contentOfs: Array(clubCollectionA)) let clubCollectionB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() clubCollectionB.clear() @@ -133,7 +133,7 @@ struct SynchronizationTests { // Create let eventA: Event = Event(creator: userId, club: nil, name: "test-b") - await eventCollectionA.addOrUpdateAsync(instance: eventA) + try await eventCollectionA.addOrUpdateAsync(instance: eventA) // Retrieve Event let dataB = try await self.secondStoreCenter.testSynchronizeOnceAsync() @@ -143,13 +143,13 @@ struct SynchronizationTests { // Create club on 2nd StoreCenter let club = Club(creator: userId, name: "Padel Club", acronym: "PC") - await clubCollectionB.addOrUpdateAsync(instance: club) + try await clubCollectionB.addOrUpdateAsync(instance: club) guard let eventB = eventCollectionB.findById(eventA.id) else { throw SyncTestError.instanceNotFound(id: eventA.id) } eventB.club = club.id - await eventCollectionB.addOrUpdateAsync(instance: eventB) + try await eventCollectionB.addOrUpdateAsync(instance: eventB) // Synchronize 1st StoreCenter let dataA = try await StoreCenter.main.testSynchronizeOnceAsync() @@ -182,7 +182,7 @@ struct SynchronizationTests { // Setup TeamReg let teamRegColA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() - await teamRegColA.deleteAsync(contentOfs: Array(teamRegColA)) + try await teamRegColA.deleteAsync(contentOfs: Array(teamRegColA)) let teamRegColB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() teamRegColB.clear() @@ -191,8 +191,8 @@ struct SynchronizationTests { // Create let trA = TeamRegistration(tournament: tournament.id) - await teamRegColA.addOrUpdateAsync(instance: trA) - await teamRegColA.deleteAsync(instance: trA) + try await teamRegColA.addOrUpdateAsync(instance: trA) + try await teamRegColA.deleteAsync(instance: trA) #expect(teamRegColA.count == 0) let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() @@ -207,8 +207,10 @@ struct SynchronizationTests { } // Setup events collections - let eventCollectionA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() - await eventCollectionA.deleteAsync(contentOfs: Array(eventCollectionA)) + let eventCollectionA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection(inMemory: true) + try await eventCollectionA.loadOnceAsync() + + try await eventCollectionA.deleteAsync(contentOfs: Array(eventCollectionA)) let eventCollectionB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() eventCollectionB.clear() @@ -220,7 +222,7 @@ struct SynchronizationTests { // Create let eventA: Event = Event(creator: userId, club: nil, name: "test-b") - await eventCollectionA.addOrUpdateAsync(instance: eventA) + try await eventCollectionA.addOrUpdateAsync(instance: eventA) #expect(eventCollectionA.count == 1) let serverEvents: [Event] = try await StoreCenter.main.service().get() @@ -236,12 +238,12 @@ struct SynchronizationTests { throw SyncTestError.instanceNotFound(id: eventA.id) } eventA.name = "my event is nice" - await eventCollectionA.addOrUpdateAsync(instance: eventA) + try await eventCollectionA.addOrUpdateAsync(instance: eventA) eventB.name = "my event is better" - await eventCollectionB.addOrUpdateAsync(instance: eventB) + try await eventCollectionB.addOrUpdateAsync(instance: eventB) - await eventCollectionA.addOrUpdateAsync(instance: eventA) + try await eventCollectionA.addOrUpdateAsync(instance: eventA) let _ = try await StoreCenter.main.testSynchronizeOnceAsync() let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() @@ -253,5 +255,58 @@ struct SynchronizationTests { #expect(eventCollectionB.first?.name == "my event is nice") } - + + /// In this test, the first user: + /// - creates one event and 2 clubs + /// - shares the event with a second user + /// - changes the club on the event + /// Here we want to test that the first Club is removed and the second one is received + @Test func testRelationshipChange() async throws { + + guard let userId = StoreCenter.main.userId else { + throw TestError.notAuthenticated + } + + // Setup + let eventColA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() + let clubColA: SyncedCollection = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection() + let eventColB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() + let clubColB: SyncedCollection = await self.secondStoreCenter.mainStore.asyncLoadingSynchronizedCollection() + + if let dataAccessCollection = StoreCenter.main.dataAccessCollection { + try await dataAccessCollection.deleteAsync(contentOfs: Array(dataAccessCollection)) + } + + try await eventColA.deleteAsync(contentOfs: Array(eventColA)) + try await clubColA.deleteAsync(contentOfs: Array(clubColA)) + + let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() + + #expect(eventColB.count == 0) + #expect(clubColB.count == 0) + + // Create + let club1A = Club(creator: userId, name: "Club 1", acronym: "C1") + try await clubColA.addOrUpdateAsync(instance: club1A) + let club2A = Club(creator: userId, name: "Club 2", acronym: "C2") + try await clubColA.addOrUpdateAsync(instance: club2A) + + let eventA = Event(creator: userId, club: club1A.id, name: "event 1") + try await eventColA.addOrUpdateAsync(instance: eventA) + + // Share with user2 + let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() + #expect(eventColB.count == 1) + #expect(clubColB.count == 2) + + // Change the club + eventA.club = club2A.id + try await eventColA.addOrUpdateAsync(instance: eventA) + let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync() + + #expect(eventColB.first?.club == eventA.club) + + } + + }