Settings: Deflake SettingsTest.SettingsMain.

The tests were flaking because there wasn't a reliable signal to wait
for after currentRouteChanged() calls to signify that cr-view-manager
had finished transitioning to the newly displayed view. The test code
was calling flushTasks() which was not sufficient.

Fixed by exposed a whenViewSwitchingDone() method which returns a
Promise that can reliably signal when the test can make assertions. A
similar approach is being used at https://crrev.com/c/6784912 for the
same reason.

Bug: 435560735
Change-Id: I2eb3a5f0b6ee01f074578ce0cd0968093c290a98
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6813306
Commit-Queue: John Lee <[email protected]>
Auto-Submit: Demetrios Papadopoulos <[email protected]>
Reviewed-by: John Lee <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1496137}
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.ts b/chrome/browser/resources/settings/settings_main/settings_main.ts
index 5abd2dbc..76d99d9b 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.ts
+++ b/chrome/browser/resources/settings/settings_main/settings_main.ts
@@ -28,6 +28,7 @@
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import type {CrViewManagerElement} from 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';
 import {assert} from 'chrome://resources/js/assert.js';
+import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 import {beforeNextRender, flush, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {ensureLazyLoaded} from '../ensure_lazy_loaded.js';
@@ -148,6 +149,7 @@
   declare private languages_?: LanguagesModel;
   // </if>
 
+  private pendingViewSwitching_: PromiseResolver<void> = new PromiseResolver();
   private topLevelEquivalentRoute_: Route = getTopLevelRoute();
 
   override connectedCallback() {
@@ -166,6 +168,8 @@
   }
 
   override async currentRouteChanged(route: Route) {
+    this.pendingViewSwitching_ = new PromiseResolver();
+
     if (routes.ADVANCED && routes.ADVANCED.contains(route)) {
       // Load the lazy module immediately, don't wait for requestIdleCallback()
       // to fire. No-op if it has already fired.
@@ -177,6 +181,7 @@
 
     if (this.lastRoute_ === effectiveRoute) {
       // Nothing to do.
+      this.pendingViewSwitching_.resolve();
       return;
     }
 
@@ -191,14 +196,23 @@
       if (this.lastRoute_ !== effectiveRoute || !this.isConnected) {
         // A newer currentRouteChanged call happened while awaiting or no longer
         // connected (both can happen in tests). Do nothing.
+        this.pendingViewSwitching_.resolve();
         return;
       }
       sectionElement = this.$.switcher.querySelector(`#${newSection}`);
     }
 
     assert(sectionElement);
-    this.$.switcher.switchView(
+    await this.$.switcher.switchView(
         sectionElement.id, 'no-animation', 'no-animation');
+    this.pendingViewSwitching_.resolve();
+  }
+
+  // Exposed for tests, to allow making visibility assertions about
+  // cr-view-manager views without flaking. Should be called after
+  // currentRouteChanged is called.
+  whenViewSwitchingDone(): Promise<void> {
+    return this.pendingViewSwitching_.promise;
   }
 
   /**
diff --git a/chrome/test/data/webui/settings/settings_main_plugins_test.ts b/chrome/test/data/webui/settings/settings_main_plugins_test.ts
index 1744e67a..ac54503c 100644
--- a/chrome/test/data/webui/settings/settings_main_plugins_test.ts
+++ b/chrome/test/data/webui/settings/settings_main_plugins_test.ts
@@ -47,6 +47,7 @@
 
   setup(function() {
     createSettingsMain();
+    return settingsMain.whenViewSwitchingDone();
   });
 
   test('UpdatesActiveViewWhenRouteChanges', async function() {
@@ -86,7 +87,7 @@
 
     for (const {route, pluginTag} of routesToVisit) {
       Router.getInstance().navigateTo(route);
-      await flushTasks();
+      await settingsMain.whenViewSwitchingDone();
       assertActive(pluginTag, route.path);
     }
   });
@@ -174,7 +175,7 @@
 
     // Case2: Guest mode.
     createSettingsMain({isGuest: true});
-    await flushTasks();
+    await settingsMain.whenViewSwitchingDone();
     active = settingsMain.$.switcher.querySelector<HTMLElement>(
         '.active[slot=view]');
     assertTrue(!!active);