OverrideStorageTests.swift 7.7 KB

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