/* * Copyright 2015 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.samples.apps.iosched.myschedule; import android.content.res.TypedArray; import android.support.test.InstrumentationRegistry; import android.support.test.filters.FlakyTest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.Suppress; import com.google.samples.apps.iosched.R; import com.google.samples.apps.iosched.model.ScheduleItem; import com.google.samples.apps.iosched.settings.SettingsUtils; import com.google.samples.apps.iosched.testutils.MatchersHelper; import com.google.samples.apps.iosched.util.TimeUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import static android.support.test.espresso.Espresso.onData; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; /** * UI tests for {@link MyScheduleActivity} interacting with other activities (adding/removing * session from schedule), when the user is attending the conference and the conference starts in 3 * hours. * <p/> * This should be run on devices with a narrow layout only (phones all orientation, tablets in * portrait mode) */ @RunWith(AndroidJUnit4.class) @LargeTest public class MyScheduleActivity_InteractionsTest { @Rule public ActivityTestRule<MyScheduleActivity> mActivityRule = new ActivityTestRule<>( MyScheduleActivity.class); @Before public void setStartTimeAndDisableReminders() { // Set up time to 3 hours before conference TimeUtils.setCurrentTimeRelativeToStartOfConference( InstrumentationRegistry.getTargetContext(), TimeUtils.HOUR * 3); // Don't show notifications for sessions as they get in the way of the UI SettingsUtils.setShowSessionReminders(InstrumentationRegistry.getTargetContext(), false); } /** * This will fail if there is no free slot with available sessions. Due to the fact it interacts * with other screens that manipulate the schedule, it cannot be written with the {@link * StubMyScheduleModel}, as this model always returns the same schedule items. */ @Test @Suppress // Test isn't deterministic when run as part of the full test suite. public void addEventToMySchedule_Flaky() { // Given a free slot with available sessions findFreeSlotWithAvailableSessions(); // When adding the first available session String title = addFirstAvailableSession(); // Then the session is shown onView(withText(title)).check(matches(isDisplayed())); // Clean up removeSessionFromSchedule(title); } /** * This will fail if there is no free slot with available sessions. Due to the fact it interacts * with other screens that manipulate the schedule, it cannot be written with the {@link * StubMyScheduleModel}, as this model always returns the same schedule items. */ @Test @Suppress // Test isn't deterministic when run as part of the full test suite. public void removeEventToMySchedule_Flaky() { // Given a session in the schedule findFreeSlotWithAvailableSessions(); String title = addFirstAvailableSession(); onView(withText(title)).check(matches(isDisplayed())); // When the session is removed removeSessionFromSchedule(title); // Then the session is not shown anymore onView(withText(title)).check(matches(not(isDisplayed()))); } /** * This finds the first free slow with available session and click on "Browse sessions" so the * list of available sessions is now displayed */ private void findFreeSlotWithAvailableSessions() { TypedArray ids = InstrumentationRegistry.getTargetContext().getResources() .obtainTypedArray(R.array.myschedule_listview_ids); int listViewId = ids.getResourceId(1, 0); onData(allOf(is(instanceOf(ScheduleItem.class)), new FirstFreeSlotWithAvailableSessionsMatcher())) .inAdapterView(withId(listViewId)).onChildView(withId(R.id.browse_sessions)) .perform(click()); } /** * This assumes that the screen shows a list of available sessions. It adds the first one to the * schedule then goes back to the schedule screen. * * @return the title of the session that was added */ private String addFirstAvailableSession() { onData(is(instanceOf(Integer.class))).inAdapterView(withId(R.id.sessions_list)) .atPosition(0).perform(click()); // Session details screen String title = MatchersHelper.getText(withId(R.id.session_title)); onView(withId(R.id.add_schedule_button)).perform(click()); onView(withContentDescription(InstrumentationRegistry.getTargetContext() .getString( R.string.close_and_go_back))) .perform(click()); onView(withContentDescription(InstrumentationRegistry.getTargetContext() .getString( R.string.close_and_go_back))) .perform(click()); return title; } private void removeSessionFromSchedule(String sessionTitle) { onView(withText(sessionTitle)).perform(click()); onView(withId(R.id.add_schedule_button)).perform(click()); onView(withContentDescription(InstrumentationRegistry.getTargetContext() .getString( R.string.close_and_go_back))) .perform(click()); } }