Skip to content

Commit 3df435b

Browse files
authored
feat: Serialize select elements values (#295)
* WIP: Serialize select elements values * Add linting back Still fighting TS though * Rather than use an improper type that makes TS happy, use any I'd rather make something `any` than cast everything to a type that's incorrect but makes TS happy.
1 parent fdd2a53 commit 3df435b

File tree

5 files changed

+98
-44
lines changed

5 files changed

+98
-44
lines changed

package-lock.json

Lines changed: 21 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/percy-agent-client/dom.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ export interface DOMOptions {
33
domTransformation?: (dom: HTMLDocument) => void
44
}
55

6+
const FORM_ELEMENTS_SELECTOR = 'input, textarea, select'
7+
68
/**
79
* A single class to encapsulate all DOM operations that need to be performed to
810
* capture the customer's application state.
@@ -110,20 +112,38 @@ class DOM {
110112
*
111113
*/
112114
private serializeInputElements(clonedDOM: HTMLDocument): void {
113-
const formNodes = this.originalDOM.querySelectorAll('input, textarea')
115+
const formNodes = this.originalDOM.querySelectorAll(FORM_ELEMENTS_SELECTOR)
114116
const formElements = Array.from(formNodes) as HTMLFormElement[]
115117

116118
formElements.forEach((elem) => {
117119
const inputId = elem.getAttribute('data-percy-element-id')
118120
const selector = `[data-percy-element-id="${inputId}"]`
119-
const cloneEl = clonedDOM.querySelector(selector) as HTMLInputElement
121+
const cloneEl = clonedDOM.querySelector(selector) as any
120122

121123
switch (elem.type) {
122124
case 'checkbox':
123125
case 'radio':
124126
if (elem.checked) {
125127
cloneEl!.setAttribute('checked', '')
126128
}
129+
break
130+
case 'select-one':
131+
if (elem.selectedIndex !== -1) {
132+
cloneEl.options[elem.selectedIndex].setAttribute('selected', 'true')
133+
}
134+
break
135+
case 'select-multiple':
136+
const selectedOptions = Array.from(elem.selectedOptions)
137+
const clonedOptions = Array.from(cloneEl.options)
138+
139+
if (selectedOptions.length) {
140+
selectedOptions.forEach((option: any) => {
141+
const matchingOption = clonedOptions
142+
.find((cloneOption: any) => option.text === cloneOption.text) as HTMLOptionElement
143+
matchingOption.setAttribute('selected', 'true')
144+
})
145+
}
146+
127147
break
128148
case 'textarea':
129149
// setting text or value does not work but innerText does
@@ -192,7 +212,7 @@ class DOM {
192212
$el.setAttribute('data-percy-element-id', ID)
193213
}
194214

195-
const formNodes = this.originalDOM.querySelectorAll('input, textarea')
215+
const formNodes = this.originalDOM.querySelectorAll(FORM_ELEMENTS_SELECTOR)
196216
const formElements = Array.from(formNodes) as HTMLFormElement[]
197217
// loop through each form element and apply an ID for serialization later
198218
formElements.forEach((elem) => {

test/integration/agent-integration.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ describe('Integration test', () => {
134134
await page.type('#testInputText', 'test input value')
135135
await page.type('#testTextarea', 'test textarea value')
136136
await page.click('#testCheckbox')
137+
await page.select('#testSelect', 'maybe')
137138
await page.click('#testRadioButton')
138139

139140
const domSnapshot = await snapshot(page, 'Serialize input elements')
@@ -142,6 +143,7 @@ describe('Integration test', () => {
142143
expect($('#testInputText').attr('value')).to.equal('test input value')
143144
expect($('#testTextarea').text()).to.equal('test textarea value')
144145
expect($('#testCheckbox').attr('checked')).to.equal('checked')
146+
expect($('#testSelect').children().eq(2).attr('selected')).to.equal('selected')
145147
expect($('#testRadioButton').attr('checked')).to.equal('checked')
146148
})
147149
})

test/integration/testcases/stabilize-dom.html

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,25 @@
55
<meta charset="utf-8"/>
66
</head>
77
<body>
8-
<p>These elements below are used for testing purposes:</p>
9-
10-
<!-- Test elements for input element serialization. -->
8+
<p>These elements below are used for testing purposes:</p>
119
<p>
1210
<input id="testInputText" />
11+
</p>
12+
<p>
1313
<input id="testCheckbox" type="checkbox"/>
14+
</p>
15+
<p>
1416
<input id="testRadioButton" type="radio"/>
17+
</p>
18+
<p>
19+
<select id="testSelect">
20+
<option value="yes">Yes</option>
21+
<option value="no">No</option>
22+
<option value="maybe">Maybe</option>
23+
</select>
24+
</p>
25+
<p>
1526
<textarea id="testTextarea" name="testTextArea" rows="10"></textarea>
1627
</p>
17-
<!-- End of test elements for input element serialization. -->
1828
</body>
1929
</html>

0 commit comments

Comments
 (0)