adds sync tests

sync3
Laurent 6 months ago
parent b80cd18db1
commit 8a8a421891
  1. 109
      PadelClubDataTests/DataAccessSyncTests.swift
  2. 157
      PadelClubDataTests/SynchronizationTests.swift

@ -0,0 +1,109 @@
//
// DataAccessSyncTests.swift
// PadelClubDataTests
//
// Created by Laurent Morvillier on 02/05/2025.
//
import Testing
@testable import PadelClubData
@testable import LeStorage
struct DataAccessSyncTests {
let username1: String = "UserDataTests"
let password1: String = "MyPass1234--"
let username2: String = "seconduser"
let password2: String = "MyPass1234--"
var secondStoreCenter: StoreCenter
init() async throws {
self.secondStoreCenter = StoreCenter(directoryName: "storage-2")
self.secondStoreCenter.configureURLs(secureScheme: false, domain: "127.0.0.1:8000", webSockets: false)
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)
self.secondStoreCenter.classProject = "PadelClubData"
let token2 = try? self.secondStoreCenter.rawTokenShouldNotBeUsed()
try await self.login(storeCenter: self.secondStoreCenter, username: self.username2, password: self.password2)
StoreCenter.main.configureURLs(secureScheme: false, domain: "127.0.0.1:8000", webSockets: false)
StoreCenter.main.tokenKeychain = MockKeychainStore(fileName: "storage/token.json")
StoreCenter.main.deviceKeychain = MockKeychainStore(fileName: "storage/device.json")
try StoreCenter.main.deviceKeychain.add(value: UUID().uuidString)
StoreCenter.main.classProject = "PadelClubData"
let token = try? StoreCenter.main.rawTokenShouldNotBeUsed()
try await self.login(storeCenter: StoreCenter.main, username: self.username1, password: self.password1)
}
mutating func login(storeCenter: StoreCenter, username: String, password: String) async throws {
let _: CustomUser = try await storeCenter.service().login(username: username, password: password)
}
@Test func testSetup() async throws {
#expect(StoreCenter.main.isAuthenticated)
#expect(self.secondStoreCenter.isAuthenticated)
guard let userId1 = StoreCenter.main.userId else {
throw TestError.notAuthenticated
}
guard let userId2 = self.secondStoreCenter.userId else {
throw TestError.notAuthenticated
}
#expect(userId1 != userId2)
}
@Test func testDataAccess() 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<Event> = await StoreCenter.main.mainStore.synchronizedCollectionWithFileLoading()
let tournamentColA: SyncedCollection<Tournament> = await StoreCenter.main.mainStore.synchronizedCollectionWithFileLoading()
let eventColB: SyncedCollection<Event> = await self.secondStoreCenter.mainStore.synchronizedCollectionWithFileLoading()
let tournamentColB: SyncedCollection<Tournament> = await self.secondStoreCenter.mainStore.synchronizedCollectionWithFileLoading()
await eventColA.deleteAsync(contentOfs: Array(eventColA))
await tournamentColA.deleteAsync(contentOfs: Array(tournamentColA))
let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync()
#expect(eventColB.count == 0)
#expect(tournamentColB.count == 0)
// Create
let eventA = Event(creator: userId1)
await eventColA.addOrUpdateAsync(instance: eventA)
let tournamentA = Tournament(event: eventA.id, name: "P100")
await tournamentColA.addOrUpdateAsync(instance: tournamentA)
// Share with user2
try StoreCenter.main.setAuthorizedUsers(for: tournamentA, users: [userId2])
let dataB = try await self.secondStoreCenter.testSynchronizeOnceAsync()
let syncDataB = try SyncData(data: dataB, storeCenter: self.secondStoreCenter)
#expect(syncDataB.grants.count == 2)
#expect(eventColB.count == 1)
#expect(tournamentColB.count == 1)
// Remove sharing from user2
try StoreCenter.main.setAuthorizedUsers(for: tournamentA, users: [])
let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync()
#expect(eventColB.count == 0)
#expect(tournamentColB.count == 0)
}
}

@ -9,6 +9,11 @@ import Testing
@testable import PadelClubData
@testable import LeStorage
enum SyncTestError: Error {
case instanceNotFound(id: String)
case missingSyncData
}
struct SynchronizationTests {
let username: String = "UserDataTests"
@ -73,6 +78,9 @@ struct SynchronizationTests {
#expect(eventCollection2.hasLoaded == true)
eventCollection2.clear()
// cleanup sync residues
let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync()
// Create
let event: Event = Event(creator: userId, club: nil, name: "test")
await eventCollection1.addOrUpdateAsync(instance: event)
@ -83,12 +91,157 @@ struct SynchronizationTests {
try await eventCollection1.loadDataFromServerIfAllowed(clear: true)
#expect(eventCollection1.count == 1)
try await self.secondStoreCenter.testSynchronizeOnceAsync()
let data = try await self.secondStoreCenter.testSynchronizeOnceAsync()
let syncData = try SyncData(data: data, storeCenter: self.secondStoreCenter)
#expect(syncData.updates.count == 1)
#expect(syncData.deletions.count == 0)
#expect(eventCollection2.count == 1)
try await self.secondStoreCenter.testSynchronizeOnceAsync()
let data2 = try await self.secondStoreCenter.testSynchronizeOnceAsync()
let syncData2 = try SyncData(data: data2, storeCenter: self.secondStoreCenter)
#expect(syncData2.updates.count == 0)
#expect(syncData.deletions.count == 0)
#expect(eventCollection2.count == 1)
}
@Test func testSynchronizationBothWays() async throws {
guard let userId = StoreCenter.main.userId else {
throw TestError.notAuthenticated
}
// Setup events collections
let eventCollectionA: SyncedCollection<Event> = await StoreCenter.main.mainStore.synchronizedCollectionWithFileLoading()
await eventCollectionA.deleteAsync(contentOfs: Array(eventCollectionA))
let eventCollectionB: SyncedCollection<Event> = await self.secondStoreCenter.mainStore.synchronizedCollectionWithFileLoading()
eventCollectionB.clear()
// Setup clubs collections
let clubCollectionA: SyncedCollection<Club> = await StoreCenter.main.mainStore.synchronizedCollectionWithFileLoading()
await clubCollectionA.deleteAsync(contentOfs: Array(clubCollectionA))
let clubCollectionB: SyncedCollection<Club> = await self.secondStoreCenter.mainStore.synchronizedCollectionWithFileLoading()
clubCollectionB.clear()
// cleanup sync residues
let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync()
// Create
let eventA: Event = Event(creator: userId, club: nil, name: "test-b")
await eventCollectionA.addOrUpdateAsync(instance: eventA)
// Retrieve Event
let dataB = try await self.secondStoreCenter.testSynchronizeOnceAsync()
let syncDataB = try SyncData(data: dataB, storeCenter: self.secondStoreCenter)
#expect(syncDataB.updates.count == 1)
#expect(eventCollectionB.count == 1)
// Create club on 2nd StoreCenter
let club = Club(creator: userId, name: "Padel Club", acronym: "PC")
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)
// Synchronize 1st StoreCenter
let dataA = try await StoreCenter.main.testSynchronizeOnceAsync()
let syncDataA = try SyncData(data: dataA, storeCenter: StoreCenter.main)
#expect(eventCollectionA.count == 1)
#expect(clubCollectionB.count == 1)
#expect(syncDataA.updates.count == 2)
guard let clubArray = syncDataA.updates.first(where: { $0.type == Club.self }) else {
throw SyncTestError.missingSyncData
}
#expect(clubArray.items.count == 1)
guard let eventArray = syncDataA.updates.first(where: { $0.type == Event.self }) else {
throw SyncTestError.missingSyncData
}
#expect(eventArray.items.count == 1)
guard let eventACopy = eventCollectionA.findById(eventA.id) else {
throw SyncTestError.instanceNotFound(id: eventA.id)
}
#expect(eventACopy.club == club.id)
}
@Test func testSynchronizationDelete() async throws {
// Setup tournament
let tournament = Tournament()
// Setup TeamReg
let teamRegColA: SyncedCollection<TeamRegistration> = await StoreCenter.main.mainStore.synchronizedCollectionWithFileLoading()
await teamRegColA.deleteAsync(contentOfs: Array(teamRegColA))
let teamRegColB: SyncedCollection<TeamRegistration> = await self.secondStoreCenter.mainStore.synchronizedCollectionWithFileLoading()
teamRegColB.clear()
// cleanup sync residues
let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync()
// Create
let trA = TeamRegistration(tournament: tournament.id)
await teamRegColA.addOrUpdateAsync(instance: trA)
await teamRegColA.deleteAsync(instance: trA)
#expect(teamRegColA.count == 0)
let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync()
#expect(teamRegColB.count == 0)
}
@Test func testSyncConflictResolution() async throws {
guard let userId = StoreCenter.main.userId else {
throw TestError.notAuthenticated
}
// Setup events collections
let eventCollectionA: SyncedCollection<Event> = await StoreCenter.main.mainStore.synchronizedCollectionWithFileLoading()
await eventCollectionA.deleteAsync(contentOfs: Array(eventCollectionA))
let eventCollectionB: SyncedCollection<Event> = await self.secondStoreCenter.mainStore.synchronizedCollectionWithFileLoading()
eventCollectionB.clear()
// cleanup sync residues
let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync()
// Create
let eventA: Event = Event(creator: userId, club: nil, name: "test-b")
await eventCollectionA.addOrUpdateAsync(instance: eventA)
// Retrieve Event
let dataB = try await self.secondStoreCenter.testSynchronizeOnceAsync()
let syncDataB = try SyncData(data: dataB, storeCenter: self.secondStoreCenter)
#expect(syncDataB.updates.count == 1)
#expect(eventCollectionB.count == 1)
guard let eventB = eventCollectionB.findById(eventA.id) else {
throw SyncTestError.instanceNotFound(id: eventA.id)
}
eventA.name = "my event is nice"
await eventCollectionA.addOrUpdateAsync(instance: eventA)
eventB.name = "my event is better"
await eventCollectionB.addOrUpdateAsync(instance: eventB)
await eventCollectionA.addOrUpdateAsync(instance: eventA)
let _ = try await StoreCenter.main.testSynchronizeOnceAsync()
let _ = try await self.secondStoreCenter.testSynchronizeOnceAsync()
#expect(eventCollectionA.count == 1)
#expect(eventCollectionB.count == 1)
#expect(eventCollectionA.first?.name == "my event is nice")
#expect(eventCollectionB.first?.name == "my event is nice")
}
}

Loading…
Cancel
Save