Skip to content

Commit

Permalink
shows descriptors
Browse files Browse the repository at this point in the history
Note: The functions must adhere to strict camel case. So the naming convention is "desc<Something>A" rather than "descA<Something>"

Future CLs will style this better. This is to have something for now.

Change-Id: Iaacdb8d6578ae8c6a8c3daf446c1a9abe0edc7cd
Bug: b/301443005
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4932182
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Commit-Queue: Paul Adedeji <pauladedeji@google.com>
Reviewed-by: Tibor Goldschwendt <tiborg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1209452}
  • Loading branch information
Paul Adedeji authored and Chromium LUCI CQ committed Oct 13, 2023
1 parent 1cba116 commit 0c3f425
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,43 @@ <h2 slot="heading">Wallpaper Search</h2>
placeholder="Query"
value="{{query_}}">
</cr-input>
<cr-button id="descriptorBtnA" hidden$="[[!descriptors_]]"
on-click="onDescriptorMenuClickA_">
Descriptor A
</cr-button>
<cr-action-menu id="descriptorMenuA">
<template is="dom-repeat" items="[[descriptors_.descriptorA]]">
<span>[[item.category]]</span>
<template is="dom-repeat" items="[[item.labels]]">
<button class="dropdown-item">
<span>[[item]]</span>
</button>
</template>
</template>
</cr-action-menu>
<cr-button id="descriptorBtnB" hidden$="[[!descriptors_]]"
on-click="onDescriptorMenuClickB_">
Descriptor B
</cr-button>
<cr-action-menu id="descriptorMenuB">
<template is="dom-repeat" items="[[descriptors_.descriptorB]]">
<button class="dropdown-item">
<img src="[[item.imagePath]]"></img>
<span>[[item.label]]</span>
</button>
</template>
</cr-action-menu>
<cr-button id="descriptorBtnC" hidden$="[[!descriptors_]]"
on-click="onDescriptorMenuClickC_">
Descriptor C
</cr-button>
<cr-action-menu id="descriptorMenuC">
<template is="dom-repeat" items="[[descriptors_.descriptorC]]">
<button class="dropdown-item">
<span>[[item]]</span>
</button>
</template>
</cr-action-menu>
<div id="btnContainer">
<cr-button
id="submitButton"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@ import 'chrome://customize-chrome-side-panel.top-chrome/shared/sp_heading.js';
import 'chrome://customize-chrome-side-panel.top-chrome/shared/sp_shared_style.css.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_grid/cr_grid.js';
import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.js';

import {SpHeading} from 'chrome://customize-chrome-side-panel.top-chrome/shared/sp_heading.js';
import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {CustomizeChromePageHandlerInterface, Descriptors} from './customize_chrome.mojom-webui.js';
import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js';
import {getTemplate} from './wallpaper_search.html.js';

export interface WallpaperSearchElement {
$: {
descriptorMenuA: CrActionMenuElement,
descriptorMenuB: CrActionMenuElement,
descriptorMenuC: CrActionMenuElement,
heading: SpHeading,
queryInput: CrInputElement,
submitButton: CrButtonElement,
Expand All @@ -35,16 +41,30 @@ export class WallpaperSearchElement extends PolymerElement {

static get properties() {
return {
descriptors_: Object,
emptyContainers_: Object,
query_: String,
results_: Object,
};
}

private descriptors_: Descriptors|null;
private emptyContainers_: number[];
private query_: string;
private results_: string[];

private pageHandler_: CustomizeChromePageHandlerInterface;

constructor() {
super();
this.pageHandler_ = CustomizeChromeApiProxy.getInstance().handler;
this.pageHandler_.getDescriptors().then(({descriptors}) => {
if (descriptors) {
this.descriptors_ = descriptors;
}
});
}

focusOnBackButton() {
this.$.heading.getBackButton().focus();
}
Expand All @@ -53,9 +73,21 @@ export class WallpaperSearchElement extends PolymerElement {
this.dispatchEvent(new Event('back-click'));
}

private onDescriptorMenuClickA_(e: Event) {
this.$.descriptorMenuA.showAt(e.target as HTMLElement);
}

private onDescriptorMenuClickB_(e: Event) {
this.$.descriptorMenuB.showAt(e.target as HTMLElement);
}

private onDescriptorMenuClickC_(e: Event) {
this.$.descriptorMenuC.showAt(e.target as HTMLElement);
}

private async onSearchClick_() {
const {results} = await CustomizeChromeApiProxy.getInstance()
.handler.getWallpaperSearchResults(this.query_);
const {results} =
await this.pageHandler_.getWallpaperSearchResults(this.query_);
this.results_ = results;
this.emptyContainers_ = Array.from(
{length: results.length > 0 ? 6 - results.length : 0}, () => 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ suite('AppTest', () => {
mock, new CustomizeChromePageCallbackRouter()));
handler.setResultFor('getBackgroundImages', new Promise(() => {}));
handler.setResultFor('getBackgroundCollections', new Promise(() => {}));
handler.setResultFor('getDescriptors', new Promise(() => {}));
callbackRouter = CustomizeChromeApiProxy.getInstance()
.callbackRouter.$.bindNewPipeAndPassRemote();
customizeChromeApp = document.createElement('customize-chrome-app');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,90 +4,164 @@

import 'chrome://customize-chrome-side-panel.top-chrome/wallpaper_search.js';

import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js';
import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, Descriptors} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js';
import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js';
import {WallpaperSearchElement} from 'chrome://customize-chrome-side-panel.top-chrome/wallpaper_search.js';
import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
import {TestMock} from 'chrome://webui-test/test_mock.js';
import {eventToPromise} from 'chrome://webui-test/test_util.js';

import {installMock} from './test_support.js';
import {$$, assertNotStyle, installMock} from './test_support.js';

suite('WallpaperSearchTest', () => {
let handler: TestMock<CustomizeChromePageHandlerRemote>;
let wallpaperSearchElement: WallpaperSearchElement;

async function createWallpaperSearchElement(
descriptors: Descriptors|null = null): Promise<WallpaperSearchElement> {
handler.setResultFor('getDescriptors', Promise.resolve({descriptors}));
wallpaperSearchElement =
document.createElement('customize-chrome-wallpaper-search');
document.body.appendChild(wallpaperSearchElement);
return wallpaperSearchElement;
}

setup(async () => {
document.body.innerHTML = window.trustedTypes!.emptyHTML;
handler = installMock(
CustomizeChromePageHandlerRemote,
(mock: CustomizeChromePageHandlerRemote) =>
CustomizeChromeApiProxy.setInstance(
mock, new CustomizeChromePageCallbackRouter()));
wallpaperSearchElement =
document.createElement('customize-chrome-wallpaper-search');
document.body.appendChild(wallpaperSearchElement);
});

test('wallpaper search element added to side panel', async () => {
assertTrue(document.body.contains(wallpaperSearchElement));
});
suite('Misc', () => {
test('wallpaper search element added to side panel', async () => {
createWallpaperSearchElement();
assertTrue(document.body.contains(wallpaperSearchElement));
});

test('clicking back button creates event', async () => {
const eventPromise = eventToPromise('back-click', wallpaperSearchElement);
wallpaperSearchElement.$.heading.getBackButton().click();
const event = await eventPromise;
assertTrue(!!event);
test('clicking back button creates event', async () => {
createWallpaperSearchElement();
const eventPromise = eventToPromise('back-click', wallpaperSearchElement);
wallpaperSearchElement.$.heading.getBackButton().click();
const event = await eventPromise;
assertTrue(!!event);
});
});

test('clicking search invokes backend', () => {
wallpaperSearchElement.$.queryInput.value = 'foo';
wallpaperSearchElement.$.submitButton.click();
assertEquals(1, handler.getCallCount('getWallpaperSearchResults'));
assertEquals('foo', handler.getArgs('getWallpaperSearchResults')[0]);
});
suite('Descriptors', () => {
test('descriptors are fetched from the backend', () => {
createWallpaperSearchElement();
assertEquals(1, handler.getCallCount('getDescriptors'));
});

test('empty result shows error message', async () => {
const emptyResultPromise = Promise.resolve({results: []});
handler.setResultFor('getWallpaperSearchResults', emptyResultPromise);
wallpaperSearchElement.$.submitButton.click();
await emptyResultPromise;
assertTrue(wallpaperSearchElement.$.queryInput.invalid);
assertEquals('Error', wallpaperSearchElement.$.queryInput.errorMessage);
});
test('descriptor menus populate correctly', async () => {
createWallpaperSearchElement({
descriptorA: [{category: 'foo', labels: ['bar', 'baz']}],
descriptorB: [{label: 'foo', imagePath: 'bar.png'}],
descriptorC: ['foo', 'bar', 'baz'],
});
await flushTasks();

assertNotStyle(
$$(wallpaperSearchElement, '#descriptorBtnA')!, 'display', 'none');
assertNotStyle(
$$(wallpaperSearchElement, '#descriptorBtnB')!, 'display', 'none');
assertNotStyle(
$$(wallpaperSearchElement, '#descriptorBtnC')!, 'display', 'none');
assertEquals(
2,
wallpaperSearchElement.shadowRoot!
.querySelectorAll('#descriptorMenuA .dropdown-item')
.length);
assertEquals(
1,
wallpaperSearchElement.shadowRoot!
.querySelectorAll('#descriptorMenuB .dropdown-item')
.length);
assertEquals(
3,
wallpaperSearchElement.shadowRoot!
.querySelectorAll('#descriptorMenuC .dropdown-item')
.length);
});

test('empty result shows no tiles', async () => {
const emptyResultPromise = Promise.resolve({results: []});
handler.setResultFor('getWallpaperSearchResults', emptyResultPromise);
test('descriptor menus open', async () => {
createWallpaperSearchElement({
descriptorA: [{category: 'foo', labels: ['bar', 'baz']}],
descriptorB: [{label: 'foo', imagePath: 'bar.png'}],
descriptorC: ['foo', 'bar', 'baz'],
});
await flushTasks();
assertFalse(wallpaperSearchElement.$.descriptorMenuA.open);

wallpaperSearchElement.$.submitButton.click();
await emptyResultPromise;
await waitAfterNextRender(wallpaperSearchElement);
$$<HTMLElement>(wallpaperSearchElement, '#descriptorBtnA')!.click();

assertTrue(!wallpaperSearchElement.shadowRoot!.querySelector('.tile'));
assertTrue(wallpaperSearchElement.$.descriptorMenuA.open);
});
});

test('shows mix of filled and empty containers', async () => {
const resultPromise = Promise.resolve({results: ['123', '456']});
handler.setResultFor('getWallpaperSearchResults', resultPromise);

wallpaperSearchElement.$.submitButton.click();
await resultPromise;
await waitAfterNextRender(wallpaperSearchElement);

// There should always be 6 tiles total. Since there are 2 images in the
// response, there should be 2 result tiles and the remaining 4 should be
// empty.
assertEquals(
wallpaperSearchElement.shadowRoot!.querySelectorAll('.tile').length, 6);
assertEquals(
wallpaperSearchElement.shadowRoot!.querySelectorAll('.tile.result')
.length,
2);
assertEquals(
wallpaperSearchElement.shadowRoot!.querySelectorAll('.tile.empty')
.length,
4);
suite('Search', () => {
test('clicking search invokes backend', () => {
createWallpaperSearchElement();

wallpaperSearchElement.$.queryInput.value = 'foo';
wallpaperSearchElement.$.submitButton.click();

assertEquals(1, handler.getCallCount('getWallpaperSearchResults'));
assertEquals('foo', handler.getArgs('getWallpaperSearchResults')[0]);
});

test('empty result shows error message', async () => {
const emptyResultPromise = Promise.resolve({results: []});
handler.setResultFor('getWallpaperSearchResults', emptyResultPromise);
createWallpaperSearchElement();

wallpaperSearchElement.$.submitButton.click();
await emptyResultPromise;

assertTrue(wallpaperSearchElement.$.queryInput.invalid);
assertEquals('Error', wallpaperSearchElement.$.queryInput.errorMessage);
});


test('empty result shows no tiles', async () => {
const emptyResultPromise = Promise.resolve({results: []});
handler.setResultFor('getWallpaperSearchResults', emptyResultPromise);
createWallpaperSearchElement();

wallpaperSearchElement.$.submitButton.click();
await emptyResultPromise;
await waitAfterNextRender(wallpaperSearchElement);

assertTrue(!wallpaperSearchElement.shadowRoot!.querySelector('.tile'));
});

test('shows mix of filled and empty containers', async () => {
const resultPromise = Promise.resolve({results: ['123', '456']});
handler.setResultFor('getWallpaperSearchResults', resultPromise);
createWallpaperSearchElement();

wallpaperSearchElement.$.submitButton.click();
await resultPromise;
await waitAfterNextRender(wallpaperSearchElement);

// There should always be 6 tiles total. Since there are 2 images in the
// response, there should be 2 result tiles and the remaining 4 should be
// empty.
assertEquals(
wallpaperSearchElement.shadowRoot!.querySelectorAll('.tile').length,
6);
assertEquals(
wallpaperSearchElement.shadowRoot!.querySelectorAll('.tile.result')
.length,
2);
assertEquals(
wallpaperSearchElement.shadowRoot!.querySelectorAll('.tile.empty')
.length,
4);
});
});
});

0 comments on commit 0c3f425

Please sign in to comment.