Skip to content

Commit a1ce01a

Browse files
committed
Add fieldset/fieldset-validation-element and tests
1 parent 6ee1982 commit a1ce01a

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"./plugins/mrujs": "./src/plugins/mrujs.js",
1515
"./utils": "./src/util.js",
1616
"./fieldset/rendering": "./src/fieldset/rendering.js",
17+
"./fieldset/fieldset-validation-element": "./src/fieldset/fieldset-validation-element.js",
1718
"./fieldset/util": "./src/fieldset/util.js"
1819
},
1920
"scripts": {
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { cloneNodesObserver } from '../util.js'
2+
import { getErrorListFromContainer, getErrorContainer } from '../error-containers.js'
3+
4+
/**
5+
* @class
6+
* @classdesc
7+
* An abstract class that can be subclassed to provide specific validation
8+
* scenarios for a fieldset. For example: {@link MinimumCheckboxValuesFieldsetValidationElement}
9+
* is a subclass that validates that at least one value for the field name specified in
10+
* this element is present in the `FormData`
11+
*/
12+
export class FieldsetValidationElement extends HTMLElement {
13+
constructor() {
14+
super();
15+
}
16+
17+
connectedCallback() {
18+
if(!this.isConnected){ return }
19+
this.setupErrorListCloning()
20+
}
21+
22+
/**
23+
* Calls {@link cloneNodesObserver} to
24+
* clone {@link FieldsetValidationElement#errorContainer} into
25+
* {@link FieldsetValidationElement#errorContainerARIA} and keep them in sync.
26+
*/
27+
setupErrorListCloning() {
28+
cloneNodesObserver(
29+
getErrorListFromContainer(this.errorContainer),
30+
getErrorListFromContainer(this.errorContainerARIA)
31+
)
32+
}
33+
34+
/**
35+
* The `form` of the {@link FieldsetValidationElement#fieldset}
36+
*/
37+
get form() {
38+
return this.fieldset.form
39+
}
40+
41+
/**
42+
* The element with the ID from the `fieldset` attribute
43+
*/
44+
get fieldset() {
45+
return document.getElementById(this.getAttribute(`fieldset`))
46+
}
47+
48+
/**
49+
* The `field-name` attribute`
50+
*/
51+
get fieldName() {
52+
return this.getAttribute(`field-name`)
53+
}
54+
55+
/**
56+
* See {@link getErrorContainer}, uses {@link FieldsetValidationElement#fieldset}
57+
*/
58+
get errorContainer(){
59+
return getErrorContainer(this.fieldset);
60+
}
61+
62+
/**
63+
* The element with the ID from the `error-container-aria` attribute
64+
*/
65+
get errorContainerARIA(){
66+
return document.getElementById(this.getAttribute(`error-container-aria`))
67+
}
68+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { html, fixture, assert } from '@open-wc/testing';
2+
3+
import {FieldsetValidationElement} from '@practical-computer/error-handling/fieldset/fieldset-validation-element'
4+
5+
class CustomFieldsetValidationElement extends FieldsetValidationElement {
6+
get customProperty() {
7+
return "hello"
8+
}
9+
}
10+
11+
if (!window.customElements.get('custom-fieldset-validation')) {
12+
window.customElements.define('custom-fieldset-validation', CustomFieldsetValidationElement);
13+
}
14+
15+
suite('ErrorHandlingElement', async () => {
16+
test(`can subclassed`, async() => {
17+
const container = await fixture(html`
18+
<div>
19+
<form id="test-form" aria-describedby='test-form-error-container'>
20+
<fieldset id="terms-fieldset" aria-describedby="terms-fieldset-errors">
21+
<legend>
22+
Terms
23+
24+
<section id="terms-fieldset-errors-aria">
25+
<ul></ul>
26+
</section>
27+
28+
</legend>
29+
30+
<custom-fieldset-validation fieldset="terms-fieldset" field-name="terms" error-container-aria="terms-fieldset-errors-aria">
31+
<input type="checkbox" name="privacy" required>
32+
<input type="checkbox" name="service" required>
33+
</custom-fieldset-validation>
34+
35+
<section id="terms-fieldset-errors" data-error-container>
36+
<ul>
37+
<li data-visible data-error-type="error_1">An ad-hoc error from the initial load</li>
38+
<li data-visible data-error-type="error_2">Another ad-hoc error from the initial load</li>
39+
</ul>
40+
</section>
41+
</fieldset>
42+
</form>
43+
44+
<template id="pf-error-list-item-template">
45+
<li><span>‼️</span> <span data-error-message></span></li>
46+
</template>
47+
</div>
48+
`)
49+
50+
const element = container.querySelector(`custom-fieldset-validation`)
51+
52+
assert.equal(`terms`, element.fieldName)
53+
assert.equal(`test-form`, element.form.id)
54+
assert.equal(`terms-fieldset`, element.fieldset.id)
55+
assert.equal(`terms-fieldset-errors`, element.errorContainer.id)
56+
assert.equal(`terms-fieldset-errors-aria`, element.errorContainerARIA.id)
57+
assert.equal(`hello`, element.customProperty)
58+
})
59+
})

test/test-runner.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ import './request-processing.test.js';
99
import './event-handlers.test.js';
1010
import './plugins/mrujs.test.js';
1111
import './fieldset/rendering.test.js';
12+
import './fieldset/fieldset-validation-element.test.js';
1213
import './fieldset/util.test.js';

0 commit comments

Comments
 (0)