OverrideStorageTests.swift 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import CoreData
  2. import Foundation
  3. import Swinject
  4. import Testing
  5. @testable import Trio
  6. @Suite("Override Storage Tests", .serialized) struct OverrideStorageTests: Injectable {
  7. @Injected() var storage: OverrideStorage!
  8. let resolver: Resolver
  9. var coreDataStack: CoreDataStack!
  10. var testContext: NSManagedObjectContext!
  11. init() async throws {
  12. // Create test context
  13. // As we are only using this single test context to initialize our in-memory DeterminationStorage we need to perform the Unit Tests serialized
  14. coreDataStack = try await CoreDataStack.createForTests()
  15. testContext = coreDataStack.newTaskContext()
  16. // Create assembler with test assembly
  17. let assembler = Assembler([
  18. StorageAssembly(),
  19. ServiceAssembly(),
  20. APSAssembly(),
  21. NetworkAssembly(),
  22. UIAssembly(),
  23. SecurityAssembly(),
  24. TestAssembly(testContext: testContext) // Add our test assembly last to override Storage
  25. ])
  26. resolver = assembler.resolver
  27. injectServices(resolver)
  28. }
  29. @Test("Storage is correctly initialized") func testStorageInitialization() {
  30. // Verify storage exists
  31. #expect(storage != nil, "OverrideStorage should be injected")
  32. // Verify it's the correct type
  33. #expect(storage is BaseOverrideStorage, "Storage should be of type BaseOverrideStorage")
  34. }
  35. @Test("Store and retrieve override") func testStoreAndRetrieveOverride() async throws {
  36. // Given
  37. let testOverride = Override(
  38. name: "Test Override",
  39. enabled: false,
  40. date: Date(),
  41. duration: 120,
  42. indefinite: false,
  43. percentage: 130,
  44. smbIsOff: true,
  45. isPreset: false,
  46. id: UUID().uuidString,
  47. overrideTarget: true,
  48. target: 110,
  49. advancedSettings: false,
  50. isfAndCr: false,
  51. isf: false,
  52. cr: false,
  53. smbIsScheduledOff: false,
  54. start: 1,
  55. end: 2,
  56. smbMinutes: 100,
  57. uamMinutes: 120
  58. )
  59. // When
  60. try await storage.storeOverride(override: testOverride)
  61. // Then verify stored entries
  62. let storedEntries = try await coreDataStack.fetchEntitiesAsync(
  63. ofType: OverrideStored.self,
  64. onContext: testContext,
  65. predicate: NSPredicate(format: "name == %@", "Test Override"),
  66. key: "date",
  67. ascending: false
  68. ) as? [OverrideStored]
  69. #expect(storedEntries?.isEmpty == false, "Should have stored entries")
  70. #expect(storedEntries?.count == 1, "Should have exactly one entry")
  71. let storedOverride = storedEntries?.first
  72. #expect(storedOverride?.name == "Test Override", "Name should match")
  73. #expect(storedOverride?.percentage == 130, "Percentage should match")
  74. #expect(storedOverride?.target?.decimalValue == 110, "Target should match")
  75. #expect(storedOverride?.isPreset == false, "isPreset should match")
  76. }
  77. @Test("Store and retrieve override preset") func testStoreAndRetrieveOverridePreset() async throws {
  78. // Given
  79. let testPreset = Override(
  80. name: "Test Preset",
  81. enabled: false,
  82. date: Date(),
  83. duration: 0,
  84. indefinite: true,
  85. percentage: 120,
  86. smbIsOff: true,
  87. isPreset: true,
  88. id: UUID().uuidString,
  89. overrideTarget: true,
  90. target: 110,
  91. advancedSettings: false,
  92. isfAndCr: false,
  93. isf: false,
  94. cr: false,
  95. smbIsScheduledOff: false,
  96. start: 1,
  97. end: 2,
  98. smbMinutes: 100,
  99. uamMinutes: 120
  100. )
  101. // When
  102. try await storage.storeOverride(override: testPreset)
  103. let presetIDs = try await storage.fetchForOverridePresets()
  104. // Then
  105. #expect(!presetIDs.isEmpty, "Should have stored preset")
  106. let storedPresets = try await testContext.perform {
  107. try presetIDs.map { try testContext.existingObject(with: $0) as! OverrideStored }
  108. }
  109. #expect(storedPresets.count >= 1, "Should have at least one preset")
  110. let storedPreset = storedPresets.first { $0.name == "Test Preset" }
  111. #expect(storedPreset != nil, "Should find the test preset")
  112. #expect(storedPreset?.isPreset == true, "Should be marked as preset")
  113. #expect(storedPreset?.indefinite == true, "Should be indefinite")
  114. #expect(storedPreset?.percentage == 120, "Percentage should match")
  115. }
  116. @Test("Delete override preset") func testDeleteOverridePreset() async throws {
  117. // Given
  118. let testPreset = Override(
  119. name: "Delete Test",
  120. enabled: false,
  121. date: Date(),
  122. duration: 0,
  123. indefinite: true,
  124. percentage: 120,
  125. smbIsOff: true,
  126. isPreset: true,
  127. id: UUID().uuidString,
  128. overrideTarget: true,
  129. target: 110,
  130. advancedSettings: false,
  131. isfAndCr: false,
  132. isf: false,
  133. cr: false,
  134. smbIsScheduledOff: false,
  135. start: 1,
  136. end: 2,
  137. smbMinutes: 100,
  138. uamMinutes: 120
  139. )
  140. // Store the preset
  141. try await storage.storeOverride(override: testPreset)
  142. // Get the stored preset's ObjectID
  143. let storedEntries = try await coreDataStack.fetchEntitiesAsync(
  144. ofType: OverrideStored.self,
  145. onContext: testContext,
  146. predicate: NSPredicate(format: "name == %@", "Delete Test"),
  147. key: "date",
  148. ascending: false
  149. ) as? [OverrideStored]
  150. guard let objectID = storedEntries?.first?.objectID else {
  151. throw TestError("Failed to get stored preset's ObjectID")
  152. }
  153. // When
  154. await storage.deleteOverridePreset(objectID)
  155. // Then verify deletion
  156. let remainingEntries = try await coreDataStack.fetchEntitiesAsync(
  157. ofType: OverrideStored.self,
  158. onContext: testContext,
  159. predicate: NSPredicate(format: "name == %@", "Delete Test"),
  160. key: "date",
  161. ascending: false
  162. ) as? [OverrideStored]
  163. #expect(remainingEntries?.isEmpty == true, "Should have no entries after deletion")
  164. }
  165. @Test("Get overrides not yet uploaded to Nightscout") func testGetOverridesNotYetUploadedToNightscout() async throws {
  166. // Given
  167. let testOverride = Override(
  168. name: "NS Test",
  169. enabled: true, // getOverridesNotYetUploadedToNightscout() fetches only active overrides
  170. date: Date(),
  171. duration: 90,
  172. indefinite: false,
  173. percentage: 120,
  174. smbIsOff: true,
  175. isPreset: true,
  176. id: UUID().uuidString,
  177. overrideTarget: true,
  178. target: 110,
  179. advancedSettings: false,
  180. isfAndCr: false,
  181. isf: false,
  182. cr: false,
  183. smbIsScheduledOff: false,
  184. start: 1,
  185. end: 2,
  186. smbMinutes: 100,
  187. uamMinutes: 120
  188. )
  189. // When
  190. try await storage.storeOverride(override: testOverride)
  191. let notUploadedOverrides = try await storage.getOverridesNotYetUploadedToNightscout()
  192. // Then
  193. #expect(!notUploadedOverrides.isEmpty == true, "Should have overrides not uploaded to NS")
  194. #expect(notUploadedOverrides[0].notes == "NS Test", "Override name should match")
  195. #expect(notUploadedOverrides[0].duration == 90, "Duration should match")
  196. #expect(notUploadedOverrides[0].eventType == .nsExercise, "Event type should be exercise")
  197. }
  198. }