Skip to content

Commit ca0be04

Browse files
New: Add useAsKey option
1 parent 7fd8a70 commit ca0be04

File tree

4 files changed

+59
-10
lines changed

4 files changed

+59
-10
lines changed

src/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface Config {
6565
dom?: DOMConfig
6666
overrides?: SelectorsToElement,
6767
useFragment?: boolean,
68+
useAsKey: string[],
6869
}
6970

7071
/**
@@ -76,6 +77,7 @@ const mandatoryConfig: Config = {
7677
RETURN_DOM_FRAGMENT: true,
7778
RETURN_DOM_IMPORT: false,
7879
},
80+
useAsKey: ['key'],
7981
}
8082

8183
/**
@@ -85,6 +87,7 @@ const defaultConfig: Config = {
8587
dom: {
8688
ADD_ATTR: ['key'],
8789
},
90+
useAsKey: ['key'],
8891
useFragment: false,
8992
}
9093

src/react.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const reactAttributesMap: { [keyof: string]: string } = {
5454
usemap: 'useMap',
5555
}
5656

57-
function transformAttributes(attributesMap: NamedNodeMap): Attributes {
57+
function transformAttributes(attributesMap: NamedNodeMap, options: Config): Attributes {
5858
const attributes = getAttributes(attributesMap)
5959
const transformedAttributes: Attributes = {}
6060
Object.keys(attributes).forEach((key) => {
@@ -63,7 +63,16 @@ function transformAttributes(attributesMap: NamedNodeMap): Attributes {
6363
} else {
6464
transformedAttributes[key] = attributes[key]
6565
}
66+
67+
if (!transformedAttributes.key) {
68+
const isKey = options.useAsKey.some((possibleKey) => possibleKey === key)
69+
70+
if (isKey) {
71+
transformedAttributes.key = attributes[key]
72+
}
73+
}
6674
})
75+
6776
return transformedAttributes
6877
}
6978

@@ -72,7 +81,7 @@ function renderTextNode(node: Node & ChildNode) {
7281
}
7382

7483
function renderElementNode(node: Node & ChildNode, options: Config) {
75-
const element = transform(node as EnrichedElement)
84+
const element = transform(node as EnrichedElement, options)
7685

7786
if (element.override) {
7887
return React.cloneElement(element.override(element.attributes, node.textContent))
@@ -84,9 +93,9 @@ function renderElementNode(node: Node & ChildNode, options: Config) {
8493
return React.createElement(element.nodeName, element.attributes)
8594
}
8695

87-
function transform(element: EnrichedElement) {
96+
function transform(element: EnrichedElement, options: Config) {
8897
return {
89-
attributes: transformAttributes(element.attributes),
98+
attributes: transformAttributes(element.attributes, options),
9099
childNodes: element.childNodes,
91100
nodeName: element.nodeName.toLowerCase(),
92101
nodeType: element.nodeType,

tests/config.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('Options', () => {
1111
RETURN_DOM_FRAGMENT: true,
1212
RETURN_DOM_IMPORT: false,
1313
},
14+
useAsKey: ['key'],
1415
useFragment: false,
1516
})
1617
})
@@ -29,6 +30,7 @@ describe('Options', () => {
2930
RETURN_DOM_FRAGMENT: true,
3031
RETURN_DOM_IMPORT: false,
3132
},
33+
useAsKey: ['key'],
3234
useFragment: false,
3335
})
3436
})
@@ -46,6 +48,7 @@ describe('Options', () => {
4648
RETURN_DOM_FRAGMENT: true,
4749
RETURN_DOM_IMPORT: false,
4850
},
51+
useAsKey: ['key'],
4952
useFragment: false,
5053
})
5154
})

tests/react.spec.ts

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('React', () => {
1616
link.setAttribute('key', 'link')
1717
div.appendChild(link)
1818

19-
const wrapper = shallowWrapper(render(div.childNodes, {}))
19+
const wrapper = shallowWrapper(render(div.childNodes, { useAsKey: ['key'] }))
2020
expect(wrapper.find('a').text()).toEqual('Link')
2121
})
2222

@@ -26,7 +26,7 @@ describe('React', () => {
2626
newLine.setAttribute('key', 'test')
2727
div.appendChild(newLine)
2828

29-
const wrapper = shallowWrapper(render(div.childNodes, {}))
29+
const wrapper = shallowWrapper(render(div.childNodes, { useAsKey: ['key'] }))
3030
expect(wrapper.find('br')).toHaveLength(1)
3131
})
3232

@@ -35,7 +35,7 @@ describe('React', () => {
3535
const text = document.createTextNode('Text')
3636
div.appendChild(text)
3737

38-
const wrapper = shallowWrapper(render(div.childNodes, {}))
38+
const wrapper = shallowWrapper(render(div.childNodes, { useAsKey: ['key'] }))
3939
expect(wrapper.text()).toEqual('Text')
4040
})
4141

@@ -44,7 +44,7 @@ describe('React', () => {
4444
const comment = document.createComment('Comment')
4545
div.appendChild(comment)
4646

47-
const wrapper = shallowWrapper(render(div.childNodes, {}))
47+
const wrapper = shallowWrapper(render(div.childNodes, { useAsKey: ['key'] }))
4848
expect(wrapper.children()).toHaveLength(0)
4949
})
5050

@@ -56,7 +56,7 @@ describe('React', () => {
5656
span.setAttribute('key', 'test')
5757
div.appendChild(span)
5858

59-
const wrapper = shallowWrapper(render(div.childNodes, {}))
59+
const wrapper = shallowWrapper(render(div.childNodes, { useAsKey: ['key'] }))
6060
expect(wrapper.find('span')).toHaveLength(1)
6161
expect(wrapper.find('span').prop('htmlFor')).toEqual('test')
6262
expect(wrapper.find('span').prop('className')).toEqual('test')
@@ -72,9 +72,43 @@ describe('React', () => {
7272
link.textContent = 'Link'
7373
div.appendChild(link)
7474

75-
const wrapper = shallowWrapper(render(div.childNodes, { useFragment: true }))
75+
const wrapper = shallowWrapper(render(div.childNodes, { useFragment: true, useAsKey: ['key'] }))
7676
expect(wrapper.find('a').text()).toEqual('Link')
7777
})
7878
})
79+
80+
describe('#useAsKey', () => {
81+
it('should use key as a default key', () => {
82+
const div = document.createElement('div')
83+
const link = document.createElement('a')
84+
link.textContent = 'Link'
85+
link.setAttribute('key', 'link')
86+
div.appendChild(link)
87+
88+
const wrapper = shallowWrapper(render(div.childNodes, { useFragment: true, useAsKey: ['key'] }))
89+
expect(wrapper.find('a').key()).toEqual('link')
90+
})
91+
92+
it('should use other element in the list as fallback key', () => {
93+
const div = document.createElement('div')
94+
const link = document.createElement('a')
95+
link.textContent = 'Link'
96+
link.setAttribute('class', 'fallback key')
97+
div.appendChild(link)
98+
99+
const wrapper = shallowWrapper(render(div.childNodes, { useFragment: true, useAsKey: ['key', 'id', 'class'] }))
100+
expect(wrapper.find('a').key()).toEqual('fallback key')
101+
})
102+
103+
it('should use null if no key match', () => {
104+
const div = document.createElement('div')
105+
const link = document.createElement('a')
106+
link.textContent = 'Link'
107+
div.appendChild(link)
108+
109+
const wrapper = shallowWrapper(render(div.childNodes, { useFragment: true, useAsKey: ['key', 'id'] }))
110+
expect(wrapper.find('a').key()).toEqual(null)
111+
})
112+
})
79113
})
80114
})

0 commit comments

Comments
 (0)