blob: 45d91edfa7bb3c2df8a100ea82bfc0f81100ec22 [file] [log] [blame]
// Copyright 2022 The Chromium OS 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 launcher
import (
"context"
"io/ioutil"
"os"
"chromiumos/tast/local/chrome"
"chromiumos/tast/local/chrome/ash"
"chromiumos/tast/local/chrome/uiauto"
"chromiumos/tast/local/chrome/uiauto/faillog"
"chromiumos/tast/local/chrome/uiauto/launcher"
"chromiumos/tast/local/chrome/uiauto/nodewith"
"chromiumos/tast/testing"
)
var fakeAppInfoForSortSmokeTest = launcher.FakeAppInfoForSort{
AlphabeticalNames: []string{"a", "B", "c", "d", "E"},
ColorOrderNames: []string{"white", "red", "yellow", "cyan", "blue", "purple", "black"},
IconFileNames: []string{"app_list_sort_smoke_white.png", "app_list_sort_smoke_red.png", "app_list_sort_smoke_yellow.png", "app_list_sort_smoke_cyan.png",
"app_list_sort_smoke_blue.png", "app_list_sort_smoke_purple.png", "app_list_sort_smoke_black.png"}}
func init() {
testing.AddTest(&testing.Test{
Func: AppListSortSmoke,
LacrosStatus: testing.LacrosVariantUnknown,
Desc: "Basic smoke tests for the app list sorting",
Contacts: []string{
"cros-system-ui-eng@google.com",
"chromeos-sw-engprod@google.com",
"andrewxu@chromium.org",
"tbarzic@chromium.org",
},
Attr: []string{"group:mainline", "informational"},
SoftwareDeps: []string{"chrome"},
Data: fakeAppInfoForSortSmokeTest.IconFileNames,
Params: []testing.Param{
{
Name: "clamshell_alphabetical",
Val: launcher.SortTestType{TabletMode: false, SortMethod: launcher.AlphabeticalSort, OrderedAppNames: fakeAppInfoForSortSmokeTest.AlphabeticalNames},
},
{
Name: "tablet_alphabetical",
Val: launcher.SortTestType{TabletMode: true, SortMethod: launcher.AlphabeticalSort, OrderedAppNames: fakeAppInfoForSortSmokeTest.AlphabeticalNames},
},
{
Name: "clamshell_color",
Val: launcher.SortTestType{TabletMode: false, SortMethod: launcher.ColorSort, OrderedAppNames: fakeAppInfoForSortSmokeTest.ColorOrderNames},
},
{
Name: "tablet_color",
Val: launcher.SortTestType{TabletMode: true, SortMethod: launcher.ColorSort, OrderedAppNames: fakeAppInfoForSortSmokeTest.ColorOrderNames},
},
},
})
}
// AppListSortSmoke verifies that the app order after sort is expected.
func AppListSortSmoke(ctx context.Context, s *testing.State) {
var opts []chrome.Option
testParam := s.Param().(launcher.SortTestType)
fakeAppNamesInOrder := testParam.OrderedAppNames
extDirBase, err := ioutil.TempDir("", "")
if err != nil {
s.Fatal("Failed to create a temporary directory: ", err)
}
defer os.RemoveAll(extDirBase)
// Prepare fake apps based on the sort method to be verified.
switch testParam.SortMethod {
case launcher.AlphabeticalSort:
opts, err = ash.GeneratePrepareFakeAppsWithNamesOptions(extDirBase, fakeAppNamesInOrder)
case launcher.ColorSort:
iconFileNames := fakeAppInfoForSortSmokeTest.IconFileNames
iconData := make([][]byte, len(iconFileNames))
for index, imageName := range iconFileNames {
imageBytes, err := launcher.ReadImageBytesFromFilePath(s.DataPath(imageName))
if err != nil {
s.Fatalf("Failed to read image byte data from %q: %v", imageName, err)
}
iconData[index] = imageBytes
}
opts, err = ash.GeneratePrepareFakeAppsWithIconDataOptions(extDirBase, fakeAppNamesInOrder, iconData)
}
if err != nil {
s.Fatalf("Failed to create the fake apps for verifying %v: %v", testParam.SortMethod, err)
}
// Enable the app list sort.
opts = append(opts, chrome.EnableFeatures("ProductivityLauncher", "LauncherAppSort"))
cr, err := chrome.New(ctx, opts...)
if err != nil {
s.Fatal("Chrome login failed: ", err)
}
defer cr.Close(ctx)
defer faillog.DumpUITreeWithScreenshotOnError(ctx, s.OutDir(), s.HasError, cr, "ui_tree")
tconn, err := cr.TestAPIConn(ctx)
if err != nil {
s.Fatal("Failed to connect Test API: ", err)
}
tabletMode := testParam.TabletMode
originallyEnabled, err := ash.TabletModeEnabled(ctx, tconn)
if err != nil {
s.Fatal("Failed to check if DUT is in tablet mode: ", err)
}
cleanup, err := ash.EnsureTabletModeEnabled(ctx, tconn, tabletMode)
if err != nil {
s.Fatal("Failed to ensure clamshell/tablet mode: ", err)
}
defer cleanup(ctx)
// Ensure that the tablet launcher is closed before opening a launcher instance for test in clamshell.
if originallyEnabled && !tabletMode {
if err := ash.WaitForLauncherState(ctx, tconn, ash.Closed); err != nil {
s.Fatal("Launcher not closed after transition to clamshell mode: ", err)
}
}
// Ensure that the launcher shows.
if tabletMode {
if err := launcher.OpenExpandedView(tconn)(ctx); err != nil {
s.Fatal("Failed to open expanded Application list view: ", err)
}
} else {
if err := launcher.OpenBubbleLauncher(tconn)(ctx); err != nil {
s.Fatal("Failed to open bubble launcher: ", err)
}
}
if err := launcher.WaitForStableNumberOfApps(ctx, tconn); err != nil {
s.Fatal("Failed to wait for item count in app list to stabilize: ", err)
}
appsGrid := nodewith.ClassName(launcher.BubbleAppsGridViewClass)
if tabletMode {
appsGrid = nodewith.ClassName(launcher.PagedAppsGridViewClass)
}
lastFakeAppName := fakeAppNamesInOrder[len(fakeAppNamesInOrder)-1]
lastFakeApp := nodewith.ClassName(launcher.ExpandedItemsClass).Ancestor(appsGrid).Name(lastFakeAppName)
ui := uiauto.New(tconn)
if err := ui.WaitForLocation(lastFakeApp)(ctx); err != nil {
s.Fatalf("Failed to wait for the fake app %q location to be idle: %v", lastFakeAppName, err)
}
indices, err := launcher.FetchItemIndicesByName(ctx, ui, []string{lastFakeAppName}, appsGrid)
if err != nil {
s.Fatalf("Failed to get the view index of the app %q: %v", lastFakeAppName, err)
}
srcIndex := indices[0]
// Move the fake app that should be placed at rear in the sorting order to
// the front. It ensures that apps are out of order before sorting.
if srcIndex != 0 {
if err := launcher.DragIconAfterIcon(ctx, tconn, srcIndex, 0, appsGrid)(ctx); err != nil {
s.Fatalf("Failed to drag the app %q from %d to the front: %v", lastFakeAppName, srcIndex, err)
}
}
if err := ui.WaitForLocation(lastFakeApp)(ctx); err != nil {
s.Fatal("Failed to wait for the dragged item bounds to become stable: ", err)
}
defaultFakeAppIndices, err := launcher.FetchItemIndicesByName(ctx, ui, fakeAppNamesInOrder, appsGrid)
if err != nil {
s.Fatal("Failed to get the indices of the fake apps: ", err)
}
if err := launcher.TriggerAppListSortAndWaitForUndoButtonExist(ctx, ui, testParam.SortMethod, lastFakeApp); err != nil {
s.Fatalf("Failed to trigger %v: %v", testParam.SortMethod, err)
}
// App items not on the first launcher page get hidden temporarily during sort animation. Wait
// for them to reappear before proceeding.
if err := launcher.VerifyFakeAppsOrdered(ctx, ui, appsGrid, fakeAppNamesInOrder, true /*wait=*/); err != nil {
s.Fatal("Failed to verify fake apps order: ", err)
}
undoButton := nodewith.Name(launcher.GetUndoButtonNameForSortType(testParam.SortMethod)).ClassName("PillButton")
if err := uiauto.Combine("undo alphabetical sorting",
ui.LeftClick(undoButton),
ui.WaitUntilGone(undoButton),
ui.WaitForLocation(lastFakeApp),
)(ctx); err != nil {
s.Fatal("Failed to undo alphabetical sorting: ", err)
}
// App items not on the first launcher page get hidden temporarily during sort revert animation.
// Wait for them to reappear before proceeding.
for _, name := range fakeAppNamesInOrder {
if err := ui.WaitUntilExists(nodewith.ClassName(launcher.ExpandedItemsClass).Name(name).Ancestor(appsGrid))(ctx); err != nil {
s.Fatalf("Failed to find app %q after sort revert: %v", name, err)
}
}
recoveredIndices, err := launcher.FetchItemIndicesByName(ctx, ui, fakeAppNamesInOrder, appsGrid)
if err != nil {
s.Fatal("Failed to get fake apps' indices after reverting sorting: ", err)
}
// Verify that after reverting sorting, fake apps' indices are the same with the default ones.
if len(defaultFakeAppIndices) != len(recoveredIndices) {
s.Fatalf("App count mismatch after sort revert: got %d, expecting %d", len(recoveredIndices), len(defaultFakeAppIndices))
}
for i := range defaultFakeAppIndices {
if defaultFakeAppIndices[i] != recoveredIndices[i] {
s.Fatalf("Unexpected app order after sort revert: got %v, expecting: %v", recoveredIndices, defaultFakeAppIndices)
}
}
if err := launcher.TriggerAppListSortAndWaitForUndoButtonExist(ctx, ui, testParam.SortMethod, lastFakeApp); err != nil {
s.Fatalf("Failed to trigger %v after reverting: %v", testParam.SortMethod, err)
}
if tabletMode {
if err := launcher.HideTabletModeLauncher(tconn)(ctx); err != nil {
s.Fatal("Failed to hide the launcher in tablet: ", err)
}
} else if err := launcher.CloseBubbleLauncher(tconn)(ctx); err != nil {
s.Fatal("Failed to close the bubble launcher: ", err)
}
// Show the launcher again.
if tabletMode {
if err := launcher.OpenExpandedView(tconn)(ctx); err != nil {
s.Fatal("Failed to open Expanded Application list view for reshowing: ", err)
}
} else {
if err := launcher.OpenBubbleLauncher(tconn)(ctx); err != nil {
s.Fatal("Failed to open bubble launcher for reshowing: ", err)
}
}
if err := ui.Gone(undoButton)(ctx); err != nil {
s.Fatal("Didn't expect to find undo button: ", err)
}
if err := launcher.VerifyFakeAppsOrdered(ctx, ui, appsGrid, fakeAppNamesInOrder, false /*wait=*/); err != nil {
s.Fatal("Failed to verify fake apps order after reshowing the launcher: ", err)
}
}