blob: 8b50fd7a90eb378a08f314056f451a85248437f4 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.plugins.quickactionsexample;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.util.Log;
import androidx.lifecycle.Lifecycle;
import androidx.test.core.app.ActivityScenario;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
import io.flutter.plugins.quickactions.QuickActionsPlugin;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class QuickActionsTest {
private Context context;
private UiDevice device;
private ActivityScenario<QuickActionsTestActivity> scenario;
@Before
public void setUp() {
context = ApplicationProvider.getApplicationContext();
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
scenario = ensureAppRunToView();
ensureAllAppShortcutsAreCreated();
}
@After
public void tearDown() {
scenario.close();
Log.i(QuickActionsTest.class.getSimpleName(), "Run to completion");
}
@Test
public void quickActionPluginIsAdded() {
final ActivityScenario<QuickActionsTestActivity> scenario =
ActivityScenario.launch(QuickActionsTestActivity.class);
scenario.onActivity(
activity -> {
assertTrue(activity.engine.getPlugins().has(QuickActionsPlugin.class));
});
}
@Test
public void appShortcutsAreCreated() {
List<ShortcutInfo> expectedShortcuts = createMockShortcuts();
ShortcutManager shortcutManager =
(ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE);
List<ShortcutInfo> dynamicShortcuts = shortcutManager.getDynamicShortcuts();
// Assert the app shortcuts defined in ../lib/main.dart.
assertFalse(dynamicShortcuts.isEmpty());
assertEquals(expectedShortcuts.size(), dynamicShortcuts.size());
for (ShortcutInfo expectedShortcut : expectedShortcuts) {
ShortcutInfo dynamicShortcut =
dynamicShortcuts
.stream()
.filter(s -> s.getId().equals(expectedShortcut.getId()))
.findFirst()
.get();
assertEquals(expectedShortcut.getShortLabel(), dynamicShortcut.getShortLabel());
assertEquals(expectedShortcut.getLongLabel(), dynamicShortcut.getLongLabel());
}
}
@Test
public void appShortcutLaunchActivityAfterStarting() {
// Arrange
List<ShortcutInfo> shortcuts = createMockShortcuts();
ShortcutInfo firstShortcut = shortcuts.get(0);
ShortcutManager shortcutManager =
(ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE);
List<ShortcutInfo> dynamicShortcuts = shortcutManager.getDynamicShortcuts();
ShortcutInfo dynamicShortcut =
dynamicShortcuts
.stream()
.filter(s -> s.getId().equals(firstShortcut.getId()))
.findFirst()
.get();
Intent dynamicShortcutIntent = dynamicShortcut.getIntent();
AtomicReference<QuickActionsTestActivity> initialActivity = new AtomicReference<>();
scenario.onActivity(initialActivity::set);
String appReadySentinel = " has launched";
// Act
context.startActivity(dynamicShortcutIntent);
device.wait(Until.hasObject(By.descContains(appReadySentinel)), 2000);
AtomicReference<QuickActionsTestActivity> currentActivity = new AtomicReference<>();
scenario.onActivity(currentActivity::set);
// Assert
Assert.assertTrue(
"AppShortcut:" + firstShortcut.getId() + " does not launch the correct activity",
// We can only find the shortcut type in content description while inspecting it in Ui
// Automator Viewer.
device.hasObject(By.desc(firstShortcut.getId() + appReadySentinel)));
// This is Android SingleTop behavior in which Android does not destroy the initial activity and
// launch a new activity.
Assert.assertEquals(initialActivity.get(), currentActivity.get());
}
private void ensureAllAppShortcutsAreCreated() {
device.wait(Until.hasObject(By.text("actions ready")), 1000);
}
private List<ShortcutInfo> createMockShortcuts() {
List<ShortcutInfo> expectedShortcuts = new ArrayList<>();
String actionOneLocalizedTitle = "Action one";
expectedShortcuts.add(
new ShortcutInfo.Builder(context, "action_one")
.setShortLabel(actionOneLocalizedTitle)
.setLongLabel(actionOneLocalizedTitle)
.build());
String actionTwoLocalizedTitle = "Action two";
expectedShortcuts.add(
new ShortcutInfo.Builder(context, "action_two")
.setShortLabel(actionTwoLocalizedTitle)
.setLongLabel(actionTwoLocalizedTitle)
.build());
return expectedShortcuts;
}
private ActivityScenario<QuickActionsTestActivity> ensureAppRunToView() {
final ActivityScenario<QuickActionsTestActivity> scenario =
ActivityScenario.launch(QuickActionsTestActivity.class);
scenario.moveToState(Lifecycle.State.STARTED);
return scenario;
}
}