diff --git a/src/env.d.ts b/src/env.d.ts index b439ffda8..a432f9fec 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1,15 +1,19 @@ interface ShadyCSS { - styleElement(host: Element, overrideProps?: {[key: string]: string}): void; + styleElement(host: Element, overrideProps?: { [key: string]: string }): void; getComputedStyleValue(element: Element, property: string): string; - ScopingShim: undefined|{ - prepareAdoptedCssText(cssText: string[], name: string): void; - }; + ScopingShim: + | undefined + | { + prepareAdoptedCssText(cssText: string[], name: string): void; + }; nativeShadow: boolean; } interface ShadyDOM { inUse: boolean; flush: () => void; + noPatch: boolean | string; + wrap: (node: Element | DocumentFragment) => Element | DocumentFragment; } interface Window { @@ -23,7 +27,7 @@ interface ShadowRoot { adoptedStyleSheets: CSSStyleSheet[]; } -declare var ShadowRoot: {prototype: ShadowRoot; new (): ShadowRoot;} +declare var ShadowRoot: { prototype: ShadowRoot; new (): ShadowRoot }; interface CSSStyleSheet { replaceSync(cssText: string): void; diff --git a/src/lib/decorators.ts b/src/lib/decorators.ts index 8681c7c41..9d0059813 100644 --- a/src/lib/decorators.ts +++ b/src/lib/decorators.ts @@ -19,7 +19,7 @@ * not an arrow function. */ -import {LitElement} from '../lit-element.js'; +import {LitElement, wrap} from '../lit-element.js'; import {PropertyDeclaration, UpdatingElement} from './updating-element.js'; @@ -221,7 +221,7 @@ export function query(selector: string, cache?: boolean) { name?: PropertyKey): any => { const descriptor = { get(this: LitElement) { - return this.renderRoot.querySelector(selector); + return wrap(this.renderRoot).querySelector(selector); }, enumerable: true, configurable: true, @@ -232,7 +232,7 @@ export function query(selector: string, cache?: boolean) { if ((this as unknown as {[key: string]: Element | null})[key as string] === undefined) { ((this as unknown as {[key: string]: Element | null})[key as string] = - this.renderRoot.querySelector(selector)); + wrap(this.renderRoot).querySelector(selector)); } return ( this as unknown as {[key: string]: Element | null})[key as string]; @@ -289,7 +289,7 @@ export function queryAsync(selector: string) { const descriptor = { async get(this: LitElement) { await this.updateComplete; - return this.renderRoot.querySelector(selector); + return wrap(this.renderRoot).querySelector(selector); }, enumerable: true, configurable: true, @@ -331,7 +331,7 @@ export function queryAll(selector: string) { name?: PropertyKey): any => { const descriptor = { get(this: LitElement) { - return this.renderRoot.querySelectorAll(selector); + return wrap(this.renderRoot).querySelectorAll(selector); }, enumerable: true, configurable: true, @@ -460,8 +460,8 @@ export function queryAssignedNodes( get(this: LitElement) { const slotSelector = `slot${slotName ? `[name=${slotName}]` : ':not([name])'}`; - const slot = this.renderRoot.querySelector(slotSelector); - let nodes = slot && (slot as HTMLSlotElement).assignedNodes({flatten}); + const slot = wrap(this.renderRoot).querySelector(slotSelector); + let nodes = slot && (wrap(slot) as HTMLSlotElement).assignedNodes({flatten}); if (nodes && selector) { nodes = nodes.filter( (node) => node.nodeType === Node.ELEMENT_NODE && diff --git a/src/lit-element.ts b/src/lit-element.ts index 20f3740c6..bc16a088e 100644 --- a/src/lit-element.ts +++ b/src/lit-element.ts @@ -87,6 +87,14 @@ export interface CSSResultArray extends */ const renderNotImplemented = {}; +const needsWrap = + window.ShadyDOM && + window.ShadyDOM!.inUse && + window.ShadyDOM!.noPatch === true; +export const wrap = (element: Element | DocumentFragment) => { + return needsWrap ? window.ShadyDOM!.wrap(element) : element; +}; + /** * Base element class that manages element properties and attributes, and * renders a lit-html template. @@ -236,7 +244,7 @@ export class LitElement extends UpdatingElement { * @returns {Element|DocumentFragment} Returns a node into which to render. */ protected createRenderRoot(): Element|ShadowRoot { - return this.attachShadow({mode: 'open'}); + return (wrap(this) as Element).attachShadow({mode: 'open'}); } /** diff --git a/src/test/lib/decorators_test.ts b/src/test/lib/decorators_test.ts index 9563f1ec4..6c2b44f35 100644 --- a/src/test/lib/decorators_test.ts +++ b/src/test/lib/decorators_test.ts @@ -13,7 +13,7 @@ */ import {eventOptions, property} from '../../lib/decorators.js'; -import {customElement, html, LitElement, PropertyValues, query, queryAll, queryAssignedNodes, queryAsync} from '../../lit-element.js'; +import {customElement, html, LitElement, PropertyValues, query, queryAll, queryAssignedNodes, queryAsync, wrap} from '../../lit-element.js'; import {generateElementName} from '../test-helpers.js'; const flush = @@ -73,12 +73,12 @@ suite('decorators', () => { setup(() => { container = document.createElement('div'); container.id = 'test-container'; - document.body.appendChild(container); + wrap(document.body).appendChild(container); }); teardown(() => { if (container !== undefined) { - container.parentElement!.removeChild(container); + wrap(container.parentElement!).removeChild(container); (container as any) = undefined; } }); @@ -129,7 +129,7 @@ suite('decorators', () => { } customElements.define(generateElementName(), E); const el = new E(); - container.appendChild(el); + wrap(container).appendChild(el); await el.updateComplete; assert.equal(el.updateCount, 1); assert.equal(el.noAttr, 'noAttr'); @@ -206,7 +206,7 @@ suite('decorators', () => { } customElements.define(generateElementName(), E); const el = new E(); - container.appendChild(el); + wrap(container).appendChild(el); await el.updateComplete; assert.equal(el._foo, undefined); assert.equal(el.updatedContent, undefined); @@ -267,7 +267,7 @@ suite('decorators', () => { } customElements.define(generateElementName(), E); const el = new E(); - container.appendChild(el); + wrap(container).appendChild(el); await el.updateComplete; assert.equal(el.updateCount, 1); assert.equal(el.noAttr, 'noAttr'); @@ -343,7 +343,7 @@ suite('decorators', () => { test('returns an element when it exists', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; const div = c.div; assert.instanceOf(div, HTMLDivElement); @@ -352,7 +352,7 @@ suite('decorators', () => { test('returns null when no match', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; assert.isNull(c.span); }); @@ -360,7 +360,7 @@ suite('decorators', () => { test('returns cached value', async () => { const c = new C(); c.condition = true; - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; assert.equal(c.span, c.renderRoot.querySelector('span')); assert.instanceOf(c.span, HTMLSpanElement); @@ -388,7 +388,7 @@ suite('decorators', () => { test('returns elements when they exists', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; const divs = c.divs; // This is not true in ShadyDOM: @@ -398,7 +398,7 @@ suite('decorators', () => { test('returns empty NodeList when no match', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; const spans = c.spans; // This is not true in ShadyDOM: @@ -459,17 +459,17 @@ suite('decorators', () => { test('returns assignedNodes for slot', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; await c.assignedNodesEl.updateComplete; // Note, `defaultAssigned` does not `flatten` so we test that the property // reflects current state and state when nodes are added or removed. assert.deepEqual(c.assignedNodesEl.defaultAssigned, [c.div]); const child = document.createElement('div'); - c.assignedNodesEl.appendChild(child); + wrap(c.assignedNodesEl).appendChild(child); flush(); assert.deepEqual(c.assignedNodesEl.defaultAssigned, [c.div, child]); - c.assignedNodesEl.removeChild(child); + wrap(c.assignedNodesEl).removeChild(child); flush(); assert.deepEqual(c.assignedNodesEl.defaultAssigned, [c.div]); }); @@ -478,7 +478,7 @@ suite('decorators', () => { 'returns assignedNodes for unnamed slot that is not first slot', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; await c.assignedNodesEl.updateComplete; assert.deepEqual(c.assignedNodesEl2.defaultAssigned, [c.div2]); @@ -486,7 +486,7 @@ suite('decorators', () => { test('returns flattened assignedNodes for slot', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; await c.assignedNodesEl.updateComplete; // Note, `defaultAssigned` does `flatten` so we test that the property @@ -495,18 +495,18 @@ suite('decorators', () => { assert.deepEqual(c.assignedNodesEl.footerAssigned, []); const child1 = document.createElement('div'); const child2 = document.createElement('div'); - c.appendChild(child1); - c.appendChild(child2); + wrap(c).appendChild(child1); + wrap(c).appendChild(child2); flush(); assert.deepEqual(c.assignedNodesEl.footerAssigned, [child1, child2]); - c.removeChild(child2); + wrap(c).removeChild(child2); flush(); assert.deepEqual(c.assignedNodesEl.footerAssigned, [child1]); }); test('returns assignedNodes for slot filtered by selector', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; await c.assignedNodesEl.updateComplete; // Note, `defaultAssigned` does `flatten` so we test that the property @@ -516,11 +516,11 @@ suite('decorators', () => { const child1 = document.createElement('div'); const child2 = document.createElement('div'); child2.classList.add('item'); - c.appendChild(child1); - c.appendChild(child2); + wrap(c).appendChild(child1); + wrap(c).appendChild(child2); flush(); assert.deepEqual(c.assignedNodesEl.footerAssignedItems, [child2]); - c.removeChild(child2); + wrap(c).removeChild(child2); flush(); assert.deepEqual(c.assignedNodesEl.footerAssignedItems, []); }); @@ -540,7 +540,7 @@ suite('decorators', () => { definedMatches = false; } const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; await c.assignedNodesEl.updateComplete; assert.deepEqual(c.assignedNodesEl.footerAssignedItems, []); @@ -549,13 +549,13 @@ suite('decorators', () => { const text1 = document.createTextNode(''); const text2 = document.createTextNode(''); child2.classList.add('item'); - c.appendChild(child1); - c.appendChild(text1); - c.appendChild(child2); - c.appendChild(text2); + wrap(c).appendChild(child1); + wrap(c).appendChild(text1); + wrap(c).appendChild(child2); + wrap(c).appendChild(text2); flush(); assert.deepEqual(c.assignedNodesEl.footerAssignedItems, [child2]); - c.removeChild(child2); + wrap(c).removeChild(child2); flush(); assert.deepEqual(c.assignedNodesEl.footerAssignedItems, []); if (definedMatches && descriptor !== undefined) { @@ -585,7 +585,7 @@ suite('decorators', () => { test('returns an element when it exists after update', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); let div = await c.blah; assert.instanceOf(div, HTMLDivElement); assert.isFalse(div.hasAttribute('foo')); @@ -597,7 +597,7 @@ suite('decorators', () => { test('returns null when no match', async () => { const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); const span = await c.nope; assert.isNull(span); }); @@ -625,9 +625,9 @@ suite('decorators', () => { } const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; - const button = c.shadowRoot!.querySelector('button')!; + const button = (wrap(c) as Element).shadowRoot!.querySelector('button')!; button.click(); assert.equal(c.eventPhase, Event.CAPTURING_PHASE); }); @@ -653,9 +653,9 @@ suite('decorators', () => { } const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; - const button = c.shadowRoot!.querySelector('button')!; + const button = (wrap(c) as Element).shadowRoot!.querySelector('button')!; button.click(); button.click(); assert.equal(c.clicked, 1); @@ -687,9 +687,9 @@ suite('decorators', () => { } const c = new C(); - container.appendChild(c); + wrap(container).appendChild(c); await c.updateComplete; - const button = c.shadowRoot!.querySelector('button')!; + const button = (wrap(c) as Element).shadowRoot!.querySelector('button')!; button.click(); assert.isFalse(c.defaultPrevented); }); diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index ef1161382..8a28fb496 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -14,7 +14,7 @@ import {customElement, property} from '../../lib/decorators.js'; import {ComplexAttributeConverter, defaultConverter, PropertyDeclaration, PropertyDeclarations, PropertyValues, UpdatingElement} from '../../lib/updating-element.js'; -import {generateElementName} from '../test-helpers.js'; +import {generateElementName, wrap} from '../test-helpers.js'; // tslint:disable:no-any ok in tests @@ -2352,9 +2352,9 @@ suite('UpdatingElement', () => { inner: E|null = null; firstUpdated() { - this.attachShadow({mode: 'open'}); + (wrap(this) as Element).attachShadow({mode: 'open'}); this.inner = document.createElement('x-1224') as E; - this.shadowRoot!.appendChild(this.inner); + (wrap(this) as Element).shadowRoot!.appendChild(this.inner); } get updateComplete() { diff --git a/src/test/lit-element_styling_test.ts b/src/test/lit-element_styling_test.ts index b94927a67..469a120f9 100644 --- a/src/test/lit-element_styling_test.ts +++ b/src/test/lit-element_styling_test.ts @@ -14,7 +14,7 @@ import '@webcomponents/shadycss/apply-shim.min.js'; -import {css, CSSResult, html as htmlWithStyles, LitElement, unsafeCSS} from '../lit-element.js'; +import {css, CSSResult, html as htmlWithStyles, LitElement, unsafeCSS, wrap} from '../lit-element.js'; import {generateElementName, getComputedStyleValue, nextFrame} from './test-helpers.js'; @@ -25,12 +25,12 @@ suite('Styling', () => { setup(() => { container = document.createElement('div'); - document.body.appendChild(container); + wrap(document.body).appendChild(container); }); teardown(() => { - if (container && container.parentNode) { - container.parentNode.removeChild(container); + if (container && wrap(container).parentNode) { + wrap(wrap(container).parentNode as Element).removeChild(container); } }); @@ -48,9 +48,9 @@ suite('Styling', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); }); @@ -74,9 +74,9 @@ suite('Styling', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '4px'); }); @@ -97,9 +97,9 @@ suite('Styling', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '8px'); }); @@ -130,18 +130,18 @@ suite('Styling', () => { } firstUpdated() { - this.inner = this.shadowRoot!.querySelector('x-inner')! as LitElement; + this.inner = (wrap(this) as Element).shadowRoot!.querySelector('x-inner')! as LitElement; } } customElements.define(name, E); const el = document.createElement(name) as E; - container.appendChild(el); + wrap(container).appendChild(el); // Workaround for Safari 9 Promise timing bugs. await el.updateComplete && await el.inner!.updateComplete; await nextFrame(); - const div = el.inner!.shadowRoot!.querySelector('div'); + const div = (wrap(el.inner!) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '8px'); }); @@ -173,7 +173,7 @@ suite('Styling', () => { } firstUpdated() { - this.inner = this.shadowRoot!.querySelector('x-inner1'); + this.inner = (wrap(this) as Element).shadowRoot!.querySelector('x-inner1'); } }); const name2 = generateElementName(); @@ -189,19 +189,19 @@ suite('Styling', () => { }); const el = document.createElement(name1) as LitElement; const el2 = document.createElement(name2); - container.appendChild(el); - container.appendChild(el2); + wrap(container).appendChild(el); + wrap(container).appendChild(el2); let div: Element|null; // Workaround for Safari 9 Promise timing bugs. await el.updateComplete; await nextFrame(); - const inner = el.shadowRoot!.querySelector('x-inner1'); - div = inner!.shadowRoot!.querySelector('div'); + const inner = (wrap(el) as Element).shadowRoot!.querySelector('x-inner1'); + div = (wrap(inner!) as Element).shadowRoot!.querySelector('div'); assert.equal( getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); - el2.shadowRoot!.appendChild(inner!); + (wrap(el2) as Element).shadowRoot!.appendChild(inner!); // Workaround for Safari 9 Promise timing bugs. await el.updateComplete; @@ -239,19 +239,19 @@ suite('Styling', () => { } firstUpdated() { - this.inner = this.shadowRoot!.querySelector('x-inner2') as LitElement; + this.inner = (wrap(this) as Element).shadowRoot!.querySelector('x-inner2') as LitElement; } } customElements.define(name, E); const el = document.createElement(name) as E; - container.appendChild(el); + wrap(container).appendChild(el); // Workaround for Safari 9 Promise timing bugs. await el.updateComplete && await el.inner!.updateComplete; await nextFrame(); - const div = el.shadowRoot!.querySelector( - 'x-inner2')!.shadowRoot!.querySelector('div'); + const div = (wrap((wrap(el) as Element).shadowRoot!.querySelector( + 'x-inner2')!) as Element).shadowRoot!.querySelector('div'); assert.equal( getComputedStyleValue(div!, 'border-top-width').trim(), '10px'); }); @@ -295,15 +295,15 @@ suite('Styling', () => { firstUpdated() { this.applied = - this.shadowRoot!.querySelector('x-applied') as LitElement; + (wrap(this) as Element).shadowRoot!.querySelector('x-applied') as LitElement; } } customElements.define(name, E); const firstApplied = document.createElement('x-applied') as I; - container.appendChild(firstApplied); + wrap(container).appendChild(firstApplied); const el = document.createElement(name) as E; - container.appendChild(el); + wrap(container).appendChild(el); // Workaround for Safari 9 Promise timing bugs. await firstApplied.updateComplete && el.updateComplete && @@ -328,12 +328,12 @@ suite('Static get styles', () => { setup(() => { container = document.createElement('div'); - document.body.appendChild(container); + wrap(document.body).appendChild(container); }); teardown(() => { - if (container && container.parentNode) { - container.parentNode.removeChild(container); + if (container && wrap(container).parentNode) { + wrap(wrap(container).parentNode as Element).removeChild(container); } }); @@ -359,11 +359,11 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); - const span = el.shadowRoot!.querySelector('span'); + const span = (wrap(el) as Element).shadowRoot!.querySelector('span'); assert.equal( getComputedStyleValue(span!, 'border-top-width').trim(), '3px'); }); @@ -397,9 +397,9 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - assert.equal(el.shadowRoot!.querySelectorAll('style').length, 2); + assert.equal((wrap(el) as Element).shadowRoot!.querySelectorAll('style').length, 2); }); test('static get styles can be a single CSSResult', async () => { @@ -417,9 +417,9 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); }); @@ -445,11 +445,11 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); - const span = el.shadowRoot!.querySelector('span'); + const span = (wrap(el) as Element).shadowRoot!.querySelector('span'); assert.equal( getComputedStyleValue(span!, 'border-top-width').trim(), '3px'); }); @@ -493,9 +493,9 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal( getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); }); @@ -531,12 +531,12 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); assert.equal(getComputedStyleValue(div!, 'padding-top').trim(), '4px'); - const span = el.shadowRoot!.querySelector('span'); + const span = (wrap(el) as Element).shadowRoot!.querySelector('span'); assert.equal( getComputedStyleValue(span!, 'border-top-width').trim(), '3px'); }); @@ -560,9 +560,9 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); }); @@ -602,12 +602,12 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const level1 = el.shadowRoot!.querySelector('.level1'); - const level2 = el.shadowRoot!.querySelector('.level2'); - const level3 = el.shadowRoot!.querySelector('.level3'); - const level4 = el.shadowRoot!.querySelector('.level4'); + const level1 = (wrap(el) as Element).shadowRoot!.querySelector('.level1'); + const level2 = (wrap(el) as Element).shadowRoot!.querySelector('.level2'); + const level3 = (wrap(el) as Element).shadowRoot!.querySelector('.level3'); + const level4 = (wrap(el) as Element).shadowRoot!.querySelector('.level4'); assert.equal( getComputedStyleValue(level1!, 'border-top-width').trim(), '1px'); assert.equal( @@ -638,11 +638,11 @@ suite('Static get styles', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); - const span = el.shadowRoot!.querySelector('span'); + const span = (wrap(el) as Element).shadowRoot!.querySelector('span'); assert.equal( getComputedStyleValue(span!, 'border-top-width').trim(), '3px'); }); @@ -700,20 +700,20 @@ suite('Static get styles', () => { } }); let el = document.createElement(base); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); el = document.createElement(sub); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const span = el.shadowRoot!.querySelector('span'); + const span = (wrap(el) as Element).shadowRoot!.querySelector('span'); assert.equal( getComputedStyleValue(span!, 'border-top-width').trim(), '3px'); el = document.createElement(subsub); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const p = el.shadowRoot!.querySelector('p'); + const p = (wrap(el) as Element).shadowRoot!.querySelector('p'); assert.equal(getComputedStyleValue(p!, 'border-top-width').trim(), '4px'); }); @@ -751,19 +751,19 @@ suite('Static get styles', () => { } }); let el = document.createElement(base); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - let div = el.shadowRoot!.querySelector('div'); + let div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '2px'); el = document.createElement(sub); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - div = el.shadowRoot!.querySelector('div'); + div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '3px'); el = document.createElement(subsub); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - div = el.shadowRoot!.querySelector('div'); + div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal(getComputedStyleValue(div!, 'border-top-width').trim(), '4px'); }); @@ -782,9 +782,9 @@ suite('Static get styles', () => { }); const el = document.createElement(sub); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal( getComputedStyle(div!).getPropertyValue('border-top-width').trim(), '4px'); @@ -812,8 +812,8 @@ suite('Static get styles', () => { }); const el1 = document.createElement(base); const el2 = document.createElement(base); - container.appendChild(el1); - container.appendChild(el2); + wrap(container).appendChild(el1); + wrap(container).appendChild(el2); await Promise.all([ (el1 as LitElement).updateComplete, (el2 as LitElement).updateComplete @@ -917,14 +917,14 @@ suite('Static get styles', () => { }); const el = document.createElement(base); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div')!; + const div = (wrap(el) as Element).shadowRoot!.querySelector('div')!; assert.equal( getComputedStyle(div).getPropertyValue('border-top-width').trim(), '4px'); - const span = el.shadowRoot!.querySelector('span')!; + const span = (wrap(el) as Element).shadowRoot!.querySelector('span')!; assert.equal( getComputedStyle(span).getPropertyValue('border-top-width').trim(), '4px'); @@ -964,10 +964,10 @@ suite('Static get styles', () => { }); const el = document.createElement(base); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - const div = el.shadowRoot!.querySelector('div')!; + const div = (wrap(el) as Element).shadowRoot!.querySelector('div')!; assert.equal( getComputedStyle(div).getPropertyValue('border-top-width').trim(), '4px'); @@ -1016,9 +1016,9 @@ suite('ShadyDOM', () => { } }); const el = document.createElement(name) as LitElement; - container.appendChild(el); + wrap(container).appendChild(el); await el.updateComplete; - const div = el.shadowRoot!.querySelector('div'); + const div = (wrap(el) as Element).shadowRoot!.querySelector('div'); assert.equal( getComputedStyleValue(div!, 'border-top-width').trim(), '6px'); border = `4px solid orange`; diff --git a/src/test/lit-element_test.ts b/src/test/lit-element_test.ts index 2405b5cdb..8e043531d 100644 --- a/src/test/lit-element_test.ts +++ b/src/test/lit-element_test.ts @@ -12,7 +12,7 @@ * http://polymer.github.io/PATENTS.txt */ -import {html, LitElement, property} from '../lit-element.js'; +import {html, LitElement, property, wrap} from '../lit-element.js'; import {generateElementName, stripExpressionDelimeters} from './test-helpers.js'; @@ -25,12 +25,12 @@ suite('LitElement', () => { setup(() => { container = document.createElement('div'); - document.body.appendChild(container); + wrap(document.body).appendChild(container); }); teardown(() => { - if (container && container.parentNode) { - container.parentNode.removeChild(container); + if (container && wrap(container).parentNode) { + wrap(wrap(container).parentNode as Element).removeChild(container); } }); @@ -43,12 +43,12 @@ suite('LitElement', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await new Promise((resolve) => { setTimeout(() => { - assert.ok(el.shadowRoot); + assert.ok((wrap(el) as Element).shadowRoot); assert.equal( - stripExpressionDelimeters(el.shadowRoot!.innerHTML), rendered); + stripExpressionDelimeters((wrap(el) as Element).shadowRoot!.innerHTML), rendered); resolve(); }); }); @@ -67,9 +67,9 @@ suite('LitElement', () => { } }); const el = document.createElement(name); - container.appendChild(el); + wrap(container).appendChild(el); await (el as LitElement).updateComplete; - assert.notOk(el.shadowRoot); + assert.notOk((wrap(el) as Element).shadowRoot); assert.equal(stripExpressionDelimeters(el.innerHTML), rendered); }); @@ -82,10 +82,10 @@ suite('LitElement', () => { } customElements.define(generateElementName(), E); const el = new E(); - container.appendChild(el); + wrap(container).appendChild(el); await el.updateComplete; - assert.ok(el.shadowRoot); - assert.equal(stripExpressionDelimeters(el.shadowRoot!.innerHTML), rendered); + assert.ok((wrap(el) as Element).shadowRoot); + assert.equal(stripExpressionDelimeters((wrap(el) as Element).shadowRoot!.innerHTML), rendered); }); test( @@ -106,9 +106,9 @@ suite('LitElement', () => { } customElements.define(generateElementName(), E); const el = new E(); - container.appendChild(el); + wrap(container).appendChild(el); await el.updateComplete; - const d = el.shadowRoot!.querySelector('div')!; + const d = (wrap(el) as Element).shadowRoot!.querySelector('div')!; assert.equal(d.getAttribute('attr'), 'attr'); assert.equal((d as any).prop, 'prop'); const e = new Event('zug'); @@ -130,9 +130,9 @@ suite('LitElement', () => { } customElements.define(generateElementName(), E); const el = new E(); - container.appendChild(el); + wrap(container).appendChild(el); await el.updateComplete; - const div = el.shadowRoot!.querySelector('div')!; + const div = (wrap(el) as Element).shadowRoot!.querySelector('div')!; const event = new Event('test'); div.dispatchEvent(event); assert.equal(el.event, event); @@ -167,7 +167,7 @@ suite('LitElement', () => { } firstUpdated() { - this.inner = this.shadowRoot!.querySelector('x-2448'); + this.inner = (wrap(this) as Element).shadowRoot!.querySelector('x-2448'); } get updateComplete() { @@ -176,16 +176,16 @@ suite('LitElement', () => { } customElements.define(generateElementName(), F); const el = new F(); - container.appendChild(el); + wrap(container).appendChild(el); await el.updateComplete; - assert.equal(el.inner!.shadowRoot!.textContent, 'outer'); + assert.equal((wrap(el.inner!) as Element).shadowRoot!.textContent, 'outer'); assert.equal((el.inner! as any).attr, 'outer'); assert.equal(el.inner!.getAttribute('attr'), 'outer'); assert.equal(el.inner!.bool, false); el.bar = 'test'; el.bool = true; await el.updateComplete; - assert.equal(el.inner!.shadowRoot!.textContent, 'test'); + assert.equal((wrap(el.inner!) as Element).shadowRoot!.textContent, 'test'); assert.equal((el.inner! as any).attr, 'test'); assert.equal(el.inner!.getAttribute('attr'), 'test'); assert.equal(el.inner!.bool, true); @@ -226,10 +226,10 @@ suite('LitElement', () => { customElements.define(generateElementName(), F); const el = new F(); - container.appendChild(el); + wrap(container).appendChild(el); while (!(await el.updateComplete)) { } - assert.equal(el.shadowRoot!.textContent, 'foo'); + assert.equal((wrap(el) as Element).shadowRoot!.textContent, 'foo'); }); test( @@ -249,9 +249,9 @@ suite('LitElement', () => { } customElements.define(generateElementName(), A); const a = new A(); - container.appendChild(a); + wrap(container).appendChild(a); await a.updateComplete; - assert.equal(a.shadowRoot!.textContent, '5'); + assert.equal((wrap(a) as Element).shadowRoot!.textContent, '5'); shouldThrow = true; a.foo = 10; let threw = false; @@ -262,12 +262,12 @@ suite('LitElement', () => { } assert.isTrue(threw); assert.equal(a.foo, 10); - assert.equal(a.shadowRoot!.textContent, '5'); + assert.equal((wrap(a) as Element).shadowRoot!.textContent, '5'); shouldThrow = false; a.foo = 20; await a.updateComplete; assert.equal(a.foo, 20); - assert.equal(a.shadowRoot!.textContent, '20'); + assert.equal((wrap(a) as Element).shadowRoot!.textContent, '20'); }); test( @@ -282,7 +282,7 @@ suite('LitElement', () => { const a = new A(); const testDom = document.createElement('div'); a.appendChild(testDom); - container.appendChild(a); + wrap(container).appendChild(a); await a.updateComplete; assert.equal( testDom.parentNode, diff --git a/src/test/test-helpers.ts b/src/test/test-helpers.ts index a33e4328a..f548d26ac 100644 --- a/src/test/test-helpers.ts +++ b/src/test/test-helpers.ts @@ -24,3 +24,6 @@ export const nextFrame = () => export const getComputedStyleValue = (element: Element, property: string) => window.ShadyCSS ? window.ShadyCSS.getComputedStyleValue(element, property) : getComputedStyle(element).getPropertyValue(property); + +export const wrap = (node: Element) => + window.ShadyDOM ? window.ShadyDOM.wrap(node) : node; \ No newline at end of file diff --git a/test/runner-noPatch.html b/test/runner-noPatch.html new file mode 100644 index 000000000..5a2f8b27c --- /dev/null +++ b/test/runner-noPatch.html @@ -0,0 +1,38 @@ + + + + lit-element tests + + + + + + + + + + + + +