From 30dabdf8fc893d0557364f67c56b593b46c6254c Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Fri, 23 Aug 2019 13:28:33 -0700 Subject: [PATCH] refactor(core): remove testing-only DOM manipulation utils from DomAdapters (#32291) PR Close #32291 --- packages/common/test/directives/ng_if_spec.ts | 3 +- packages/core/test/application_ref_spec.ts | 4 +-- packages/core/test/dom/dom_adapter_spec.ts | 31 ------------------ packages/core/test/linker/integration_spec.ts | 9 +++--- packages/core/test/view/text_spec.ts | 8 ++--- .../src/dom_test_component_renderer.ts | 5 +-- .../src/browser/browser_adapter.ts | 17 ---------- .../src/browser/generic_browser_adapter.ts | 1 - .../platform-browser/src/dom/dom_adapter.ts | 32 +++++++------------ .../testing/src/browser_util.ts | 19 +++++++++-- .../platform-browser/testing/src/matchers.ts | 10 +++--- .../platform-server/src/domino_adapter.ts | 2 -- .../platform-server/test/integration_spec.ts | 10 +++--- .../src/web_workers/worker/worker_adapter.ts | 8 ----- 14 files changed, 53 insertions(+), 106 deletions(-) diff --git a/packages/common/test/directives/ng_if_spec.ts b/packages/common/test/directives/ng_if_spec.ts index 79c805406c..a88119c7df 100644 --- a/packages/common/test/directives/ng_if_spec.ts +++ b/packages/common/test/directives/ng_if_spec.ts @@ -103,8 +103,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers'; fixture.detectChanges(); expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(3); - expect(getDOM().getText(fixture.nativeElement)) - .toEqual('helloNumberhelloStringhelloFunction'); + expect(fixture.nativeElement.textContent).toEqual('helloNumberhelloStringhelloFunction'); getComponent().numberCondition = 0; fixture.detectChanges(); diff --git a/packages/core/test/application_ref_spec.ts b/packages/core/test/application_ref_spec.ts index 943baf6b50..8151b14c7c 100644 --- a/packages/core/test/application_ref_spec.ts +++ b/packages/core/test/application_ref_spec.ts @@ -15,7 +15,7 @@ import {ComponentRef} from '@angular/core/src/linker/component_factory'; import {getLocaleId} from '@angular/core/src/render3'; import {BrowserModule} from '@angular/platform-browser'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; -import {dispatchEvent, getContent} from '@angular/platform-browser/testing/src/browser_util'; +import {createTemplate, dispatchEvent, getContent} from '@angular/platform-browser/testing/src/browser_util'; import {expect} from '@angular/platform-browser/testing/src/matchers'; import {onlyInIvy} from '@angular/private/testing'; @@ -35,7 +35,7 @@ class SomeComponent { function createRootEl(selector = 'bootstrap-app') { const doc = TestBed.get(DOCUMENT); const rootEl = getDOM().firstChild( - getContent(getDOM().createTemplate(`<${selector}>`))); + getContent(createTemplate(`<${selector}>`))); const oldRoots = getDOM().querySelectorAll(doc, selector); for (let i = 0; i < oldRoots.length; i++) { getDOM().remove(oldRoots[i]); diff --git a/packages/core/test/dom/dom_adapter_spec.ts b/packages/core/test/dom/dom_adapter_spec.ts index 63e366b2d7..af272f2ae4 100644 --- a/packages/core/test/dom/dom_adapter_spec.ts +++ b/packages/core/test/dom/dom_adapter_spec.ts @@ -17,37 +17,6 @@ import {el, isTextNode, stringifyElement} from '@angular/platform-browser/testin defaultDoc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument(); }); - it('should not coalesque text nodes', () => { - const el1 = el('
a
'); - const el2 = el('
b
'); - getDOM().appendChild(el2, getDOM().firstChild(el1)); - expect(getDOM().childNodes(el2).length).toBe(2); - - const el2Clone = getDOM().clone(el2); - expect(getDOM().childNodes(el2Clone).length).toBe(2); - }); - - it('should clone correctly', () => { - const el1 = el('
ab
'); - const clone = getDOM().clone(el1); - - expect(clone).not.toBe(el1); - getDOM().setAttribute(clone, 'test', '1'); - expect(stringifyElement(clone)).toEqual('
ab
'); - expect(getDOM().getAttribute(el1, 'test')).toBeFalsy(); - - const cNodes = getDOM().childNodes(clone); - const firstChild = cNodes[0]; - const secondChild = cNodes[1]; - expect(getDOM().parentElement(firstChild)).toBe(clone); - expect(getDOM().nextSibling(firstChild)).toBe(secondChild); - expect(isTextNode(firstChild)).toBe(true); - - expect(getDOM().parentElement(secondChild)).toBe(clone); - expect(getDOM().nextSibling(secondChild)).toBeFalsy(); - expect(getDOM().isElementNode(secondChild)).toBe(true); - }); - it('should be able to create text nodes and use them with the other APIs', () => { const t = getDOM().createTextNode('hello'); expect(isTextNode(t)).toBe(true); diff --git a/packages/core/test/linker/integration_spec.ts b/packages/core/test/linker/integration_spec.ts index 68ca936052..f18b9fc323 100644 --- a/packages/core/test/linker/integration_spec.ts +++ b/packages/core/test/linker/integration_spec.ts @@ -1006,8 +1006,8 @@ function declareTests(config?: {useJit: boolean}) { getDOM().dispatchEvent(fixture.debugElement.children[1].nativeElement, dispatchedEvent2); expect(getDOM().isPrevented(dispatchedEvent)).toBe(true); expect(getDOM().isPrevented(dispatchedEvent2)).toBe(false); - expect(getDOM().getChecked(fixture.debugElement.children[0].nativeElement)).toBeFalsy(); - expect(getDOM().getChecked(fixture.debugElement.children[1].nativeElement)).toBeTruthy(); + expect(fixture.debugElement.children[0].nativeElement.checked).toBeFalsy(); + expect(fixture.debugElement.children[1].nativeElement.checked).toBeTruthy(); }); } @@ -2689,15 +2689,14 @@ class ComponentWithoutView { @Directive({selector: '[no-duplicate]'}) class DuplicateDir { constructor(elRef: ElementRef) { - getDOM().setText(elRef.nativeElement, getDOM().getText(elRef.nativeElement) + 'noduplicate'); + getDOM().setText(elRef.nativeElement, elRef.nativeElement.textContent + 'noduplicate'); } } @Directive({selector: '[no-duplicate]'}) class OtherDuplicateDir { constructor(elRef: ElementRef) { - getDOM().setText( - elRef.nativeElement, getDOM().getText(elRef.nativeElement) + 'othernoduplicate'); + getDOM().setText(elRef.nativeElement, elRef.nativeElement.textContent + 'othernoduplicate'); } } diff --git a/packages/core/test/view/text_spec.ts b/packages/core/test/view/text_spec.ts index 427fdad852..47b74a4ecd 100644 --- a/packages/core/test/view/text_spec.ts +++ b/packages/core/test/view/text_spec.ts @@ -19,7 +19,7 @@ import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, compViewDef, createAndGetRoot it('should create text nodes without parents', () => { const rootNodes = createAndGetRootNodes(compViewDef([textDef(0, null, ['a'])])).rootNodes; expect(rootNodes.length).toBe(1); - expect(getDOM().getText(rootNodes[0])).toBe('a'); + expect(rootNodes[0].textContent).toBe('a'); }); it('should create views with multiple root text nodes', () => { @@ -36,8 +36,8 @@ import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, compViewDef, createAndGetRoot textDef(1, null, ['a']), ])).rootNodes; expect(rootNodes.length).toBe(1); - const textNode = getDOM().firstChild(rootNodes[0]); - expect(getDOM().getText(textNode)).toBe('a'); + const textNode = getDOM().firstChild(rootNodes[0]) as Element; + expect(textNode.textContent).toBe('a'); }); it('should add debug information to the renderer', () => { @@ -61,7 +61,7 @@ import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, compViewDef, createAndGetRoot Services.checkAndUpdateView(view); - expect(getDOM().getText(rootNodes[0])).toBe('0a1b2'); + expect(rootNodes[0].textContent).toBe('0a1b2'); }); }); diff --git a/packages/platform-browser-dynamic/testing/src/dom_test_component_renderer.ts b/packages/platform-browser-dynamic/testing/src/dom_test_component_renderer.ts index cecb67241b..ca23fe4391 100644 --- a/packages/platform-browser-dynamic/testing/src/dom_test_component_renderer.ts +++ b/packages/platform-browser-dynamic/testing/src/dom_test_component_renderer.ts @@ -19,8 +19,9 @@ export class DOMTestComponentRenderer extends TestComponentRenderer { constructor(@Inject(DOCUMENT) private _doc: any) { super(); } insertRootElement(rootElId: string) { - const rootEl = getDOM().firstChild( - getContent(getDOM().createTemplate(`
`))); + const template = getDOM().getDefaultDocument().createElement('template'); + template.innerHTML = `
`; + const rootEl = getDOM().firstChild(getContent(template)); // TODO(juliemr): can/should this be optional? const oldRoots = getDOM().querySelectorAll(this._doc, '[id^=root]'); diff --git a/packages/platform-browser/src/browser/browser_adapter.ts b/packages/platform-browser/src/browser/browser_adapter.ts index 1ec8fd3e0e..dab73efa3e 100644 --- a/packages/platform-browser/src/browser/browser_adapter.ts +++ b/packages/platform-browser/src/browser/browser_adapter.ts @@ -146,14 +146,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { nextSibling(el: Node): Node|null { return el.nextSibling; } parentElement(el: Node): Node|null { return el.parentNode; } childNodes(el: any): Node[] { return el.childNodes; } - childNodesAsList(el: Node): any[] { - const childNodes = el.childNodes; - const res = []; - for (let i = 0; i < childNodes.length; i++) { - res[i] = childNodes[i]; - } - return res; - } clearNodes(el: Node) { while (el.firstChild) { el.removeChild(el.firstChild); @@ -168,17 +160,9 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { return node; } insertBefore(parent: Node, ref: Node, node: Node) { parent.insertBefore(node, ref); } - getText(el: Node): string|null { return el.textContent; } setText(el: Node, value: string) { el.textContent = value; } getValue(el: any): string { return el.value; } - setValue(el: any, value: string) { el.value = value; } - getChecked(el: any): boolean { return el.checked; } createComment(text: string): Comment { return this.getDefaultDocument().createComment(text); } - createTemplate(html: any): HTMLElement { - const t = this.getDefaultDocument().createElement('template'); - t.innerHTML = html; - return t; - } createElement(tagName: string, doc?: Document): HTMLElement { doc = doc || this.getDefaultDocument(); return doc.createElement(tagName); @@ -192,7 +176,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { return doc.createTextNode(text); } getHost(el: HTMLElement): HTMLElement { return (el).host; } - clone(node: Node): Node { return node.cloneNode(true); } getElementsByTagName(element: any, name: string): HTMLElement[] { return element.getElementsByTagName(name); } diff --git a/packages/platform-browser/src/browser/generic_browser_adapter.ts b/packages/platform-browser/src/browser/generic_browser_adapter.ts index 3b630f0d65..e7791cdaef 100644 --- a/packages/platform-browser/src/browser/generic_browser_adapter.ts +++ b/packages/platform-browser/src/browser/generic_browser_adapter.ts @@ -19,6 +19,5 @@ import {DomAdapter} from '../dom/dom_adapter'; export abstract class GenericBrowserDomAdapter extends DomAdapter { constructor() { super(); } - getDistributedNodes(el: HTMLElement): Node[] { return (el).getDistributedNodes(); } supportsDOMEvents(): boolean { return true; } } diff --git a/packages/platform-browser/src/dom/dom_adapter.ts b/packages/platform-browser/src/dom/dom_adapter.ts index 23cb359904..b6cc5ff7fc 100644 --- a/packages/platform-browser/src/dom/dom_adapter.ts +++ b/packages/platform-browser/src/dom/dom_adapter.ts @@ -60,31 +60,22 @@ export abstract class DomAdapter { abstract nextSibling(el: any): Node|null; abstract parentElement(el: any): Node|null; abstract childNodes(el: any): Node[]; - abstract childNodesAsList(el: any): Node[]; - abstract clearNodes(el: any): any; - abstract appendChild(el: any, node: any): any; - abstract removeChild(el: any, node: any): any; - abstract remove(el: any): Node; - abstract insertBefore(parent: any, ref: any, node: any): any; - abstract getText(el: any): string|null; - abstract setText(el: any, value: string): any; - abstract getValue(el: any): string; - abstract setValue(el: any, value: string): any; - abstract getChecked(el: any): boolean; - abstract createComment(text: string): any; - abstract createTemplate(html: any): HTMLElement; - abstract createElement(tagName: any, doc?: any): HTMLElement; - abstract createElementNS(ns: string, tagName: string, doc?: any): Element; - abstract createTextNode(text: string, doc?: any): Text; - abstract getHost(el: any): any; - abstract getDistributedNodes(el: any): Node[]; - abstract clone /**/ (node: Node /*T*/): Node /*T*/; - abstract getElementsByTagName(element: any, name: string): HTMLElement[]; // Used by Meta + abstract remove(el: any): Node; abstract getAttribute(element: any, attribute: string): string|null; // Used by platform-server + abstract clearNodes(el: any): any; + abstract appendChild(el: any, node: any): any; + abstract removeChild(el: any, node: any): any; + abstract insertBefore(parent: any, ref: any, node: any): any; + abstract setText(el: any, value: string): any; + abstract createComment(text: string): any; + abstract createElement(tagName: any, doc?: any): HTMLElement; + abstract createElementNS(ns: string, tagName: string, doc?: any): Element; + abstract createTextNode(text: string, doc?: any): Text; + abstract getElementsByTagName(element: any, name: string): HTMLElement[]; abstract addClass(element: any, className: string): any; abstract removeClass(element: any, className: string): any; abstract getStyle(element: any, styleName: string): any; @@ -107,6 +98,7 @@ export abstract class DomAdapter { // Used by Testability abstract isShadowRoot(node: any): boolean; + abstract getHost(el: any): any; // Used by KeyEventsPlugin abstract getEventKey(event: any): string; diff --git a/packages/platform-browser/testing/src/browser_util.ts b/packages/platform-browser/testing/src/browser_util.ts index c7d5da8e0d..11a89eef5e 100644 --- a/packages/platform-browser/testing/src/browser_util.ts +++ b/packages/platform-browser/testing/src/browser_util.ts @@ -95,7 +95,7 @@ export function dispatchEvent(element: any, eventType: any): void { } export function el(html: string): HTMLElement { - return getDOM().firstChild(getContent(getDOM().createTemplate(html))); + return getDOM().firstChild(getContent(createTemplate(html))); } export function normalizeCSS(css: string): string { @@ -160,7 +160,7 @@ export function stringifyElement(el: any /** TODO #9100 */): string { } else if (isCommentNode(el)) { result += ``; } else { - result += getDOM().getText(el); + result += el.textContent; } return result; @@ -212,3 +212,18 @@ export function hasClass(element: any, className: string): boolean { export function sortedClassList(element: any): any[] { return Array.prototype.slice.call(element.classList, 0).sort(); } + +export function createTemplate(html: any): HTMLElement { + const t = getDOM().getDefaultDocument().createElement('template'); + t.innerHTML = html; + return t; +} + +export function childNodesAsList(el: Node): any[] { + const childNodes = el.childNodes; + const res = []; + for (let i = 0; i < childNodes.length; i++) { + res[i] = childNodes[i]; + } + return res; +} diff --git a/packages/platform-browser/testing/src/matchers.ts b/packages/platform-browser/testing/src/matchers.ts index ef7a151930..763813d42c 100644 --- a/packages/platform-browser/testing/src/matchers.ts +++ b/packages/platform-browser/testing/src/matchers.ts @@ -11,7 +11,7 @@ import {Type, ɵglobal as global} from '@angular/core'; import {ComponentFixture} from '@angular/core/testing'; import {By, ɵgetDOM as getDOM} from '@angular/platform-browser'; -import {hasClass, hasStyle, isCommentNode} from './browser_util'; +import {childNodesAsList, hasClass, hasStyle, isCommentNode} from './browser_util'; @@ -293,18 +293,18 @@ function elementText(n: any): string { } if (getDOM().isElementNode(n) && (n as Element).tagName == 'CONTENT') { - return elementText(Array.prototype.slice.apply(getDOM().getDistributedNodes(n))); + return elementText(Array.prototype.slice.apply((n).getDistributedNodes())); } if (hasShadowRoot(n)) { - return elementText(getDOM().childNodesAsList((n).shadowRoot)); + return elementText(childNodesAsList((n).shadowRoot)); } if (hasNodes(n)) { - return elementText(getDOM().childNodesAsList(n)); + return elementText(childNodesAsList(n)); } - return getDOM().getText(n) !; + return (n as any).textContent; } function hasShadowRoot(node: any): boolean { diff --git a/packages/platform-server/src/domino_adapter.ts b/packages/platform-server/src/domino_adapter.ts index 4a0ee77820..04a8e23a5f 100644 --- a/packages/platform-server/src/domino_adapter.ts +++ b/packages/platform-server/src/domino_adapter.ts @@ -197,8 +197,6 @@ export class DominoAdapter extends BrowserDomAdapter { performanceNow(): number { return Date.now(); } - getDistributedNodes(el: any): Node[] { throw _notImplemented('getDistributedNodes'); } - supportsCookies(): boolean { return false; } getCookie(name: string): string { throw _notImplemented('getCookie'); } } diff --git a/packages/platform-server/test/integration_spec.ts b/packages/platform-server/test/integration_spec.ts index 80ded7a44b..b3e93f19d8 100644 --- a/packages/platform-server/test/integration_spec.ts +++ b/packages/platform-server/test/integration_spec.ts @@ -412,7 +412,7 @@ class HiddenModule { expect(doc.head).toBe(getDOM().querySelector(doc, 'head')); expect(doc.body).toBe(getDOM().querySelector(doc, 'body')); - expect(getDOM().getText(doc.documentElement)).toEqual('Works!'); + expect(doc.documentElement.textContent).toEqual('Works!'); platform.destroy(); }); @@ -428,13 +428,13 @@ class HiddenModule { platform.bootstrapModule(ExampleModule).then((moduleRef) => { const doc = moduleRef.injector.get(DOCUMENT); - expect(getDOM().getText(doc.documentElement)).toEqual('Works!'); + expect(doc.documentElement.textContent).toEqual('Works!'); platform.destroy(); }); platform2.bootstrapModule(ExampleModule2).then((moduleRef) => { const doc = moduleRef.injector.get(DOCUMENT); - expect(getDOM().getText(doc.documentElement)).toEqual('Works too!'); + expect(doc.documentElement.textContent).toEqual('Works too!'); platform2.destroy(); }); })); @@ -449,7 +449,7 @@ class HiddenModule { const state = ref.injector.get(PlatformState); const doc = ref.injector.get(DOCUMENT); const title = getDOM().querySelector(doc, 'title'); - expect(getDOM().getText(title)).toBe('Test App Title'); + expect(title.textContent).toBe('Test App Title'); expect(state.renderToString()).toContain('Test App Title'); }); })); @@ -477,7 +477,7 @@ class HiddenModule { const head = getDOM().getElementsByTagName(doc, 'head')[0]; const styles: any[] = head.children as any; expect(styles.length).toBe(1); - expect(getDOM().getText(styles[0])).toContain('color: red'); + expect(styles[0].textContent).toContain('color: red'); expect(getDOM().getAttribute(styles[0], 'ng-transition')).toBe('example-styles'); }); })); diff --git a/packages/platform-webworker/src/web_workers/worker/worker_adapter.ts b/packages/platform-webworker/src/web_workers/worker/worker_adapter.ts index f54dd66d0f..3027e2f28b 100644 --- a/packages/platform-webworker/src/web_workers/worker/worker_adapter.ts +++ b/packages/platform-webworker/src/web_workers/worker/worker_adapter.ts @@ -69,25 +69,17 @@ export class WorkerDomAdapter extends DomAdapter { nextSibling(el: any): Node { throw 'not implemented'; } parentElement(el: any): Node { throw 'not implemented'; } childNodes(el: any): Node[] { throw 'not implemented'; } - childNodesAsList(el: any): Node[] { throw 'not implemented'; } clearNodes(el: any) { throw 'not implemented'; } appendChild(el: any, node: any) { throw 'not implemented'; } removeChild(el: any, node: any) { throw 'not implemented'; } remove(el: any): Node { throw 'not implemented'; } insertBefore(parent: any, el: any, node: any) { throw 'not implemented'; } - getText(el: any): string { throw 'not implemented'; } setText(el: any, value: string) { throw 'not implemented'; } - getValue(el: any): string { throw 'not implemented'; } - setValue(el: any, value: string) { throw 'not implemented'; } - getChecked(el: any): boolean { throw 'not implemented'; } createComment(text: string): any { throw 'not implemented'; } - createTemplate(html: any): HTMLElement { throw 'not implemented'; } createElement(tagName: any, doc?: any): HTMLElement { throw 'not implemented'; } createElementNS(ns: string, tagName: string, doc?: any): Element { throw 'not implemented'; } createTextNode(text: string, doc?: any): Text { throw 'not implemented'; } getHost(el: any): any { throw 'not implemented'; } - getDistributedNodes(el: any): Node[] { throw 'not implemented'; } - clone(node: Node): Node { throw 'not implemented'; } getElementsByTagName(element: any, name: string): HTMLElement[] { throw 'not implemented'; } addClass(element: any, className: string) { throw 'not implemented'; } removeClass(element: any, className: string) { throw 'not implemented'; }