/* * Copyright (c) 2022 Proton AG * * This file is part of Proton Mail. * * Proton Mail is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Proton Mail is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Proton Mail. If not, see https://www.gnu.org/licenses/. */ package ch.protonmail.android.compose.presentation.ui import android.content.Intent import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.launchActivity import androidx.test.espresso.Espresso.onView import androidx.test.espresso.ViewInteraction import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.replaceText import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.assertThat import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner import ch.protonmail.android.R import ch.protonmail.android.util.withProtonInputEditTextId import org.hamcrest.core.AllOf import org.junit.runner.RunWith import kotlin.test.BeforeTest import kotlin.test.Test /** * Test suite for [SetMessageExpirationActivity] */ @RunWith(AndroidJUnit4ClassRunner::class) class SetMessageExpirationActivityTest { @BeforeTest fun setup() { Intents.init() } // region inputs @Test fun noneInputIsSetCorrectly() { // given val expectedDays = 0 val expectedHours = 0 // when launchActivity(expectedDays, expectedHours) // then onNoneCheck().checkSelected() onOneHourCheck().checkNotSelected() onOneDayCheck().checkNotSelected() onThreeDaysCheck().checkNotSelected() onOneWeekCheck().checkNotSelected() onCustomCheck().checkNotSelected() onCustomPickerView().checkNotVisible() } @Test fun oneHourInputIsSetCorrectly() { // given val expectedDays = 0 val expectedHours = 1 // when launchActivity(expectedDays, expectedHours) // then onNoneCheck().checkNotSelected() onOneHourCheck().checkSelected() onOneDayCheck().checkNotSelected() onThreeDaysCheck().checkNotSelected() onOneWeekCheck().checkNotSelected() onCustomCheck().checkNotSelected() onCustomPickerView().checkNotVisible() } @Test fun oneDayInputIsSetCorrectly() { // given val expectedDays = 1 val expectedHours = 0 // when launchActivity(expectedDays, expectedHours) // then onNoneCheck().checkNotSelected() onOneHourCheck().checkNotSelected() onOneDayCheck().checkSelected() onThreeDaysCheck().checkNotSelected() onOneWeekCheck().checkNotSelected() onCustomCheck().checkNotSelected() onCustomPickerView().checkNotVisible() } @Test fun threeDaysInputIsSetCorrectly() { // given val expectedDays = 3 val expectedHours = 0 // when launchActivity(expectedDays, expectedHours) // then onNoneCheck().checkNotSelected() onOneHourCheck().checkNotSelected() onOneDayCheck().checkNotSelected() onThreeDaysCheck().checkSelected() onOneWeekCheck().checkNotSelected() onCustomCheck().checkNotSelected() onCustomPickerView().checkNotVisible() } @Test fun oneWeekInputIsSetCorrectly() { // given val expectedDays = 7 val expectedHours = 0 // when launchActivity(expectedDays, expectedHours) // then onNoneCheck().checkNotSelected() onOneHourCheck().checkNotSelected() onOneDayCheck().checkNotSelected() onThreeDaysCheck().checkNotSelected() onOneWeekCheck().checkSelected() onCustomCheck().checkNotSelected() onCustomPickerView().checkNotVisible() } // region outputs @Test fun noneResultIsSetCorrectly() { // given val expectedDays = 0 val expectedHours = 0 // when val scenario = launchActivity() onNoneView().performSelection() performSetClick() // then assertResult(scenario, expectedDays, expectedHours) } @Test fun oneHourResultIsSetCorrectly() { // given val expectedDays = 0 val expectedHours = 1 // when val scenario = launchActivity() onOneHourView().performSelection() performSetClick() // then assertResult(scenario, expectedDays, expectedHours) } @Test fun oneDayResultIsSetCorrectly() { // given val expectedDays = 1 val expectedHours = 0 // when val scenario = launchActivity() onOneDayView().performSelection() performSetClick() // then assertResult(scenario, expectedDays, expectedHours) } @Test fun threeDaysResultIsSetCorrectly() { // given val expectedDays = 3 val expectedHours = 0 // when val scenario = launchActivity() onThreeDaysView().performSelection() performSetClick() // then assertResult(scenario, expectedDays, expectedHours) } @Test fun oneWeekResultIsSetCorrectly() { // given val expectedDays = 7 val expectedHours = 0 // when val scenario = launchActivity() onOneWeekView().performSelection() performSetClick() // then assertResult(scenario, expectedDays, expectedHours) } private fun assertResult( scenario: ActivityScenario, expectedDays: Int, expectedHours: Int ) { val resultIntent = scenario.result.resultData assertThat( resultIntent, AllOf.allOf( hasExtra(ARG_SET_MESSAGE_EXPIRATION_DAYS, expectedDays), hasExtra(ARG_SET_MESSAGE_EXPIRATION_HOURS, expectedHours) ) ) } // endregion private fun launchActivity( extraExpirationDays: Int? = 0, extraExpirationHours: Int? = 0 ) = launchActivity( Intent(ApplicationProvider.getApplicationContext(), SetMessageExpirationActivity::class.java) .apply { extraExpirationDays?.let { putExtra(ARG_SET_MESSAGE_EXPIRATION_DAYS, it) } extraExpirationHours?.let { putExtra(ARG_SET_MESSAGE_EXPIRATION_HOURS, it) } } ) private fun onNoneView(): ViewInteraction = onView(withId(R.id.set_msg_expiration_none_text_view)) private fun onOneHourView(): ViewInteraction = onView(withId(R.id.set_msg_expiration_1_hour_text_view)) private fun onOneDayView(): ViewInteraction = onView(withId(R.id.set_msg_expiration_1_day_text_view)) private fun onThreeDaysView(): ViewInteraction = onView(withId(R.id.set_msg_expiration_3_days_text_view)) private fun onOneWeekView(): ViewInteraction = onView(withId(R.id.set_msg_expiration_1_week_text_view)) private fun onCustomView(): ViewInteraction = onView(withId(R.id.set_msg_expiration_custom_text_view)) private fun onNoneCheck(): ViewInteraction = onView(withId(R.id.set_msg_expiration_none_check)) private fun onOneHourCheck(): ViewInteraction = onView(withId(R.id.set_msg_expiration_1_hour_check)) private fun onOneDayCheck(): ViewInteraction = onView(withId(R.id.set_msg_expiration_1_day_check)) private fun onThreeDaysCheck(): ViewInteraction = onView(withId(R.id.set_msg_expiration_3_days_check)) private fun onOneWeekCheck(): ViewInteraction = onView(withId(R.id.set_msg_expiration_1_week_check)) private fun onCustomCheck(): ViewInteraction = onView(withId(R.id.set_msg_expiration_custom_check)) private fun onCustomPickerView(): ViewInteraction = onView(withId(R.id.set_msg_expiration_picker_view)) private fun onCustomDaysView(): ViewInteraction = onView(withProtonInputEditTextId(R.id.days_and_hours_picker_days_input)) private fun onCustomHoursView(): ViewInteraction = onView(withProtonInputEditTextId(R.id.days_and_hours_picker_hours_input)) private fun ViewInteraction.checkSelected(): ViewInteraction = checkVisible() private fun ViewInteraction.checkNotSelected(): ViewInteraction = checkNotVisible() private fun ViewInteraction.checkVisible(): ViewInteraction = check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun ViewInteraction.checkNotVisible(): ViewInteraction = check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))) private fun ViewInteraction.matchesNumberText(number: Int): ViewInteraction = check(matches(withText(number.toString()))) private fun ViewInteraction.performSelection(): ViewInteraction = perform(click()) @Suppress("SameParameterValue") private fun setCustomDaysAndHours(days: Int, hours: Int) { onCustomDaysView().perform(replaceText(days.toString())) onCustomHoursView().perform(replaceText(hours.toString())) } private fun performSetClick(): ViewInteraction = onView(withId(R.id.set_msg_expiration_set)).perform(click()) }