Merge "Lit Migration of GrLabeledAutocomplete"
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
index ea9495c..4c26f89 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
@@ -37,7 +37,7 @@
 
 declare global {
   interface HTMLElementEventMap {
-    'text-changed': CustomEvent;
+    'text-changed': CustomEvent<string>;
     'value-changed': CustomEvent;
   }
   interface HTMLElementTagNameMap {
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts b/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
index 8faa5e7..6054d9c 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group.ts
@@ -57,7 +57,7 @@
 
 declare global {
   interface HTMLElementEventMap {
-    'text-changed': CustomEvent;
+    'text-changed': CustomEvent<string>;
     'value-changed': CustomEvent;
   }
   interface HTMLElementTagNameMap {
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.ts b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.ts
index 85f29cb..753835d 100644
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.ts
+++ b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.ts
@@ -16,24 +16,19 @@
  */
 import '../gr-autocomplete/gr-autocomplete';
 import '../../../styles/shared-styles';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-labeled-autocomplete_html';
-import {customElement, property} from '@polymer/decorators';
+import {LitElement, css, html, PropertyValues} from 'lit';
+import {customElement, property, query} from 'lit/decorators';
 import {
   GrAutocomplete,
   AutocompleteQuery,
 } from '../gr-autocomplete/gr-autocomplete';
+import {assertIsDefined} from '../../../utils/common-util';
+import {fire} from '../../../utils/event-util';
 
-export interface GrLabeledAutocomplete {
-  $: {
-    autocomplete: GrAutocomplete;
-  };
-}
 @customElement('gr-labeled-autocomplete')
-export class GrLabeledAutocomplete extends PolymerElement {
-  static get template() {
-    return htmlTemplate;
-  }
+export class GrLabeledAutocomplete extends LitElement {
+  @query('#autocomplete')
+  autocomplete?: GrAutocomplete;
 
   /**
    * Fired when a value is chosen.
@@ -44,7 +39,7 @@
   @property({type: Object})
   query: AutocompleteQuery = () => Promise.resolve([]);
 
-  @property({type: String, notify: true})
+  @property({type: String})
   text = '';
 
   @property({type: String})
@@ -56,15 +51,73 @@
   @property({type: Boolean})
   disabled = false;
 
-  _handleTriggerClick(e: Event) {
+  static override get styles() {
+    return css`
+      :host {
+        display: block;
+        width: 12em;
+      }
+      #container {
+        background: var(--chip-background-color);
+        border-radius: 1em;
+        padding: var(--spacing-m);
+      }
+      #header {
+        color: var(--deemphasized-text-color);
+        font-weight: var(--font-weight-bold);
+        font-size: var(--font-size-small);
+      }
+      #body {
+        display: flex;
+      }
+      #trigger {
+        color: var(--deemphasized-text-color);
+        cursor: pointer;
+        padding-left: var(--spacing-s);
+      }
+      #trigger:hover {
+        color: var(--primary-text-color);
+      }
+    `;
+  }
+
+  override render() {
+    return html`
+      <div id="container">
+        <div id="header">${this.label}</div>
+        <div id="body">
+          <gr-autocomplete
+            id="autocomplete"
+            threshold="0"
+            .query="${this.query}"
+            ?disabled="${this.disabled}"
+            .placeholder="${this.placeholder}"
+            borderless=""
+          ></gr-autocomplete>
+          <div id="trigger" @click="${this._handleTriggerClick}">▼</div>
+        </div>
+      </div>
+    `;
+  }
+
+  override willUpdate(changedProperties: PropertyValues) {
+    if (changedProperties.has('text')) {
+      fire(this, 'text-changed', this.text);
+    }
+  }
+
+  // Private but used in tests.
+  _handleTriggerClick = (e: Event) => {
     // Stop propagation here so we don't confuse gr-autocomplete, which
     // listens for taps on body to try to determine when it's blurred.
     e.stopPropagation();
-    this.$.autocomplete.focus();
-  }
+    assertIsDefined(this.autocomplete);
+    this.autocomplete.focus();
+  };
 
   setText(text: string) {
-    this.$.autocomplete.setText(text);
+    assertIsDefined(this.autocomplete);
+    this.autocomplete.setText(text);
   }
 
   clear() {
@@ -73,6 +126,9 @@
 }
 
 declare global {
+  interface HTMLElementEventMap {
+    'text-changed': CustomEvent<string>;
+  }
   interface HTMLElementTagNameMap {
     'gr-labeled-autocomplete': GrLabeledAutocomplete;
   }
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_html.ts b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_html.ts
deleted file mode 100644
index 934ab84..0000000
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_html.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
-  <style include="shared-styles">
-    :host {
-      display: block;
-      width: 12em;
-    }
-    #container {
-      background: var(--chip-background-color);
-      border-radius: 1em;
-      padding: var(--spacing-m);
-    }
-    #header {
-      color: var(--deemphasized-text-color);
-      font-weight: var(--font-weight-bold);
-      font-size: var(--font-size-small);
-    }
-    #body {
-      display: flex;
-    }
-    #trigger {
-      color: var(--deemphasized-text-color);
-      cursor: pointer;
-      padding-left: var(--spacing-s);
-    }
-    #trigger:hover {
-      color: var(--primary-text-color);
-    }
-  </style>
-  <div id="container">
-    <div id="header">[[label]]</div>
-    <div id="body">
-      <gr-autocomplete
-        id="autocomplete"
-        threshold="0"
-        query="[[query]]"
-        disabled="[[disabled]]"
-        placeholder="[[placeholder]]"
-        borderless=""
-      ></gr-autocomplete>
-      <div id="trigger" on-click="_handleTriggerClick">▼</div>
-    </div>
-  </div>
-`;
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.ts b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.ts
index d6fc45f..49b14b4 100644
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.ts
@@ -18,28 +18,51 @@
 import '../../../test/common-test-setup-karma';
 import './gr-labeled-autocomplete';
 import {GrLabeledAutocomplete} from './gr-labeled-autocomplete';
+import {assertIsDefined} from '../../../utils/common-util';
 
 const basicFixture = fixtureFromElement('gr-labeled-autocomplete');
 
 suite('gr-labeled-autocomplete tests', () => {
   let element: GrLabeledAutocomplete;
 
-  setup(() => {
+  setup(async () => {
     element = basicFixture.instantiate();
+    await element.updateComplete;
   });
 
   test('tapping trigger focuses autocomplete', () => {
     const e = {stopPropagation: () => undefined};
     const stopPropagationStub = sinon.stub(e, 'stopPropagation');
-    const autocompleteStub = sinon.stub(element.$.autocomplete, 'focus');
+    assertIsDefined(element.autocomplete);
+    const autocompleteStub = sinon.stub(element.autocomplete, 'focus');
     element._handleTriggerClick(e as Event);
     assert.isTrue(stopPropagationStub.calledOnce);
     assert.isTrue(autocompleteStub.calledOnce);
   });
 
   test('setText', () => {
-    const setTextStub = sinon.stub(element.$.autocomplete, 'setText');
+    assertIsDefined(element.autocomplete);
+    const setTextStub = sinon.stub(element.autocomplete, 'setText');
     element.setText('foo-bar');
     assert.isTrue(setTextStub.calledWith('foo-bar'));
   });
+
+  test('shadowDom', async () => {
+    element.label = 'Some label';
+    await element.updateComplete;
+
+    expect(element).shadowDom.to.equal(`
+      <div id="container">
+        <div id="header">Some label</div>
+        <div id="body">
+          <gr-autocomplete
+            id="autocomplete"
+            threshold="0"
+            borderless=""
+          ></gr-autocomplete>
+          <div id="trigger">▼</div>
+        </div>
+      </div>
+    `);
+  });
 });
diff --git a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.ts b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.ts
index 31efa73..99aebb1 100644
--- a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.ts
@@ -26,8 +26,9 @@
 suite('gr-repo-branch-picker tests', () => {
   let element: GrRepoBranchPicker;
 
-  setup(() => {
+  setup(async () => {
     element = basicFixture.instantiate();
+    await flush();
   });
 
   suite('_getRepoSuggestions', () => {