Skip to content

Commit 509697e

Browse files
committed
feat(mock-doc): add dataset to element
1 parent d50a242 commit 509697e

3 files changed

Lines changed: 98 additions & 0 deletions

File tree

src/mock-doc/dataset.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { MockElement } from './node';
2+
3+
4+
export function dataset(elm: MockElement) {
5+
const ds: any = {};
6+
const attributes = elm.attributes;
7+
const attrLen = attributes.length;
8+
9+
for (let i = 0; i < attrLen; i++) {
10+
const attr = attributes.item(i);
11+
const nodeName = attr.nodeName;
12+
if (nodeName.startsWith('data-')) {
13+
ds[dashToPascalCase(nodeName)] = attr.nodeValue;
14+
}
15+
}
16+
17+
return new Proxy(ds, {
18+
get(_obj, camelCaseProp: string) {
19+
return ds[camelCaseProp];
20+
},
21+
set(_obj, camelCaseProp: string, value) {
22+
const dataAttr = toDataAttribute(camelCaseProp);
23+
elm.setAttribute(dataAttr, value);
24+
return true;
25+
}
26+
});
27+
}
28+
29+
function toDataAttribute(str: string) {
30+
return 'data-' + String(str).replace(/([A-Z0-9])/g, g => ' ' + g[0]).trim().replace(/ /g, '-').toLowerCase();
31+
}
32+
33+
function dashToPascalCase(str: string) {
34+
str = String(str).substr(5);
35+
return str.split('-').map((segment, index) => {
36+
if (index === 0) {
37+
return segment.charAt(0).toLowerCase() + segment.slice(1);
38+
}
39+
return segment.charAt(0).toUpperCase() + segment.slice(1);
40+
}).join('');
41+
}

src/mock-doc/node.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { attributeChanged, checkAttributeChanged, connectNode, disconnectNode } from './custom-element-registry';
22
import { closest, matches, selectAll, selectOne } from './selector';
33
import { CSSStyleDeclaration, createCSSStyleDeclaration } from './css-style-declaration';
4+
import { dataset } from './dataset';
45
import { MockAttr, MockAttributeMap, cloneAttributes } from './attribute';
56
import { MockClassList } from './class-list';
67
import { MockEvent, addEventListener, dispatchEvent, removeEventListener, resetEventListeners } from './event';
@@ -251,6 +252,10 @@ export class MockElement extends MockNode {
251252
return closest(selector, this);
252253
}
253254

255+
get dataset() {
256+
return dataset(this);
257+
}
258+
254259
get dir() { return this.getAttributeNS(null, 'dir') || ''; }
255260
set dir(value: string) { this.setAttributeNS(null, 'dir', value); }
256261

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { createDocument } from '../document';
2+
3+
4+
describe('dataset', () => {
5+
const doc = createDocument();
6+
let elm: HTMLElement;
7+
8+
beforeEach(() => {
9+
elm = doc.createElement('div');
10+
});
11+
12+
it('get dataset object', () => {
13+
elm.dataset.milesPerHour = '88';
14+
expect(elm.dataset).toEqual({
15+
milesPerHour: '88'
16+
});
17+
});
18+
19+
it('get dataset from attr set', () => {
20+
elm.setAttribute('data-miles-per-hour', '88');
21+
expect(elm.dataset.milesPerHour).toBe('88');
22+
});
23+
24+
it('get dataset', () => {
25+
elm.dataset.milesPerHour = 88 as any;
26+
expect(elm.dataset.milesPerHour).toBe('88');
27+
});
28+
29+
it('set data dash case attr with bracket notation', () => {
30+
elm.dataset['milesPerHour'] = '88';
31+
expect(elm.getAttribute('data-miles-per-hour')).toBe('88');
32+
});
33+
34+
it('set data dash case attr', () => {
35+
elm.dataset.milesPerHour = '88';
36+
expect(elm.getAttribute('data-miles-per-hour')).toBe('88');
37+
expect(elm.dataset).toEqual({
38+
milesPerHour: '88'
39+
});
40+
});
41+
42+
it('set data attr', () => {
43+
elm.dataset.mph = '88';
44+
expect(elm.getAttribute('data-mph')).toBe('88');
45+
});
46+
47+
it('set data attr with bracket notation', () => {
48+
elm.dataset['mph'] = '88';
49+
expect(elm.getAttribute('data-mph')).toBe('88');
50+
});
51+
52+
});

0 commit comments

Comments
 (0)