blob: 8b86214b7c6f299ded198616794206b2df172bd7 [file] [log] [blame]
/*
* Copyright (C) 2018 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.contentcaptureservice.cts;
import static android.contentcaptureservice.cts.Assertions.assertDecorViewAppeared;
import static android.contentcaptureservice.cts.Assertions.assertRightActivity;
import static android.contentcaptureservice.cts.Assertions.assertSessionId;
import static android.contentcaptureservice.cts.Assertions.assertSessionResumed;
import static android.contentcaptureservice.cts.Assertions.assertViewAppeared;
import static android.contentcaptureservice.cts.Assertions.assertViewTreeFinished;
import static android.contentcaptureservice.cts.Assertions.assertViewTreeStarted;
import static android.contentcaptureservice.cts.Assertions.assertViewsOptionallyDisappeared;
import static com.google.common.truth.Truth.assertThat;
import android.contentcaptureservice.cts.CtsContentCaptureService.Session;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.autofill.AutofillId;
import android.view.contentcapture.ContentCaptureEvent;
import android.view.contentcapture.ContentCaptureSessionId;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import java.util.List;
public class LoginActivity extends AbstractRootViewActivity {
private static final String TAG = LoginActivity.class.getSimpleName();
/**
* Mininum number of events generated when the activity starts.
*
* <p>Used on {@link #assertInitialViewsAppeared(Session, int)} and
* {@link #assertInitialViewsDisappeared(List, int)}.
*/
public static final int MIN_EVENTS = 11;
TextView mUsernameLabel;
EditText mUsername;
TextView mPasswordLabel;
EditText mPassword;
@Override
protected void setContentViewOnCreate(Bundle savedInstanceState) {
setContentView(R.layout.login_activity);
mUsernameLabel = findViewById(R.id.username_label);
mUsername = findViewById(R.id.username);
mPasswordLabel = findViewById(R.id.password_label);
mPassword = findViewById(R.id.password);
}
@Override
public void assertDefaultEvents(@NonNull Session session) {
final int additionalEvents = 0;
final List<ContentCaptureEvent> events = assertInitialViewsAppeared(session,
additionalEvents);
assertInitialViewsDisappeared(events, additionalEvents);
}
/**
* Asserts the events generated when this activity was launched, up to the
* {@code TYPE_INITIAL_VIEW_HIERARCHY_FINISHED} event.
*/
@NonNull
public List<ContentCaptureEvent> assertInitialViewsAppeared(@NonNull Session session,
int additionalEvents) {
final List<ContentCaptureEvent> events = assertJustInitialViewsAppeared(session,
additionalEvents);
assertViewTreeFinished(events, MIN_EVENTS - 1);
return events;
}
/**
* Asserts the events generated when this activity was launched, but without the
* {@code TYPE_INITIAL_VIEW_HIERARCHY_FINISHED} event.
*/
@NonNull
public List<ContentCaptureEvent> assertJustInitialViewsAppeared(@NonNull Session session,
int additionalEvents) {
assertBaseInformation(session);
final LoginActivity activity = this;
final ContentCaptureSessionId sessionId = session.id;
final List<ContentCaptureEvent> events = session.getEvents();
Log.v(TAG, "events(" + events.size() + "): " + events);
// TODO(b/123540067): ideally it should be X so it reflects just the views defined
// in the layout - right now it's generating events for 2 intermediate parents
// (android:action_mode_bar_stub and android:content), we should try to create an
// activity without them
final AutofillId rootId = activity.getRootView().getAutofillId();
assertThat(events.size()).isAtLeast(MIN_EVENTS + additionalEvents);
// TODO(b/123540067): get rid of those intermediated parents
final View grandpa1 = activity.getGrandParent();
final View grandpa2 = activity.getGrandGrandParent();
final View decorView = activity.getDecorView();
final View rootView = activity.getRootView();
assertSessionResumed(events, 0);
assertViewTreeStarted(events, 1);
assertDecorViewAppeared(events, 2, decorView);
assertViewAppeared(events, 3, grandpa2, decorView.getAutofillId());
assertViewAppeared(events, 4, grandpa1, grandpa2.getAutofillId());
assertViewAppeared(events, 5, sessionId, rootView, grandpa1.getAutofillId());
assertViewAppeared(events, 6, sessionId, activity.mUsernameLabel, rootId);
assertViewAppeared(events, 7, sessionId, activity.mUsername, rootId);
assertViewAppeared(events, 8, sessionId, activity.mPasswordLabel, rootId);
assertViewAppeared(events, 9, sessionId, activity.mPassword, rootId);
return events;
}
/**
* Asserts the events generated when this activity was launched, up to the
* {@code TYPE_INITIAL_VIEW_HIERARCHY_FINISHED} event.
*/
@NonNull
public EventsAssertor assertInitialViewsAppeared(@NonNull Session session) {
assertBaseInformation(session);
final LoginActivity activity = this;
final ContentCaptureSessionId sessionId = session.id;
final List<ContentCaptureEvent> events = session.getEvents();
Log.v(TAG, "events(" + events.size() + "): " + events);
final AutofillId rootId = activity.getRootView().getAutofillId();
final View grandpa1 = activity.getGrandParent();
final View grandpa2 = activity.getGrandGrandParent();
final View decorView = activity.getDecorView();
final View rootView = activity.getRootView();
EventsAssertor assertor = new EventsAssertor(events);
assertor.isAtLeast(MIN_EVENTS)
.assertSessionResumed()
.assertViewTreeStarted()
.assertDecorViewAppeared(decorView)
.assertViewAppeared(grandpa2, decorView.getAutofillId())
.assertViewAppeared(grandpa1, grandpa2.getAutofillId())
.assertViewAppeared(sessionId, rootView, grandpa1.getAutofillId())
.assertViewAppeared(sessionId, activity.mUsernameLabel, rootId)
.assertViewAppeared(sessionId, activity.mUsername, rootId)
.assertViewAppeared(sessionId, activity.mPasswordLabel, rootId)
.assertViewAppeared(sessionId, activity.mPassword, rootId)
.assertViewTreeFinished();
return assertor;
}
private void assertBaseInformation(@NonNull Session session) {
final LoginActivity activity = this;
final ContentCaptureSessionId sessionId = session.id;
assertRightActivity(session, sessionId, activity);
assertSessionId(sessionId, activity.mUsernameLabel);
assertSessionId(sessionId, activity.mUsername);
assertSessionId(sessionId, activity.mPassword);
assertSessionId(sessionId, activity.mPasswordLabel);
}
/**
* Asserts the initial views disappeared after the activity was finished.
*/
public void assertInitialViewsDisappeared(@NonNull List<ContentCaptureEvent> events,
int additionalEvents) {
// TODO(b/122315042): this method is currently a mess, so let's disable for now and properly
// fix these assertions later...
if (true) return;
final LoginActivity activity = this;
final AutofillId rootId = activity.getRootView().getAutofillId();
final View decorView = activity.getDecorView();
final View grandpa1 = activity.getGrandParent();
final View grandpa2 = activity.getGrandGrandParent();
// Besides the additional events from the test case, we also need to account for the
final int i = MIN_EVENTS + additionalEvents;
assertViewTreeStarted(events, i);
// TODO(b/122315042): sometimes we get decor view disappareared events, sometimes we don't
// As we don't really care about those, let's fix it!
try {
assertViewsOptionallyDisappeared(events, i + 1,
rootId,
grandpa1.getAutofillId(), grandpa2.getAutofillId(),
activity.mUsernameLabel.getAutofillId(), activity.mUsername.getAutofillId(),
activity.mPasswordLabel.getAutofillId(), activity.mPassword.getAutofillId());
} catch (AssertionError e) {
Log.e(TAG, "Hack-ignoring assertion without decor view: " + e);
// Try again removing it...
assertViewsOptionallyDisappeared(events, i + 1,
rootId,
grandpa1.getAutofillId(), grandpa2.getAutofillId(),
decorView.getAutofillId(),
activity.mUsernameLabel.getAutofillId(), activity.mUsername.getAutofillId(),
activity.mPasswordLabel.getAutofillId(), activity.mPassword.getAutofillId());
}
assertViewTreeFinished(events, i + 2);
}
/**
* Asserts the initial views disappeared after the activity was finished.
*/
public void assertInitialViewsDisappeared(@NonNull EventsAssertor assertor) {
final LoginActivity activity = this;
final AutofillId rootId = activity.getRootView().getAutofillId();
final View decorView = activity.getDecorView();
final View grandpa1 = activity.getGrandParent();
final View grandpa2 = activity.getGrandGrandParent();
assertor.assertViewTreeStarted()
.assertViewDisappeared(
rootId, grandpa1.getAutofillId(), grandpa2.getAutofillId(),
decorView.getAutofillId(),
activity.mUsernameLabel.getAutofillId(), activity.mUsername.getAutofillId(),
activity.mPasswordLabel.getAutofillId(), activity.mPassword.getAutofillId())
.assertViewTreeFinished();
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "AutofillIds: " + "usernameLabel=" + mUsernameLabel.getAutofillId()
+ ", username=" + mUsername.getAutofillId()
+ ", passwordLabel=" + mPasswordLabel.getAutofillId()
+ ", password=" + mPassword.getAutofillId());
}
}