blob: 154db786157e379820a568f82585e7d15d831895 [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 com.google.common.truth.Truth.assertWithMessage;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Base class for an activity that has the following fields:
*
* <ul>
* <li>A DatePicker (id: date_picker)
* <li>An EditText that is filled with the DatePicker when it changes (id: output)
* <li>An OK button that finishes it and navigates to the {@link WelcomeActivity}
* </ul>
*
* <p>It's abstract because the sub-class must provide the view id, so it can support multiple
* UI types (like calendar and spinner).
*/
abstract class AbstractDatePickerActivity extends AbstractAutoFillActivity {
private static final long OK_TIMEOUT_MS = 1000;
static final String ID_DATE_PICKER = "date_picker";
static final String ID_OUTPUT = "output";
private DatePicker mDatePicker;
private EditText mOutput;
private Button mOk;
private FillExpectation mExpectation;
private CountDownLatch mOkLatch;
protected abstract int getContentView();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentView());
mDatePicker = (DatePicker) findViewById(R.id.date_picker);
mDatePicker.setOnDateChangedListener((v, y, m, d) -> updateOutputWithDate(y, m, d));
mOutput = (EditText) findViewById(R.id.output);
mOk = (Button) findViewById(R.id.ok);
mOk.setOnClickListener((v) -> ok());
}
public DatePicker getDatePicker() {
return mDatePicker;
}
private void updateOutputWithDate(int year, int month, int day) {
final String date = year + "/" + month + "/" + day;
mOutput.setText(date);
}
private void ok() {
final Intent intent = new Intent(this, WelcomeActivity.class);
intent.putExtra(WelcomeActivity.EXTRA_MESSAGE, "Good news everyone! The world didn't end!");
startActivity(intent);
if (mOkLatch != null) {
// Latch is not set when activity launched outside tests
mOkLatch.countDown();
}
finish();
}
/**
* Sets the expectation for an auto-fill request, so it can be asserted through
* {@link #assertAutoFilled()} later.
*/
void expectAutoFill(String output, int year, int month, int day) {
mExpectation = new FillExpectation(output, year, month, day);
mOutput.addTextChangedListener(mExpectation.outputWatcher);
mDatePicker.setOnDateChangedListener((v, y, m, d) -> {
updateOutputWithDate(y, m, d);
mExpectation.dateListener.onDateChanged(v, y, m, d);
});
}
/**
* Asserts the activity was auto-filled with the values passed to
* {@link #expectAutoFill(String, int, int, int)}.
*/
void assertAutoFilled() throws Exception {
assertWithMessage("expectAutoFill() not called").that(mExpectation).isNotNull();
mExpectation.outputWatcher.assertAutoFilled();
mExpectation.dateListener.assertAutoFilled();
}
/**
* Visits the {@code output} in the UiThread.
*/
void onOutput(Visitor<EditText> v) {
syncRunOnUiThread(() -> v.visit(mOutput));
}
/**
* Sets the date in the {@link DatePicker}.
*/
void setDate(int year, int month, int day) {
syncRunOnUiThread(() -> mDatePicker.updateDate(year, month, day));
}
/**
* Taps the ok button in the UI thread.
*/
void tapOk() throws Exception {
mOkLatch = new CountDownLatch(1);
syncRunOnUiThread(() -> mOk.performClick());
boolean called = mOkLatch.await(OK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
assertWithMessage("Timeout (%s ms) waiting for OK action", OK_TIMEOUT_MS)
.that(called).isTrue();
}
/**
* Holder for the expected auto-fill values.
*/
private final class FillExpectation {
private final MultipleTimesTextWatcher outputWatcher;
private final OneTimeDateListener dateListener;
private FillExpectation(String output, int year, int month, int day) {
// Output is called twice: by the DateChangeListener and by auto-fill.
outputWatcher = new MultipleTimesTextWatcher("output", 2, mOutput, output);
dateListener = new OneTimeDateListener("datePicker", mDatePicker, year, month, day);
}
}
}