blob: 6ba5431e0b05afaefa8c39801b0ca92c82e1981d [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 android.autofillservice.cts;
import static android.autofillservice.cts.CheckoutActivity.ID_ADDRESS;
import static android.autofillservice.cts.CheckoutActivity.ID_CC_EXPIRATION;
import static android.autofillservice.cts.CheckoutActivity.ID_CC_NUMBER;
import static android.autofillservice.cts.CheckoutActivity.ID_HOME_ADDRESS;
import static android.autofillservice.cts.CheckoutActivity.ID_SAVE_CC;
import static android.autofillservice.cts.CheckoutActivity.ID_WORK_ADDRESS;
import static android.autofillservice.cts.CheckoutActivity.INDEX_ADDRESS_WORK;
import static android.autofillservice.cts.CheckoutActivity.INDEX_CC_EXPIRATION_NEVER;
import static android.autofillservice.cts.CheckoutActivity.INDEX_CC_EXPIRATION_TODAY;
import static android.autofillservice.cts.CheckoutActivity.INDEX_CC_EXPIRATION_TOMORROW;
import static android.autofillservice.cts.Helper.assertListValue;
import static android.autofillservice.cts.Helper.assertTextAndValue;
import static android.autofillservice.cts.Helper.assertTextIsSanitized;
import static android.autofillservice.cts.Helper.assertToggleIsSanitized;
import static android.autofillservice.cts.Helper.assertToggleValue;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
import static android.autofillservice.cts.Helper.getContext;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD;
import static android.view.View.AUTOFILL_TYPE_LIST;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.assist.AssistStructure.ViewNode;
import android.autofillservice.cts.CannedFillResponse.CannedDataset;
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import java.util.Arrays;
/**
* Test case for an activity containing non-TextField views.
*/
public class CheckoutActivityTest extends AutoFillServiceTestCase {
@Rule
public final AutofillActivityTestRule<CheckoutActivity> mActivityRule =
new AutofillActivityTestRule<CheckoutActivity>(CheckoutActivity.class);
private CheckoutActivity mActivity;
@Before
public void setActivity() {
mActivity = mActivityRule.getActivity();
}
@After
public void finishWelcomeActivity() {
WelcomeActivity.finishIt();
}
@Test
public void testAutofill() throws Exception {
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(new CannedDataset.Builder()
.setPresentation(createPresentation("ACME CC"))
.setField(ID_CC_NUMBER, "4815162342")
.setField(ID_CC_EXPIRATION, INDEX_CC_EXPIRATION_NEVER)
.setField(ID_ADDRESS, 1)
.setField(ID_SAVE_CC, true)
.build());
mActivity.expectAutoFill("4815162342", INDEX_CC_EXPIRATION_NEVER, R.id.work_address,
true);
// Trigger auto-fill.
mActivity.onCcNumber((v) -> v.requestFocus());
final FillRequest fillRequest = sReplier.getNextFillRequest();
// Assert properties of Spinner field.
final ViewNode ccExpirationNode =
assertTextIsSanitized(fillRequest.structure, ID_CC_EXPIRATION);
assertThat(ccExpirationNode.getClassName()).isEqualTo(Spinner.class.getName());
assertThat(ccExpirationNode.getAutofillType()).isEqualTo(AUTOFILL_TYPE_LIST);
final CharSequence[] options = ccExpirationNode.getAutofillOptions();
assertWithMessage("ccExpirationNode.getAutoFillOptions()").that(options).isNotNull();
assertWithMessage("Wrong auto-fill options for spinner").that(options).asList()
.containsExactly(
getContext().getResources().getStringArray(R.array.cc_expiration_values))
.inOrder();
// Auto-fill it.
sUiBot.selectDataset("ACME CC");
// Check the results.
mActivity.assertAutoFilled();
}
@Test
public void testAutofillDynamicAdapter() throws Exception {
// Set activity.
mActivity.onCcExpiration((v) -> v.setAdapter(new ArrayAdapter<String>(getContext(),
android.R.layout.simple_spinner_item,
Arrays.asList("YESTERDAY", "TODAY", "TOMORROW", "NEVER"))));
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(new CannedDataset.Builder()
.setPresentation(createPresentation("ACME CC"))
.setField(ID_CC_NUMBER, "4815162342")
.setField(ID_CC_EXPIRATION, INDEX_CC_EXPIRATION_NEVER)
.setField(ID_ADDRESS, 1)
.setField(ID_SAVE_CC, true)
.build());
mActivity.expectAutoFill("4815162342", INDEX_CC_EXPIRATION_NEVER, R.id.work_address,
true);
// Trigger auto-fill.
mActivity.onCcNumber((v) -> v.requestFocus());
final FillRequest fillRequest = sReplier.getNextFillRequest();
// Assert properties of Spinner field.
final ViewNode ccExpirationNode =
assertTextIsSanitized(fillRequest.structure, ID_CC_EXPIRATION);
assertThat(ccExpirationNode.getClassName()).isEqualTo(Spinner.class.getName());
assertThat(ccExpirationNode.getAutofillType()).isEqualTo(AUTOFILL_TYPE_LIST);
final CharSequence[] options = ccExpirationNode.getAutofillOptions();
assertWithMessage("ccExpirationNode.getAutoFillOptions()").that(options).isNull();
// Auto-fill it.
sUiBot.selectDataset("ACME CC");
// Check the results.
mActivity.assertAutoFilled();
}
// TODO: this should be a pure unit test exercising onProvideAutofillStructure(),
// but that would require creating a custom ViewStructure.
@Test
public void testGetAutofillOptionsSorted() throws Exception {
// Set service.
enableService();
// Set activity.
mActivity.onCcExpirationAdapter((adapter) -> adapter.sort((a, b) -> {
return ((String) a).compareTo((String) b);
}));
// Set expectations.
sReplier.addResponse(new CannedDataset.Builder()
.setPresentation(createPresentation("ACME CC"))
.setField(ID_CC_NUMBER, "4815162342")
.setField(ID_CC_EXPIRATION, INDEX_CC_EXPIRATION_NEVER)
.setField(ID_ADDRESS, 1)
.setField(ID_SAVE_CC, true)
.build());
mActivity.expectAutoFill("4815162342", INDEX_CC_EXPIRATION_NEVER, R.id.work_address,
true);
// Trigger auto-fill.
mActivity.onCcNumber((v) -> v.requestFocus());
final FillRequest fillRequest = sReplier.getNextFillRequest();
// Assert properties of Spinner field.
final ViewNode ccExpirationNode =
assertTextIsSanitized(fillRequest.structure, ID_CC_EXPIRATION);
assertThat(ccExpirationNode.getClassName()).isEqualTo(Spinner.class.getName());
assertThat(ccExpirationNode.getAutofillType()).isEqualTo(AUTOFILL_TYPE_LIST);
final CharSequence[] options = ccExpirationNode.getAutofillOptions();
assertWithMessage("Wrong auto-fill options for spinner").that(options).asList()
.containsExactly("never", "today", "tomorrow", "yesterday").inOrder();
// Auto-fill it.
sUiBot.selectDataset("ACME CC");
// Check the results.
mActivity.assertAutoFilled();
}
@Test
public void testSanitization() throws Exception {
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_CREDIT_CARD,
ID_CC_NUMBER, ID_CC_EXPIRATION, ID_ADDRESS, ID_SAVE_CC)
.build());
// Dynamically change view contents
mActivity.onCcNumber((v) -> v.setText("108"));
mActivity.onCcExpiration((v) -> v.setSelection(INDEX_CC_EXPIRATION_TOMORROW, true));
mActivity.onHomeAddress((v) -> v.setChecked(true));
mActivity.onSaveCc((v) -> v.setChecked(true));
// Trigger auto-fill.
mActivity.onCcNumber((v) -> v.requestFocus());
// Assert sanitization on fill request: everything should be sanitized!
final FillRequest fillRequest = sReplier.getNextFillRequest();
assertTextIsSanitized(fillRequest.structure, ID_CC_NUMBER);
assertTextIsSanitized(fillRequest.structure, ID_CC_EXPIRATION);
assertToggleIsSanitized(fillRequest.structure, ID_HOME_ADDRESS);
assertToggleIsSanitized(fillRequest.structure, ID_SAVE_CC);
// Trigger save.
mActivity.onCcNumber((v) -> v.setText("4815162342"));
mActivity.onCcExpiration((v) -> v.setSelection(INDEX_CC_EXPIRATION_TODAY));
mActivity.onAddress((v) -> v.check(R.id.work_address));
mActivity.onSaveCc((v) -> v.setChecked(false));
mActivity.tapBuy();
sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_CREDIT_CARD);
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
// Assert sanitization on save: everything should be available!
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_CC_NUMBER), "4815162342");
assertListValue(findNodeByResourceId(saveRequest.structure, ID_CC_EXPIRATION),
INDEX_CC_EXPIRATION_TODAY);
assertListValue(findNodeByResourceId(saveRequest.structure, ID_ADDRESS),
INDEX_ADDRESS_WORK);
assertToggleValue(findNodeByResourceId(saveRequest.structure, ID_HOME_ADDRESS), false);
assertToggleValue(findNodeByResourceId(saveRequest.structure, ID_WORK_ADDRESS), true);
assertToggleValue(findNodeByResourceId(saveRequest.structure, ID_SAVE_CC), false);
}
}