UNPKG

10.9 kBJavaScriptView Raw
1var test = require('tape');
2var InputView = require('../ampersand-expanding-textarea-view');
3var customTemplate = '<label class="custominput"><span data-hook="label"></span><textarea data-hook="input-mirror"></textarea><div contenteditable="true" data-hook="input-primary"></div><div data-hook="message-container"><p data-hook="message-text"></p></div></label>';
4
5if (!Function.prototype.bind) Function.prototype.bind = require('function-bind');
6
7function isHidden(el) {
8 return el.style.display === 'none';
9}
10
11function hasClass(el, klass) {
12 return el.classList.contains(klass);
13}
14
15test('basic initialization', function (t) {
16 var input = new InputView({
17 name: 'title'
18 });
19 input.render();
20 t.equal(input.el.tagName, 'LABEL');
21 t.equal(input.el.querySelectorAll('textarea').length, 2);
22 t.equal(input.el.querySelector('textarea').getAttribute('name'), 'title');
23 t.end();
24});
25
26test('initialize with value', function (t) {
27 var input = new InputView({
28 name: 'title',
29 value: 'Once upon a time'
30 });
31
32 input.render();
33
34 t.equal(input.el.querySelector('textarea').value, 'Once upon a time');
35 t.end();
36});
37
38test('can initialize with template without having to extend', function (t) {
39 var input = new InputView({
40 name: 'title',
41 value: 'Once upon a time',
42 template: customTemplate
43 });
44
45 input.render();
46
47 t.equal(input.el.className, 'custominput');
48 t.end();
49});
50
51test('should be able to extend a template as well', function (t) {
52 var input = new (InputView.extend({
53 template: customTemplate
54 }))({name: 'title',
55 value: 'Once upon a time',
56 });
57
58 input.render();
59
60 t.equal(input.el.className, 'custominput');
61 t.end();
62
63 input.render();
64});
65
66test('reset value', function (t) {
67 var input = new InputView({
68 name: 'title'
69 });
70 input.render();
71 input.setValue('something');
72 t.equal(input.input.value, 'something', 'Value should be updated');
73 input.reset();
74 t.equal(input.input.value, '', 'Value should be reset');
75
76 var input2 = new InputView({
77 name: 'title',
78 value: 'start'
79 });
80 input2.render();
81 t.equal(input2.input.value, 'start', 'Value should be set initially');
82 input2.setValue('somethingelse');
83 t.equal(input2.input.value, 'somethingelse', 'value should be updated');
84 input2.reset();
85 t.equal(input2.input.value, 'start', 'value should have been reset to original');
86
87 t.end();
88});
89
90test('clear', function (t) {
91 var input = new InputView({
92 name: 'title',
93 value: 'something'
94 });
95 input.render();
96
97 t.equal(input.input.value, 'something');
98 input.reset();
99 t.equal(input.input.value, 'something', 'reset should do nothing');
100 input.clear();
101 t.equal(input.input.value, '');
102 t.equal(input.value, '');
103
104 var input2 = new InputView({
105 name: 'thing'
106 });
107 input2.render();
108 t.equal(input2.value, '');
109 input2.setValue('thing');
110 t.equal(input2.input.value, 'thing');
111 t.equal(input2.value, 'thing');
112 input2.clear();
113 t.equal(input2.input.value, '');
114 t.equal(input2.value, '');
115
116 t.end();
117});
118
119test('initalize with a value of `0`', function(t) {
120 var input = new InputView({
121 name: 'title',
122 type: 'number',
123 value: 0
124 });
125
126 input.render();
127
128 t.equal(parseFloat(input.el.querySelector('textarea').value), 0);
129 t.end();
130});
131
132test('Tests with required true and false', function (t) {
133 var inputs = [
134 new InputView({
135 name: 'title',
136 required: true,
137 tests: [
138 function (val) {
139 if (val.length < 5) return 'Must be 5+ characters.';
140 }
141 ]
142 }),
143 new InputView({
144 name: 'title',
145 required: false,
146 tests: [
147 function (val) {
148 if (val.length < 5) return 'Must be 5+ characters.';
149 }
150 ]
151 }),
152 ];
153
154 inputs.forEach(function (input) {
155 input.render();
156
157 var inputElement = input.el.querySelector('textarea');
158 var messageContainer = input.el.querySelector('[data-hook=message-container]');
159
160 //"Trigger change events"
161 //TODO: this should be real dom events
162 inputElement.value = 'O';
163 input.handleInputChanged();
164
165 // At this point we are not yet blurred so there should no messages or classes
166 t.notOk(input.valid, 'Input should be invalid');
167 t.ok(isHidden(messageContainer), 'Message should not be visible');
168 t.notOk(hasClass(inputElement, 'input-invalid'), 'Does not have invalid class');
169 t.notOk(hasClass(inputElement, 'input-valid'), 'Doest not have valid class');
170
171 // Another change to an empty state
172 inputElement.value = '';
173 input.handleInputChanged();
174
175
176 // should still not show errors
177 t.notOk(input.valid, 'Input should be invalid');
178 t.ok(isHidden(messageContainer), 'Message should not be visible');
179 t.notOk(hasClass(inputElement, 'input-invalid'), 'Does not have invalid class');
180 t.notOk(hasClass(inputElement, 'input-valid'), 'Doest not have valid class');
181
182 // Blur to trigger invalid message/class
183 inputElement.value = 'O';
184 input.handleInputChanged();
185 input.handleBlur();
186
187 t.notOk(input.valid, 'Input should be invalid');
188 t.notOk(isHidden(messageContainer), 'Message should be visible');
189 t.ok(hasClass(inputElement, 'input-invalid'), 'Has invalid class');
190 t.notOk(hasClass(inputElement, 'input-valid'), 'Does not have valid class');
191
192 //"Trigger change events again"
193 inputElement.value = 'Once upon a time!';
194 input.handleInputChanged();
195 input.handleBlur();
196
197 t.ok(input.valid, 'Input should be valid');
198 t.ok(isHidden(messageContainer), 'Message should not be visible');
199 t.notOk(hasClass(inputElement, 'input-invalid'), 'Does not have invalid class');
200 t.ok(hasClass(inputElement, 'input-valid'), 'Has valid class');
201 });
202
203 t.end();
204});
205
206test('allow setting root element class', function (t) {
207 var input = new InputView();
208 input.render();
209 t.equal(input.el.className, '');
210
211 input = new InputView({
212 rootElementClass: 'something'
213 });
214 input.render();
215
216 t.equal(input.el.className, 'something');
217 input.rootElementClass = 'somethingelse';
218 t.equal(input.el.className, 'somethingelse');
219
220 t.end();
221});
222
223test('validityClass is present on submit even if unchanged', function (t) {
224 [
225 new InputView({
226 name: 'title',
227 required: true
228 }),
229 new InputView({
230 name: 'title',
231 required: true,
232 value: ''
233 })
234 ].forEach(function (input) {
235 input.render();
236
237 var inputElement = input.el.querySelector('textarea');
238 var messageContainer = input.el.querySelector('[data-hook=message-container]');
239
240 // "Trigger submit on the input"
241 // TODO: should we pull in form-view and do a dom submit event?
242 input.beforeSubmit();
243
244 t.notOk(input.valid, 'Input should be invalid');
245 t.notOk(isHidden(messageContainer), 'Message should be visible');
246 t.ok(hasClass(inputElement, 'input-invalid'), 'Has invalid class');
247 t.notOk(hasClass(inputElement, 'input-valid'), 'Does not have valid class');
248 });
249
250 t.end();
251});
252
253test('Required views display message and class after edited', function (t) {
254 [
255 new InputView({
256 name: 'title',
257 required: true
258 }),
259 new InputView({
260 name: 'title',
261 required: true,
262 value: ''
263 })
264 ].forEach(function (input) {
265 input.render();
266
267 var inputElement = input.el.querySelector('textarea');
268 var messageContainer = input.el.querySelector('[data-hook=message-container]');
269
270 inputElement.value = 'Required string';
271 input.handleInputChanged();
272 input.handleBlur();
273
274 t.ok(input.valid, 'Input should be valid');
275 t.ok(isHidden(messageContainer), 'Message should not be visible');
276 t.notOk(hasClass(inputElement, 'input-invalid'), 'Does not have invalid class');
277 t.ok(hasClass(inputElement, 'input-valid'), 'Has valid class');
278
279 // Changing the value back to an empty string should show invalid
280 // message and class even though it is technically "unchanged"
281 inputElement.value = '';
282 input.handleInputChanged();
283 input.handleBlur();
284
285 t.notOk(input.valid, 'Input should be invalid');
286 t.notOk(isHidden(messageContainer), 'Message should be visible');
287 t.ok(hasClass(inputElement, 'input-invalid'), 'Has invalid class');
288 t.notOk(hasClass(inputElement, 'input-valid'), 'Does not have valid class');
289 });
290
291 t.end();
292});
293
294test('value reports changed in cases where it shouldnt', function (t) {
295 [
296 new InputView({
297 name: 'title'
298 }),
299 new InputView({
300 name: 'title',
301 value: ''
302 }),
303 new InputView({
304 name: 'title',
305 value: null
306 })
307 ].forEach(function (input) {
308 input.render();
309
310 var inputElement = input.el.querySelector('textarea');
311
312 // Setting the input value directly and trigger input changed
313 inputElement.value = '0';
314 input.handleInputChanged();
315 t.ok(input.changed, 'Input is changed');
316
317 inputElement.value = '';
318 input.handleInputChanged();
319 t.notOk(input.changed, 'Input is not changed when empty string');
320
321 inputElement.value = null;
322 input.handleInputChanged();
323 t.notOk(input.changed, 'Input is not changed when null');
324
325 // Using the `setValue` method
326 input.setValue('0');
327 t.ok(input.changed, 'Input is changed');
328
329 input.setValue('');
330 t.notOk(input.changed, 'Input is not changed when empty string');
331
332 input.setValue(null);
333 t.notOk(input.changed, 'Input is not changed when null');
334 });
335
336 t.end();
337});
338
339test('textarea grows in height as the text wraps', function (t) {
340 var input = new InputView(),
341 textarea,
342 initialHeight,
343 singleLineHeight;
344
345 input.render();
346
347 textarea = input.el.querySelector('textarea');
348
349 initialHeight = textarea.style.height;
350 input.setValue('Test');
351
352 window.setTimeout(function () {
353 singleLineHeight = textarea.style.height;
354
355 t.equal(initialHeight, '', 'The initial height should not be set');
356 t.notEqual(initialHeight, singleLineHeight, 'Input height changes when new text is entered');
357 t.end();
358 }, 900);
359});