[gold] corpus-selector-sk: Add page object and use it in tests.

Change-Id: I8d47578e7f2dd9d345a5d4683acbaf87a29c661d
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/300417
Commit-Queue: Leandro Lovisolo <lovisolo@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/golden/modules/corpus-selector-sk/corpus-selector-sk_po.ts b/golden/modules/corpus-selector-sk/corpus-selector-sk_po.ts
new file mode 100644
index 0000000..652b0da
--- /dev/null
+++ b/golden/modules/corpus-selector-sk/corpus-selector-sk_po.ts
@@ -0,0 +1,32 @@
+import { PageObject } from '../../../infra-sk/modules/page_object/page_object';
+
+/** A page object for the CorpusSelectorSkPO component. */
+export class CorpusSelectorSkPO extends PageObject {
+  async isLoadingMessageVisible() {
+    return (await this.selectOnePOE('p')) !== null;
+  }
+
+  async getCorpora() {
+    return this.selectAllPOEThenMap('li', (li) => li.innerText);
+  }
+
+  /** Returns the selected corpus, or null if none is selected. */
+  async getSelectedCorpus() {
+    const selectedCorpora = await this.selectAllPOEThenMap('li.selected', (li) => li.innerText);
+
+    // There can be at most one selected corpora.
+    if (selectedCorpora.length > 1) {
+      throw new Error('there are more than one selected corpora');
+    }
+
+    if (selectedCorpora.length) {
+      return selectedCorpora[0];
+    }
+    return null;
+  }
+
+  async clickCorpus(corpus: string) {
+    const li = await this.selectAllPOEThenFind('li', async (li) => (await li.innerText) === corpus);
+    await li!.click();
+  }
+}
diff --git a/golden/modules/corpus-selector-sk/corpus-selector-sk_test.ts b/golden/modules/corpus-selector-sk/corpus-selector-sk_test.ts
index 9159324..f5b2dde 100644
--- a/golden/modules/corpus-selector-sk/corpus-selector-sk_test.ts
+++ b/golden/modules/corpus-selector-sk/corpus-selector-sk_test.ts
@@ -1,7 +1,7 @@
 import './index';
-import { $, $$ } from 'common-sk/modules/dom';
 import { eventPromise, noEventPromise, setUpElementUnderTest } from '../../../infra-sk/modules/test_util';
 import { CorpusSelectorSk } from './corpus-selector-sk';
+import { CorpusSelectorSkPO } from './corpus-selector-sk_po';
 import { stringCorpora, customTypeCorpora, TestCorpus } from './test_data';
 
 const expect = chai.expect;
@@ -11,44 +11,47 @@
     const newInstance = setUpElementUnderTest<CorpusSelectorSk<string>>('corpus-selector-sk');
 
     let corpusSelectorSk: CorpusSelectorSk<string>;
+    let corpusSelectorSkPO: CorpusSelectorSkPO;
 
     beforeEach(() => {
       corpusSelectorSk = newInstance();
       corpusSelectorSk.corpora = stringCorpora;
       corpusSelectorSk.selectedCorpus = 'gm';
+
+      corpusSelectorSkPO = new CorpusSelectorSkPO(corpusSelectorSk);
     });
 
-    it('shows a loading indicator when the corpora is empty', () => {
+    it('shows a loading indicator when the corpora is empty', async () => {
       corpusSelectorSk.corpora = [];
-      expect(corpusSelectorSk.innerText).to.equal('Loading corpora details...');
+      expect(await corpusSelectorSkPO.isLoadingMessageVisible()).to.be.true;
     });
 
-    it('shows the available corpora', () => {
-      expect(availableCorporaOnUI(corpusSelectorSk)).to.deep.equal([
+    it('shows the available corpora', async () => {
+      expect(await corpusSelectorSkPO.getCorpora()).to.deep.equal([
         'canvaskit', 'colorImage', 'gm', 'image', 'pathkit', 'skp', 'svg'
       ]);
     });
 
-    it('shows the available corpora using a custom renderer function', () => {
+    it('shows the available corpora using a custom renderer function', async () => {
       corpusSelectorSk.corpusRendererFn = (corpus) => `(${corpus})`;
-      expect(availableCorporaOnUI(corpusSelectorSk)).to.deep.equal([
+      expect(await corpusSelectorSkPO.getCorpora()).to.deep.equal([
         '(canvaskit)', '(colorImage)', '(gm)', '(image)', '(pathkit)', '(skp)', '(svg)'
       ]);
     });
 
-    it('shows the selected corpus', () => {
-      expect(selectedCorpusOnUI(corpusSelectorSk)).to.equal('gm');
+    it('shows the selected corpus', async () => {
+      expect(await corpusSelectorSkPO.getSelectedCorpus()).to.equal('gm');
     })
 
-    it('can handle an empty selection', () => {
+    it('can handle an empty selection', async () => {
       corpusSelectorSk.selectedCorpus = null;
-      expect(selectedCorpusOnUI(corpusSelectorSk)).to.be.undefined;
+      expect(await corpusSelectorSkPO.getSelectedCorpus()).to.be.null;
     });
 
-    it('can change the selection programmatically', () => {
+    it('can change the selection programmatically', async () => {
       corpusSelectorSk.selectedCorpus = 'image';
       expect(corpusSelectorSk.selectedCorpus).to.equal('image');
-      expect(selectedCorpusOnUI(corpusSelectorSk)).to.equal('image');
+      expect(await corpusSelectorSkPO.getSelectedCorpus()).to.equal('image');
     });
 
     it('does not emit "corpus-selected" when selection changes programmatically', async () => {
@@ -58,22 +61,22 @@
     });
 
     describe('clicking on a corpus', () => {
-      it('changes the selection', () => {
-        clickCorpus(corpusSelectorSk, 'colorImage');
+      it('changes the selection', async () => {
+        await corpusSelectorSkPO.clickCorpus('colorImage');
         expect(corpusSelectorSk.selectedCorpus).to.equal('colorImage');
-        expect(selectedCorpusOnUI(corpusSelectorSk)).to.equal('colorImage');
+        expect(await corpusSelectorSkPO.getSelectedCorpus()).to.equal('colorImage');
       });
 
       it('emits event "corpus-selected" with the new corpus', async () => {
         const corpusSelected = eventPromise<CustomEvent<string>>('corpus-selected');
-        clickCorpus(corpusSelectorSk, 'colorImage');
+        await corpusSelectorSkPO.clickCorpus('colorImage');
         const newSelection = (await corpusSelected).detail;
         expect(newSelection).to.equal('colorImage');
       });
 
       it('does not emit "corpus-selected" if it\'s the current corpus', async () => {
         const noEvent = noEventPromise('corpus-selected');
-        clickCorpus(corpusSelectorSk, 'gm');
+        await corpusSelectorSkPO.clickCorpus('gm');
         await noEvent;
       })
     });
@@ -83,6 +86,7 @@
     const newInstance = setUpElementUnderTest<CorpusSelectorSk<TestCorpus>>('corpus-selector-sk');
 
     let corpusSelectorSk: CorpusSelectorSk<TestCorpus>;
+    let corpusSelectorSkPO: CorpusSelectorSkPO;
 
     beforeEach(() => {
       corpusSelectorSk = newInstance();
@@ -90,10 +94,12 @@
         (c: TestCorpus) => `${c.name} : ${c.untriagedCount} / ${c.negativeCount}`;
       corpusSelectorSk.corpora = customTypeCorpora;
       corpusSelectorSk.selectedCorpus = customTypeCorpora.find(corpus => corpus.name === 'gm')!;
+
+      corpusSelectorSkPO = new CorpusSelectorSkPO(corpusSelectorSk);
     });
 
-    it('handles a non-trivial custom corpus renderer function', () => {
-      expect(availableCorporaOnUI(corpusSelectorSk)).to.deep.equal([
+    it('handles a non-trivial custom corpus renderer function', async () => {
+      expect(await corpusSelectorSkPO.getCorpora()).to.deep.equal([
           'canvaskit : 2 / 2',
           'colorImage : 0 / 1',
           'gm : 61 / 1494',
@@ -104,28 +110,18 @@
       ]);
     });
 
-    it('changes the selection when clicking on a corpus', () => {
-      clickCorpus(corpusSelectorSk, 'skp : 0 / 1');
+    it('changes the selection when clicking on a corpus', async () => {
+      await corpusSelectorSkPO.clickCorpus('skp : 0 / 1');
       expect(corpusSelectorSk.selectedCorpus)
         .to.deep.equal(customTypeCorpora.find(corpus => corpus.name === 'skp')!);
-      expect(selectedCorpusOnUI(corpusSelectorSk)).to.equal('skp : 0 / 1');
+      expect(await corpusSelectorSkPO.getSelectedCorpus()).to.equal('skp : 0 / 1');
     });
 
     it('emits "corpus-selected" with custom corpus object when selection changes', async () => {
       const corpusSelected = eventPromise<CustomEvent<TestCorpus>>('corpus-selected');
-      clickCorpus(corpusSelectorSk, 'skp : 0 / 1');
+      await corpusSelectorSkPO.clickCorpus('skp : 0 / 1');
       const newSelection = (await corpusSelected).detail;
       expect(newSelection).to.deep.equal(customTypeCorpora.find(corpus => corpus.name === 'skp')!);
     });
   });
 });
-
-const availableCorporaOnUI =
-  <T>(el: CorpusSelectorSk<T>) => $<HTMLLIElement>('li', el).map((li) => li.innerText);
-
-const selectedCorpusOnUI =
-  <T>(el: CorpusSelectorSk<T>) => $$<HTMLLIElement>('li.selected', el)?.innerText;
-
-const clickCorpus =
-  <T>(el: CorpusSelectorSk<T>, label: string) =>
-    $<HTMLLIElement>('li').find(li => li.innerText === label)!.click();