Skip to content

Commit 1aa9cae

Browse files
fix(mock-doc): make MockAttributeMap iterable (#2788)
1 parent 9c18fa0 commit 1aa9cae

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

src/mock-doc/attribute.ts

+21-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ const attrHandler = {
55
if (prop in obj) {
66
return obj[prop];
77
}
8-
if (!isNaN(prop as any)) {
8+
if (typeof prop !== 'symbol' && !isNaN(prop as any)) {
99
return (obj as MockAttributeMap).__items[prop as any];
1010
}
1111
return undefined;
1212
},
1313
};
1414

15-
export const createAttributeProxy = (caseInsensitive: boolean) => new Proxy(new MockAttributeMap(caseInsensitive), attrHandler);
15+
export const createAttributeProxy = (caseInsensitive: boolean) =>
16+
new Proxy(new MockAttributeMap(caseInsensitive), attrHandler);
1617

1718
export class MockAttributeMap {
1819
__items: MockAttr[] = [];
@@ -54,7 +55,9 @@ export class MockAttributeMap {
5455

5556
getNamedItemNS(namespaceURI: string, attrName: string) {
5657
namespaceURI = getNamespaceURI(namespaceURI);
57-
return this.__items.find(attr => attr.name === attrName && getNamespaceURI(attr.namespaceURI) === namespaceURI) || null;
58+
return (
59+
this.__items.find(attr => attr.name === attrName && getNamespaceURI(attr.namespaceURI) === namespaceURI) || null
60+
);
5861
}
5962

6063
removeNamedItem(attr: MockAttr) {
@@ -69,6 +72,21 @@ export class MockAttributeMap {
6972
}
7073
}
7174
}
75+
76+
[Symbol.iterator]() {
77+
let i = 0;
78+
79+
return {
80+
next: () => ({
81+
done: i === this.length,
82+
value: this.item(i++),
83+
}),
84+
};
85+
}
86+
87+
get [Symbol.toStringTag]() {
88+
return 'MockAttributeMap';
89+
}
7290
}
7391

7492
function getNamespaceURI(namespaceURI: string) {

src/mock-doc/test/attribute.spec.ts

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
1+
import { MockAttr, MockAttributeMap } from '../attribute';
12
import { MockDocument } from '../document';
23
import { MockElement, MockHTMLElement } from '../node';
34
import { XLINK_NS } from '../../runtime/runtime-constants';
4-
import { MockImageElement } from '../element';
55

66
describe('attributes', () => {
77
let doc: MockDocument;
88
beforeEach(() => {
99
doc = new MockDocument();
1010
});
1111

12+
it('attribute map is iterable', () => {
13+
const map = new MockAttributeMap();
14+
const attr = new MockAttr('attr', 'value');
15+
map.setNamedItem(attr);
16+
17+
expect(Array.from(map)[0]).toBe(attr);
18+
});
19+
1220
it('should get attributes by index', () => {
1321
const element = new MockHTMLElement(doc, 'div');
1422
element.setAttribute('attr-0', 'value-0');
@@ -67,7 +75,9 @@ describe('attributes', () => {
6775
expect(element.getAttribute('prop5')).toBe('hola');
6876
expect(element.getAttribute('prop6')).toBe('');
6977

70-
expect(element).toEqualHtml(`<div prop1=\"null\" prop2=\"undefined\" prop3=\"0\" prop4=\"1\" prop5=\"hola\" prop6></div>`);
78+
expect(element).toEqualHtml(
79+
`<div prop1=\"null\" prop2=\"undefined\" prop3=\"0\" prop4=\"1\" prop5=\"hola\" prop6></div>`,
80+
);
7181
});
7282

7383
it('should cast attributeNS values to string', () => {
@@ -86,7 +96,9 @@ describe('attributes', () => {
8696
expect(element.getAttribute('prop5')).toBe('hola');
8797
expect(element.getAttribute('prop6')).toBe('');
8898

89-
expect(element).toEqualHtml(`<div prop1=\"null\" prop2=\"undefined\" prop3=\"0\" prop4=\"1\" prop5=\"hola\" prop6></div>`);
99+
expect(element).toEqualHtml(
100+
`<div prop1=\"null\" prop2=\"undefined\" prop3=\"0\" prop4=\"1\" prop5=\"hola\" prop6></div>`,
101+
);
90102
});
91103

92104
it('attributes are case insensible in HTMLElement', () => {
@@ -126,7 +138,7 @@ describe('attributes', () => {
126138
});
127139

128140
it('draggable default value', () => {
129-
const div = doc.createElement('div')
141+
const div = doc.createElement('div');
130142
expect(div.draggable).toEqual(false);
131143

132144
const img = doc.createElement('img');

0 commit comments

Comments
 (0)