diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/sync/NsClient.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/sync/NsClient.kt index 6de50eae90b..778d103e20f 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/sync/NsClient.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/sync/NsClient.kt @@ -46,6 +46,6 @@ interface NsClient : Sync { fun resetToFullSync() - fun dbAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) - fun dbUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) + fun nsAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) + fun nsUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) } \ No newline at end of file diff --git a/plugins/sync/build.gradle b/plugins/sync/build.gradle index f1253e74ea8..2cbb59d236f 100644 --- a/plugins/sync/build.gradle +++ b/plugins/sync/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation project(':core:utils') implementation project(':core:validators') + testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" testImplementation "androidx.work:work-testing:$work_version" testImplementation project(':implementation') testImplementation project(':plugins:aps') diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/DataSyncSelectorImplementation.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/DataSyncSelectorImplementation.kt index b38d6eea6b6..6c3766c5bd6 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/DataSyncSelectorImplementation.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/DataSyncSelectorImplementation.kt @@ -135,14 +135,14 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new bolus.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd( + activePlugin.activeNsClient?.nsAdd( "treatments", DataSyncSelector.PairBolus(bolus.first, bolus.second.id), " $startId/$lastDbId" ) // with nsId = update if it's modified record bolus.first.interfaceIDs.nightscoutId != null && bolus.first.id != bolus.second.id -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairBolus(bolus.first, bolus.second.id), "$startId/$lastDbId" @@ -188,10 +188,10 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new carb.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd("treatments", DataSyncSelector.PairCarbs(carb.first, carb.second.id), "$startId/$lastDbId") + activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairCarbs(carb.first, carb.second.id), "$startId/$lastDbId") // with nsId = update if it's modified record carb.first.interfaceIDs.nightscoutId != null && carb.first.id != carb.second.id -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairCarbs(carb.first, carb.second.id), "$startId/$lastDbId" @@ -237,14 +237,14 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new bolusCalculatorResult.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd( + activePlugin.activeNsClient?.nsAdd( "treatments", DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId" ) // with nsId = update if it's modified record bolusCalculatorResult.first.interfaceIDs.nightscoutId != null && bolusCalculatorResult.first.id != bolusCalculatorResult.second.id -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId" ) @@ -289,14 +289,14 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new tt.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd( + activePlugin.activeNsClient?.nsAdd( "treatments", DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id), "$startId/$lastDbId" ) // existing with nsId = update tt.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id), "$startId/$lastDbId" @@ -342,10 +342,10 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new food.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd("food", DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId") + activePlugin.activeNsClient?.nsAdd("food", DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId") // with nsId = update food.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "food", DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId" @@ -392,10 +392,10 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new gv.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd("entries", DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId") + activePlugin.activeNsClient?.nsAdd("entries", DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId") // with nsId = update else -> // gv.first.interfaceIDs.nightscoutId != null - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "entries", DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId" @@ -445,10 +445,10 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new te.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd("treatments", DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId") + activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId") // nsId = update te.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId" @@ -480,7 +480,7 @@ class DataSyncSelectorImplementation @Inject constructor( when { // without nsId = create new deviceStatus.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd("devicestatus", DataSyncSelector.PairDeviceStatus(deviceStatus, 0), "$startId/$lastDbId") + activePlugin.activeNsClient?.nsAdd("devicestatus", DataSyncSelector.PairDeviceStatus(deviceStatus, 0), "$startId/$lastDbId") // with nsId = ignore deviceStatus.interfaceIDs.nightscoutId != null -> Any() } @@ -524,14 +524,14 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new tb.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd( + activePlugin.activeNsClient?.nsAdd( "treatments", DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id), "$startId/$lastDbId" ) // with nsId = update tb.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id), "$startId/$lastDbId" @@ -579,14 +579,14 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new eb.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd( + activePlugin.activeNsClient?.nsAdd( "treatments", DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id), "$startId/$lastDbId" ) // with nsId = update eb.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id), "$startId/$lastDbId" @@ -638,10 +638,10 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new ps.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd("treatments", DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId") + activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId") // with nsId = update ps.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId" @@ -687,14 +687,14 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new ps.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd( + activePlugin.activeNsClient?.nsAdd( "treatments", DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId" ) // with nsId = update ps.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId" @@ -740,10 +740,10 @@ class DataSyncSelectorImplementation @Inject constructor( } // without nsId = create new oe.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.dbAdd("treatments", DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId") + activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId") // existing with nsId = update oe.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.dbUpdate( + activePlugin.activeNsClient?.nsUpdate( "treatments", DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId" @@ -765,7 +765,7 @@ class DataSyncSelectorImplementation @Inject constructor( if (lastChange > lastSync) { if (activePlugin.activeProfileSource.profile?.allProfilesValid != true) return val profileJson = activePlugin.activeProfileSource.profile?.data ?: return - activePlugin.activeNsClient?.dbAdd("profile", DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()), "") + activePlugin.activeNsClient?.nsAdd("profile", DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()), "") } } } \ No newline at end of file diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NSClientPlugin.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NSClientPlugin.kt index 34f41d287df..0eb8b45715e 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NSClientPlugin.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NSClientPlugin.kt @@ -244,7 +244,7 @@ class NSClientPlugin @Inject constructor( dataSyncSelector.resetToNextFullSync() } - override fun dbAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) { + override fun nsAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) { when (dataPair) { is DataSyncSelector.PairBolus -> dataPair.value.toJson(true, dateUtil) is DataSyncSelector.PairCarbs -> dataPair.value.toJson(true, dateUtil) @@ -266,7 +266,7 @@ class NSClientPlugin @Inject constructor( } } - override fun dbUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) { + override fun nsUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) { val id = when (dataPair) { is DataSyncSelector.PairBolus -> dataPair.value.interfaceIDs.nightscoutId is DataSyncSelector.PairCarbs -> dataPair.value.interfaceIDs.nightscoutId diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NsClientReceiverDelegate.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NsClientReceiverDelegate.kt index aecbbf12d09..b515ee08abe 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NsClientReceiverDelegate.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NsClientReceiverDelegate.kt @@ -1,5 +1,6 @@ package info.nightscout.plugins.sync.nsclient +import info.nightscout.androidaps.annotations.OpenForTesting import info.nightscout.interfaces.receivers.ReceiverStatusStore import info.nightscout.plugins.sync.R import info.nightscout.rx.bus.RxBus @@ -11,6 +12,7 @@ import info.nightscout.shared.sharedPreferences.SP import javax.inject.Inject import javax.inject.Singleton +@OpenForTesting @Singleton class NsClientReceiverDelegate @Inject constructor( private val rxBus: RxBus, diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt index 1b227f07055..65b6649bcc4 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt @@ -120,7 +120,7 @@ class NSClientV3Plugin @Inject constructor( } private val disposable = CompositeDisposable() - private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) + var scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private lateinit var runLoop: Runnable private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper) private val listLog: MutableList = ArrayList() @@ -320,11 +320,11 @@ class NSClientV3Plugin @Inject constructor( storeLastLoadedSrvModified() } - override fun dbAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) { + override fun nsAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) { dbOperation(collection, dataPair, progress, Operation.CREATE) } - override fun dbUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) { + override fun nsUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) { dbOperation(collection, dataPair, progress, Operation.UPDATE) } diff --git a/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3PluginTest.kt b/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3PluginTest.kt new file mode 100644 index 00000000000..54f392d9ae8 --- /dev/null +++ b/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3PluginTest.kt @@ -0,0 +1,101 @@ +package info.nightscout.plugins.sync.nsclientV3 + +import android.content.Context +import dagger.android.AndroidInjector +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.TestBase +import info.nightscout.core.utils.fabric.FabricPrivacy +import info.nightscout.database.entities.DeviceStatus +import info.nightscout.database.impl.AppRepository +import info.nightscout.interfaces.Config +import info.nightscout.interfaces.XDripBroadcast +import info.nightscout.interfaces.logging.UserEntryLogger +import info.nightscout.interfaces.nsclient.StoreDataForDb +import info.nightscout.interfaces.profile.ProfileFunction +import info.nightscout.interfaces.pump.VirtualPump +import info.nightscout.interfaces.source.NSClientSource +import info.nightscout.interfaces.sync.DataSyncSelector +import info.nightscout.interfaces.ui.UiInteraction +import info.nightscout.plugins.sync.nsShared.StoreDataForDbImpl +import info.nightscout.plugins.sync.nsclient.NsClientReceiverDelegate +import info.nightscout.rx.bus.RxBus +import info.nightscout.sdk.interfaces.NSAndroidClient +import info.nightscout.sdk.localmodel.treatment.CreateUpdateResponse +import info.nightscout.shared.interfaces.ResourceHelper +import info.nightscout.shared.sharedPreferences.SP +import info.nightscout.shared.utils.DateUtil +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` +import org.mockito.internal.verification.Times + +@Suppress("SpellCheckingInspection") +internal class NSClientV3PluginTest : TestBase() { + + @Mock lateinit var rxBus: RxBus + @Mock lateinit var rh: ResourceHelper + @Mock lateinit var context: Context + @Mock lateinit var fabricPrivacy: FabricPrivacy + @Mock lateinit var sp: SP + @Mock lateinit var nsClientReceiverDelegate: NsClientReceiverDelegate + @Mock lateinit var config: Config + @Mock lateinit var dateUtil: DateUtil + @Mock lateinit var uiInteraction: UiInteraction + @Mock lateinit var dataSyncSelector: DataSyncSelector + @Mock lateinit var profileFunction: ProfileFunction + @Mock lateinit var nsAndroidClient: NSAndroidClient + @Mock lateinit var repository: AppRepository + @Mock lateinit var uel: UserEntryLogger + @Mock lateinit var nsClientSource: NSClientSource + @Mock lateinit var xDripBroadcast: XDripBroadcast + @Mock lateinit var virtualPump: VirtualPump + + private lateinit var storeDataForDb: StoreDataForDb + private lateinit var sut: NSClientV3Plugin + + private val injector = HasAndroidInjector { + AndroidInjector { + } + } + + @BeforeEach + fun prepare() { + storeDataForDb = StoreDataForDbImpl(aapsLogger, rxBus, repository, sp, uel, dateUtil, config, nsClientSource, xDripBroadcast, virtualPump, uiInteraction) + sut = + NSClientV3Plugin( + injector, aapsLogger, aapsSchedulers, rxBus, rh, context, fabricPrivacy, + sp, nsClientReceiverDelegate, config, dateUtil, uiInteraction, storeDataForDb, dataSyncSelector, profileFunction + ) + sut.nsAndroidClient = nsAndroidClient + } + + @Test + @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class) + fun nsAddDeviceStatus() = runTest { + sut.scope = CoroutineScope(UnconfinedTestDispatcher(testScheduler)) + val deviceStatus = DeviceStatus( + timestamp = 10000, + suggested = "{\"temp\":\"absolute\",\"bg\":133,\"tick\":-6,\"eventualBG\":67,\"targetBG\":99,\"insulinReq\":0,\"deliverAt\":\"2023-01-02T15:29:33.374Z\",\"sensitivityRatio\":1,\"variable_sens\":97.5,\"predBGs\":{\"IOB\":[133,127,121,116,111,106,101,97,93,89,85,81,78,75,72,69,67,65,62,60,58,57,55,54,52,51,50,49,48,47,46,45,45,44,43,43,42,42,41,41,41,41,40,40,40,40,39],\"ZT\":[133,127,121,115,110,105,101,96,92,88,84,81,77,74,71,69,66,64,62,59,58,56,54,53,51,50,49,48,47,46,45,44,44,43,42,42,41,41,40,40,40,39,39,39,39,39,39,39],\"UAM\":[133,127,121,115,110,105,101,96,92,88,84,81,77,74,71,69,66,64,62,59,58,56,54,53,51,50,49,48,47,46,45,44,44,43,42,42,41,41,40,40,40,39]},\"reason\":\"COB: 0, Dev: 0.1, BGI: -0.3, ISF: 5.4, CR: 13, Target: 5.5, minPredBG 2.2, minGuardBG 2.1, IOBpredBG 2.2, UAMpredBG 2.2; minGuardBG 2.1<4.0\",\"COB\":0,\"IOB\":0.692,\"duration\":90,\"rate\":0,\"timestamp\":\"2023-01-02T15:29:39.460Z\"}", + iob = "{\"iob\":0.692,\"basaliob\":-0.411,\"activity\":0.0126,\"time\":\"2023-01-02T15:29:39.460Z\"}", + enacted = "{\"temp\":\"absolute\",\"bg\":133,\"tick\":-6,\"eventualBG\":67,\"targetBG\":99,\"insulinReq\":0,\"deliverAt\":\"2023-01-02T15:29:33.374Z\",\"sensitivityRatio\":1,\"variable_sens\":97.5,\"predBGs\":{\"IOB\":[133,127,121,116,111,106,101,97,93,89,85,81,78,75,72,69,67,65,62,60,58,57,55,54,52,51,50,49,48,47,46,45,45,44,43,43,42,42,41,41,41,41,40,40,40,40,39],\"ZT\":[133,127,121,115,110,105,101,96,92,88,84,81,77,74,71,69,66,64,62,59,58,56,54,53,51,50,49,48,47,46,45,44,44,43,42,42,41,41,40,40,40,39,39,39,39,39,39,39],\"UAM\":[133,127,121,115,110,105,101,96,92,88,84,81,77,74,71,69,66,64,62,59,58,56,54,53,51,50,49,48,47,46,45,44,44,43,42,42,41,41,40,40,40,39]},\"reason\":\"COB: 0, Dev: 0.1, BGI: -0.3, ISF: 5.4, CR: 13, Target: 5.5, minPredBG 2.2, minGuardBG 2.1, IOBpredBG 2.2, UAMpredBG 2.2; minGuardBG 2.1<4.0\",\"COB\":0,\"IOB\":0.692,\"duration\":90,\"rate\":0,\"timestamp\":\"2023-01-02T15:29:39.460Z\"}", + device = "openaps://samsung SM-G970F", + pump = "{\"battery\":{\"percent\":75},\"status\":{\"status\":\"normal\",\"timestamp\":\"2023-01-02T15:20:20.656Z\"},\"extended\":{\"Version\":\"3.1.0.3-dev-e-295e1ad18f-2022.12.24\"," + + "\"LastBolus\":\"02.01.23 15:24\",\"LastBolusAmount\":\"1\",\"TempBasalAbsoluteRate\":\"0\",\"TempBasalStart\":\"02.01.23 16:20\",\"TempBasalRemaining\":\"55\",\"BaseBasalRate\":\"0" + + ".41\",\"ActiveProfile\":\"L29_U200 IC\"},\"reservoir\":\"133\",\"clock\":\"2023-01-02T15:25:05.826Z\"}", + uploaderBattery = 60, + configuration = "{\"insulin\":5,\"insulinConfiguration\":{},\"sensitivity\":2,\"sensitivityConfiguration\":{\"openapsama_min_5m_carbimpact\":8,\"absorption_cutoff\":4,\"autosens_max\":1.2,\"autosens_min\":0.7},\"overviewConfiguration\":{\"units\":\"mmol\",\"QuickWizard\":\"[]\",\"eatingsoon_duration\":60,\"eatingsoon_target\":4,\"activity_duration\":180,\"activity_target\":7.5,\"hypo_duration\":90,\"hypo_target\":8,\"low_mark\":3.9,\"high_mark\":10,\"statuslights_cage_warning\":72,\"statuslights_cage_critical\":96,\"statuslights_iage_warning\":120,\"statuslights_iage_critical\":150,\"statuslights_sage_warning\":168,\"statuslights_sage_critical\":336,\"statuslights_sbat_warning\":25,\"statuslights_sbat_critical\":5,\"statuslights_bage_warning\":720,\"statuslights_bage_critical\":800,\"statuslights_res_warning\":30,\"statuslights_res_critical\":10,\"statuslights_bat_warning\":50,\"statuslights_bat_critical\":25,\"boluswizard_percentage\":70},\"safetyConfiguration\":{\"age\":\"resistantadult\",\"treatmentssafety_maxbolus\":10,\"treatmentssafety_maxcarbs\":70}}" + ) + val dataPair = DataSyncSelector.PairDeviceStatus(deviceStatus, 1000) + `when`(nsAndroidClient.createDeviceStatus(anyObject())).thenReturn(CreateUpdateResponse(201, null)) + sut.nsAdd("devicestatus", dataPair, "1/3") + Assertions.assertEquals(1, storeDataForDb.nsIdDeviceStatuses.size) + verify(dataSyncSelector, Times(1)).confirmLastDeviceStatusIdIfGreater(1000) + verify(dataSyncSelector, Times(1)).processChangedDeviceStatusesCompat() + } +} \ No newline at end of file