Skip to content

Commit

Permalink
fix(mock-doc): case sensible attributes in element (#1642)
Browse files Browse the repository at this point in the history
* fix(mock-doc): case sensible attributes in element

* conforms to standard
  • Loading branch information
manucorporat authored Jun 17, 2019
1 parent 95cbc3b commit e0c2ba5
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 83 deletions.
65 changes: 36 additions & 29 deletions src/mock-doc/attribute.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,79 @@
import { XLINK_NS } from '../runtime/runtime-constants';


export class MockAttributeMap {
items: MockAttr[] = [];

constructor(
public caseInsensitive = false
) {}

get length() {
return this.items.length;
}

getNamedItem(attrName: string) {
attrName = attrName.toLowerCase();
return this.items.find(attr => attr.name === attrName && (attr.namespaceURI == null || attr.namespaceURI === 'http://www.w3.org/1999/xlink')) || null;
item(index: number) {
return this.items[index] || null;
}

setNamedItem(attr: MockAttr) {
attr.namespaceURI = null;
this.setNamedItemNS(attr);
}

removeNamedItem(attr: MockAttr) {
this.removeNamedItemNS(attr);
}

item(index: number) {
return this.items[index] || null;
}

getNamedItemNS(namespaceURI: string, attrName: string) {
if (namespaceURI == null || namespaceURI === 'http://www.w3.org/1999/xlink') {
return this.getNamedItem(attrName);
}

attrName = attrName.toLowerCase();
return this.items.find(attr => attr.name === attrName && attr.namespaceURI === namespaceURI) || null;
}

setNamedItemNS(attr: MockAttr) {
if (attr != null && attr.value != null) {
attr.value = String(attr.value);
}

const existingAttr = this.items.find(a => a.name.toLowerCase() === attr.name.toLowerCase() && a.namespaceURI === attr.namespaceURI);
const existingAttr = this.items.find(a => a.name === attr.name && a.namespaceURI === attr.namespaceURI);
if (existingAttr != null) {
existingAttr.value = attr.value;
} else {
this.items.push(attr);
}
}

getNamedItem(attrName: string) {
if (this.caseInsensitive) {
attrName = attrName.toLowerCase();
}
return this.getNamedItemNS(null, attrName);
}

getNamedItemNS(namespaceURI: string, attrName: string) {
namespaceURI = getNamespaceURI(namespaceURI);
return this.items.find(attr => attr.name === attrName && getNamespaceURI(attr.namespaceURI) === namespaceURI) || null;
}

removeNamedItem(attr: MockAttr) {
this.removeNamedItemNS(attr);
}

removeNamedItemNS(attr: MockAttr) {
for (let i = 0, ii = this.items.length; i < ii; i++) {
if (this.items[i].name.toLowerCase() === attr.name && this.items[i].namespaceURI === attr.namespaceURI) {
if (this.items[i].name === attr.name && this.items[i].namespaceURI === attr.namespaceURI) {
this.items.splice(i, 1);
break;
}
}
}
}

function getNamespaceURI(namespaceURI: string) {
return namespaceURI === XLINK_NS ? null : namespaceURI;
}

export function cloneAttributes(srcAttrs: MockAttributeMap, sortByName = false) {
const dstAttrs = new MockAttributeMap();
const dstAttrs = new MockAttributeMap(srcAttrs.caseInsensitive);
if (srcAttrs != null) {
const attrLen = srcAttrs.length;

if (sortByName && attrLen > 1) {
const sortedAttrs: MockAttr[] = [];
for (let i = 0; i < attrLen; i++) {
const srcAttr = srcAttrs.item(i);
const dstAttr = new MockAttr(srcAttr.name.toLowerCase(), srcAttr.value, srcAttr.namespaceURI);
const dstAttr = new MockAttr(srcAttr.name, srcAttr.value, srcAttr.namespaceURI);
sortedAttrs.push(dstAttr);
}

Expand Down Expand Up @@ -98,10 +105,10 @@ export class MockAttr {
private _value: string;
private _namespaceURI: string;

constructor(attrName: string, attrValue = '', namespaceURL: string = null) {
this._name = attrName.toLowerCase();
constructor(attrName: string, attrValue = '', namespaceURI: string = null) {
this._name = attrName;
this._value = String(attrValue || '');
this._namespaceURI = (namespaceURL != null) ? namespaceURL.toLowerCase() : namespaceURL;
this._namespaceURI = namespaceURI;
}

get name() {
Expand All @@ -122,7 +129,7 @@ export class MockAttr {
return this._name;
}
set nodeName(value) {
this._name = value.toLowerCase();
this._name = value;
}

get nodeValue() {
Expand All @@ -136,6 +143,6 @@ export class MockAttr {
return this._namespaceURI;
}
set namespaceURI(namespaceURI) {
this._namespaceURI = (namespaceURI != null) ? namespaceURI.toLowerCase() : namespaceURI;
this._namespaceURI = namespaceURI;
}
}
4 changes: 2 additions & 2 deletions src/mock-doc/custom-element-registry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MockElement, MockNode } from './node';
import { MockHTMLElement, MockNode } from './node';
import { NODE_TYPES } from './constants';


Expand Down Expand Up @@ -156,7 +156,7 @@ export function createCustomElement(customElements: MockCustomElementRegistry, o
}
});

const elm = new MockElement(ownerDocument, tagName);
const elm = new MockHTMLElement(ownerDocument, tagName);

proxyElements.set(host, elm);

Expand Down
4 changes: 2 additions & 2 deletions src/mock-doc/document-fragment.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MockElement } from './node';
import { MockHTMLElement } from './node';
import { NODE_NAMES, NODE_TYPES } from './constants';


export class MockDocumentFragment extends MockElement {
export class MockDocumentFragment extends MockHTMLElement {

constructor(ownerDocument: any) {
super(ownerDocument, null);
Expand Down
4 changes: 2 additions & 2 deletions src/mock-doc/document-type-node.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MockElement } from './node';
import { MockHTMLElement } from './node';
import { NODE_TYPES } from './constants';


export class MockDocumentTypeNode extends MockElement {
export class MockDocumentTypeNode extends MockHTMLElement {

constructor(ownerDocument: any) {
super(ownerDocument, '!DOCTYPE');
Expand Down
29 changes: 19 additions & 10 deletions src/mock-doc/document.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { NODE_NAMES, NODE_TYPES } from './constants';
import { createElement } from './element';
import { MockComment } from './comment-node';
import { MockDocumentFragment } from './document-fragment';
import { MockDocumentTypeNode } from './document-type-node';
import { MockElement, MockTextNode, resetElement } from './node';
import { NODE_NAMES, NODE_TYPES } from './constants';
import { MockElement, MockHTMLElement, MockTextNode, resetElement } from './node';
import { MockComment } from './comment-node';
import { parseDocumentUtil } from './parse-util';
import { parseHtmlToFragment } from './parse-html';
import { resetEventListeners } from './event';
import { MockWindow } from './window';
import { MockAttr } from './attribute';


export class MockDocument extends MockElement {
export class MockDocument extends MockHTMLElement {
defaultView: any;
cookie: string;
referrer: string;
Expand All @@ -35,11 +36,11 @@ export class MockDocument extends MockElement {
}

} else if (html !== false) {
const documentElement = new MockElement(this, 'html');
const documentElement = new MockHTMLElement(this, 'html');
this.appendChild(documentElement);

documentElement.appendChild(new MockElement(this, 'head'));
documentElement.appendChild(new MockElement(this, 'body'));
documentElement.appendChild(new MockHTMLElement(this, 'head'));
documentElement.appendChild(new MockHTMLElement(this, 'body'));
}
}

Expand Down Expand Up @@ -74,7 +75,7 @@ export class MockDocument extends MockElement {
}
}

const documentElement = new MockElement(this, 'html');
const documentElement = new MockHTMLElement(this, 'html');
this.appendChild(documentElement);
return documentElement;
}
Expand All @@ -98,7 +99,7 @@ export class MockDocument extends MockElement {
}
}

const head = new MockElement(this, 'head');
const head = new MockHTMLElement(this, 'head');
documentElement.insertBefore(head, documentElement.firstChild);
return head;
}
Expand All @@ -123,7 +124,7 @@ export class MockDocument extends MockElement {
}
}

const body = new MockElement(this, 'body');
const body = new MockHTMLElement(this, 'body');
documentElement.appendChild(body);
return body;
}
Expand Down Expand Up @@ -151,6 +152,14 @@ export class MockDocument extends MockElement {
return new MockComment(this, data);
}

createAttribute(attrName: string) {
return new MockAttr(attrName.toLowerCase());
}

createAttributeNS(namespaceURI: string, attrName: string) {
return new MockAttr(attrName, undefined, namespaceURI);
}

createElement(tagName: string) {
if (tagName === NODE_NAMES.DOCUMENT_NODE) {
const doc = new MockDocument(false as any);
Expand Down
28 changes: 16 additions & 12 deletions src/mock-doc/element.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { cloneAttributes } from './attribute';
import { createCustomElement } from './custom-element-registry';
import { MockDocumentFragment } from './document-fragment';
import { MockElement } from './node';
import { MockElement, MockHTMLElement } from './node';
import { URL } from 'url';


Expand Down Expand Up @@ -41,6 +41,10 @@ export function createElement(ownerDocument: any, tagName: string) {

case 'title':
return new MockTitleElement(ownerDocument);

case 'svg':
case 'symbol':
return new MockElement(ownerDocument, tagName);
}

if (ownerDocument != null && tagName.includes('-')) {
Expand All @@ -50,11 +54,11 @@ export function createElement(ownerDocument: any, tagName: string) {
}
}

return new MockElement(ownerDocument, tagName);
return new MockHTMLElement(ownerDocument, tagName);
}


class MockAnchorElement extends MockElement {
class MockAnchorElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'a');
}
Expand All @@ -68,7 +72,7 @@ class MockAnchorElement extends MockElement {
}


class MockButtonElement extends MockElement {
class MockButtonElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'button');
}
Expand All @@ -78,7 +82,7 @@ patchPropAttributes(MockButtonElement.prototype, {
});


class MockImgElement extends MockElement {
class MockImgElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'img');
}
Expand All @@ -96,7 +100,7 @@ patchPropAttributes(MockImgElement.prototype, {
});


class MockInputElement extends MockElement {
class MockInputElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'input');
}
Expand Down Expand Up @@ -136,7 +140,7 @@ patchPropAttributes(MockInputElement.prototype, {
width: Number
});

class MockFormElement extends MockElement {
class MockFormElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'form');
}
Expand All @@ -146,7 +150,7 @@ patchPropAttributes(MockFormElement.prototype, {
});


class MockLinkElement extends MockElement {
class MockLinkElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'link');
}
Expand All @@ -166,7 +170,7 @@ patchPropAttributes(MockLinkElement.prototype, {
});


class MockMetaElement extends MockElement {
class MockMetaElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'meta');
}
Expand All @@ -178,7 +182,7 @@ patchPropAttributes(MockMetaElement.prototype, {
});


class MockScriptElement extends MockElement {
class MockScriptElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'script');
}
Expand All @@ -195,7 +199,7 @@ patchPropAttributes(MockScriptElement.prototype, {
});


export class MockTemplateElement extends MockElement {
export class MockTemplateElement extends MockHTMLElement {
content: MockDocumentFragment;

constructor(ownerDocument: any) {
Expand Down Expand Up @@ -233,7 +237,7 @@ export class MockTemplateElement extends MockElement {
}


class MockTitleElement extends MockElement {
class MockTitleElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'title');
}
Expand Down
2 changes: 1 addition & 1 deletion src/mock-doc/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

export { MockAttr, MockAttributeMap, cloneAttributes } from './attribute';
export { MockComment } from './comment-node';
export { MockElement, MockNode, MockTextNode } from './node';
export { MockHTMLElement, MockElement, MockNode, MockTextNode } from './node';
export { MockCustomEvent, MockKeyboardEvent } from './event';
export { MockDocument, createDocument, createFragment, resetDocument } from './document';
export { MockWindow, cloneDocument, cloneWindow, constrainTimeouts, resetWindow } from './window';
Expand Down
Loading

0 comments on commit e0c2ba5

Please sign in to comment.