Skip to content

Commit 84bda82

Browse files
committed
clean up test coverage
1 parent 47113c1 commit 84bda82

File tree

4 files changed

+68
-22
lines changed

4 files changed

+68
-22
lines changed

custom-elements.json

+3-4
Original file line numberDiff line numberDiff line change
@@ -201,19 +201,18 @@
201201
},
202202
{
203203
"kind": "field",
204-
"name": "validateAfterFirstBlur",
204+
"name": "onlyValidateOnBlur",
205205
"type": {
206206
"text": "boolean"
207207
},
208208
"readonly": true
209209
},
210210
{
211211
"kind": "field",
212-
"name": "shouldValidate",
212+
"name": "validateOnKeystroke",
213213
"type": {
214214
"text": "boolean"
215-
},
216-
"readonly": true
215+
}
217216
}
218217
],
219218
"attributes": [

examples/index.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ <h2 tabindex="-1" id="success1" class="success" hidden>Your submission was succe
2222
<button value="1" name="form">submit</button>
2323
</form>
2424

25-
<!-- <h2>Form that has custom validity messages</h2>
25+
<h2>Form that has custom validity messages</h2>
2626
<p>Input 422 for an error response.</p>
2727
<h2 tabindex="-1" id="success2" class="success" hidden>Your submission was successful</h2>
2828
<form id="custom">
@@ -34,13 +34,13 @@ <h2 tabindex="-1" id="success2" class="success" hidden>Your submission was succe
3434
<p id="state2" aria-atomic="true" aria-live="polite" class="state"></p>
3535
</auto-check>
3636
<button value="2" name="form">submit</button>
37-
</form> -->
37+
</form>
3838

39-
<h2>validate-after-first-blur</h2>
39+
<h2>only-validate-on-blur</h2>
4040
<h2 tabindex="-1" id="success3" class="success" hidden>Your submission was successful</h2>
4141
<form>
4242
<label for="simple-field2">Desired username*:</label>
43-
<auto-check csrf="foo" src="/demo" required validate-after-first-blur>
43+
<auto-check csrf="foo" src="/demo" required only-validate-on-blur>
4444
<input id="simple-field2" autofocus name="foo" required aria-describedby="state3" />
4545
<p id="state3" aria-atomic="true" aria-live="polite" class="state"></p>
4646
</auto-check>

src/auto-check-element.ts

+26-12
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ export class AutoCheckElement extends HTMLElement {
101101
const input = this.input
102102
if (!input) return
103103

104-
if (!this.validateAfterFirstBlur) {
105-
this.setAttribute('should-validate', '')
104+
if (!this.onlyValidateOnBlur) {
105+
this.setAttribute('validate-on-keystroke', '')
106106
}
107107

108108
const checker = debounce(check.bind(null, this), 300)
@@ -192,13 +192,21 @@ export class AutoCheckElement extends HTMLElement {
192192
return AllowedHttpMethods[this.getAttribute('http-method') as keyof typeof AllowedHttpMethods] || 'POST'
193193
}
194194

195-
get validateAfterFirstBlur(): boolean {
196-
const value = this.getAttribute('validate-after-first-blur')
195+
get onlyValidateOnBlur(): boolean {
196+
const value = this.getAttribute('only-validate-on-blur')
197197
return value === 'true' || value === ''
198198
}
199199

200-
get shouldValidate(): boolean {
201-
const value = this.getAttribute('should-validate')
200+
set validateOnKeystroke(enabled: boolean) {
201+
if (enabled) {
202+
this.setAttribute('validate-on-keystroke', '')
203+
} else {
204+
this.removeAttribute('validate-on-keystroke')
205+
}
206+
}
207+
208+
get validateOnKeystroke(): boolean {
209+
const value = this.getAttribute('validate-on-keystroke')
202210
return value === 'true' || value === ''
203211
}
204212
}
@@ -213,9 +221,9 @@ function handleChange(checker: () => void, event: Event) {
213221
if (input.value.length === 0) return
214222

215223
if (
216-
(event.type !== 'blur' && !autoCheckElement.validateAfterFirstBlur) || // Existing default behavior
217-
(event.type === 'blur' && autoCheckElement.validateAfterFirstBlur) || // Only validate on blur if validate-after-first-blur is set
218-
(autoCheckElement.validateAfterFirstBlur && autoCheckElement.shouldValidate) // Only validate on key inputs in validate-after-first-blur mode if should-validate is set (when input is invalid)
224+
(event.type !== 'blur' && !autoCheckElement.onlyValidateOnBlur) || // Existing default behavior
225+
(event.type === 'blur' && autoCheckElement.onlyValidateOnBlur) || // Only validate on blur if only-validate-on-blur is set
226+
(autoCheckElement.onlyValidateOnBlur && autoCheckElement.validateOnKeystroke) // Only validate on key inputs in only-validate-on-blur mode if validate-on-keystroke is set (when input is invalid)
219227
) {
220228
checker()
221229
setLoadingState(event)
@@ -333,12 +341,18 @@ async function check(autoCheckElement: AutoCheckElement) {
333341
if (autoCheckElement.required) {
334342
input.setCustomValidity('')
335343
}
336-
if (autoCheckElement.validateAfterFirstBlur) {
337-
autoCheckElement.removeAttribute('should-validate')
344+
// We do not have good test coverage for this code path.
345+
// To test, ensure that the input only validates on blur
346+
// once it has been "healed" by a valid input after
347+
// previously being in an invalid state.
348+
if (autoCheckElement.onlyValidateOnBlur) {
349+
autoCheckElement.validateOnKeystroke = false
338350
}
339351
input.dispatchEvent(new AutoCheckSuccessEvent(response.clone()))
340352
} else {
341-
autoCheckElement.setAttribute('should-validate', '')
353+
if (autoCheckElement.onlyValidateOnBlur) {
354+
autoCheckElement.validateOnKeystroke = true
355+
}
342356
const event = new AutoCheckErrorEvent(response.clone())
343357
input.dispatchEvent(event)
344358
if (autoCheckElement.required) {

test/auto-check.js

+35-2
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ describe('auto-check element', function () {
2222
})
2323
})
2424

25-
describe('when validate-after-first-blur is true', function () {
25+
describe('when only-validate-on-blur is true', function () {
2626
let checker
2727
let input
2828

2929
beforeEach(function () {
3030
const container = document.createElement('div')
3131
container.innerHTML = `
32-
<auto-check csrf="foo" src="/success" validate-after-first-blur>
32+
<auto-check csrf="foo" src="/success" only-validate-on-blur>
3333
<input>
3434
</auto-check>`
3535
document.body.append(container)
@@ -45,6 +45,35 @@ describe('auto-check element', function () {
4545
assert.deepEqual(events, [])
4646
})
4747

48+
it('does not emit on blur if input is blank', async function () {
49+
const events = []
50+
input.addEventListener('auto-check-start', event => events.push(event.type))
51+
triggerBlur(input)
52+
assert.deepEqual(events, [])
53+
})
54+
55+
it('emits on blur', async function () {
56+
const events = []
57+
input.addEventListener('auto-check-start', event => events.push(event.type))
58+
triggerInput(input, 'hub')
59+
triggerBlur(input)
60+
assert.deepEqual(events, ['auto-check-start'])
61+
})
62+
63+
it('emits on input change if input is invalid after blur', async function () {
64+
const events = []
65+
input.addEventListener('auto-check-start', event => events.push(event.type))
66+
67+
checker.src = '/fail'
68+
triggerInput(input, 'hub')
69+
triggerBlur(input)
70+
await once(input, 'auto-check-complete')
71+
triggerInput(input, 'hub2')
72+
triggerInput(input, 'hub3')
73+
74+
assert.deepEqual(events, ['auto-check-start', 'auto-check-start', 'auto-check-start'])
75+
})
76+
4877
afterEach(function () {
4978
document.body.innerHTML = ''
5079
checker = null
@@ -361,3 +390,7 @@ function triggerInput(input, value) {
361390
input.value = value
362391
return input.dispatchEvent(new InputEvent('input'))
363392
}
393+
394+
function triggerBlur(input) {
395+
return input.dispatchEvent(new FocusEvent('blur'))
396+
}

0 commit comments

Comments
 (0)