• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!doctype html>
2<!--
3@license
4Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
5This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
6The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
7The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
8Code distributed by Google as part of the polymer project is also
9subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
10-->
11<html>
12<head>
13
14  <title>paper-input tests</title>
15
16  <meta charset="utf-8">
17  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
18  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
19
20  <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
21
22  <script src="../../web-component-tester/browser.js"></script>
23  <script src="../../iron-test-helpers/test-helpers.js"></script>
24  <script src="../../iron-test-helpers/mock-interactions.js"></script>
25
26  <link rel="import" href="../paper-input.html">
27  <link rel="import" href="letters-only.html">
28
29</head>
30<body>
31
32  <test-fixture id="basic">
33    <template>
34      <paper-input></paper-input>
35    </template>
36  </test-fixture>
37
38  <test-fixture id="has-tabindex">
39    <template>
40      <paper-input tabindex="0"></paper-input>
41    </template>
42  </test-fixture>
43
44  <test-fixture id="label">
45    <template>
46      <paper-input label="foo"></paper-input>
47    </template>
48  </test-fixture>
49
50  <test-fixture id="label-has-value">
51    <template>
52      <paper-input label="foo" value="bar"></paper-input>
53    </template>
54  </test-fixture>
55
56  <test-fixture id="error">
57    <template>
58      <paper-input auto-validate pattern="[0-9]*" value="foobar" error-message="error"></paper-input>
59    </template>
60  </test-fixture>
61
62  <test-fixture id="required">
63    <template>
64      <paper-input auto-validate required error-message="error"></paper-input>
65    </template>
66  </test-fixture>
67
68  <test-fixture id="required-no-auto-validate">
69    <template>
70      <paper-input required error-message="error"></paper-input>
71    </template>
72  </test-fixture>
73
74  <test-fixture id="required-char-counter">
75    <template>
76      <paper-input auto-validate char-counter required error-message="error"></paper-input>
77    </template>
78  </test-fixture>
79
80  <test-fixture id="char-counter">
81    <template>
82      <paper-input char-counter value="foobar"></paper-input>
83    </template>
84  </test-fixture>
85
86  <test-fixture id="type-number-char-counter">
87    <template>
88      <paper-input type="number" char-counter value="1138"></paper-input>
89    </template>
90  </test-fixture>
91
92  <test-fixture id="always-float-label">
93    <template>
94      <paper-input always-float-label label="foo"></paper-input>
95    </template>
96  </test-fixture>
97
98  <test-fixture id="placeholder">
99    <template>
100      <paper-input label="foo" placeholder="bar"></paper-input>
101    </template>
102  </test-fixture>
103
104  <test-fixture id="date">
105    <template>
106      <paper-input label="foo" type="date"></paper-input>
107    </template>
108  </test-fixture>
109
110  <letters-only></letters-only>
111
112  <test-fixture id="validator">
113    <template>
114      <paper-input value="123123" validator="letters-only" auto-validate></paper-input>
115    </template>
116  </test-fixture>
117
118  <test-fixture id="multiple-inputs">
119    <template>
120      <paper-input label="one"></paper-input>
121      <paper-input label="two"></paper-input>
122      <paper-input label="three"></paper-input>
123      <paper-input label="four"></paper-input>
124    </template>
125  </test-fixture>
126
127  <script>
128
129    suite('basic', function() {
130
131      test('setting value sets the input value', function() {
132        var input = fixture('basic');
133        input.value = 'foobar';
134        assert.equal(input.inputElement.value, input.value, 'inputElement.value equals input.value');
135      });
136
137      test('placeholder does not overlap label', function() {
138        var input = fixture('placeholder');
139        assert.equal(input.inputElement.placeholder, input.placeholder, 'inputElement.placeholder equals input.placeholder');
140        assert.equal(input.noLabelFloat, false);
141        var floatingLabel = Polymer.dom(Polymer.dom(input.root).querySelector('paper-input-container').root).querySelector('.label-is-floating');
142        assert.ok(floatingLabel);
143      });
144
145      test('special types autofloat the label', function() {
146        var input = fixture('date');
147        // Browsers that don't support special <input> types like `date` fallback
148        // to `text`, so make sure to only test if type is still preserved after
149        // the element is attached.
150        if (input.inputElement.type === "date") {
151          assert.equal(input.alwaysFloatLabel, true);
152          var floatingLabel = Polymer.dom(Polymer.dom(input.root).querySelector('paper-input-container').root).querySelector('.label-is-floating');
153          assert.ok(floatingLabel);
154        }
155      });
156
157      test('always-float-label attribute works without placeholder', function() {
158        var input = fixture('always-float-label');
159        var container = Polymer.dom(input.root).querySelector('paper-input-container');
160        var inputContent = Polymer.dom(container.root).querySelector('.input-content');
161        assert.isTrue(inputContent.classList.contains('label-is-floating'), 'label is floating');
162      });
163
164      test('error message is displayed', function() {
165        var input = fixture('error');
166        forceXIfStamp(input);
167        var error = Polymer.dom(input.root).querySelector('paper-input-error');
168        assert.ok(error, 'paper-input-error exists');
169        assert.notEqual(getComputedStyle(error).display, 'none', 'error is not display:none');
170      });
171
172      test('empty required input shows error', function() {
173        var input = fixture('required');
174        forceXIfStamp(input);
175        var error = Polymer.dom(input.root).querySelector('paper-input-error');
176        assert.ok(error, 'paper-input-error exists');
177        assert.notEqual(getComputedStyle(error).display, 'none', 'error is not display:none');
178      });
179
180      test('character counter is displayed', function() {
181        var input = fixture('char-counter');
182        forceXIfStamp(input);
183        var counter = Polymer.dom(input.root).querySelector('paper-input-char-counter')
184        assert.ok(counter, 'paper-input-char-counter exists');
185        assert.equal(counter._charCounterStr, input.value.length, 'character counter shows the value length');
186      });
187
188      test('character counter is correct for type=number', function() {
189        var input = fixture('type-number-char-counter');
190        forceXIfStamp(input);
191        var counter = Polymer.dom(input.root).querySelector('paper-input-char-counter')
192        assert.ok(counter, 'paper-input-char-counter exists');
193        assert.equal(counter._charCounterStr, input.value.toString().length, 'character counter shows the value length');
194      });
195
196      test('validator is used', function() {
197        var input = fixture('validator');
198        assert.ok(input.inputElement.invalid, 'input is invalid');
199      });
200
201      test('caret position is preserved', function() {
202        var input = fixture('basic');
203        var ironInput = Polymer.dom(input.root).querySelector('input[is="iron-input"]');
204        input.value = 'nananana';
205        ironInput.selectionStart = 2;
206        ironInput.selectionEnd = 2;
207
208        input.updateValueAndPreserveCaret('nanananabatman');
209
210        assert.equal(ironInput.selectionStart, 2, 'selectionStart is preserved');
211        assert.equal(ironInput.selectionEnd, 2, 'selectionEnd is preserved');
212      });
213
214    });
215
216    suite('focus/blur events', function() {
217      var input;
218
219      setup(function() {
220        input = fixture('basic');
221      });
222
223      // At the moment, it is very hard to correctly fire exactly
224      // one focus/blur events on a paper-input. This is because
225      // when a paper-input is focused, it needs to focus
226      // its underlying native input, which will also fire a `blur`
227      // event.
228      test('focus events fired on host element', function() {
229        input.addEventListener('focus', function(event) {
230          assert(input.focused, 'input is focused');
231        });
232        MockInteractions.focus(input);
233      });
234
235      test('focus events fired on host element if nested element is focused', function() {
236        input.addEventListener('focus', function(event) {
237          assert(input.focused, 'input is focused');
238        });
239        MockInteractions.focus(input.inputElement);
240      });
241
242      test('blur events fired on host element', function() {
243        MockInteractions.focus(input);
244        input.addEventListener('blur', function(event) {
245          assert(!input.focused, 'input is blurred');
246        });
247        MockInteractions.blur(input);
248      });
249
250      test('blur events fired on host element nested element is blurred', function() {
251        MockInteractions.focus(input);
252        input.addEventListener('blur', function(event) {
253          assert(!input.focused, 'input is blurred');
254        });
255        MockInteractions.blur(input.inputElement);
256      });
257
258      test('focusing then bluring sets the focused attribute correctly', function() {
259        MockInteractions.focus(input);
260        assert(input.focused, 'input is focused');
261        MockInteractions.blur(input);
262        assert(!input.focused, 'input is blurred');
263        MockInteractions.focus(input.inputElement);
264        assert(input.focused, 'input is focused');
265        MockInteractions.blur(input.inputElement);
266        assert(!input.focused, 'input is blurred');
267      });
268
269      test('focusing then bluring with shift-tab removes the focused attribute correctly', function() {
270        MockInteractions.focus(input);
271        assert(input.focused, 'input is focused');
272
273        // Fake a shift-tab induced blur by forcing the flag.
274        input._shiftTabPressed = true;
275        MockInteractions.blur(input.inputElement);
276        assert(!input.focused, 'input is blurred');
277      });
278    });
279
280    suite('focused styling (integration test)', function() {
281
282      test('underline is colored when input is focused', function(done) {
283        var input = fixture('basic');
284        var container = Polymer.dom(input.root).querySelector('paper-input-container');
285        var line = Polymer.dom(container.root).querySelector('.underline');
286        assert.isFalse(line.classList.contains('is-highlighted'), 'line is not highlighted when input is not focused');
287        MockInteractions.focus(input.inputElement);
288        requestAnimationFrame(function() {
289          assert.isTrue(line.classList.contains('is-highlighted'), 'line is highlighted when input is focused');
290          done();
291        });
292      });
293
294    });
295
296    suite('validation', function() {
297
298      test('invalid attribute updated after calling validate()', function() {
299        var input = fixture('required-no-auto-validate');
300        forceXIfStamp(input);
301        input.validate();
302        var error = Polymer.dom(input.root).querySelector('paper-input-error');
303        assert.ok(error, 'paper-input-error exists');
304        assert.notEqual(getComputedStyle(error).display, 'none', 'error is not display:none');
305        assert.isTrue(input.invalid, 'invalid is true');
306      });
307
308    });
309
310    suite('a11y', function() {
311      test('has aria-labelledby, which is monotonically increasing', function() {
312        var inputs = fixture('multiple-inputs');
313
314        // Find the first index of the input in this fixture. Since the label
315        // ids monotonically increase every time a new input is created, and
316        // this fixture isn't the first one in the document, we're going to start
317        // at an ID > 1.
318        var firstLabel = Polymer.dom(inputs[0].root).querySelector('label').id;
319        var index = parseInt(firstLabel.substr(firstLabel.lastIndexOf('-') + 1));
320
321        for (var i = 0; i < inputs.length; i++ ) {
322          var input = inputs[i].inputElement;
323          var label = Polymer.dom(inputs[i].root).querySelector('label').id;
324
325          assert.isTrue(input.hasAttribute('aria-labelledby'));
326          assert.equal(label, 'paper-input-label-' + (index++));
327          assert.equal(input.getAttribute('aria-labelledby'), label);
328        }
329      });
330
331      test('has aria-describedby for error message', function() {
332        var input = fixture('required');
333        forceXIfStamp(input);
334        assert.isTrue(input.inputElement.hasAttribute('aria-describedby'));
335        assert.equal(input.inputElement.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-error').id, 'aria-describedby points to the error message');
336      });
337
338      test('has aria-describedby for character counter', function() {
339        var input = fixture('char-counter');
340        forceXIfStamp(input);
341        assert.isTrue(input.inputElement.hasAttribute('aria-describedby'));
342        assert.equal(input.inputElement.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-char-counter').id, 'aria-describedby points to the character counter');
343      });
344
345      test('has aria-describedby for character counter and error', function() {
346        var input = fixture('required-char-counter');
347        forceXIfStamp(input);
348        assert.isTrue(input.inputElement.hasAttribute('aria-describedby'));
349        assert.equal(input.inputElement.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-error').id + ' ' + Polymer.dom(input.root).querySelector('paper-input-char-counter').id, 'aria-describedby points to the error message and character counter');
350      });
351
352      test('focus an input with tabindex', function(done) {
353        var input = fixture('has-tabindex');
354        flush(function() {
355          MockInteractions.focus(input);
356          flush(function() {
357            assert.equal(input.shadowRoot ? input.shadowRoot.activeElement :
358                document.activeElement, input._focusableElement);
359            done();
360          });
361        });
362      });
363    });
364
365  </script>
366
367</body>
368</html>
369