@3t-transform/threeteeui 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/app-globals-3a1e7e63.js +5 -0
- package/dist/cjs/css-shim-211819bc.js +6 -0
- package/dist/cjs/dom-9deb26c8.js +75 -0
- package/dist/cjs/index-11cfdabe.js +3297 -0
- package/dist/cjs/{index-b3010e55.js → index-451f61dd.js} +1 -3
- package/dist/cjs/loader.cjs.js +18 -2
- package/dist/cjs/shadow-css-bf3843d2.js +389 -0
- package/dist/cjs/tttx-button.cjs.entry.js +1 -1
- package/dist/cjs/tttx-form.cjs.entry.js +1 -1
- package/dist/cjs/tttx-icon.cjs.entry.js +1 -1
- package/dist/cjs/tttx-keyvalue-block.cjs.entry.js +1 -1
- package/dist/cjs/tttx-list.cjs.entry.js +34 -4
- package/dist/cjs/tttx-loading-spinner.cjs.entry.js +1 -1
- package/dist/cjs/tttx-standalone-input.cjs.entry.js +1 -1
- package/dist/cjs/tttx-toolbar.cjs.entry.js +20 -0
- package/dist/cjs/tttx.cjs.js +116 -4
- package/dist/collection/collection-manifest.json +2 -1
- package/dist/collection/components/atoms/tttx-button/test/tttx-button.e2e.js +9 -0
- package/dist/collection/components/atoms/tttx-button/test/tttx-button.spec.js +83 -0
- package/dist/collection/components/atoms/tttx-icon/test/tttx-icon.e2e.js +9 -0
- package/dist/collection/components/atoms/tttx-icon/test/tttx-icon.spec.js +16 -0
- package/dist/collection/components/atoms/tttx-keyvalue-block/test/tttx-keyvalue-block.spec.js +216 -0
- package/dist/collection/components/atoms/tttx-loading-spinner/Test/tttx-loading-spinner.spec.js +64 -0
- package/dist/collection/components/molecules/tttx-form/lib/setErrorState.spec.js +38 -0
- package/dist/collection/components/molecules/tttx-form/lib/validityCheck.spec.js +214 -0
- package/dist/collection/components/molecules/tttx-form/test/tttx-form.e2e.js +9 -0
- package/dist/collection/components/molecules/tttx-form/test/tttx-form.spec.js +232 -0
- package/dist/collection/components/molecules/tttx-list/test/ttttx-list.spec.e2e.js +26 -0
- package/dist/collection/components/molecules/tttx-list/test/tttx-list.spec.js +183 -0
- package/dist/collection/components/molecules/tttx-standalone-input/test/tttx-standalone-input.e2e.js +9 -0
- package/dist/collection/components/molecules/tttx-standalone-input/test/tttx-standalone-input.spec.js +219 -0
- package/dist/collection/components/molecules/tttx-toolbar/test/tttx-toolbar.test.js +0 -0
- package/dist/collection/components/molecules/tttx-toolbar/tttx-toolbar.css +30 -0
- package/dist/collection/components/molecules/tttx-toolbar/tttx-toolbar.js +44 -0
- package/dist/collection/components/molecules/tttx-toolbar/tttx-toolbar.stories.js +20 -0
- package/dist/collection/shared/test/domsanitiser.options.spec.js +23 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +5 -0
- package/dist/components/tttx-list.js +33 -3
- package/dist/components/tttx-toolbar.d.ts +11 -0
- package/dist/components/tttx-toolbar.js +36 -0
- package/dist/esm/app-globals-0f993ce5.js +3 -0
- package/dist/esm/css-shim-9d54a2f2.js +4 -0
- package/dist/esm/dom-6be6f662.js +73 -0
- package/dist/esm/{index-31631990.js → index-0350f122.js} +1 -3
- package/dist/esm/index-dbe25028.js +3262 -0
- package/dist/esm/loader.js +18 -2
- package/dist/esm/shadow-css-ed4599f8.js +387 -0
- package/dist/esm/tttx-button.entry.js +1 -1
- package/dist/esm/tttx-form.entry.js +1 -1
- package/dist/esm/tttx-icon.entry.js +1 -1
- package/dist/esm/tttx-keyvalue-block.entry.js +1 -1
- package/dist/esm/tttx-list.entry.js +34 -4
- package/dist/esm/tttx-loading-spinner.entry.js +1 -1
- package/dist/esm/tttx-standalone-input.entry.js +1 -1
- package/dist/esm/tttx-toolbar.entry.js +16 -0
- package/dist/esm/tttx.js +116 -4
- package/dist/tttx/app-globals-0f993ce5.js +3 -0
- package/dist/tttx/css-shim-9d54a2f2.js +4 -0
- package/dist/tttx/dom-6be6f662.js +73 -0
- package/dist/tttx/index-dbe25028.js +3262 -0
- package/dist/tttx/index.esm.js +1 -0
- package/dist/tttx/p-0a85dda4.entry.js +1 -0
- package/dist/tttx/{p-1f3d39fc.entry.js → p-1b015a9d.entry.js} +1 -1
- package/dist/tttx/{p-2e7f486e.entry.js → p-4f3958fa.entry.js} +1 -1
- package/dist/tttx/{p-14270585.entry.js → p-5cae1beb.entry.js} +1 -1
- package/dist/tttx/{p-0c6a665d.js → p-62869344.js} +1 -1
- package/dist/tttx/{p-979ebe65.entry.js → p-92465671.entry.js} +1 -1
- package/dist/tttx/{p-84d90779.entry.js → p-a0179cb1.entry.js} +1 -1
- package/dist/tttx/{p-263d093c.entry.js → p-cc6644c9.entry.js} +1 -1
- package/dist/tttx/{p-39f991c3.entry.js → p-cd1565e0.entry.js} +1 -1
- package/dist/tttx/shadow-css-ed4599f8.js +387 -0
- package/dist/tttx/tttx-button.entry.js +30 -0
- package/dist/tttx/tttx-form.entry.js +373 -0
- package/dist/tttx/tttx-icon.entry.js +17 -0
- package/dist/tttx/tttx-keyvalue-block.entry.js +63 -0
- package/dist/tttx/tttx-list.entry.js +1730 -0
- package/dist/tttx/tttx-loading-spinner.entry.js +22 -0
- package/dist/tttx/tttx-standalone-input.entry.js +66 -0
- package/dist/tttx/tttx-toolbar.entry.js +16 -0
- package/dist/tttx/tttx.esm.js +129 -1
- package/dist/types/components/atoms/tttx-button/test/tttx-button.e2e.d.ts +1 -0
- package/dist/types/components/atoms/tttx-button/test/tttx-button.spec.d.ts +1 -0
- package/dist/types/components/atoms/tttx-icon/test/tttx-icon.e2e.d.ts +1 -0
- package/dist/types/components/atoms/tttx-icon/test/tttx-icon.spec.d.ts +1 -0
- package/dist/types/components/atoms/tttx-keyvalue-block/test/tttx-keyvalue-block.spec.d.ts +1 -0
- package/dist/types/components/atoms/tttx-loading-spinner/Test/tttx-loading-spinner.spec.d.ts +1 -0
- package/dist/types/components/molecules/tttx-form/lib/setErrorState.spec.d.ts +1 -0
- package/dist/types/components/molecules/tttx-form/lib/validityCheck.spec.d.ts +1 -0
- package/dist/types/components/molecules/tttx-form/test/tttx-form.e2e.d.ts +1 -0
- package/dist/types/components/molecules/tttx-form/test/tttx-form.spec.d.ts +1 -0
- package/dist/types/components/molecules/tttx-list/test/ttttx-list.spec.e2e.d.ts +1 -0
- package/dist/types/components/molecules/tttx-list/test/tttx-list.spec.d.ts +1 -0
- package/dist/types/components/molecules/tttx-standalone-input/test/tttx-standalone-input.e2e.d.ts +1 -0
- package/dist/types/components/molecules/tttx-standalone-input/test/tttx-standalone-input.spec.d.ts +1 -0
- package/dist/types/components/molecules/tttx-toolbar/test/tttx-toolbar.test.d.ts +0 -0
- package/dist/types/components/molecules/tttx-toolbar/tttx-toolbar.d.ts +4 -0
- package/dist/types/components/molecules/tttx-toolbar/tttx-toolbar.stories.d.ts +13 -0
- package/dist/types/components.d.ts +15 -0
- package/dist/types/shared/test/domsanitiser.options.spec.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import validityCheck from './validityCheck';
|
|
2
|
+
// badInput
|
|
3
|
+
// customError
|
|
4
|
+
// patternMismatch
|
|
5
|
+
// rangeOverflow
|
|
6
|
+
// rangeUnderflow
|
|
7
|
+
// stepMismatch
|
|
8
|
+
// tooLong
|
|
9
|
+
// tooShort
|
|
10
|
+
// typeMismatch
|
|
11
|
+
// valid
|
|
12
|
+
// valueMissing
|
|
13
|
+
describe('validityCheck', () => {
|
|
14
|
+
it('should return a valid response when there are no validation issues', async () => {
|
|
15
|
+
const preventDefault = jest.fn();
|
|
16
|
+
const event = {
|
|
17
|
+
target: {
|
|
18
|
+
value: 'test',
|
|
19
|
+
validity: {
|
|
20
|
+
valid: true
|
|
21
|
+
},
|
|
22
|
+
dataset: {}
|
|
23
|
+
},
|
|
24
|
+
preventDefault
|
|
25
|
+
};
|
|
26
|
+
const result = validityCheck(event);
|
|
27
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
28
|
+
expect(result).toStrictEqual({
|
|
29
|
+
"errorMessage": "",
|
|
30
|
+
"hasError": false,
|
|
31
|
+
"target": event.target
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
it('should return the required property when there is a value missing', async () => {
|
|
35
|
+
const preventDefault = jest.fn();
|
|
36
|
+
const event = {
|
|
37
|
+
target: {
|
|
38
|
+
dataset: {
|
|
39
|
+
required: 'This is required'
|
|
40
|
+
},
|
|
41
|
+
value: 'test',
|
|
42
|
+
validity: {
|
|
43
|
+
valid: false,
|
|
44
|
+
valueMissing: true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
preventDefault
|
|
48
|
+
};
|
|
49
|
+
const result = validityCheck(event);
|
|
50
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
51
|
+
expect(result).toStrictEqual({
|
|
52
|
+
"errorMessage": "This is required",
|
|
53
|
+
"hasError": true,
|
|
54
|
+
"target": event.target
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
it('should return a default error message property when there is a value missing', async () => {
|
|
58
|
+
const preventDefault = jest.fn();
|
|
59
|
+
const event = {
|
|
60
|
+
target: {
|
|
61
|
+
dataset: {},
|
|
62
|
+
value: 'test',
|
|
63
|
+
validity: {
|
|
64
|
+
valid: false,
|
|
65
|
+
valueMissing: true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
preventDefault
|
|
69
|
+
};
|
|
70
|
+
const result = validityCheck(event);
|
|
71
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
72
|
+
expect(result).toStrictEqual({
|
|
73
|
+
"errorMessage": 'This field is required',
|
|
74
|
+
"hasError": true,
|
|
75
|
+
"target": event.target
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
it('should return the pattern property when there is a patternMismatch', async () => {
|
|
79
|
+
const preventDefault = jest.fn();
|
|
80
|
+
const event = {
|
|
81
|
+
target: {
|
|
82
|
+
dataset: {
|
|
83
|
+
pattern: 'Incorrect format CUSTOM'
|
|
84
|
+
},
|
|
85
|
+
value: 'test',
|
|
86
|
+
validity: {
|
|
87
|
+
valid: false,
|
|
88
|
+
patternMismatch: true
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
preventDefault
|
|
92
|
+
};
|
|
93
|
+
const result = validityCheck(event);
|
|
94
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
95
|
+
expect(result).toStrictEqual({
|
|
96
|
+
"errorMessage": "Incorrect format CUSTOM",
|
|
97
|
+
"hasError": true,
|
|
98
|
+
"target": event.target
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
it('should return the a default error message when there is a patternMismatch', async () => {
|
|
102
|
+
const preventDefault = jest.fn();
|
|
103
|
+
const event = {
|
|
104
|
+
target: {
|
|
105
|
+
dataset: {},
|
|
106
|
+
value: 'test',
|
|
107
|
+
validity: {
|
|
108
|
+
valid: false,
|
|
109
|
+
patternMismatch: true
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
preventDefault
|
|
113
|
+
};
|
|
114
|
+
const result = validityCheck(event);
|
|
115
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
116
|
+
expect(result).toStrictEqual({
|
|
117
|
+
"errorMessage": 'Incorrect format',
|
|
118
|
+
"hasError": true,
|
|
119
|
+
"target": event.target
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
it('should return the badinput error message property when there is a badInput', async () => {
|
|
123
|
+
const preventDefault = jest.fn();
|
|
124
|
+
const event = {
|
|
125
|
+
target: {
|
|
126
|
+
dataset: {
|
|
127
|
+
badinput: 'There is a bad input'
|
|
128
|
+
},
|
|
129
|
+
value: 'test',
|
|
130
|
+
validity: {
|
|
131
|
+
valid: false,
|
|
132
|
+
badInput: true
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
preventDefault
|
|
136
|
+
};
|
|
137
|
+
const result = validityCheck(event);
|
|
138
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
139
|
+
expect(result).toStrictEqual({
|
|
140
|
+
"errorMessage": "There is a bad input",
|
|
141
|
+
"hasError": true,
|
|
142
|
+
"target": event.target
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
it('should return a default error message property when there is a badInput', async () => {
|
|
146
|
+
const preventDefault = jest.fn();
|
|
147
|
+
const event = {
|
|
148
|
+
target: {
|
|
149
|
+
value: 'test',
|
|
150
|
+
validity: {
|
|
151
|
+
valid: false,
|
|
152
|
+
badInput: true
|
|
153
|
+
},
|
|
154
|
+
dataset: {}
|
|
155
|
+
},
|
|
156
|
+
preventDefault
|
|
157
|
+
};
|
|
158
|
+
const result = validityCheck(event);
|
|
159
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
160
|
+
expect(result).toStrictEqual({
|
|
161
|
+
"errorMessage": 'Wrong input type',
|
|
162
|
+
"hasError": true,
|
|
163
|
+
"target": event.target
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
it('should return a message for an item out of range (underflow) with custom message', async () => {
|
|
167
|
+
const preventDefault = jest.fn();
|
|
168
|
+
const event = {
|
|
169
|
+
target: {
|
|
170
|
+
value: '0',
|
|
171
|
+
validity: {
|
|
172
|
+
valid: false,
|
|
173
|
+
rangeOverflow: true
|
|
174
|
+
},
|
|
175
|
+
dataset: {
|
|
176
|
+
range: 'Value is out of range'
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
preventDefault
|
|
180
|
+
};
|
|
181
|
+
const result = validityCheck(event);
|
|
182
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
183
|
+
expect(result).toStrictEqual({
|
|
184
|
+
"errorMessage": "Value is out of range",
|
|
185
|
+
"hasError": true,
|
|
186
|
+
"target": event.target
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
it('should return a message for an item out of range (underflow)', async () => {
|
|
190
|
+
const preventDefault = jest.fn();
|
|
191
|
+
const event = {
|
|
192
|
+
target: {
|
|
193
|
+
value: '0',
|
|
194
|
+
validity: {
|
|
195
|
+
valid: false,
|
|
196
|
+
rangeOverflow: true
|
|
197
|
+
},
|
|
198
|
+
dataset: {}
|
|
199
|
+
},
|
|
200
|
+
preventDefault
|
|
201
|
+
};
|
|
202
|
+
const result = validityCheck(event);
|
|
203
|
+
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
204
|
+
expect(result).toStrictEqual({
|
|
205
|
+
"errorMessage": "Invalid value",
|
|
206
|
+
"hasError": true,
|
|
207
|
+
"target": event.target
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
// it('target.validity.rangeOverflow', async () => {
|
|
211
|
+
// });
|
|
212
|
+
// it('target.validity.rangeUnderflow', async () => {
|
|
213
|
+
// });
|
|
214
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { newE2EPage } from '@stencil/core/testing';
|
|
2
|
+
describe('tttx-form', () => {
|
|
3
|
+
it('renders', async () => {
|
|
4
|
+
const page = await newE2EPage();
|
|
5
|
+
await page.setContent('<tttx-form></tttx-form>');
|
|
6
|
+
const element = await page.find('tttx-form');
|
|
7
|
+
expect(element).toHaveClass('hydrated');
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { h } from '@stencil/core';
|
|
2
|
+
import { newSpecPage } from '@stencil/core/testing';
|
|
3
|
+
import { TttxForm } from '../tttx-form';
|
|
4
|
+
describe('tttx-form', () => {
|
|
5
|
+
it('renders', async () => {
|
|
6
|
+
const page = await newSpecPage({
|
|
7
|
+
components: [TttxForm],
|
|
8
|
+
html: '<tttx-form></tttx-form>',
|
|
9
|
+
});
|
|
10
|
+
expect(page.root).toEqualHtml(`
|
|
11
|
+
<tttx-form>
|
|
12
|
+
<mock:shadow-root>
|
|
13
|
+
<form>
|
|
14
|
+
<fieldset></fieldset>
|
|
15
|
+
</form>
|
|
16
|
+
</mock:shadow-root>
|
|
17
|
+
</tttx-form>
|
|
18
|
+
`);
|
|
19
|
+
});
|
|
20
|
+
it('renders a single form item', async () => {
|
|
21
|
+
const singleFormItemSchema = {
|
|
22
|
+
properties: {
|
|
23
|
+
input: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
format: 'string',
|
|
26
|
+
form: {
|
|
27
|
+
type: 'text',
|
|
28
|
+
label: 'Input Field',
|
|
29
|
+
validation: {
|
|
30
|
+
required: {
|
|
31
|
+
message: 'Please enter something'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const page = await newSpecPage({
|
|
39
|
+
components: [TttxForm],
|
|
40
|
+
html: `<tttx-form formschema='${JSON.stringify(singleFormItemSchema)}'></tttx-form>`,
|
|
41
|
+
});
|
|
42
|
+
expect(page.root).toEqualHtml(`
|
|
43
|
+
<tttx-form formschema='${JSON.stringify(singleFormItemSchema)}'>
|
|
44
|
+
<mock:shadow-root>
|
|
45
|
+
<form>
|
|
46
|
+
<fieldset>
|
|
47
|
+
<label class="inputBlock">
|
|
48
|
+
Input Field
|
|
49
|
+
<input autocomplete="off" data-required="Please enter something" name="input" placeholder="" required="" type="text" />
|
|
50
|
+
<div class="errorBubble"></div>
|
|
51
|
+
</label>
|
|
52
|
+
<input class="button primary-blue" type="submit" value="Save">
|
|
53
|
+
</fieldset>
|
|
54
|
+
</form>
|
|
55
|
+
</mock:shadow-root>
|
|
56
|
+
</tttx-form>
|
|
57
|
+
`);
|
|
58
|
+
});
|
|
59
|
+
it('renders without validation', async () => {
|
|
60
|
+
const singleFormItemSchema = {
|
|
61
|
+
properties: {
|
|
62
|
+
input: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
format: 'string',
|
|
65
|
+
form: {
|
|
66
|
+
type: 'text',
|
|
67
|
+
label: 'Input Field'
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const page = await newSpecPage({
|
|
73
|
+
components: [TttxForm],
|
|
74
|
+
html: `<tttx-form formschema='${JSON.stringify(singleFormItemSchema)}'></tttx-form>`,
|
|
75
|
+
});
|
|
76
|
+
expect(page.root).toEqualHtml(`
|
|
77
|
+
<tttx-form formschema='${JSON.stringify(singleFormItemSchema)}'>
|
|
78
|
+
<mock:shadow-root>
|
|
79
|
+
<form>
|
|
80
|
+
<fieldset>
|
|
81
|
+
<label class="inputBlock">
|
|
82
|
+
Input Field
|
|
83
|
+
<span class="optional">
|
|
84
|
+
(optional)
|
|
85
|
+
</span>
|
|
86
|
+
<input autocomplete="off" name="input" placeholder="" type="text" />
|
|
87
|
+
<div class="errorBubble"></div>
|
|
88
|
+
</label>
|
|
89
|
+
<input class="button primary-blue" type="submit" value="Save">
|
|
90
|
+
</fieldset>
|
|
91
|
+
</form>
|
|
92
|
+
</mock:shadow-root>
|
|
93
|
+
</tttx-form>
|
|
94
|
+
`);
|
|
95
|
+
});
|
|
96
|
+
it('renders a complex form', async () => {
|
|
97
|
+
const formSchema = {
|
|
98
|
+
properties: {
|
|
99
|
+
title: {
|
|
100
|
+
type: 'string',
|
|
101
|
+
format: 'string',
|
|
102
|
+
form: {
|
|
103
|
+
type: 'text',
|
|
104
|
+
placeholder: 'Mr, Mrs, Dr, Hon Rev',
|
|
105
|
+
label: 'Title',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
forename: {
|
|
109
|
+
type: 'string',
|
|
110
|
+
format: 'string',
|
|
111
|
+
form: {
|
|
112
|
+
type: 'text',
|
|
113
|
+
placeholder: 'John',
|
|
114
|
+
label: 'Forename',
|
|
115
|
+
validation: {
|
|
116
|
+
required: {
|
|
117
|
+
message: 'Please enter your forename',
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
surname: {
|
|
123
|
+
type: 'string',
|
|
124
|
+
format: 'string',
|
|
125
|
+
form: {
|
|
126
|
+
type: 'text',
|
|
127
|
+
placeholder: 'Doe',
|
|
128
|
+
label: 'Surname',
|
|
129
|
+
validation: {
|
|
130
|
+
required: {
|
|
131
|
+
message: 'Please enter your surname',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
postcode: {
|
|
137
|
+
type: 'string',
|
|
138
|
+
format: 'string',
|
|
139
|
+
form: {
|
|
140
|
+
type: 'text',
|
|
141
|
+
placeholder: 'AB10',
|
|
142
|
+
label: 'Start of postcode',
|
|
143
|
+
validation: {
|
|
144
|
+
required: {
|
|
145
|
+
message: 'Please enter the beginning of your postcode',
|
|
146
|
+
},
|
|
147
|
+
pattern: {
|
|
148
|
+
pattern: '^([A-Za-z][0-9])$|^([A-Za-z][0-9]{2})$|^([A-Za-z]{2}[0-9])$|^([A-Za-z]{2}[0-9]{2})$|^([A-Za-z][0-9][A-Za-z])$|^([A-Za-z]{2}[0-9][A-Za-z])$|^(GIR|BF|BX|XX)$',
|
|
149
|
+
message: 'Please enter the first half of your postcode. EG: ZZ99',
|
|
150
|
+
},
|
|
151
|
+
maxlength: 4,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
age: {
|
|
156
|
+
type: 'number',
|
|
157
|
+
format: 'number',
|
|
158
|
+
form: {
|
|
159
|
+
type: 'number',
|
|
160
|
+
placeholder: '',
|
|
161
|
+
label: 'Age',
|
|
162
|
+
validation: {
|
|
163
|
+
required: {
|
|
164
|
+
message: 'Please enter your age',
|
|
165
|
+
},
|
|
166
|
+
badInput: {
|
|
167
|
+
message: 'Please enter a number',
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
dob: {
|
|
173
|
+
type: 'string',
|
|
174
|
+
format: 'date-time',
|
|
175
|
+
form: {
|
|
176
|
+
type: 'date',
|
|
177
|
+
placeholder: '',
|
|
178
|
+
label: 'Date of birth',
|
|
179
|
+
validation: {
|
|
180
|
+
required: {
|
|
181
|
+
message: 'Please enter your date of birth',
|
|
182
|
+
},
|
|
183
|
+
minmax: {
|
|
184
|
+
min: '1900-01-01',
|
|
185
|
+
max: '2100-12-31',
|
|
186
|
+
message: 'Please enter a date between 1900 and 2100',
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
const page = await newSpecPage({
|
|
194
|
+
components: [TttxForm],
|
|
195
|
+
template: () => (h("tttx-form", { formschema: formSchema })),
|
|
196
|
+
});
|
|
197
|
+
expect(page.root).toEqualHtml(`
|
|
198
|
+
<tttx-form>
|
|
199
|
+
<mock:shadow-root>
|
|
200
|
+
<form>
|
|
201
|
+
<fieldset>
|
|
202
|
+
<label class="inputBlock">Title<span class="optional"> (optional)</span>
|
|
203
|
+
<input autocomplete="off" name="title" placeholder="Mr, Mrs, Dr, Hon Rev" type="text" />
|
|
204
|
+
<div class="errorBubble"></div>
|
|
205
|
+
</label>
|
|
206
|
+
<label class="inputBlock">Forename
|
|
207
|
+
<input autocomplete="off" data-required="Please enter your forename" name="forename" placeholder="John" required="" type="text"/>
|
|
208
|
+
<div class="errorBubble"></div>
|
|
209
|
+
</label>
|
|
210
|
+
<label class="inputBlock">Surname
|
|
211
|
+
<input autocomplete="off" data-required="Please enter your surname" name="surname" placeholder="Doe" required="" type="text">
|
|
212
|
+
<div class="errorBubble"></div>
|
|
213
|
+
</label>
|
|
214
|
+
<label class="inputBlock">Start of postcode
|
|
215
|
+
<input autocomplete="off" data-pattern="Please enter the first half of your postcode. EG: ZZ99" data-required="Please enter the beginning of your postcode" maxlength="4" name="postcode" pattern="^([A-Za-z][0-9])$|^([A-Za-z][0-9]{2})$|^([A-Za-z]{2}[0-9])$|^([A-Za-z]{2}[0-9]{2})$|^([A-Za-z][0-9][A-Za-z])$|^([A-Za-z]{2}[0-9][A-Za-z])$|^(GIR|BF|BX|XX)$" placeholder="AB10" required="" type="text">
|
|
216
|
+
<div class="errorBubble"></div>
|
|
217
|
+
</label>
|
|
218
|
+
<label class="inputBlock">Age
|
|
219
|
+
<input autocomplete="off" data-badinput="Please enter a number" data-required="Please enter your age" name="age" placeholder="" required="" type="number">
|
|
220
|
+
<div class="errorBubble"></div>
|
|
221
|
+
</label>
|
|
222
|
+
<label class="inputBlock">Date of birth
|
|
223
|
+
<input autocomplete="off" data-range="Please enter a date between 1900 and 2100" data-required="Please enter your date of birth" max="2100-12-31" min="1900-01-01" name="dob" placeholder="" required="" type="date">
|
|
224
|
+
<div class="errorBubble"></div>
|
|
225
|
+
</label>
|
|
226
|
+
<input type="submit" class="button primary-blue" value="Save"></fieldset>
|
|
227
|
+
</form>
|
|
228
|
+
</mock:shadow-root>
|
|
229
|
+
</tttx-form>
|
|
230
|
+
`);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { newE2EPage } from '@stencil/core/testing';
|
|
2
|
+
describe('tttx-list', () => {
|
|
3
|
+
it('sanitises the html of the element property', async () => {
|
|
4
|
+
const page = await newE2EPage();
|
|
5
|
+
await page.setContent('<tttx-list></tttx-list>');
|
|
6
|
+
await page.$eval('tttx-list', (elm) => {
|
|
7
|
+
elm.data = [{ element: '<span><tttx-icon icon="egg" color="blue"></tttx-icon></span>Test<script>alert(4)</script>' }];
|
|
8
|
+
});
|
|
9
|
+
await page.waitForChanges();
|
|
10
|
+
const element = await page.find('tttx-list');
|
|
11
|
+
expect(element).toEqualHtml(`
|
|
12
|
+
<tttx-list class="hydrated">
|
|
13
|
+
<mock:shadow-root>
|
|
14
|
+
<ul class="list">
|
|
15
|
+
<li class="item">
|
|
16
|
+
<span class="item-content">
|
|
17
|
+
<span><tttx-icon class="hydrated" icon="egg" color="blue"></tttx-icon></span>
|
|
18
|
+
Test
|
|
19
|
+
</span>
|
|
20
|
+
</li>
|
|
21
|
+
</ul>
|
|
22
|
+
</mock:shadow-root>
|
|
23
|
+
</tttx-list>
|
|
24
|
+
`);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { newSpecPage } from '@stencil/core/testing';
|
|
2
|
+
import { TttxList } from '../tttx-list';
|
|
3
|
+
describe('tttx-list', () => {
|
|
4
|
+
it('renders data using JS objects (with icon, clickable)', async () => {
|
|
5
|
+
const page = await newSpecPage({
|
|
6
|
+
components: [TttxList],
|
|
7
|
+
html: '<tttx-list></tttx-list>',
|
|
8
|
+
});
|
|
9
|
+
page.rootInstance.data = [{ icon: 'info', element: '<span><tttx-icon icon="egg" color="blue" /></span> Test', clickable: true }];
|
|
10
|
+
await page.waitForChanges();
|
|
11
|
+
expect(page.root).toEqualHtml(`
|
|
12
|
+
<tttx-list>
|
|
13
|
+
<mock:shadow-root>
|
|
14
|
+
<ul class="list">
|
|
15
|
+
<li class="item clickable">
|
|
16
|
+
<span class="item-content">
|
|
17
|
+
<span><tttx-icon icon="egg" color="blue"></tttx-icon></span>
|
|
18
|
+
Test
|
|
19
|
+
</span>
|
|
20
|
+
<tttx-icon class="align-right" icon="info"></tttx-icon>
|
|
21
|
+
</li>
|
|
22
|
+
</ul>
|
|
23
|
+
</mock:shadow-root>
|
|
24
|
+
</tttx-list>
|
|
25
|
+
`);
|
|
26
|
+
});
|
|
27
|
+
it('renders data using JS objects (with icon, clickable:false)', async () => {
|
|
28
|
+
const page = await newSpecPage({
|
|
29
|
+
components: [TttxList],
|
|
30
|
+
html: '<tttx-list></tttx-list>',
|
|
31
|
+
});
|
|
32
|
+
page.rootInstance.data = [{ icon: 'info', element: '<span><tttx-icon icon="egg" color="blue" /></span> Test' }];
|
|
33
|
+
await page.waitForChanges();
|
|
34
|
+
expect(page.root).toEqualHtml(`
|
|
35
|
+
<tttx-list>
|
|
36
|
+
<mock:shadow-root>
|
|
37
|
+
<ul class="list">
|
|
38
|
+
<li class="item">
|
|
39
|
+
<span class="item-content">
|
|
40
|
+
<span><tttx-icon icon="egg" color="blue"></tttx-icon></span>
|
|
41
|
+
Test
|
|
42
|
+
</span>
|
|
43
|
+
<tttx-icon class="align-right" icon="info"></tttx-icon>
|
|
44
|
+
</li>
|
|
45
|
+
</ul>
|
|
46
|
+
</mock:shadow-root>
|
|
47
|
+
</tttx-list>
|
|
48
|
+
`);
|
|
49
|
+
});
|
|
50
|
+
it('renders data using JS objects (without icon, clickable)', async () => {
|
|
51
|
+
const page = await newSpecPage({
|
|
52
|
+
components: [TttxList],
|
|
53
|
+
html: '<tttx-list></tttx-list>',
|
|
54
|
+
});
|
|
55
|
+
page.rootInstance.data = [{ element: '<span><tttx-icon icon="egg" color="blue" /></span> Test', clickable: true }];
|
|
56
|
+
await page.waitForChanges();
|
|
57
|
+
expect(page.root).toEqualHtml(`
|
|
58
|
+
<tttx-list>
|
|
59
|
+
<mock:shadow-root>
|
|
60
|
+
<ul class="list">
|
|
61
|
+
<li class="item clickable">
|
|
62
|
+
<span class="item-content">
|
|
63
|
+
<span><tttx-icon icon="egg" color="blue"></tttx-icon></span>
|
|
64
|
+
Test
|
|
65
|
+
</span>
|
|
66
|
+
</li>
|
|
67
|
+
</ul>
|
|
68
|
+
</mock:shadow-root>
|
|
69
|
+
</tttx-list>
|
|
70
|
+
`);
|
|
71
|
+
});
|
|
72
|
+
it('renders data using JS objects (without icon, clickable:false)', async () => {
|
|
73
|
+
const page = await newSpecPage({
|
|
74
|
+
components: [TttxList],
|
|
75
|
+
html: '<tttx-list></tttx-list>',
|
|
76
|
+
});
|
|
77
|
+
page.rootInstance.data = [{ element: '<span><tttx-icon icon="egg" color="blue" /></span> Test' }];
|
|
78
|
+
await page.waitForChanges();
|
|
79
|
+
expect(page.root).toEqualHtml(`
|
|
80
|
+
<tttx-list>
|
|
81
|
+
<mock:shadow-root>
|
|
82
|
+
<ul class="list">
|
|
83
|
+
<li class="item">
|
|
84
|
+
<span class="item-content">
|
|
85
|
+
<span><tttx-icon icon="egg" color="blue"></tttx-icon></span>
|
|
86
|
+
Test
|
|
87
|
+
</span>
|
|
88
|
+
</li>
|
|
89
|
+
</ul>
|
|
90
|
+
</mock:shadow-root>
|
|
91
|
+
</tttx-list>
|
|
92
|
+
`);
|
|
93
|
+
});
|
|
94
|
+
it('renders data using JSON', async () => {
|
|
95
|
+
const data = '[{ "icon": "info", "element": "<span><tttx-icon icon=\\"egg\\" color=\\"blue\\" /></span> Test", "clickable": true }]';
|
|
96
|
+
const page = await newSpecPage({
|
|
97
|
+
components: [TttxList],
|
|
98
|
+
html: `<tttx-list data='${data}'></tttx-list>`,
|
|
99
|
+
});
|
|
100
|
+
await page.waitForChanges();
|
|
101
|
+
expect(page.root).toEqualHtml(`
|
|
102
|
+
<tttx-list data="[{ "icon": "info", "element": "<span><tttx-icon icon=\\"egg\\" color=\\"blue\\" /></span> Test", "clickable": true }]">
|
|
103
|
+
<mock:shadow-root>
|
|
104
|
+
<ul class="list">
|
|
105
|
+
<li class="item clickable">
|
|
106
|
+
<span class="item-content">
|
|
107
|
+
<span><tttx-icon icon="egg" color="blue"></tttx-icon></span>
|
|
108
|
+
Test
|
|
109
|
+
</span>
|
|
110
|
+
<tttx-icon class="align-right" icon="info"></tttx-icon>
|
|
111
|
+
</li>
|
|
112
|
+
</ul>
|
|
113
|
+
</mock:shadow-root>
|
|
114
|
+
</tttx-list>
|
|
115
|
+
`);
|
|
116
|
+
});
|
|
117
|
+
it('renders nothing when there is no data', async () => {
|
|
118
|
+
const page = await newSpecPage({
|
|
119
|
+
components: [TttxList],
|
|
120
|
+
html: '<tttx-list></tttx-list>',
|
|
121
|
+
});
|
|
122
|
+
page.rootInstance.data = [];
|
|
123
|
+
await page.waitForChanges();
|
|
124
|
+
expect(page.root).toEqualHtml(`
|
|
125
|
+
<tttx-list>
|
|
126
|
+
<mock:shadow-root>
|
|
127
|
+
<ul class="list">
|
|
128
|
+
</ul>
|
|
129
|
+
</mock:shadow-root>
|
|
130
|
+
</tttx-list>
|
|
131
|
+
`);
|
|
132
|
+
});
|
|
133
|
+
it('emits listRowClick event when a clickable row is clicked', async () => {
|
|
134
|
+
const page = await newSpecPage({
|
|
135
|
+
components: [TttxList],
|
|
136
|
+
html: '<tttx-list name="test-list"></tttx-list>',
|
|
137
|
+
});
|
|
138
|
+
const eventSpy = jest.fn();
|
|
139
|
+
page.doc.addEventListener('listRowClick', eventSpy);
|
|
140
|
+
page.rootInstance.data = [
|
|
141
|
+
{ element: '<div>Item 1</div>', clickable: true, rowData: 'Item 1' },
|
|
142
|
+
{ element: '<div>Item 2</div>', clickable: false, rowData: 'Item 2' },
|
|
143
|
+
];
|
|
144
|
+
await page.waitForChanges();
|
|
145
|
+
const clickableItem = page.root.shadowRoot.querySelector('.clickable');
|
|
146
|
+
clickableItem.dispatchEvent(new Event('click'));
|
|
147
|
+
expect(eventSpy).toHaveBeenCalledWith(expect.objectContaining({
|
|
148
|
+
detail: { name: 'test-list', data: 'Item 1' },
|
|
149
|
+
}));
|
|
150
|
+
});
|
|
151
|
+
it('does not emit listRowClick event when a non-clickable row is clicked', async () => {
|
|
152
|
+
const page = await newSpecPage({
|
|
153
|
+
components: [TttxList],
|
|
154
|
+
html: '<tttx-list></tttx-list>',
|
|
155
|
+
});
|
|
156
|
+
const eventSpy = jest.fn();
|
|
157
|
+
page.doc.addEventListener('listRowClick', eventSpy);
|
|
158
|
+
page.rootInstance.data = [
|
|
159
|
+
{ element: '<div>Item 1</div>', clickable: true, rowData: 'Item 1' },
|
|
160
|
+
{ element: '<div>Item 2</div>', clickable: false, rowData: 'Item 2' },
|
|
161
|
+
];
|
|
162
|
+
await page.waitForChanges();
|
|
163
|
+
const nonClickableItem = page.root.shadowRoot.querySelector(':not(.clickable)');
|
|
164
|
+
await nonClickableItem.dispatchEvent(new Event('click'));
|
|
165
|
+
expect(eventSpy).not.toHaveBeenCalled();
|
|
166
|
+
});
|
|
167
|
+
it('does not emit listRowClick event when a row without rowData is clicked', async () => {
|
|
168
|
+
const page = await newSpecPage({
|
|
169
|
+
components: [TttxList],
|
|
170
|
+
html: '<tttx-list></tttx-list>',
|
|
171
|
+
});
|
|
172
|
+
const eventSpy = jest.fn();
|
|
173
|
+
page.doc.addEventListener('listRowClick', eventSpy);
|
|
174
|
+
page.rootInstance.data = [
|
|
175
|
+
{ element: '<div>Item 1</div>', clickable: true },
|
|
176
|
+
{ element: '<div>Item 2</div>', clickable: false },
|
|
177
|
+
];
|
|
178
|
+
await page.waitForChanges();
|
|
179
|
+
const nonClickableItem = page.root.shadowRoot.querySelector('.clickable');
|
|
180
|
+
await nonClickableItem.dispatchEvent(new Event('click'));
|
|
181
|
+
expect(eventSpy).not.toHaveBeenCalled();
|
|
182
|
+
});
|
|
183
|
+
});
|
package/dist/collection/components/molecules/tttx-standalone-input/test/tttx-standalone-input.e2e.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { newE2EPage } from '@stencil/core/testing';
|
|
2
|
+
describe('tttx-standalone-input', () => {
|
|
3
|
+
it('renders', async () => {
|
|
4
|
+
const page = await newE2EPage();
|
|
5
|
+
await page.setContent('<tttx-standalone-input></tttx-standalone-input>');
|
|
6
|
+
const element = await page.find('tttx-standalone-input');
|
|
7
|
+
expect(element).toHaveClass('hydrated');
|
|
8
|
+
});
|
|
9
|
+
});
|