diff --git a/engine/src/main/java/com/google/android/fhir/sync/download/ResourceParamsBasedDownloadWorkManager.kt b/engine/src/main/java/com/google/android/fhir/sync/download/ResourceParamsBasedDownloadWorkManager.kt index de7052104f..94c95c0b23 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/download/ResourceParamsBasedDownloadWorkManager.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/download/ResourceParamsBasedDownloadWorkManager.kt @@ -102,30 +102,30 @@ class ResourceParamsBasedDownloadWorkManager( throw FHIRException(response.issueFirstRep.diagnostics) } - return if (response is Bundle && response.type == Bundle.BundleType.SEARCHSET) { - response.link - .firstOrNull { component -> component.relation == "next" } - ?.url?.let { next -> urlOfTheNextPagesToDownloadForAResource.add(next) } - - response.entry - .map { it.resource } - .also { resources -> - resources - .groupBy { it.resourceType } - .entries.map { map -> - map.value - .filter { it.meta.lastUpdated != null } - .let { - context.saveLastUpdatedTimestamp( - map.key, - it.maxOfOrNull { it.meta.lastUpdated }?.toTimeZoneString() - ) - } - } - } - } else { - emptyList() + if ((response !is Bundle || response.type != Bundle.BundleType.SEARCHSET)) { + return emptyList() } + + response.link + .firstOrNull { component -> component.relation == "next" } + ?.url?.let { next -> urlOfTheNextPagesToDownloadForAResource.add(next) } + + return response.entry + .map { it.resource } + .also { resources -> + resources + .groupBy { it.resourceType } + .entries.map { map -> + map.value + .filter { it.meta.lastUpdated != null } + .let { + context.saveLastUpdatedTimestamp( + map.key, + it.maxOfOrNull { it.meta.lastUpdated }?.toTimeZoneString() + ) + } + } + } } interface TimestampContext { diff --git a/engine/src/main/java/com/google/android/fhir/sync/upload/request/TransactionBundleGenerator.kt b/engine/src/main/java/com/google/android/fhir/sync/upload/request/TransactionBundleGenerator.kt index 2f4a698b5f..b068c4a222 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/upload/request/TransactionBundleGenerator.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/upload/request/TransactionBundleGenerator.kt @@ -76,7 +76,7 @@ class TransactionBundleGenerator( httpVerbToUseForCreate: Bundle.HTTPVerb, httpVerbToUseForUpdate: Bundle.HTTPVerb, generatedBundleSize: Int, - useETagForUpload: Boolean + useETagForUpload: Boolean, ): TransactionBundleGenerator { val createFunction = diff --git a/engine/src/test/java/com/google/android/fhir/sync/download/ResourceParamsBasedDownloadWorkManagerTest.kt b/engine/src/test/java/com/google/android/fhir/sync/download/ResourceParamsBasedDownloadWorkManagerTest.kt index 53dd0d79d2..e59cb98ae1 100644 --- a/engine/src/test/java/com/google/android/fhir/sync/download/ResourceParamsBasedDownloadWorkManagerTest.kt +++ b/engine/src/test/java/com/google/android/fhir/sync/download/ResourceParamsBasedDownloadWorkManagerTest.kt @@ -17,11 +17,14 @@ package com.google.android.fhir.sync.download import com.google.android.fhir.logicalId +import com.google.android.fhir.sync.DownloadRequest import com.google.android.fhir.sync.SyncDataParams import com.google.android.fhir.sync.UrlDownloadRequest import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.runTest import org.hl7.fhir.exceptions.FHIRException +import org.hl7.fhir.r4.model.Binary import org.hl7.fhir.r4.model.Bundle import org.hl7.fhir.r4.model.OperationOutcome import org.hl7.fhir.r4.model.Patient @@ -35,78 +38,80 @@ import org.robolectric.RobolectricTestRunner class ResourceParamsBasedDownloadWorkManagerTest { @Test - fun getNextRequestUrl_shouldReturnNextResourceUrls() = runBlockingTest { - val downloadManager = - ResourceParamsBasedDownloadWorkManager( - mapOf( - ResourceType.Patient to mapOf(Patient.ADDRESS_CITY.paramName to "NAIROBI"), - ResourceType.Immunization to emptyMap(), - ResourceType.Observation to emptyMap(), - ), - TestResourceParamsBasedDownloadWorkManagerContext("2022-03-20") - ) + fun getNextRequestUrl_shouldReturnNextResourceUrls() = + runTest(StandardTestDispatcher()) { + val downloadManager = + ResourceParamsBasedDownloadWorkManager( + mapOf( + ResourceType.Patient to mapOf(Patient.ADDRESS_CITY.paramName to "NAIROBI"), + ResourceType.Immunization to emptyMap(), + ResourceType.Observation to emptyMap(), + ), + TestResourceParamsBasedDownloadWorkManagerContext("2022-03-20") + ) - val urlsToDownload = mutableListOf() - do { - val url = downloadManager.getNextRequest()?.let { (it as UrlDownloadRequest).url } - if (url != null) { - urlsToDownload.add(url) - } - } while (url != null) + val urlsToDownload = mutableListOf() + do { + val url = downloadManager.getNextRequest()?.let { (it as UrlDownloadRequest).url } + if (url != null) { + urlsToDownload.add(url) + } + } while (url != null) - assertThat(urlsToDownload) - .containsExactly( - "Patient?address-city=NAIROBI&_sort=_lastUpdated&_lastUpdated=gt2022-03-20", - "Observation?_sort=_lastUpdated&_lastUpdated=gt2022-03-20", - "Immunization?_sort=_lastUpdated&_lastUpdated=gt2022-03-20" - ) - } + assertThat(urlsToDownload) + .containsExactly( + "Patient?address-city=NAIROBI&_sort=_lastUpdated&_lastUpdated=gt2022-03-20", + "Observation?_sort=_lastUpdated&_lastUpdated=gt2022-03-20", + "Immunization?_sort=_lastUpdated&_lastUpdated=gt2022-03-20" + ) + } @Test - fun getNextRequestUrl_shouldReturnResourceAndPageUrlsAsNextUrls() = runBlockingTest { - val downloadManager = - ResourceParamsBasedDownloadWorkManager( - mapOf(ResourceType.Patient to emptyMap(), ResourceType.Observation to emptyMap()), - TestResourceParamsBasedDownloadWorkManagerContext("2022-03-20") - ) + fun getNextRequestUrl_shouldReturnResourceAndPageUrlsAsNextUrls() = + runTest(StandardTestDispatcher()) { + val downloadManager = + ResourceParamsBasedDownloadWorkManager( + mapOf(ResourceType.Patient to emptyMap(), ResourceType.Observation to emptyMap()), + TestResourceParamsBasedDownloadWorkManagerContext("2022-03-20") + ) - val urlsToDownload = mutableListOf() - do { - val url = downloadManager.getNextRequest()?.let { (it as UrlDownloadRequest).url } - if (url != null) { - urlsToDownload.add(url) - } - // Call process response so that It can add the next page url to be downloaded next. - when (url) { - "Patient?_sort=_lastUpdated&_lastUpdated=gt2022-03-20", - "Observation?_sort=_lastUpdated&_lastUpdated=gt2022-03-20" -> { - downloadManager.processResponse( - Bundle().apply { - type = Bundle.BundleType.SEARCHSET - addLink( - Bundle.BundleLinkComponent().apply { - relation = "next" - this.url = "http://url-to-next-page?token=pageToken" - } - ) - } - ) + val urlsToDownload = mutableListOf() + do { + val url = downloadManager.getNextRequest()?.let { (it as UrlDownloadRequest).url } + if (url != null) { + urlsToDownload.add(url) } - } - } while (url != null) - - assertThat(urlsToDownload) - .containsExactly( - "Patient?_sort=_lastUpdated&_lastUpdated=gt2022-03-20", - "http://url-to-next-page?token=pageToken", - "Observation?_sort=_lastUpdated&_lastUpdated=gt2022-03-20", - "http://url-to-next-page?token=pageToken" - ) - } + // Call process response so that It can add the next page url to be downloaded next. + when (url) { + "Patient?_sort=_lastUpdated&_lastUpdated=gt2022-03-20", + "Observation?_sort=_lastUpdated&_lastUpdated=gt2022-03-20" -> { + downloadManager.processResponse( + Bundle().apply { + type = Bundle.BundleType.SEARCHSET + addLink( + Bundle.BundleLinkComponent().apply { + relation = "next" + this.url = "http://url-to-next-page?token=pageToken" + } + ) + } + ) + } + } + } while (url != null) + + assertThat(urlsToDownload) + .containsExactly( + "Patient?_sort=_lastUpdated&_lastUpdated=gt2022-03-20", + "http://url-to-next-page?token=pageToken", + "Observation?_sort=_lastUpdated&_lastUpdated=gt2022-03-20", + "http://url-to-next-page?token=pageToken" + ) + } @Test fun getNextRequestUrl_withLastUpdatedTimeProvidedInContext_ShouldAppendGtPrefixToLastUpdatedSearchParam() = - runBlockingTest { + runTest(StandardTestDispatcher()) { val downloadManager = ResourceParamsBasedDownloadWorkManager( mapOf(ResourceType.Patient to emptyMap()), @@ -118,7 +123,7 @@ class ResourceParamsBasedDownloadWorkManagerTest { @Test fun getNextRequestUrl_withLastUpdatedSyncParamProvided_shouldReturnUrlWithExactProvidedLastUpdatedSyncParam() = - runBlockingTest { + runTest(StandardTestDispatcher()) { val downloadManager = ResourceParamsBasedDownloadWorkManager( mapOf( @@ -136,7 +141,7 @@ class ResourceParamsBasedDownloadWorkManagerTest { @Test fun getNextRequestUrl_withLastUpdatedSyncParamHavingGtPrefix_shouldReturnUrlWithExactProvidedLastUpdatedSyncParam() = - runBlockingTest { + runTest(StandardTestDispatcher()) { val downloadManager = ResourceParamsBasedDownloadWorkManager( mapOf(ResourceType.Patient to mapOf(SyncDataParams.LAST_UPDATED_KEY to "gt2022-06-28")), @@ -148,7 +153,7 @@ class ResourceParamsBasedDownloadWorkManagerTest { @Test fun getNextRequestUrl_withNullUpdatedTimeStamp_shouldReturnUrlWithoutLastUpdatedQueryParam() = - runBlockingTest { + runTest(StandardTestDispatcher()) { val downloadManager = ResourceParamsBasedDownloadWorkManager( mapOf(ResourceType.Patient to mapOf(Patient.ADDRESS_CITY.paramName to "NAIROBI")), @@ -160,7 +165,7 @@ class ResourceParamsBasedDownloadWorkManagerTest { @Test fun getNextRequestUrl_withEmptyUpdatedTimeStamp_shouldReturnUrlWithoutLastUpdatedQueryParam() = - runBlockingTest { + runTest(StandardTestDispatcher()) { val downloadManager = ResourceParamsBasedDownloadWorkManager( mapOf(ResourceType.Patient to mapOf(Patient.ADDRESS_CITY.paramName to "NAIROBI")), @@ -171,82 +176,32 @@ class ResourceParamsBasedDownloadWorkManagerTest { } @Test - fun `getSummaryRequestUrls should return resource summary urls`() = runBlockingTest { - val downloadManager = - ResourceParamsBasedDownloadWorkManager( - mapOf( - ResourceType.Patient to mapOf(Patient.ADDRESS_CITY.paramName to "NAIROBI"), - ResourceType.Immunization to emptyMap(), - ResourceType.Observation to emptyMap(), - ), - TestResourceParamsBasedDownloadWorkManagerContext("2022-03-20") - ) - - val urls = downloadManager.getSummaryRequestUrls() - - assertThat(urls.map { it.key }) - .containsExactly(ResourceType.Patient, ResourceType.Immunization, ResourceType.Observation) - assertThat(urls.map { it.value }) - .containsExactly( - "Patient?address-city=NAIROBI&_sort=_lastUpdated&_lastUpdated=gt2022-03-20&_summary=count", - "Immunization?_sort=_lastUpdated&_lastUpdated=gt2022-03-20&_summary=count", - "Observation?_sort=_lastUpdated&_lastUpdated=gt2022-03-20&_summary=count" - ) - } - - @Test - fun processResponse_withBundleTypeSearchSet_shouldReturnPatient() = runBlockingTest { - val downloadManager = - ResourceParamsBasedDownloadWorkManager( - emptyMap(), - NoOpResourceParamsBasedDownloadWorkManagerContext - ) - val response = - Bundle().apply { - type = Bundle.BundleType.SEARCHSET - addEntry( - Bundle.BundleEntryComponent().apply { - resource = Patient().apply { id = "Patient-Id-001" } - } - ) - addEntry( - Bundle.BundleEntryComponent().apply { - resource = Patient().apply { id = "Patient-Id-002" } - } + fun `getSummaryRequestUrls should return resource summary urls`() = + runTest(StandardTestDispatcher()) { + val downloadManager = + ResourceParamsBasedDownloadWorkManager( + mapOf( + ResourceType.Patient to mapOf(Patient.ADDRESS_CITY.paramName to "NAIROBI"), + ResourceType.Immunization to emptyMap(), + ResourceType.Observation to emptyMap(), + ), + TestResourceParamsBasedDownloadWorkManagerContext("2022-03-20") ) - } - val resources = downloadManager.processResponse(response) - assertThat(resources.map { it.logicalId }).containsExactly("Patient-Id-001", "Patient-Id-002") - } - @Test - fun processResponse_withTransactionResponseBundle_shouldReturnEmptyList() = runBlockingTest { - val downloadManager = - ResourceParamsBasedDownloadWorkManager( - emptyMap(), - NoOpResourceParamsBasedDownloadWorkManagerContext - ) - val response = - Bundle().apply { - type = Bundle.BundleType.TRANSACTIONRESPONSE - addEntry( - Bundle.BundleEntryComponent().apply { - resource = Patient().apply { id = "Patient-Id-001" } - } - ) - addEntry( - Bundle.BundleEntryComponent().apply { - resource = Patient().apply { id = "Patient-Id-002" } - } - ) - } + val urls = downloadManager.getSummaryRequestUrls() - val resources = downloadManager.processResponse(response) - assertThat(resources).hasSize(0) - } + assertThat(urls.map { it.key }) + .containsExactly(ResourceType.Patient, ResourceType.Immunization, ResourceType.Observation) + assertThat(urls.map { it.value }) + .containsExactly( + "Patient?address-city=NAIROBI&_sort=_lastUpdated&_lastUpdated=gt2022-03-20&_summary=count", + "Immunization?_sort=_lastUpdated&_lastUpdated=gt2022-03-20&_summary=count", + "Observation?_sort=_lastUpdated&_lastUpdated=gt2022-03-20&_summary=count" + ) + } @Test - fun processResponse_withOperationOutcome_shouldThrowException() { + fun `processResponse should throw exception including diagnostics from operation outcome`() { val downloadManager = ResourceParamsBasedDownloadWorkManager( emptyMap(), @@ -263,10 +218,125 @@ class ResourceParamsBasedDownloadWorkManagerTest { val exception = assertThrows(FHIRException::class.java) { - runBlockingTest { downloadManager.processResponse(response) } + runTest(StandardTestDispatcher()) { downloadManager.processResponse(response) } } + assertThat(exception.localizedMessage).isEqualTo("Server couldn't fulfil the request.") } + + @Test + fun `processResponse should return empty list for resource that is not a bundle`() = + runTest(StandardTestDispatcher()) { + val downloadManager = + ResourceParamsBasedDownloadWorkManager( + emptyMap(), + NoOpResourceParamsBasedDownloadWorkManagerContext + ) + val response = Binary().apply { contentType = "application/json" } + + assertThat(downloadManager.processResponse(response)).isEmpty() + } + + @Test + fun `processResponse should return empty list for bundle that is not a search set`() = + runTest(StandardTestDispatcher()) { + val downloadManager = + ResourceParamsBasedDownloadWorkManager( + emptyMap(), + NoOpResourceParamsBasedDownloadWorkManagerContext + ) + val response = + Bundle().apply { + type = Bundle.BundleType.TRANSACTIONRESPONSE + addEntry( + Bundle.BundleEntryComponent().apply { + resource = Patient().apply { id = "Patient-Id-001" } + } + ) + addEntry( + Bundle.BundleEntryComponent().apply { + resource = Patient().apply { id = "Patient-Id-002" } + } + ) + } + + assertThat(downloadManager.processResponse(response)).isEmpty() + } + + @Test + fun `processResponse should return resources for bundle search set`() = + runTest(StandardTestDispatcher()) { + val downloadManager = + ResourceParamsBasedDownloadWorkManager( + emptyMap(), + NoOpResourceParamsBasedDownloadWorkManagerContext + ) + val response = + Bundle().apply { + type = Bundle.BundleType.SEARCHSET + addEntry( + Bundle.BundleEntryComponent().apply { + resource = Patient().apply { id = "Patient-Id-001" } + } + ) + addEntry( + Bundle.BundleEntryComponent().apply { + resource = Patient().apply { id = "Patient-Id-002" } + } + ) + } + + assertThat(downloadManager.processResponse(response).map { it.logicalId }) + .containsExactly("Patient-Id-001", "Patient-Id-002") + } + + @Test + fun `processResponse should add next request`() = + runTest(StandardTestDispatcher()) { + val downloadManager = + ResourceParamsBasedDownloadWorkManager( + emptyMap(), + NoOpResourceParamsBasedDownloadWorkManagerContext + ) + val response = + Bundle().apply { + type = Bundle.BundleType.SEARCHSET + link = + mutableListOf( + Bundle.BundleLinkComponent().apply { + relation = "next" + url = "next_url" + } + ) + } + + downloadManager.processResponse(response) + + assertThat(downloadManager.getNextRequest()).isEqualTo(DownloadRequest.of("next_url")) + } + + @Test + fun `processResponse should not add next request if next url is missing`() = + runTest(StandardTestDispatcher()) { + val downloadManager = + ResourceParamsBasedDownloadWorkManager( + emptyMap(), + NoOpResourceParamsBasedDownloadWorkManagerContext + ) + val response = + Bundle().apply { + type = Bundle.BundleType.SEARCHSET + addEntry( + Bundle.BundleEntryComponent().apply { + resource = Patient().apply { id = "Patient-Id-001" } + } + ) + } + + downloadManager.processResponse(response) + + assertThat(downloadManager.getNextRequest()).isNull() + } } val NoOpResourceParamsBasedDownloadWorkManagerContext = diff --git a/engine/src/test/java/com/google/android/fhir/sync/upload/UploaderImplTest.kt b/engine/src/test/java/com/google/android/fhir/sync/upload/UploaderImplTest.kt index 49b75a8eb7..bc2da80244 100644 --- a/engine/src/test/java/com/google/android/fhir/sync/upload/UploaderImplTest.kt +++ b/engine/src/test/java/com/google/android/fhir/sync/upload/UploaderImplTest.kt @@ -40,7 +40,17 @@ import org.robolectric.RobolectricTestRunner class UploaderImplTest { @Test - fun `upload Bundle transaction should emit Success`() = runBlocking { + fun `upload should start`() = runBlocking { + val result = + UploaderImpl(BundleDataSource { Bundle() }, SquashedChangesUploadWorkManager()) + .upload(localChanges) + .toList() + + assertThat(result.first()).isInstanceOf(UploadState.Started::class.java) + } + + @Test + fun `upload should succeed if response is transaction response`() = runBlocking { val result = UploaderImpl( BundleDataSource { Bundle().apply { type = Bundle.BundleType.TRANSACTIONRESPONSE } }, @@ -59,17 +69,7 @@ class UploaderImplTest { } @Test - fun `upload Bundle transaction should emit Started state`() = runBlocking { - val result = - UploaderImpl(BundleDataSource { Bundle() }, SquashedChangesUploadWorkManager()) - .upload(localChanges) - .toList() - - assertThat(result.first()).isInstanceOf(UploadState.Started::class.java) - } - - @Test - fun `upload Bundle Transaction server error should emit Failure`() = runBlocking { + fun `upload should fail if response is operation outcome with issue`() = runBlocking { val result = UploaderImpl( BundleDataSource { @@ -93,7 +93,36 @@ class UploaderImplTest { } @Test - fun `upload Bundle transaction error during upload should emit Failure`() = runBlocking { + fun `upload should fail if response is empty operation outcome`() = runBlocking { + val result = + UploaderImpl( + BundleDataSource { OperationOutcome() }, + SquashedChangesUploadWorkManager(), + ) + .upload(localChanges) + .toList() + + assertThat(result).hasSize(2) + assertThat(result.last()).isInstanceOf(UploadState.Failure::class.java) + } + + @Test + fun `upload should fail if response is neither transaction response nor operation outcome`() = + runBlocking { + val result = + UploaderImpl( + BundleDataSource { Bundle().apply { type = Bundle.BundleType.SEARCHSET } }, + SquashedChangesUploadWorkManager(), + ) + .upload(localChanges) + .toList() + + assertThat(result).hasSize(2) + assertThat(result.last()).isInstanceOf(UploadState.Failure::class.java) + } + + @Test + fun `upload should fail if there is connection exception`() = runBlocking { val result = UploaderImpl( BundleDataSource { throw ConnectException("Failed to connect to server.") }, @@ -105,6 +134,7 @@ class UploaderImplTest { assertThat(result).hasSize(2) assertThat(result.last()).isInstanceOf(UploadState.Failure::class.java) } + companion object { val localChanges = listOf( diff --git a/engine/src/test/java/com/google/android/fhir/sync/upload/request/TransactionBundleGeneratorTest.kt b/engine/src/test/java/com/google/android/fhir/sync/upload/request/TransactionBundleGeneratorTest.kt index e9db8c43cf..56e41e72f9 100644 --- a/engine/src/test/java/com/google/android/fhir/sync/upload/request/TransactionBundleGeneratorTest.kt +++ b/engine/src/test/java/com/google/android/fhir/sync/upload/request/TransactionBundleGeneratorTest.kt @@ -27,6 +27,7 @@ import org.hl7.fhir.r4.model.Bundle import org.hl7.fhir.r4.model.HumanName import org.hl7.fhir.r4.model.Patient import org.hl7.fhir.r4.model.ResourceType +import org.junit.Assert.assertThrows import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @@ -292,4 +293,146 @@ class TransactionBundleGeneratorTest { assertThat(result.first().resource.entry[0].request.ifMatch).isNull() assertThat(result.first().resource.entry[1].request.ifMatch).isNull() } + + @Test + fun `getGenerator() with supported Bundle HTTPVerbs should return TransactionBundleGenerator`() = + runBlocking { + val generator = + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.PUT, + Bundle.HTTPVerb.PATCH, + generatedBundleSize = 500, + useETagForUpload = true, + ) + + assertThat(generator).isInstanceOf(TransactionBundleGenerator::class.java) + } + + @Test + fun `getGenerator() should through exception for create by DELETE`() { + val exception = + assertThrows(IllegalArgumentException::class.java) { + runBlocking { + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.DELETE, + Bundle.HTTPVerb.PATCH, + generatedBundleSize = 500, + useETagForUpload = true, + ) + } + } + assertThat(exception.localizedMessage).isEqualTo("Creation using DELETE is not supported.") + } + + @Test + fun `getGenerator() should through exception for create by GET`() { + val exception = + assertThrows(IllegalArgumentException::class.java) { + runBlocking { + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.GET, + Bundle.HTTPVerb.PATCH, + generatedBundleSize = 500, + useETagForUpload = true, + ) + } + } + assertThat(exception.localizedMessage).isEqualTo("Creation using GET is not supported.") + } + + @Test + fun `getGenerator() should through exception for create by PATCH`() { + val exception = + assertThrows(IllegalArgumentException::class.java) { + runBlocking { + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.PATCH, + Bundle.HTTPVerb.PATCH, + generatedBundleSize = 500, + useETagForUpload = true, + ) + } + } + assertThat(exception.localizedMessage).isEqualTo("Creation using PATCH is not supported.") + } + + @Test + fun `getGenerator() should through exception for create by POST`() { + val exception = + assertThrows(IllegalArgumentException::class.java) { + runBlocking { + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.POST, + Bundle.HTTPVerb.PATCH, + generatedBundleSize = 500, + useETagForUpload = true, + ) + } + } + assertThat(exception.localizedMessage).isEqualTo("Creation using POST is not supported.") + } + + @Test + fun `getGenerator() should through exception for update by DELETE`() { + val exception = + assertThrows(IllegalArgumentException::class.java) { + runBlocking { + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.PUT, + Bundle.HTTPVerb.DELETE, + generatedBundleSize = 500, + useETagForUpload = true, + ) + } + } + assertThat(exception.localizedMessage).isEqualTo("Update using DELETE is not supported.") + } + + @Test + fun `getGenerator() should through exception for update by GET`() { + val exception = + assertThrows(IllegalArgumentException::class.java) { + runBlocking { + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.PUT, + Bundle.HTTPVerb.GET, + generatedBundleSize = 500, + useETagForUpload = true, + ) + } + } + assertThat(exception.localizedMessage).isEqualTo("Update using GET is not supported.") + } + + @Test + fun `getGenerator() should through exception for update by POST`() { + val exception = + assertThrows(IllegalArgumentException::class.java) { + runBlocking { + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.PUT, + Bundle.HTTPVerb.POST, + generatedBundleSize = 500, + useETagForUpload = true, + ) + } + } + assertThat(exception.localizedMessage).isEqualTo("Update using POST is not supported.") + } + + @Test + fun `getGenerator() should through exception for update by PUT`() { + val exception = + assertThrows(IllegalArgumentException::class.java) { + runBlocking { + TransactionBundleGenerator.Factory.getGenerator( + Bundle.HTTPVerb.PUT, + Bundle.HTTPVerb.PUT, + generatedBundleSize = 500, + useETagForUpload = true, + ) + } + } + assertThat(exception.localizedMessage).isEqualTo("Update using PUT is not supported.") + } }