blob: fa7cc29f0069cdd52caf984a926d9f1e120bcd3e [file] [log] [blame]
/**
* @license
* Copyright (C) 2021 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 {define, provide, resolve, DIPolymerElement} from './dependency';
import {html, LitElement} from 'lit';
import {customElement as polyCustomElement} from '@polymer/decorators';
import {html as polyHtml} from '@polymer/polymer/lib/utils/html-tag';
import {customElement, property, query} from 'lit/decorators';
import '../test/common-test-setup-karma.js';
interface FooService {
value: string;
}
const fooToken = define<FooService>('foo');
interface BarService {
value: string;
}
const barToken = define<BarService>('bar');
class FooImpl implements FooService {
constructor(public readonly value: string) {}
}
class BarImpl implements BarService {
constructor(private readonly foo: FooService) {}
get value() {
return this.foo.value;
}
}
@customElement('lit-foo-provider')
export class LitFooProviderElement extends LitElement {
@query('bar-provider')
bar?: BarProviderElement;
@property({type: Boolean})
public showBarProvider = true;
constructor() {
super();
provide(this, fooToken, () => new FooImpl('foo'));
}
override render() {
if (this.showBarProvider) {
return html`<bar-provider></bar-provider>`;
} else {
return undefined;
}
}
}
@polyCustomElement('polymer-foo-provider')
export class PolymerFooProviderElement extends DIPolymerElement {
bar() {
return this.$.bar as BarProviderElement;
}
override connectedCallback() {
provide(this, fooToken, () => new FooImpl('foo'));
super.connectedCallback();
}
static get template() {
return polyHtml`<bar-provider id="bar"></bar-provider>`;
}
}
@customElement('bar-provider')
export class BarProviderElement extends LitElement {
@query('leaf-lit-element')
litChild?: LeafLitElement;
@query('leaf-polymer-element')
polymerChild?: LeafPolymerElement;
@property({type: Boolean})
public showLit = true;
override connectedCallback() {
super.connectedCallback();
provide(this, barToken, () => this.create());
}
private create() {
const fooRef = resolve(this, fooToken);
assert.isDefined(fooRef());
return new BarImpl(fooRef());
}
override render() {
if (this.showLit) {
return html`<leaf-lit-element></leaf-lit-element>`;
} else {
return html`<leaf-polymer-element></leaf-polymer-element>`;
}
}
}
@customElement('leaf-lit-element')
export class LeafLitElement extends LitElement {
readonly barRef = resolve(this, barToken);
override connectedCallback() {
super.connectedCallback();
assert.isDefined(this.barRef());
}
override render() {
return html`${this.barRef().value}`;
}
}
@polyCustomElement('leaf-polymer-element')
export class LeafPolymerElement extends DIPolymerElement {
readonly barRef = resolve(this, barToken);
override connectedCallback() {
super.connectedCallback();
assert.isDefined(this.barRef());
}
static get template() {
return polyHtml`Hello`;
}
}
suite('Dependency', () => {
test('It instantiates', async () => {
const fixture = fixtureFromElement('lit-foo-provider');
const element = fixture.instantiate();
await element.updateComplete;
assert.isDefined(element.bar?.litChild?.barRef());
});
test('It instantiates in polymer', async () => {
const fixture = fixtureFromElement('polymer-foo-provider');
const element = fixture.instantiate();
await element.bar().updateComplete;
assert.isDefined(element.bar().litChild?.barRef());
});
test('It works by connecting and reconnecting', async () => {
const fixture = fixtureFromElement('lit-foo-provider');
const element = fixture.instantiate();
await element.updateComplete;
assert.isDefined(element.bar?.litChild?.barRef());
element.showBarProvider = false;
await element.updateComplete;
assert.isNull(element.bar);
element.showBarProvider = true;
await element.updateComplete;
assert.isDefined(element.bar?.litChild?.barRef());
});
test('It works by connecting and reconnecting Polymer', async () => {
const fixture = fixtureFromElement('lit-foo-provider');
const element = fixture.instantiate();
await element.updateComplete;
const beta = element.bar;
assert.isDefined(beta);
assert.isNotNull(beta);
assert.isDefined(element.bar?.litChild?.barRef());
beta!.showLit = false;
await element.updateComplete;
assert.isDefined(element.bar?.polymerChild?.barRef());
});
});
declare global {
interface HTMLElementTagNameMap {
'lit-foo-provider': LitFooProviderElement;
'polymer-foo-provider': PolymerFooProviderElement;
'bar-provider': BarProviderElement;
'leaf-lit-element': LeafLitElement;
'leaf-polymer-element': LeafPolymerElement;
}
}