diff --git a/src/mock-doc/attribute.ts b/src/mock-doc/attribute.ts index 4bea220e308..8fdf11eb447 100644 --- a/src/mock-doc/attribute.ts +++ b/src/mock-doc/attribute.ts @@ -5,14 +5,15 @@ const attrHandler = { if (prop in obj) { return obj[prop]; } - if (!isNaN(prop as any)) { + if (typeof prop !== 'symbol' && !isNaN(prop as any)) { return (obj as MockAttributeMap).__items[prop as any]; } return undefined; }, }; -export const createAttributeProxy = (caseInsensitive: boolean) => new Proxy(new MockAttributeMap(caseInsensitive), attrHandler); +export const createAttributeProxy = (caseInsensitive: boolean) => + new Proxy(new MockAttributeMap(caseInsensitive), attrHandler); export class MockAttributeMap { __items: MockAttr[] = []; @@ -54,7 +55,9 @@ export class MockAttributeMap { getNamedItemNS(namespaceURI: string, attrName: string) { namespaceURI = getNamespaceURI(namespaceURI); - return this.__items.find(attr => attr.name === attrName && getNamespaceURI(attr.namespaceURI) === namespaceURI) || null; + return ( + this.__items.find(attr => attr.name === attrName && getNamespaceURI(attr.namespaceURI) === namespaceURI) || null + ); } removeNamedItem(attr: MockAttr) { @@ -69,6 +72,21 @@ export class MockAttributeMap { } } } + + [Symbol.iterator]() { + let i = 0; + + return { + next: () => ({ + done: i === this.length, + value: this.item(i++), + }), + }; + } + + get [Symbol.toStringTag]() { + return 'MockAttributeMap'; + } } function getNamespaceURI(namespaceURI: string) { diff --git a/src/mock-doc/test/attribute.spec.ts b/src/mock-doc/test/attribute.spec.ts index f1344348c90..8ae09172539 100644 --- a/src/mock-doc/test/attribute.spec.ts +++ b/src/mock-doc/test/attribute.spec.ts @@ -1,7 +1,7 @@ +import { MockAttr, MockAttributeMap } from '../attribute'; import { MockDocument } from '../document'; import { MockElement, MockHTMLElement } from '../node'; import { XLINK_NS } from '../../runtime/runtime-constants'; -import { MockImageElement } from '../element'; describe('attributes', () => { let doc: MockDocument; @@ -9,6 +9,14 @@ describe('attributes', () => { doc = new MockDocument(); }); + it('attribute map is iterable', () => { + const map = new MockAttributeMap(); + const attr = new MockAttr('attr', 'value'); + map.setNamedItem(attr); + + expect(Array.from(map)[0]).toBe(attr); + }); + it('should get attributes by index', () => { const element = new MockHTMLElement(doc, 'div'); element.setAttribute('attr-0', 'value-0'); @@ -67,7 +75,9 @@ describe('attributes', () => { expect(element.getAttribute('prop5')).toBe('hola'); expect(element.getAttribute('prop6')).toBe(''); - expect(element).toEqualHtml(`
`); + expect(element).toEqualHtml( + `
`, + ); }); it('should cast attributeNS values to string', () => { @@ -86,7 +96,9 @@ describe('attributes', () => { expect(element.getAttribute('prop5')).toBe('hola'); expect(element.getAttribute('prop6')).toBe(''); - expect(element).toEqualHtml(`
`); + expect(element).toEqualHtml( + `
`, + ); }); it('attributes are case insensible in HTMLElement', () => { @@ -126,7 +138,7 @@ describe('attributes', () => { }); it('draggable default value', () => { - const div = doc.createElement('div') + const div = doc.createElement('div'); expect(div.draggable).toEqual(false); const img = doc.createElement('img');