diff --git a/codelabs/datacapture/README.md b/codelabs/datacapture/README.md index e9a7f9e196..af44e32e18 100644 --- a/codelabs/datacapture/README.md +++ b/codelabs/datacapture/README.md @@ -76,8 +76,8 @@ of the `app/build.gradle.kts` file of your project: dependencies { // ... - implementation("com.google.android.fhir:data-capture:1.0.0") - implementation("androidx.fragment:fragment-ktx:1.5.5") + implementation("com.google.android.fhir:data-capture:1.2.0") + implementation("androidx.fragment:fragment-ktx:1.6.0") } ``` @@ -150,11 +150,11 @@ Open `MainActivity.kt` and add the following code to the `MainActivity` class: ```kotlin // Step 2: Configure a QuestionnaireFragment -val questionnaireJsonString = getStringFromAssets("questionnaire.json") +questionnaireJsonString = getStringFromAssets("questionnaire.json") + +val questionnaireFragment = + QuestionnaireFragment.builder().setQuestionnaire(questionnaireJsonString!!).build() -val questionnaireParams = bundleOf( -QuestionnaireFragment.EXTRA_QUESTIONNAIRE_JSON_STRING to questionnaireJsonString -) ``` ### Step 3: Add the QuestionnaireFragment to the FragmentContainerView @@ -168,10 +168,10 @@ Add the following code to the `MainActivity` class: ```kotlin // Step 3: Add the QuestionnaireFragment to the FragmentContainerView if (savedInstanceState == null) { - supportFragmentManager.commit { - setReorderingAllowed(true) - add(R.id.fragment_container_view, args = questionnaireParams) - } + supportFragmentManager.commit { + setReorderingAllowed(true) + add(R.id.fragment_container_view, questionnaireFragment) + } } // Submit button callback supportFragmentManager.setFragmentResultListener( diff --git a/codelabs/engine/README.md b/codelabs/engine/README.md index 67bfd6fabc..f0fc5b8ddf 100644 --- a/codelabs/engine/README.md +++ b/codelabs/engine/README.md @@ -125,7 +125,7 @@ file of your project: dependencies { // ... - implementation("com.google.android.fhir:engine:1.0.0") + implementation("com.google.android.fhir:engine:1.1.0") } ``` @@ -257,7 +257,13 @@ outlined below will guide you through the process. override fun getFhirEngine() = FhirApplication.fhirEngine(applicationContext) - override fun getUploadStrategy() = UploadStrategy.AllChangesSquashedBundlePut + override fun getUploadStrategy() = + UploadStrategy.forBundleRequest( + methodForCreate = HttpCreateMethod.PUT, + methodForUpdate = HttpUpdateMethod.PATCH, + squash = true, + bundleSize = 500, + ) } ``` diff --git a/codelabs/engine/app/build.gradle.kts b/codelabs/engine/app/build.gradle.kts index 23c48e875f..b682babd86 100644 --- a/codelabs/engine/app/build.gradle.kts +++ b/codelabs/engine/app/build.gradle.kts @@ -49,6 +49,6 @@ dependencies { androidTestImplementation("androidx.test.ext:junit:1.2.1") androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") - implementation("com.google.android.fhir:engine:1.0.0") + implementation("com.google.android.fhir:engine:1.1.0") implementation("androidx.fragment:fragment-ktx:1.8.3") } diff --git a/codelabs/engine/app/src/main/java/com/google/android/fhir/codelabs/engine/PatientItemViewHolder.kt b/codelabs/engine/app/src/main/java/com/google/android/fhir/codelabs/engine/PatientItemViewHolder.kt index 409441019f..6b115142a0 100644 --- a/codelabs/engine/app/src/main/java/com/google/android/fhir/codelabs/engine/PatientItemViewHolder.kt +++ b/codelabs/engine/app/src/main/java/com/google/android/fhir/codelabs/engine/PatientItemViewHolder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,8 +30,10 @@ class PatientItemViewHolder(binding: PatientListItemViewBinding) : fun bind(patientItem: Patient) { nameTextView.text = - patientItem.name.first().let { it.given.joinToString(separator = " ") + " " + it.family } - genderTextView.text = patientItem.gender.display + patientItem.name.firstOrNull()?.let { + it.given.joinToString(separator = " ") + " " + it.family + } + genderTextView.text = patientItem.gender?.display cityTextView.text = patientItem.address.singleOrNull()?.city } } diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt index 35ca593755..056cd47aad 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt @@ -42,6 +42,7 @@ import com.google.android.fhir.datacapture.extensions.isHelpCode import com.google.android.fhir.datacapture.extensions.isHidden import com.google.android.fhir.datacapture.extensions.isPaginated import com.google.android.fhir.datacapture.extensions.isRepeatedGroup +import com.google.android.fhir.datacapture.extensions.launchTimestamp import com.google.android.fhir.datacapture.extensions.localizedTextSpanned import com.google.android.fhir.datacapture.extensions.maxValue import com.google.android.fhir.datacapture.extensions.maxValueCqfCalculatedValueExpression @@ -64,6 +65,7 @@ import com.google.android.fhir.datacapture.validation.Valid import com.google.android.fhir.datacapture.validation.ValidationResult import com.google.android.fhir.datacapture.views.QuestionTextConfiguration import com.google.android.fhir.datacapture.views.QuestionnaireViewItem +import java.util.Date import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -74,6 +76,7 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.withIndex import kotlinx.coroutines.launch +import org.hl7.fhir.r4.model.DateTimeType import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemComponent import org.hl7.fhir.r4.model.QuestionnaireResponse @@ -160,6 +163,8 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat .forEach { questionnaireResponse.addItem(it.createQuestionnaireResponseItem()) } } } + // Add extension for questionnaire launch time stamp + questionnaireResponse.launchTimestamp = DateTimeType(Date()) questionnaireResponse.packRepeatedGroups(questionnaire) } @@ -475,6 +480,8 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat ) .map { it.copy() } unpackRepeatedGroups(this@QuestionnaireViewModel.questionnaire) + // Use authored as a submission time stamp + authored = Date() } } diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireResponses.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireResponses.kt index 0d9b3cd194..e560798035 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireResponses.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireResponses.kt @@ -16,9 +16,14 @@ package com.google.android.fhir.datacapture.extensions +import org.hl7.fhir.r4.model.DateTimeType +import org.hl7.fhir.r4.model.Extension import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.QuestionnaireResponse +internal const val EXTENSION_LAST_LAUNCHED_TIMESTAMP: String = + "http://github.com/google-android/questionnaire-lastLaunched-timestamp" + /** Pre-order list of all questionnaire response items in the questionnaire. */ val QuestionnaireResponse.allItems: List get() = item.flatMap { it.descendant } @@ -146,3 +151,20 @@ private fun unpackRepeatedGroups( listOf(questionnaireResponseItem) } } + +/** + * Adds a launch timestamp extension to the Questionnaire Response. If the extension @see + * EXTENSION_LAUNCH_TIMESTAMP already exists, it updates its value; otherwise, it adds a new one. + */ +internal var QuestionnaireResponse.launchTimestamp: DateTimeType? + get() { + val extension = this.extension.firstOrNull { it.url == EXTENSION_LAST_LAUNCHED_TIMESTAMP } + return extension?.value as? DateTimeType + } + set(value) { + extension.find { it.url == EXTENSION_LAST_LAUNCHED_TIMESTAMP }?.setValue(value) + ?: run { + // Add a new extension if none exists + extension.add(Extension(EXTENSION_LAST_LAUNCHED_TIMESTAMP, value)) + } + } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireViewModelParameterizedTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireViewModelParameterizedTest.kt index f6c62956a3..312ff4fd2a 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireViewModelParameterizedTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireViewModelParameterizedTest.kt @@ -29,6 +29,7 @@ import com.google.android.fhir.datacapture.QuestionnaireFragment.Companion.EXTRA import com.google.android.fhir.datacapture.QuestionnaireFragment.Companion.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING import com.google.android.fhir.datacapture.QuestionnaireFragment.Companion.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI import com.google.android.fhir.datacapture.QuestionnaireFragment.Companion.EXTRA_SHOW_REVIEW_PAGE_FIRST +import com.google.android.fhir.datacapture.extensions.EXTENSION_LAST_LAUNCHED_TIMESTAMP import com.google.android.fhir.datacapture.testing.DataCaptureTestApplication import com.google.common.truth.Truth.assertThat import java.io.File @@ -89,7 +90,7 @@ class QuestionnaireViewModelParameterizedTest( val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { this.questionnaire = "http://www.sample-org/FHIR/Resources/Questionnaire/a-questionnaire" @@ -135,7 +136,12 @@ class QuestionnaireViewModelParameterizedTest( val viewModel = createQuestionnaireViewModel(questionnaire, questionnaireResponse) - runTest { assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) } + runTest { + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) + } } private fun createQuestionnaireViewModel( @@ -187,6 +193,28 @@ class QuestionnaireViewModelParameterizedTest( .isEqualTo(printer.encodeResourceToString(expected)) } + /** + * Asserts that the `expected` and the `actual` Questionnaire Responses are equal ignoring the + * stamp values + */ + fun assertQuestionnaireResponseEqualsIgnoringTimestamps( + actual: QuestionnaireResponse, + expected: QuestionnaireResponse, + ) { + val actualResponseWithoutTimestamp = + actual.copy().apply { + extension.removeIf { ext -> ext.url == EXTENSION_LAST_LAUNCHED_TIMESTAMP } + authored = null + } + val expectedResponseWithoutTimestamp = + expected.copy().apply { + extension.removeIf { ext -> ext.url == EXTENSION_LAST_LAUNCHED_TIMESTAMP } + authored = null + } + assertThat(printer.encodeResourceToString(actualResponseWithoutTimestamp)) + .isEqualTo(printer.encodeResourceToString(expectedResponseWithoutTimestamp)) + } + @JvmStatic @Parameters fun parameters() = diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireViewModelTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireViewModelTest.kt index e644e4c6d6..51e00eaa1d 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireViewModelTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireViewModelTest.kt @@ -48,6 +48,7 @@ import com.google.android.fhir.datacapture.extensions.EXTENSION_ENTRY_MODE_URL import com.google.android.fhir.datacapture.extensions.EXTENSION_HIDDEN_URL import com.google.android.fhir.datacapture.extensions.EXTENSION_ITEM_CONTROL_SYSTEM import com.google.android.fhir.datacapture.extensions.EXTENSION_ITEM_CONTROL_URL +import com.google.android.fhir.datacapture.extensions.EXTENSION_LAST_LAUNCHED_TIMESTAMP import com.google.android.fhir.datacapture.extensions.EXTENSION_SDC_QUESTIONNAIRE_LAUNCH_CONTEXT import com.google.android.fhir.datacapture.extensions.EXTENSION_VARIABLE_URL import com.google.android.fhir.datacapture.extensions.EntryMode @@ -187,7 +188,7 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { this.questionnaire = "http://www.sample-org/FHIR/Resources/Questionnaire/a-questionnaire" @@ -213,7 +214,7 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -251,7 +252,7 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -324,7 +325,7 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -422,7 +423,7 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -497,7 +498,12 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire, questionnaireResponse) - runTest { assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) } + runTest { + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) + } } @Test @@ -565,7 +571,7 @@ class QuestionnaireViewModelTest { } runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( createQuestionnaireViewModel( questionnaire, questionnaireResponse, @@ -651,7 +657,12 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire, questionnaireResponse) - runTest { assertResourceEquals(questionnaireResponse, viewModel.getQuestionnaireResponse()) } + runTest { + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) + } } @Test @@ -742,7 +753,12 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire, questionnaireResponse) - runTest { assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) } + runTest { + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) + } } @Test @@ -794,7 +810,12 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire, questionnaireResponse) - runTest { assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) } + runTest { + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) + } } @Test @@ -853,7 +874,12 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire, questionnaireResponse) - runTest { assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) } + runTest { + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) + } } @Test @@ -895,7 +921,12 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire, questionnaireResponse) - runTest { assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) } + runTest { + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) + } } @Test @@ -1006,7 +1037,7 @@ class QuestionnaireViewModelTest { printer.parseResource(QuestionnaireResponse::class.java, expectedResponseString) as QuestionnaireResponse - assertResourceEquals(value, expectedResponse) + assertQuestionnaireResponseEqualsIgnoringTimestamps(value, expectedResponse) } } @@ -1134,7 +1165,7 @@ class QuestionnaireViewModelTest { printer.parseResource(QuestionnaireResponse::class.java, expectedResponseString) as QuestionnaireResponse - assertResourceEquals(value, expectedResponse) + assertQuestionnaireResponseEqualsIgnoringTimestamps(value, expectedResponse) } } @@ -3340,7 +3371,7 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -3387,7 +3418,7 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -3435,7 +3466,7 @@ class QuestionnaireViewModelTest { val viewModel = createQuestionnaireViewModel(questionnaire) runTest { - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -3489,7 +3520,7 @@ class QuestionnaireViewModelTest { val viewModel = QuestionnaireViewModel(context, state) - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -3534,7 +3565,7 @@ class QuestionnaireViewModelTest { val viewModel = QuestionnaireViewModel(context, state) - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { addItem( @@ -3621,7 +3652,10 @@ class QuestionnaireViewModelTest { val viewModel = QuestionnaireViewModel(context, state) - assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) } @Test @@ -3787,7 +3821,7 @@ class QuestionnaireViewModelTest { // Clearing the answer disables question-2 that in turn disables question-3. items.first { it.questionnaireItem.linkId == "question-1" }.clearAnswer() - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( viewModel.getQuestionnaireResponse(), QuestionnaireResponse().apply { id = "a-questionnaire-response" @@ -3809,7 +3843,10 @@ class QuestionnaireViewModelTest { }, ) - assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) } } @@ -4180,7 +4217,7 @@ class QuestionnaireViewModelTest { printer.parseResource(QuestionnaireResponse::class.java, expectedResponseString) as QuestionnaireResponse - assertResourceEquals(value, expectedResponse) + assertQuestionnaireResponseEqualsIgnoringTimestamps(value, expectedResponse) } } @@ -4278,7 +4315,7 @@ class QuestionnaireViewModelTest { val expectedResponse = printer.parseResource(QuestionnaireResponse::class.java, expectedResponseString) as QuestionnaireResponse - assertResourceEquals(value, expectedResponse) + assertQuestionnaireResponseEqualsIgnoringTimestamps(value, expectedResponse) } } @@ -4339,7 +4376,10 @@ class QuestionnaireViewModelTest { }, ) - assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) } } @@ -4459,7 +4499,7 @@ class QuestionnaireViewModelTest { ) .inOrder() - assertResourceEquals( + assertQuestionnaireResponseEqualsIgnoringTimestamps( actual = viewModel.getQuestionnaireResponse(), expected = QuestionnaireResponse().apply { @@ -4641,7 +4681,10 @@ class QuestionnaireViewModelTest { }, ) - assertResourceEquals(viewModel.getQuestionnaireResponse(), questionnaireResponse) + assertQuestionnaireResponseEqualsIgnoringTimestamps( + viewModel.getQuestionnaireResponse(), + questionnaireResponse, + ) } } @@ -7517,6 +7560,28 @@ class QuestionnaireViewModelTest { assertThat(printer.encodeResourceToString(actual)) .isEqualTo(printer.encodeResourceToString(expected)) } + + /** + * Asserts that the `expected` and the `actual` Questionnaire Responses are equal ignoring the + * stamp values + */ + private fun assertQuestionnaireResponseEqualsIgnoringTimestamps( + actual: QuestionnaireResponse, + expected: QuestionnaireResponse, + ) { + val actualResponseWithoutTimestamp = + actual.copy().apply { + extension.removeIf { ext -> ext.url == EXTENSION_LAST_LAUNCHED_TIMESTAMP } + authored = null + } + val expectedResponseWithoutTimestamp = + expected.copy().apply { + extension.removeIf { ext -> ext.url == EXTENSION_LAST_LAUNCHED_TIMESTAMP } + authored = null + } + assertThat(printer.encodeResourceToString(actualResponseWithoutTimestamp)) + .isEqualTo(printer.encodeResourceToString(expectedResponseWithoutTimestamp)) + } } } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireResponsesTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireResponsesTest.kt index 236ed8796a..275d031f01 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireResponsesTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/extensions/MoreQuestionnaireResponsesTest.kt @@ -20,6 +20,7 @@ import ca.uhn.fhir.context.FhirContext import ca.uhn.fhir.context.FhirVersionEnum import com.google.common.truth.Truth.assertThat import org.hl7.fhir.r4.model.BooleanType +import org.hl7.fhir.r4.model.DateTimeType import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemComponent import org.hl7.fhir.r4.model.QuestionnaireResponse @@ -810,4 +811,29 @@ class MoreQuestionnaireResponsesTest { assertThat(iParser.encodeResourceToString(actual)) .isEqualTo(iParser.encodeResourceToString(expected)) } + + @Test + fun `should add launchTimestamp`() { + val questionnaireResponse = QuestionnaireResponse() + val dateTimeType = DateTimeType("2024-07-05T00:00:00Z") + questionnaireResponse.launchTimestamp = dateTimeType + + assertThat(dateTimeType).isEqualTo(questionnaireResponse.launchTimestamp) + } + + @Test + fun `launchTimestamp should be null when not added`() { + assertThat(QuestionnaireResponse().launchTimestamp).isNull() + } + + @Test + fun `launchTimestamp should update if already exists`() { + val questionnaireResponse = QuestionnaireResponse() + val oldDateTimeType = DateTimeType("2024-07-01T00:00:00Z") + val newDateTimeType = DateTimeType("2024-07-05T00:00:00Z") + questionnaireResponse.launchTimestamp = oldDateTimeType + questionnaireResponse.launchTimestamp = newDateTimeType + + assertThat(newDateTimeType).isEqualTo(questionnaireResponse.launchTimestamp) + } }