diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index e828e2898e6..4211a1acc35 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,5 +1,8 @@ + + - \ No newline at end of file + diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index 80e519c3aa2..78ea4beff08 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,6 +1,6 @@ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8b199f77525..f321884c914 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,8 @@ - + package="org.oppia.app"> + + - - - - - - - - + + + + + + + + - - + + - - + + - - + android:theme="@style/SplashScreenTheme"> + diff --git a/app/src/main/java/org/oppia/app/activity/InputInteractionViewTestActivity.kt b/app/src/main/java/org/oppia/app/activity/InputInteractionViewTestActivity.kt new file mode 100644 index 00000000000..a46f7b01a08 --- /dev/null +++ b/app/src/main/java/org/oppia/app/activity/InputInteractionViewTestActivity.kt @@ -0,0 +1,17 @@ +package org.oppia.app.activity + +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import org.oppia.app.R +import org.oppia.app.customview.interaction.NumericInputInteractionView + +/** + * This is a dummy activity to test input interaction views. + * It contains [NumericInputInteractionView] . + */ +class InputInteractionViewTestActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_numeric_input_interaction_view_test) + } +} diff --git a/app/src/main/java/org/oppia/app/customview/interaction/InteractionAnswerRetriever.kt b/app/src/main/java/org/oppia/app/customview/interaction/InteractionAnswerRetriever.kt new file mode 100644 index 00000000000..5d41b7e5833 --- /dev/null +++ b/app/src/main/java/org/oppia/app/customview/interaction/InteractionAnswerRetriever.kt @@ -0,0 +1,8 @@ +package org.oppia.app.customview.interaction + +import org.oppia.app.model.InteractionObject + +/** This interface helps to get answer from input interaction views as [InteractionObject]. */ +interface InteractionAnswerRetriever { + fun getPendingAnswer(): InteractionObject +} diff --git a/app/src/main/java/org/oppia/app/customview/interaction/NumericInputInteractionView.kt b/app/src/main/java/org/oppia/app/customview/interaction/NumericInputInteractionView.kt new file mode 100644 index 00000000000..ebad8a5c729 --- /dev/null +++ b/app/src/main/java/org/oppia/app/customview/interaction/NumericInputInteractionView.kt @@ -0,0 +1,29 @@ +package org.oppia.app.customview.interaction + +import android.content.Context +import android.util.AttributeSet +import android.widget.EditText +import org.oppia.app.model.InteractionObject + +// TODO(#249): These are the attributes which should be defined in XML, that are required for this interaction view to work correctly +// digits="0123456789." +// hint="Write the digit here." +// inputType="numberDecimal" +// background="@drawable/edit_text_background" +// maxLength="200". + +/** The custom EditText class for numeric input interaction view. */ +class NumericInputInteractionView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyle: Int = android.R.attr.editTextStyle +) : EditText(context, attrs, defStyle), InteractionAnswerRetriever { + + override fun getPendingAnswer(): InteractionObject { + val interactionObjectBuilder = InteractionObject.newBuilder() + if (!text.isNullOrEmpty()) { + interactionObjectBuilder.setReal(text.toString().toDouble()) + } + return interactionObjectBuilder.build() + } +} diff --git a/app/src/main/res/layout/activity_numeric_input_interaction_view_test.xml b/app/src/main/res/layout/activity_numeric_input_interaction_view_test.xml new file mode 100644 index 00000000000..c53db5bff2c --- /dev/null +++ b/app/src/main/res/layout/activity_numeric_input_interaction_view_test.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 35f1efabe12..c96810de821 100755 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -7,5 +7,4 @@ 32dp 24dp 4dp - 8dp diff --git a/app/src/sharedTest/java/org/oppia/app/activity/InputInteractionViewTestActivityTest.kt b/app/src/sharedTest/java/org/oppia/app/activity/InputInteractionViewTestActivityTest.kt new file mode 100644 index 00000000000..477d5a702fc --- /dev/null +++ b/app/src/sharedTest/java/org/oppia/app/activity/InputInteractionViewTestActivityTest.kt @@ -0,0 +1,92 @@ +package org.oppia.app.activity + +import android.app.Activity +import android.content.Intent +import android.content.pm.ActivityInfo +import android.content.res.Configuration +import android.os.SystemClock +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.rule.ActivityTestRule +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.oppia.app.R +import org.oppia.app.model.InteractionObject +import androidx.test.core.app.ActivityScenario +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.typeText +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.matcher.ViewMatchers +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.oppia.app.customview.interaction.NumericInputInteractionView + +/** Tests for [InputInteractionViewTestActivity]. */ +@RunWith(AndroidJUnit4::class) +class InputInteractionViewTestActivityTest { + @get:Rule + var activityTestRule: ActivityTestRule = ActivityTestRule( + InputInteractionViewTestActivity::class.java, /* initialTouchMode= */ true, /* launchActivity= */ false + ) + private lateinit var activityScenario: ActivityScenario + + @Before + fun setUp() { + activityScenario = ActivityScenario.launch(InputInteractionViewTestActivity::class.java) + Intents.init() + } + + @Test + fun testNumericInputInteractionView_withNoInputText_hasCorrectPendingAnswerType() { + activityScenario.onActivity { activity -> + val textAnswerRetriever = + activity.findViewById(R.id.test_number_input_interaction_view) as NumericInputInteractionView + assertThat(textAnswerRetriever.getPendingAnswer()).isInstanceOf(InteractionObject::class.java) + assertThat(textAnswerRetriever.getPendingAnswer().real).isWithin(1e-5).of(0.0) + } + } + + @Test + fun testNumericInputInteractionView_withInputtedText_hasCorrectPendingAnswer() { + onView(withId(R.id.test_number_input_interaction_view)).perform(typeText("9")) + activityScenario.onActivity { activity -> + val textAnswerRetriever = + activity.findViewById(R.id.test_number_input_interaction_view) as NumericInputInteractionView + assertThat(textAnswerRetriever.getPendingAnswer()).isInstanceOf(InteractionObject::class.java) + assertThat(textAnswerRetriever.getPendingAnswer().objectTypeCase).isEqualTo(InteractionObject.ObjectTypeCase.REAL) + assertThat(textAnswerRetriever.getPendingAnswer().real).isEqualTo(9.0) + } + } + + @Test + fun testNumericInputInteractionView_withInputtedText_hasCorrectPendingAnswerWithDecimalValues() { + onView(withId(R.id.test_number_input_interaction_view)).perform(typeText("9.5")) + activityScenario.onActivity { activity -> + val textAnswerRetriever = + activity.findViewById(R.id.test_number_input_interaction_view) as NumericInputInteractionView + assertThat(textAnswerRetriever.getPendingAnswer().objectTypeCase).isEqualTo(InteractionObject.ObjectTypeCase.REAL) + assertThat(textAnswerRetriever.getPendingAnswer().real).isEqualTo(9.5) + } + } + + @Test + fun testTextInputInteractionView_withInputtedText_onConfigurationChange_hasCorrectPendingAnswer() { + onView(withId(R.id.test_number_input_interaction_view)).perform(typeText("9")) + activityScenario.onActivity { activity -> + activity.requestedOrientation = Configuration.ORIENTATION_LANDSCAPE + } + onView(withId(R.id.test_number_input_interaction_view)).check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + .check( + ViewAssertions.matches(ViewMatchers.withText("9")) + ) + activityScenario.recreate() + onView(withId(R.id.test_number_input_interaction_view)).check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + .check( + ViewAssertions.matches(ViewMatchers.withText("9")) + ) + } +}