refactor(core): remove testing-only DOM manipulation utils from DomAdapters (#32291)
PR Close #32291
This commit is contained in:
parent
ede5786d1e
commit
30dabdf8fc
|
@ -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();
|
||||
|
|
|
@ -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 = <HTMLElement>getDOM().firstChild(
|
||||
getContent(getDOM().createTemplate(`<${selector}></${selector}>`)));
|
||||
getContent(createTemplate(`<${selector}></${selector}>`)));
|
||||
const oldRoots = getDOM().querySelectorAll(doc, selector);
|
||||
for (let i = 0; i < oldRoots.length; i++) {
|
||||
getDOM().remove(oldRoots[i]);
|
||||
|
|
|
@ -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('<div>a</div>');
|
||||
const el2 = el('<div>b</div>');
|
||||
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('<div x="y">a<span>b</span></div>');
|
||||
const clone = getDOM().clone(el1);
|
||||
|
||||
expect(clone).not.toBe(el1);
|
||||
getDOM().setAttribute(clone, 'test', '1');
|
||||
expect(stringifyElement(clone)).toEqual('<div test="1" x="y">a<span>b</span></div>');
|
||||
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);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -19,8 +19,9 @@ export class DOMTestComponentRenderer extends TestComponentRenderer {
|
|||
constructor(@Inject(DOCUMENT) private _doc: any) { super(); }
|
||||
|
||||
insertRootElement(rootElId: string) {
|
||||
const rootEl = <HTMLElement>getDOM().firstChild(
|
||||
getContent(getDOM().createTemplate(`<div id="${rootElId}"></div>`)));
|
||||
const template = getDOM().getDefaultDocument().createElement('template');
|
||||
template.innerHTML = `<div id="${rootElId}"></div>`;
|
||||
const rootEl = <HTMLElement>getDOM().firstChild(getContent(template));
|
||||
|
||||
// TODO(juliemr): can/should this be optional?
|
||||
const oldRoots = getDOM().querySelectorAll(this._doc, '[id^=root]');
|
||||
|
|
|
@ -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 (<any>el).host; }
|
||||
clone(node: Node): Node { return node.cloneNode(true); }
|
||||
getElementsByTagName(element: any, name: string): HTMLElement[] {
|
||||
return element.getElementsByTagName(name);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,5 @@ import {DomAdapter} from '../dom/dom_adapter';
|
|||
export abstract class GenericBrowserDomAdapter extends DomAdapter {
|
||||
constructor() { super(); }
|
||||
|
||||
getDistributedNodes(el: HTMLElement): Node[] { return (<any>el).getDistributedNodes(); }
|
||||
supportsDOMEvents(): boolean { return true; }
|
||||
}
|
||||
|
|
|
@ -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 /*<T extends Node>*/ (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;
|
||||
|
|
|
@ -95,7 +95,7 @@ export function dispatchEvent(element: any, eventType: any): void {
|
|||
}
|
||||
|
||||
export function el(html: string): HTMLElement {
|
||||
return <HTMLElement>getDOM().firstChild(getContent(getDOM().createTemplate(html)));
|
||||
return <HTMLElement>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 += `<!--${el.nodeValue}-->`;
|
||||
} 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;
|
||||
}
|
||||
|
|
|
@ -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((<any>n).getDistributedNodes()));
|
||||
}
|
||||
|
||||
if (hasShadowRoot(n)) {
|
||||
return elementText(getDOM().childNodesAsList((<any>n).shadowRoot));
|
||||
return elementText(childNodesAsList((<any>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 {
|
||||
|
|
|
@ -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'); }
|
||||
}
|
||||
|
|
|
@ -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('<title>Test App Title</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');
|
||||
});
|
||||
}));
|
||||
|
|
|
@ -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'; }
|
||||
|
|
Loading…
Reference in New Issue