fix: 引入Settings的Module
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 com.android.settings.panel;
|
||||
|
||||
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Fake PanelContent for testing.
|
||||
*/
|
||||
public class FakePanelContent implements PanelContent {
|
||||
|
||||
public static final String FAKE_ACTION = "fake_action";
|
||||
|
||||
public static final CharSequence TITLE = "title";
|
||||
|
||||
public static final List<Uri> SLICE_URIS = Arrays.asList(
|
||||
WIFI_SLICE_URI
|
||||
);
|
||||
|
||||
public static final Intent INTENT = new Intent();
|
||||
|
||||
private CharSequence mTitle = TITLE;
|
||||
private CharSequence mSubTitle;
|
||||
private IconCompat mIcon;
|
||||
private int mViewType;
|
||||
private boolean mIsCustomizedButtonUsed = false;
|
||||
private CharSequence mCustomizedButtonTitle;
|
||||
private boolean mIsProgressBarVisible;
|
||||
|
||||
@Override
|
||||
public IconCompat getIcon() {
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
public void setIcon(IconCompat icon) {
|
||||
mIcon = icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSubTitle() {
|
||||
return mSubTitle;
|
||||
}
|
||||
|
||||
public void setSubTitle(CharSequence subTitle) {
|
||||
mSubTitle = subTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public void setTitle(CharSequence title) {
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Uri> getSlices() {
|
||||
return SLICE_URIS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getSeeMoreIntent() {
|
||||
return INTENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.TESTING;
|
||||
}
|
||||
|
||||
public void setViewType(int viewType) {
|
||||
mViewType = viewType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewType() {
|
||||
return mViewType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomizedButtonUsed() {
|
||||
return mIsCustomizedButtonUsed;
|
||||
}
|
||||
|
||||
public void setIsCustomizedButtonUsed(boolean isUsed) {
|
||||
mIsCustomizedButtonUsed = isUsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCustomizedButtonTitle() {
|
||||
return mCustomizedButtonTitle;
|
||||
}
|
||||
|
||||
public void setCustomizedButtonTitle(CharSequence title) {
|
||||
mCustomizedButtonTitle = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProgressBarVisible() {
|
||||
return mIsProgressBarVisible;
|
||||
}
|
||||
|
||||
public void setIsProgressBarVisible(boolean isProgressBarVisible) {
|
||||
mIsProgressBarVisible = isProgressBarVisible;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 com.android.settings.panel;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
|
||||
public class FakeSettingsPanelActivity extends SettingsPanelActivity {
|
||||
@Override
|
||||
public ComponentName getCallingActivity() {
|
||||
return new ComponentName("fake-package", "fake-class");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
final Intent intent = new Intent(FakePanelContent.FAKE_ACTION);
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* 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 com.android.settings.panel;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Ignore("b/313576125")
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(LooperMode.Mode.LEGACY)
|
||||
@Config(shadows = {
|
||||
com.android.settings.testutils.shadow.ShadowFragment.class,
|
||||
})
|
||||
public class PanelFragmentTest {
|
||||
|
||||
private static final String TITLE = "title";
|
||||
private static final String TITLE2 = "title2";
|
||||
private static final String SUBTITLE = "subtitle";
|
||||
private static final String SUBTITLE2 = "subtitle2";
|
||||
|
||||
private Context mContext;
|
||||
private PanelFragment mPanelFragment;
|
||||
private FakeSettingsPanelActivity mActivity;
|
||||
private FakeFeatureFactory mFakeFeatureFactory;
|
||||
private PanelFeatureProvider mPanelFeatureProvider;
|
||||
private FakePanelContent mFakePanelContent;
|
||||
private ArgumentCaptor<PanelContentCallback> mPanelContentCbs = ArgumentCaptor.forClass(
|
||||
PanelContentCallback.class);
|
||||
|
||||
private final String FAKE_EXTRA = "fake_extra";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
|
||||
mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
|
||||
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
|
||||
mFakePanelContent = spy(new FakePanelContent());
|
||||
doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
|
||||
}
|
||||
|
||||
private void initFakeActivity() {
|
||||
mActivity = spy(Robolectric.buildActivity(FakeSettingsPanelActivity.class).setup().get());
|
||||
|
||||
mPanelFragment =
|
||||
spy((PanelFragment)
|
||||
mActivity.getSupportFragmentManager().findFragmentById(R.id.main_content));
|
||||
doReturn(mActivity).when(mPanelFragment).getActivity();
|
||||
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT, FAKE_EXTRA);
|
||||
doReturn(bundle).when(mPanelFragment).getArguments();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreateView_countdownLatch_setup() {
|
||||
initFakeActivity();
|
||||
mPanelFragment.onCreateView(LayoutInflater.from(mContext),
|
||||
new LinearLayout(mContext), null);
|
||||
PanelSlicesLoaderCountdownLatch countdownLatch =
|
||||
mPanelFragment.mPanelSlicesLoaderCountdownLatch;
|
||||
for (Uri sliecUri : mFakePanelContent.getSlices()) {
|
||||
countdownLatch.markSliceLoaded(sliecUri);
|
||||
}
|
||||
|
||||
assertThat(countdownLatch.isPanelReadyToLoad()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_logsOpenEvent() {
|
||||
initFakeActivity();
|
||||
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
||||
0,
|
||||
SettingsEnums.PAGE_VISIBLE,
|
||||
mFakePanelContent.getMetricsCategory(),
|
||||
null,
|
||||
0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDestroy_logCloseEvent() {
|
||||
initFakeActivity();
|
||||
mPanelFragment.onDestroyView();
|
||||
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
||||
0,
|
||||
SettingsEnums.PAGE_HIDE,
|
||||
mFakePanelContent.getMetricsCategory(),
|
||||
PanelLoggingContract.PanelClosedKeys.KEY_OTHERS,
|
||||
0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void panelSeeMoreClick_logsCloseEvent() {
|
||||
initFakeActivity();
|
||||
final View.OnClickListener listener = mPanelFragment.getSeeMoreListener();
|
||||
listener.onClick(null);
|
||||
verify(mActivity).finish();
|
||||
|
||||
mPanelFragment.onDestroyView();
|
||||
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
||||
0,
|
||||
SettingsEnums.PAGE_HIDE,
|
||||
mFakePanelContent.getMetricsCategory(),
|
||||
PanelLoggingContract.PanelClosedKeys.KEY_SEE_MORE,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void panelDoneClick_logsCloseEvent() {
|
||||
initFakeActivity();
|
||||
final View.OnClickListener listener = mPanelFragment.getCloseListener();
|
||||
listener.onClick(null);
|
||||
verify(mActivity).finish();
|
||||
|
||||
mPanelFragment.onDestroyView();
|
||||
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
||||
0,
|
||||
SettingsEnums.PAGE_HIDE,
|
||||
mFakePanelContent.getMetricsCategory(),
|
||||
PanelLoggingContract.PanelClosedKeys.KEY_DONE,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportIcon_displayIconHeaderLayout() {
|
||||
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_android);
|
||||
mFakePanelContent.setIcon(icon);
|
||||
mFakePanelContent.setSubTitle(SUBTITLE);
|
||||
final ActivityController<FakeSettingsPanelActivity> activityController =
|
||||
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
|
||||
activityController.setup();
|
||||
final PanelFragment panelFragment = (PanelFragment)
|
||||
Objects.requireNonNull(activityController
|
||||
.get()
|
||||
.getSupportFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
final View titleView = panelFragment.mLayoutView.findViewById(R.id.panel_title);
|
||||
final LinearLayout panelHeader = panelFragment.mLayoutView.findViewById(R.id.panel_header);
|
||||
final TextView headerTitle = panelFragment.mLayoutView.findViewById(R.id.header_title);
|
||||
final TextView headerSubtitle = panelFragment.mLayoutView.findViewById(
|
||||
R.id.header_subtitle);
|
||||
// Check visibility
|
||||
assertThat(panelHeader.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(titleView.getVisibility()).isEqualTo(View.GONE);
|
||||
// Check content
|
||||
assertThat(headerTitle.getText()).isEqualTo(FakePanelContent.TITLE);
|
||||
assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notSupportIcon_displayDefaultHeaderLayout() {
|
||||
final ActivityController<FakeSettingsPanelActivity> activityController =
|
||||
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
|
||||
activityController.setup();
|
||||
final PanelFragment panelFragment = (PanelFragment)
|
||||
Objects.requireNonNull(activityController
|
||||
.get()
|
||||
.getSupportFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
|
||||
final View titleView = panelFragment.mLayoutView.findViewById(R.id.panel_title);
|
||||
final View panelHeader = panelFragment.mLayoutView.findViewById(R.id.panel_header);
|
||||
|
||||
assertThat(panelHeader.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onHeaderChanged_updateHeader_verifyTitle() {
|
||||
mFakePanelContent.setIcon(IconCompat.createWithResource(mContext, R.drawable.ic_android));
|
||||
mFakePanelContent.setTitle(TITLE);
|
||||
mFakePanelContent.setSubTitle(SUBTITLE);
|
||||
final ActivityController<FakeSettingsPanelActivity> activityController =
|
||||
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
|
||||
activityController.setup();
|
||||
final PanelFragment panelFragment = (PanelFragment)
|
||||
Objects.requireNonNull(activityController
|
||||
.get()
|
||||
.getSupportFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
final TextView headerTitle = panelFragment.mLayoutView.findViewById(R.id.header_title);
|
||||
final TextView headerSubtitle = panelFragment.mLayoutView.findViewById(
|
||||
R.id.header_subtitle);
|
||||
|
||||
assertThat(headerTitle.getText()).isEqualTo(TITLE);
|
||||
assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE);
|
||||
|
||||
mFakePanelContent.setTitle(TITLE2);
|
||||
mFakePanelContent.setSubTitle(SUBTITLE2);
|
||||
verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
|
||||
final PanelContentCallback panelContentCallbacks = mPanelContentCbs.getValue();
|
||||
panelContentCallbacks.onHeaderChanged();
|
||||
|
||||
assertThat(headerTitle.getText()).isEqualTo(TITLE2);
|
||||
assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forceClose_verifyFinish() {
|
||||
initFakeActivity();
|
||||
verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
|
||||
final PanelContentCallback panelContentCallbacks = spy(mPanelContentCbs.getValue());
|
||||
when(((PanelFragment.LocalPanelCallback) panelContentCallbacks).getFragmentActivity())
|
||||
.thenReturn(mActivity);
|
||||
|
||||
panelContentCallbacks.forceClose();
|
||||
|
||||
verify(mActivity).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCustomizedButtonStateChanged_isCustomized_showCustomizedTitle() {
|
||||
final ActivityController<FakeSettingsPanelActivity> activityController =
|
||||
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
|
||||
activityController.setup();
|
||||
final PanelFragment panelFragment = (PanelFragment)
|
||||
Objects.requireNonNull(activityController
|
||||
.get()
|
||||
.getSupportFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
|
||||
final Button seeMoreButton = panelFragment.mLayoutView.findViewById(R.id.see_more);
|
||||
|
||||
mFakePanelContent.setIsCustomizedButtonUsed(true);
|
||||
mFakePanelContent.setCustomizedButtonTitle("test_title");
|
||||
verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
|
||||
final PanelContentCallback panelContentCallbacks = mPanelContentCbs.getValue();
|
||||
panelContentCallbacks.onCustomizedButtonStateChanged();
|
||||
|
||||
assertThat(seeMoreButton.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
assertThat(seeMoreButton.getText()).isEqualTo("test_title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProgressBarVisibleChanged_isProgressBarVisible_showProgressBar() {
|
||||
final ActivityController<FakeSettingsPanelActivity> activityController =
|
||||
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
|
||||
activityController.setup();
|
||||
final PanelFragment panelFragment = (PanelFragment)
|
||||
Objects.requireNonNull(activityController
|
||||
.get()
|
||||
.getSupportFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
|
||||
final ProgressBar progressBar = panelFragment.mLayoutView.findViewById(R.id.progress_bar);
|
||||
|
||||
mFakePanelContent.setIsProgressBarVisible(true);
|
||||
verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
|
||||
final PanelContentCallback panelContentCallbacks = mPanelContentCbs.getValue();
|
||||
panelContentCallbacks.onProgressBarVisibleChanged();
|
||||
|
||||
assertThat(progressBar.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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 com.android.settings.panel;
|
||||
|
||||
import static com.android.settings.panel.PanelContent.VIEW_TYPE_SLIDER;
|
||||
import static com.android.settings.panel.PanelSlicesAdapter.MAX_NUM_OF_SLICES;
|
||||
import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
|
||||
import static com.android.settings.slices.CustomSliceRegistry.VOLUME_NOTIFICATION_URI;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.panel.PanelSlicesAdapter.SliceRowViewHolder;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = PanelSlicesAdapterTest.ShadowLayoutInflater.class)
|
||||
public class PanelSlicesAdapterTest {
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
private static LayoutInflater sLayoutInflater;
|
||||
|
||||
private Context mContext;
|
||||
private PanelFragment mPanelFragment;
|
||||
private PanelFeatureProvider mPanelFeatureProvider;
|
||||
private FakeFeatureFactory mFakeFeatureFactory;
|
||||
private FakePanelContent mFakePanelContent;
|
||||
private Map<Uri, LiveData<Slice>> mData = new LinkedHashMap<>();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
|
||||
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
|
||||
mFakePanelContent = new FakePanelContent();
|
||||
doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
|
||||
|
||||
ActivityController<FakeSettingsPanelActivity> activityController =
|
||||
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
|
||||
activityController.setup();
|
||||
|
||||
mPanelFragment =
|
||||
spy((PanelFragment)
|
||||
activityController
|
||||
.get()
|
||||
.getSupportFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
}
|
||||
|
||||
private void addTestLiveData(Uri uri) {
|
||||
// Create a slice to return for the LiveData
|
||||
final Slice slice = new Slice();
|
||||
final LiveData<Slice> liveData = mock(LiveData.class);
|
||||
when(liveData.getValue()).thenReturn(slice);
|
||||
mData.put(uri, liveData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edge case where fragment context is not available.
|
||||
*/
|
||||
@Test
|
||||
public void withPanelFragmentContextNull_createAdapter_noExceptionThrown() {
|
||||
when(mPanelFragment.getContext()).thenReturn(null);
|
||||
|
||||
final PanelSlicesAdapter adapter = spy(new PanelSlicesAdapter(mPanelFragment, mData, 0));
|
||||
|
||||
Assert.assertNotNull(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* ViewHolder should load and set the action label correctly.
|
||||
*/
|
||||
@Test
|
||||
public void setActionLabel_loadsActionLabel() {
|
||||
addTestLiveData(VOLUME_NOTIFICATION_URI);
|
||||
final PanelSlicesAdapter adapter = new PanelSlicesAdapter(mPanelFragment, mData, 0);
|
||||
final ViewGroup view = new FrameLayout(mContext);
|
||||
final SliceRowViewHolder viewHolder = adapter.onCreateViewHolder(view, VIEW_TYPE_SLIDER);
|
||||
|
||||
// now let's see if setActionLabel can load and set the label correctly.
|
||||
LinearLayout llRow = new LinearLayout(mContext);
|
||||
viewHolder.setActionLabel(llRow);
|
||||
|
||||
boolean isLabelSet = isActionLabelSet(llRow);
|
||||
Assert.assertTrue("Action label was not set correctly.", isLabelSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rowView the view with id row_view
|
||||
* @return whether the accessibility action label is set
|
||||
*/
|
||||
private boolean isActionLabelSet(View rowView) {
|
||||
View.AccessibilityDelegate delegate = rowView.getAccessibilityDelegate();
|
||||
if (delegate == null) {
|
||||
return false;
|
||||
}
|
||||
AccessibilityNodeInfo node = new AccessibilityNodeInfo(rowView);
|
||||
delegate.onInitializeAccessibilityNodeInfo(rowView, node);
|
||||
|
||||
boolean foundLabel = false;
|
||||
final String expectedLabel =
|
||||
mContext.getString(R.string.accessibility_action_label_panel_slice);
|
||||
for (AccessibilityNodeInfo.AccessibilityAction action : node.getActionList()) {
|
||||
if (action.equals(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK)
|
||||
&& TextUtils.equals(action.getLabel(), expectedLabel)) {
|
||||
foundLabel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return foundLabel;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sizeOfAdapter_shouldNotExceedMaxNum() {
|
||||
for (int i = 0; i < MAX_NUM_OF_SLICES + 2; i++) {
|
||||
addTestLiveData(Uri.parse("uri" + i));
|
||||
}
|
||||
|
||||
assertThat(mData.size()).isEqualTo(MAX_NUM_OF_SLICES + 2);
|
||||
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0 /* metrics category */);
|
||||
final ViewGroup view = new FrameLayout(mContext);
|
||||
final SliceRowViewHolder viewHolder =
|
||||
adapter.onCreateViewHolder(view, 0);
|
||||
|
||||
assertThat(adapter.getItemCount()).isEqualTo(MAX_NUM_OF_SLICES);
|
||||
assertThat(adapter.getData().size()).isEqualTo(MAX_NUM_OF_SLICES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mediaOutputIndicatorSlice_notSliderPanel_noSliderLayout() {
|
||||
addTestLiveData(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
|
||||
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0 /* metrics category */);
|
||||
final int position = 0;
|
||||
final ViewGroup view = new FrameLayout(mContext);
|
||||
final SliceRowViewHolder viewHolder =
|
||||
adapter.onCreateViewHolder(view, 0 /* view type*/);
|
||||
|
||||
adapter.onBindViewHolder(viewHolder, position);
|
||||
|
||||
assertThat(viewHolder.mSliceSliderLayout).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_viewTypeSlider_verifyActionLabelSet() {
|
||||
addTestLiveData(VOLUME_NOTIFICATION_URI);
|
||||
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0);
|
||||
final ViewGroup view = new FrameLayout(mContext);
|
||||
SliceRowViewHolder viewHolder = spy(adapter.onCreateViewHolder(view, 0 /* view type*/));
|
||||
adapter.onBindViewHolder(viewHolder, 0);
|
||||
|
||||
verify(viewHolder).updateActionLabel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreateViewHolder_viewTypeSlider_verifyLayout() {
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0);
|
||||
final ViewGroup view = new FrameLayout(mContext);
|
||||
final ArgumentCaptor<Integer> intArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
adapter.onCreateViewHolder(view, VIEW_TYPE_SLIDER);
|
||||
|
||||
verify(sLayoutInflater).inflate(intArgumentCaptor.capture(), eq(view), eq(false));
|
||||
assertThat(intArgumentCaptor.getValue()).isEqualTo(R.layout.panel_slice_slider_row);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreateViewHolder_viewTypeDefault_verifyLayout() {
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0);
|
||||
final ViewGroup view = new FrameLayout(mContext);
|
||||
final ArgumentCaptor<Integer> intArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
adapter.onCreateViewHolder(view, 0);
|
||||
|
||||
verify(sLayoutInflater).inflate(intArgumentCaptor.capture(), eq(view), eq(false));
|
||||
assertThat(intArgumentCaptor.getValue()).isEqualTo(R.layout.panel_slice_row);
|
||||
}
|
||||
|
||||
@Implements(LayoutInflater.class)
|
||||
public static class ShadowLayoutInflater {
|
||||
|
||||
@Implementation
|
||||
public static LayoutInflater from(Context context) {
|
||||
final LayoutInflater inflater =
|
||||
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
if (inflater == null) {
|
||||
throw new AssertionError("LayoutInflater not found.");
|
||||
}
|
||||
sLayoutInflater = spy(inflater);
|
||||
return sLayoutInflater;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 com.android.settings.panel;
|
||||
|
||||
import static android.content.res.Configuration.UI_MODE_NIGHT_NO;
|
||||
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
com.android.settings.testutils.shadow.ShadowFragment.class,
|
||||
})
|
||||
public class SettingsPanelActivityTest {
|
||||
|
||||
private FakeFeatureFactory mFakeFeatureFactory;
|
||||
private FakeSettingsPanelActivity mSettingsPanelActivity;
|
||||
private PanelFeatureProvider mPanelFeatureProvider;
|
||||
private FakePanelContent mFakePanelContent;
|
||||
@Mock
|
||||
private PanelFragment mPanelFragment;
|
||||
@Mock
|
||||
private FragmentManager mFragmentManager;
|
||||
@Mock
|
||||
private FragmentTransaction mTransaction;
|
||||
private int mOriginalUiMode;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mSettingsPanelActivity = spy(
|
||||
Robolectric.buildActivity(FakeSettingsPanelActivity.class).create().get());
|
||||
mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
|
||||
mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
|
||||
mFakePanelContent = new FakePanelContent();
|
||||
doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
|
||||
|
||||
mSettingsPanelActivity.mPanelFragment = mPanelFragment;
|
||||
when(mFragmentManager.findFragmentById(R.id.main_content)).thenReturn(mPanelFragment);
|
||||
when(mSettingsPanelActivity.getSupportFragmentManager()).thenReturn(mFragmentManager);
|
||||
mOriginalUiMode = mSettingsPanelActivity.getResources().getConfiguration().uiMode;
|
||||
when(mFragmentManager.beginTransaction()).thenReturn(mTransaction);
|
||||
when(mTransaction.add(anyInt(), any())).thenReturn(mTransaction);
|
||||
when(mTransaction.commit()).thenReturn(0); // don't care about return value
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mSettingsPanelActivity.getResources().getConfiguration().uiMode = mOriginalUiMode;
|
||||
}
|
||||
|
||||
@Ignore("b/313576125")
|
||||
@Test
|
||||
public void onStart_isNotDebuggable_shouldHideSystemOverlay() {
|
||||
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false);
|
||||
|
||||
final ActivityController<SettingsPanelActivity> activityController =
|
||||
Robolectric.buildActivity(SettingsPanelActivity.class).create();
|
||||
final SettingsPanelActivity activity = spy(activityController.get());
|
||||
final Window window = mock(Window.class);
|
||||
when(activity.getWindow()).thenReturn(window);
|
||||
activity.getLifecycle().addObserver(new HideNonSystemOverlayMixin(activity));
|
||||
|
||||
activityController.start();
|
||||
|
||||
verify(window).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
|
||||
}
|
||||
|
||||
@Ignore("b/313576125")
|
||||
@Test
|
||||
public void onStop_isNotDebuggable_shouldRemoveHideSystemOverlay() {
|
||||
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false);
|
||||
|
||||
final ActivityController<SettingsPanelActivity> activityController =
|
||||
Robolectric.buildActivity(SettingsPanelActivity.class).create();
|
||||
final SettingsPanelActivity activity = spy(activityController.get());
|
||||
final Window window = mock(Window.class);
|
||||
when(activity.getWindow()).thenReturn(window);
|
||||
activity.getLifecycle().addObserver(new HideNonSystemOverlayMixin(activity));
|
||||
|
||||
activityController.start();
|
||||
|
||||
verify(window).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
|
||||
|
||||
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
|
||||
when(window.getAttributes()).thenReturn(layoutParams);
|
||||
|
||||
activityController.stop();
|
||||
final ArgumentCaptor<WindowManager.LayoutParams> paramCaptor = ArgumentCaptor.forClass(
|
||||
WindowManager.LayoutParams.class);
|
||||
|
||||
verify(window).setAttributes(paramCaptor.capture());
|
||||
assertThat(paramCaptor.getValue().privateFlags
|
||||
& SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Ignore("b/313576125")
|
||||
@Test
|
||||
public void onStop_panelIsNotCreating_shouldForceUpdate() {
|
||||
mSettingsPanelActivity.mForceCreation = false;
|
||||
when(mPanelFragment.isPanelCreating()).thenReturn(false);
|
||||
mSettingsPanelActivity.mPanelFragment = mPanelFragment;
|
||||
|
||||
mSettingsPanelActivity.onStop();
|
||||
|
||||
assertThat(mSettingsPanelActivity.mForceCreation).isTrue();
|
||||
}
|
||||
|
||||
@Ignore("b/313576125")
|
||||
@Test
|
||||
public void onStop_panelIsCreating_shouldNotForceUpdate() {
|
||||
mSettingsPanelActivity.mForceCreation = false;
|
||||
when(mPanelFragment.isPanelCreating()).thenReturn(true);
|
||||
mSettingsPanelActivity.mPanelFragment = mPanelFragment;
|
||||
|
||||
mSettingsPanelActivity.onStop();
|
||||
|
||||
assertThat(mSettingsPanelActivity.mForceCreation).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onConfigurationChanged_shouldForceUpdate() {
|
||||
mSettingsPanelActivity.mForceCreation = false;
|
||||
|
||||
mSettingsPanelActivity.onConfigurationChanged(new Configuration());
|
||||
|
||||
assertThat(mSettingsPanelActivity.mForceCreation).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNewIntent_panelIsNotCreating_shouldUpdatePanel() {
|
||||
when(mPanelFragment.isPanelCreating()).thenReturn(false);
|
||||
|
||||
mSettingsPanelActivity.onNewIntent(mSettingsPanelActivity.getIntent());
|
||||
|
||||
verify(mPanelFragment).updatePanelWithAnimation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNewIntent_panelIsCreating_shouldNotUpdatePanel() {
|
||||
when(mPanelFragment.isPanelCreating()).thenReturn(true);
|
||||
|
||||
mSettingsPanelActivity.onNewIntent(mSettingsPanelActivity.getIntent());
|
||||
|
||||
verify(mPanelFragment, never()).updatePanelWithAnimation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNewIntent_panelIsShowingTheSameAction_shouldNotUpdatePanel() {
|
||||
when(mPanelFragment.isPanelCreating()).thenReturn(false);
|
||||
when(mPanelFragment.getArguments()).thenReturn(mSettingsPanelActivity.mBundle);
|
||||
|
||||
mSettingsPanelActivity.onNewIntent(mSettingsPanelActivity.getIntent());
|
||||
|
||||
verify(mPanelFragment, never()).updatePanelWithAnimation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreated_isWindowBottomPaddingZero() {
|
||||
int paddingBottom = mSettingsPanelActivity.getWindow().getDecorView().getPaddingBottom();
|
||||
assertThat(paddingBottom).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notInNightMode_lightNavigationBarAppearance() {
|
||||
Configuration config = mSettingsPanelActivity.getResources().getConfiguration();
|
||||
config.uiMode = UI_MODE_NIGHT_NO;
|
||||
mSettingsPanelActivity.onConfigurationChanged(config); // forces creation
|
||||
|
||||
mSettingsPanelActivity.onNewIntent(mSettingsPanelActivity.getIntent());
|
||||
verify(mFragmentManager).beginTransaction();
|
||||
|
||||
View decorView = mSettingsPanelActivity.getWindow().getDecorView();
|
||||
WindowInsetsControllerCompat controller = ViewCompat.getWindowInsetsController(decorView);
|
||||
assertThat(controller.isAppearanceLightNavigationBars()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 com.android.settings.panel;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class VolumePanelTest {
|
||||
|
||||
private VolumePanel mPanel;
|
||||
private Context mContext;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
|
||||
when(mContext.getApplicationContext()).thenReturn(mContext);
|
||||
|
||||
mPanel = VolumePanel.create(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlices_checkUri() {
|
||||
final List<Uri> uris = mPanel.getSlices();
|
||||
|
||||
assertThat(uris).containsExactly(
|
||||
CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI,
|
||||
CustomSliceRegistry.VOLUME_CALL_URI,
|
||||
CustomSliceRegistry.VOLUME_MEDIA_URI,
|
||||
CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI,
|
||||
CustomSliceRegistry.VOLUME_SEPARATE_RING_URI,
|
||||
CustomSliceRegistry.VOLUME_NOTIFICATION_URI,
|
||||
CustomSliceRegistry.VOLUME_ALARM_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSeeMoreIntent_notNull() {
|
||||
assertThat(mPanel.getSeeMoreIntent()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getViewType_checkType() {
|
||||
assertThat(mPanel.getViewType()).isEqualTo(PanelContent.VIEW_TYPE_SLIDER);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user