Skip to content

Commit

Permalink
feat: Serialize select elements values (#295)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
Robdel12 authored Jul 22, 2019
1 parent fdd2a53 commit 3df435b
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 44 deletions.
56 changes: 21 additions & 35 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 23 additions & 3 deletions src/percy-agent-client/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export interface DOMOptions {
domTransformation?: (dom: HTMLDocument) => void
}

const FORM_ELEMENTS_SELECTOR = 'input, textarea, select'

/**
* A single class to encapsulate all DOM operations that need to be performed to
* capture the customer's application state.
Expand Down Expand Up @@ -110,20 +112,38 @@ class DOM {
*
*/
private serializeInputElements(clonedDOM: HTMLDocument): void {
const formNodes = this.originalDOM.querySelectorAll('input, textarea')
const formNodes = this.originalDOM.querySelectorAll(FORM_ELEMENTS_SELECTOR)
const formElements = Array.from(formNodes) as HTMLFormElement[]

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

switch (elem.type) {
case 'checkbox':
case 'radio':
if (elem.checked) {
cloneEl!.setAttribute('checked', '')
}
break
case 'select-one':
if (elem.selectedIndex !== -1) {
cloneEl.options[elem.selectedIndex].setAttribute('selected', 'true')
}
break
case 'select-multiple':
const selectedOptions = Array.from(elem.selectedOptions)
const clonedOptions = Array.from(cloneEl.options)

if (selectedOptions.length) {
selectedOptions.forEach((option: any) => {
const matchingOption = clonedOptions
.find((cloneOption: any) => option.text === cloneOption.text) as HTMLOptionElement
matchingOption.setAttribute('selected', 'true')
})
}

break
case 'textarea':
// setting text or value does not work but innerText does
Expand Down Expand Up @@ -192,7 +212,7 @@ class DOM {
$el.setAttribute('data-percy-element-id', ID)
}

const formNodes = this.originalDOM.querySelectorAll('input, textarea')
const formNodes = this.originalDOM.querySelectorAll(FORM_ELEMENTS_SELECTOR)
const formElements = Array.from(formNodes) as HTMLFormElement[]
// loop through each form element and apply an ID for serialization later
formElements.forEach((elem) => {
Expand Down
2 changes: 2 additions & 0 deletions test/integration/agent-integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ describe('Integration test', () => {
await page.type('#testInputText', 'test input value')
await page.type('#testTextarea', 'test textarea value')
await page.click('#testCheckbox')
await page.select('#testSelect', 'maybe')
await page.click('#testRadioButton')

const domSnapshot = await snapshot(page, 'Serialize input elements')
Expand All @@ -142,6 +143,7 @@ describe('Integration test', () => {
expect($('#testInputText').attr('value')).to.equal('test input value')
expect($('#testTextarea').text()).to.equal('test textarea value')
expect($('#testCheckbox').attr('checked')).to.equal('checked')
expect($('#testSelect').children().eq(2).attr('selected')).to.equal('selected')
expect($('#testRadioButton').attr('checked')).to.equal('checked')
})
})
Expand Down
18 changes: 14 additions & 4 deletions test/integration/testcases/stabilize-dom.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,25 @@
<meta charset="utf-8"/>
</head>
<body>
<p>These elements below are used for testing purposes:</p>

<!-- Test elements for input element serialization. -->
<p>These elements below are used for testing purposes:</p>
<p>
<input id="testInputText" />
</p>
<p>
<input id="testCheckbox" type="checkbox"/>
</p>
<p>
<input id="testRadioButton" type="radio"/>
</p>
<p>
<select id="testSelect">
<option value="yes">Yes</option>
<option value="no">No</option>
<option value="maybe">Maybe</option>
</select>
</p>
<p>
<textarea id="testTextarea" name="testTextArea" rows="10"></textarea>
</p>
<!-- End of test elements for input element serialization. -->
</body>
</html>
Loading

0 comments on commit 3df435b

Please sign in to comment.