/*******************************************************************************
* Copyright 2011 The Regents of the University of California
*
* 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 org.ohmage.activity.test;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.jayway.android.robotium.solo.Solo;
import org.ohmage.OhmageApplication;
import org.ohmage.R;
import org.ohmage.activity.DashboardActivity;
import org.ohmage.activity.ResponseHistoryActivity;
import org.ohmage.activity.ResponseInfoActivity;
import org.ohmage.activity.ResponseListActivity;
import org.ohmage.db.DbContract;
import org.ohmage.db.DbContract.Campaigns;
import org.ohmage.db.DbContract.Surveys;
import org.ohmage.db.Models.Campaign;
import org.ohmage.db.Models.Response;
import org.ohmage.db.Models.Survey;
import org.ohmage.db.test.CampaignCursor;
import org.ohmage.db.test.DelegatingMockContentProvider;
import org.ohmage.db.test.EmptyMockCursor;
import org.ohmage.db.test.OhmageUriMatcher;
import org.ohmage.db.test.ResponseCursor;
import org.ohmage.db.test.SurveyCursor;
import org.ohmage.feedback.visualization.MapViewItemizedOverlay;
import org.ohmage.fragments.ResponseMapFragment;
import org.ohmage.service.SurveyGeotagService;
import org.ohmage.ui.OhmageFilterable.CampaignFilter;
import org.ohmage.ui.OhmageFilterable.CampaignSurveyFilter;
import org.ohmage.ui.OhmageFilterable.TimeFilter;
import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.test.ActivityInstrumentationTestCase2;
import android.test.mock.MockContentResolver;
import android.text.format.DateUtils;
import android.widget.FrameLayout;
import java.text.SimpleDateFormat;
import java.util.Calendar;
/**
* <p>This class contains tests for the {@link ResponseHistoryActivity}</p>
*
* <p> TODO: check starting with the campaign and survey specified in the intent </p>
*
* <h2>The data passed by the content provider</h2>
* <p>for campaigns is always 4 Campaigns with name=Campaign #X and urn=urn:campaign:X</p>
*
* for surveys
* <ul>
* <li>4 Surveys with title=Survey #X and id=Survey #X for all surveys except for Campaign #1</li>
* <li>4 Surveys with title=Campaign 1 S#X for all surveys for Campaign #1</li>
* </ul>
*
* for responses
* <ul>
* <li>8 responses with the first response having no location</li>
* <li>4 responses with the time of today, yesterday, the day before that and the day before that with a campaign filter</li>
* <li>2 responses with the time of today, and yesterday with a campaign and survey filter</li>
* <li>2 responses a month ago with a campaign and Survey #3</li>
* </ul>
*
* @author cketcham
*
*/
public class ResponseHistoryTest extends ActivityInstrumentationTestCase2<ResponseHistoryActivity> {
private Solo solo;
private DelegatingMockContentProvider provider;
Campaign[] campaigns = new Campaign[4];
{
for(int i=0; i< campaigns.length; i++) {
campaigns[i] = new Campaign();
campaigns[i].mName = "Campaign #" + i;
campaigns[i].mUrn = "urn:campaign:" + i;
}
}
Survey[] surveys = new Survey[4];
{
for(int i=0; i< surveys.length; i++) {
surveys[i] = new Survey();
surveys[i].mTitle = "Survey #" + i;
surveys[i].mSurveyID = "Survey #" + i;
}
}
/** Surveys specifically for Campaign #1 */
Survey[] surveys1 = new Survey[4];
{
for(int i=0; i< surveys.length; i++) {
surveys1[i] = new Survey();
surveys1[i].mTitle = "Campaign 1 S#" + i;
}
}
Response[] responses = new Response[4];
{
responses[0] = new Response();
responses[0].locationStatus = SurveyGeotagService.LOCATION_UNAVAILABLE;
}
/** responses specifically for a Campaign and Survey Filter */
Response[] responses2 = new Response[2];
{
for(int i=0; i< responses2.length; i++) {
responses2[i] = new Response();
responses2[i].time = Calendar.getInstance().getTimeInMillis() - DateUtils.DAY_IN_MILLIS * i;
}
}
/** responses specifically for a Campaign Filter */
Response[] responses4 = new Response[4];
{
for(int i=0; i< responses4.length; i++) {
responses4[i] = new Response();
responses4[i].time = Calendar.getInstance().getTimeInMillis() - DateUtils.DAY_IN_MILLIS * i;
}
}
public ResponseHistoryTest() {
super(ResponseHistoryActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
getInstrumentation().waitForIdleSync();
MockContentResolver fake = new MockContentResolver();
provider = new DelegatingMockContentProvider(OhmageApplication.getContext(), DbContract.CONTENT_AUTHORITY) {
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
switch(OhmageUriMatcher.getMatcher().match(uri)) {
case OhmageUriMatcher.CAMPAIGNS:
return new CampaignCursor(projection, campaigns);
case OhmageUriMatcher.CAMPAIGN_SURVEYS:
if(Campaigns.getCampaignUrn(uri).equals("urn:campaign:1"))
return new SurveyCursor(projection, surveys1);
return new SurveyCursor(projection, surveys);
case OhmageUriMatcher.RESPONSES:
return new ResponseCursor(projection, new Response[8]);
case OhmageUriMatcher.CAMPAIGN_RESPONSES:
return new ResponseCursor(projection, responses4);
case OhmageUriMatcher.CAMPAIGN_SURVEY_RESPONSES:
if(Surveys.getSurveyId(uri).equals("Survey #3") && selection != null)
return new EmptyMockCursor();
return new ResponseCursor(projection, responses2);
case OhmageUriMatcher.RESPONSE_BY_PID:
return new ResponseCursor(projection);
default:
return new EmptyMockCursor();
}
}
};
provider.addToContentResolver(fake);
OhmageApplication.setFakeContentResolver(fake);
solo = new Solo(getInstrumentation(), getActivity());
}
@Override
protected void tearDown() throws Exception{
try {
solo.finalize();
} catch (Throwable e) {
e.printStackTrace();
}
getActivity().finish();
super.tearDown();
}
public void testPreconditions() {
solo.assertCurrentActivity("expected response history", ResponseHistoryActivity.class);
}
public void testFilterBar() {
solo.clickOnText("All Campaigns");
solo.clickOnText("Campaign #2");
assertTrue(solo.searchText("Campaign #2"));
solo.clickOnText("All Surveys");
}
public void testCampaignSurveyArrows() {
// click left Campaign button
solo.clickOnButton(0);
assertTrue(solo.searchText("All Campaigns"));
// click right Campaign button
solo.clickOnButton(2);
assertTrue(solo.searchText("Campaign #0"));
// click left Survey button
solo.clickOnButton(3);
assertTrue(solo.searchText("All Surveys"));
// click right Survey button
solo.clickOnButton(5);
assertTrue(solo.searchText("Survey #0"));
}
public void testMonthArrows() {
Calendar c = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("MMMM yyy");
assertTrue(solo.searchText(format.format(c.getTime())));
c.add(Calendar.MONTH, -1);
solo.clickOnButton(6);
assertTrue(solo.searchText(format.format(c.getTime())));
c.add(Calendar.MONTH, 1);
solo.clickOnButton(8);
assertTrue(solo.searchText(format.format(c.getTime())));
c.add(Calendar.MONTH, 1);
solo.clickOnButton(8);
assertTrue(solo.searchText(format.format(c.getTime())));
}
public void testCampaignFilterContainsAllCampaigns() {
solo.clickOnText("All Campaigns");
for(Campaign c : campaigns)
assertTrue(solo.searchText(c.mName));
}
/**
* First chooses campaign #0 and checks for the correct surveys
* Then chooses campaign #1 and checks for the correct surveys
* @throws InterruptedException
*/
public void testSurveyFilterContainsCorrectSurveys() throws InterruptedException {
solo.clickOnButton(2);
assertTrue(solo.searchText("Campaign #0"));
solo.clickOnText("All Surveys");
for(Survey s : surveys)
assertTrue(solo.searchText(s.mTitle));
solo.goBack();
solo.clickOnButton(2);
assertTrue(solo.searchText("Campaign #1"));
solo.clickOnText("All Surveys");
for(Survey s : surveys1)
assertTrue(solo.searchText(s.mTitle));
for(Survey s : surveys)
assertFalse(solo.searchText(s.mTitle));
}
/**
* Tests that the filters persist when changing from calendar to mapview or back
*/
public void testFilterPersistance() {
solo.clickOnText("All Campaigns");
solo.clickOnText("Campaign #2");
solo.clickOnText("All Surveys");
solo.clickOnText("Survey #2");
assertTrue(solo.searchText("Survey #2"));
solo.clickOnText("MAP");
assertTrue(solo.searchText("Campaign #2"));
assertTrue(solo.searchText("Survey #2"));
solo.clickOnText("CALENDAR");
assertTrue(solo.searchText("Campaign #2"));
assertTrue(solo.searchText("Survey #2"));
}
public void testResponseCounts() {
// Search for the totals for this month and totals
assertTrue(solo.searchText("8 / Total: 8"));
solo.clickOnText("All Campaigns");
solo.clickOnText("Campaign #2");
assertTrue(solo.searchText("Campaign #2"));
assertTrue(solo.searchText("4 / Total: 4"));
solo.clickOnText("All Surveys");
solo.clickOnText("Survey #2");
assertTrue(solo.searchText("Survey #2"));
assertTrue(solo.searchText("2 / Total: 2"));
solo.clickOnButton(5);
assertTrue(solo.searchText("Survey #3"));
assertTrue(solo.searchText("0 / Total: 2"));
}
public void testShowResponseList() {
// Look for the 8 responses on the 31st
solo.clickOnText("^31$");
solo.assertCurrentActivity("Expected Response List", ResponseListActivity.class);
Bundle extras = solo.getCurrentActivity().getIntent().getExtras();
assertEquals(31, extras.getInt(TimeFilter.EXTRA_DAY, -1));
assertEquals(Calendar.getInstance().get(Calendar.MONTH), extras.getInt(TimeFilter.EXTRA_MONTH, -1));
assertEquals(Calendar.getInstance().get(Calendar.YEAR), extras.getInt(TimeFilter.EXTRA_YEAR, -1));
assertNull(extras.getString(CampaignFilter.EXTRA_CAMPAIGN_URN));
assertNull(extras.getString(CampaignSurveyFilter.EXTRA_SURVEY_ID));
solo.goBack();
}
public void testShowResponseListWithCampaign() {
solo.clickOnText("All Campaigns");
solo.clickOnText("Campaign #2");
assertTrue(solo.searchText("Campaign #2"));
// Click on today
solo.clickOnText("^" + Calendar.getInstance().get(Calendar.DATE) + "$");
solo.assertCurrentActivity("Expected Response List", ResponseListActivity.class);
Bundle extras = solo.getCurrentActivity().getIntent().getExtras();
assertEquals(Calendar.getInstance().get(Calendar.DATE), extras.getInt(TimeFilter.EXTRA_DAY, -1));
assertEquals(Calendar.getInstance().get(Calendar.MONTH), extras.getInt(TimeFilter.EXTRA_MONTH, -1));
assertEquals(Calendar.getInstance().get(Calendar.YEAR), extras.getInt(TimeFilter.EXTRA_YEAR, -1));
assertEquals("urn:campaign:2", extras.getString(CampaignFilter.EXTRA_CAMPAIGN_URN));
assertNull(extras.getString(CampaignSurveyFilter.EXTRA_SURVEY_ID));
solo.goBack();
}
public void testShowResponseListWithCampaignAndSurvey() {
solo.clickOnText("All Campaigns");
solo.clickOnText("Campaign #2");
solo.clickOnText("All Surveys");
solo.clickOnText("Survey #2");
// Click on today
solo.clickOnText("^" + Calendar.getInstance().get(Calendar.DATE) + "$");
solo.assertCurrentActivity("Expected Response List", ResponseListActivity.class);
Bundle extras = solo.getCurrentActivity().getIntent().getExtras();
assertEquals(Calendar.getInstance().get(Calendar.DATE), extras.getInt(TimeFilter.EXTRA_DAY, -1));
assertEquals(Calendar.getInstance().get(Calendar.MONTH), extras.getInt(TimeFilter.EXTRA_MONTH, -1));
assertEquals(Calendar.getInstance().get(Calendar.YEAR), extras.getInt(TimeFilter.EXTRA_YEAR, -1));
assertEquals("urn:campaign:2", extras.getString(CampaignFilter.EXTRA_CAMPAIGN_URN));
assertEquals("Survey #2", extras.getString(CampaignSurveyFilter.EXTRA_SURVEY_ID));
solo.goBack();
}
/**
* A few random dates with no responses on them. It would take a lot longer to check all of them...
*/
public void testDontShowResponseList() {
solo.clickOnText("^1$");
solo.assertCurrentActivity("Expected to stay on Response History", ResponseHistoryActivity.class);
solo.clickOnText("^7$");
solo.assertCurrentActivity("Expected to stay on Response History", ResponseHistoryActivity.class);
}
private MapView getFragmentMapView() {
Fragment fragment = ((ResponseHistoryActivity) solo.getCurrentActivity()).getCurrentFragment();
assertEquals(ResponseMapFragment.class, fragment.getClass());
ResponseMapFragment mapFragment = (ResponseMapFragment) fragment;
return ((MapView)((FrameLayout)mapFragment.getView().findViewById(R.id.mapview)).getChildAt(0));
}
private int countMapPins() {
int count = 0;
for(Overlay overlay: getFragmentMapView().getOverlays()) {
count += ((MapViewItemizedOverlay)overlay).size();
}
return count;
}
public void testMapShowsPins() {
solo.clickOnText("MAP");
assertEquals(8, countMapPins());
}
public void testMapShowsPins2() {
solo.clickOnText("MAP");
solo.clickOnText("All Campaigns");
solo.clickOnText("Campaign #2");
assertEquals(4, countMapPins());
solo.clickOnText("All Surveys");
solo.clickOnText("Survey #2");
assertEquals(2, countMapPins());
}
public void testRightArrowShowsPopup() {
solo.clickOnText("MAP");
// click on the right arrow
solo.clickOnText(">", 4);
assertTrue(solo.searchText("urn:mock:campaign", true));
assertTrue(solo.searchText("1/8", true));
// click on the X
solo.clickOnImage(3);
assertFalse(solo.searchText("urn:mock:campaign", true));
assertFalse(solo.searchText("1/8", true));
}
public void testRightArrowShowsPopup2() {
solo.clickOnText("MAP");
// click on the right arrow
solo.clickOnText(">", 4);
solo.clickOnText(">", 4);
assertTrue(solo.searchText("urn:mock:campaign", true));
assertTrue(solo.searchText("2/8", true));
// click on the X
solo.clickOnImage(3);
assertFalse(solo.searchText("urn:mock:campaign", true));
assertFalse(solo.searchText("2/8", true));
}
public void testLeftArrowShowsNothing() {
solo.clickOnText("MAP");
// click on the left arrow
solo.clickOnText("<", 4);
assertFalse(solo.searchText("urn:mock:campaign"));
assertFalse(solo.searchText("1/8"));
}
public void testRightArrowAll() {
solo.clickOnText("MAP");
// click on the right arrow
for(int i=0;i<8;i++)
solo.clickOnText(">", 4);
assertTrue(solo.searchText("urn:mock:campaign", true));
assertTrue(solo.searchText("8/8", true));
solo.clickOnText(">", 4);
assertTrue(solo.searchText("urn:mock:campaign", true));
assertTrue(solo.searchText("8/8", true));
for(int i=0;i<7;i++)
solo.clickOnText("<", 4);
assertTrue(solo.searchText("urn:mock:campaign", true));
assertTrue(solo.searchText("1/8", true));
solo.clickOnText("<", 4);
assertTrue(solo.searchText("urn:mock:campaign", true));
assertTrue(solo.searchText("1/8", true));
}
public void testIndexCount() {
solo.clickOnText("MAP");
solo.clickOnText("All Campaigns");
solo.clickOnText("Campaign #2");
// click on the right arrow
solo.clickOnText(">", 4);
assertTrue(solo.searchText("1/4", true));
}
public void testClickBalloon() {
solo.clickOnText("MAP");
// click on the right arrow
solo.clickOnText(">", 4);
solo.clickOnText("urn:mock:campaign");
solo.assertCurrentActivity("Expected response info activity", ResponseInfoActivity.class);
assertEquals(1, ContentUris.parseId(solo.getCurrentActivity().getIntent().getData()));
solo.goBack();
}
public void testZoom() {
solo.clickOnText("MAP");
getInstrumentation().waitForIdleSync();
int zoomLevel = getFragmentMapView().getZoomLevel();
solo.clickOnText("\\-");
getInstrumentation().waitForIdleSync();
assertTrue(zoomLevel > getFragmentMapView().getZoomLevel());
solo.clickOnText("\\+");
assertEquals(zoomLevel, getFragmentMapView().getZoomLevel());
}
public void testHomeButton() {
solo.clickOnImageButton(0);
solo.assertCurrentActivity("Expected Dashboard", DashboardActivity.class);
solo.goBack();
}
}