fix: 引入Settings的Module

This commit is contained in:
2024-12-10 14:57:24 +08:00
parent ad8fc8731d
commit df105485bd
6934 changed files with 896168 additions and 2 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}