1
/* Copyright (c) 2009, Canonical Ltd. All rights reserved. */
3
YUI().use('lazr.editor', 'lazr.testing.runner', 'node',
4
'event', 'event-simulate', 'console', 'plugin', function(Y) {
6
<h1>Single-line editing</h1> \
7
<div id='editable_single_text'> \
8
<span id='single_text' class='yui3-editable_text-text'>Some editable inline text.</span> \
9
<button id='single_edit' class='yui3-editable_text-trigger'>Edit this</button> \
12
<h1>Multi-line editing</h1> \
13
<div id='editable_multi_text'> \
14
<button id='multi_edit' class='yui3-editable_text-trigger'>Edit this</button> \
15
<span id='multi_text' class='yui3-editable_text-text'> \
16
<p>Some editable multi-line text.</p></span> \
20
var Assert = Y.Assert; // For easy access to isTrue(), etc.
22
/* Helper to stamp a Node with an ID attribute. Needed for YUI 2.X
23
* testing, which is heavily ID-based.
25
* Returns the node's 'id' attribute.
27
function id_for(node) {
28
if (!node.getAttribute('id')) {
29
var id = Y.stamp(node);
30
node.setAttribute('id', id);
32
return node.getAttribute('id');
36
* A wrapper for the Y.Event.simulate() function. The wrapper accepts
37
* CSS selectors and Node instances instead of raw nodes.
39
function simulate(selector, evtype) {
40
var rawnode = Y.Node.getDOMNode(Y.one(selector));
41
Y.Event.simulate(rawnode, evtype);
44
/* Helper function that creates a new editor instance. */
45
function make_editor(cfg) {
46
return new Y.InlineEditor(cfg);
49
/* Helper function to clean up a dynamically added widget instance. */
50
function cleanup_widget(widget) {
51
// Nuke the boundingBox, but only if we've touched the DOM.
52
if (widget.get('rendered')) {
53
var bb = widget.get('boundingBox');
54
if (bb && Y.Node.getDOMNode(bb)) {
55
var parentNode = bb.get('parentNode');
56
if (parentNode && Y.Node.getDOMNode(parentNode)) {
57
parentNode.removeChild(bb);
61
// Kill the widget itself.
65
function setup_sample_html() {
66
if (! Y.one("#scaffolding")) {
67
Y.one(document.body).appendChild(
68
Y.Node.create("<div id='scaffolding'></div>"));
71
Y.one("#scaffolding").set("innerHTML", SAMPLE_HTML);
74
function make_editable_text(cfg) {
76
// TODO: fix this ugly hack
78
contentBox: '#editable_single_text',
79
boundingBox: '#inline-edit-container'
81
return new Y.EditableText(Y.merge(defaults, cfg));
84
// Helper: convert size specification like "120px" to a number (in casu, 120).
86
function parse_size(size) {
87
return parseInt(size.replace(strip_px, ''), 10);
90
var suite = new Y.Test.Suite("Inline Editor Tests");
92
suite.add(new Y.Test.Case({
94
name: 'inline_editor_basics',
97
this.editor = make_editor();
100
tearDown: function() {
101
cleanup_widget(this.editor);
104
test_input_value_set_during_sync: function() {
105
/* The input element's value should be set during the syncUI()
108
var ed = this.editor,
114
"Sanity check: the editor's value shouldn't equal our " +
118
"Sanity check: the widget shouldn't be rendered yet.");
120
ed.set('value', desired_value);
124
ed.get('input_field').get('value'),
125
"The editor's input field's value should have been set.");
128
test_getInput_method: function() {
129
this.editor.render();
131
this.editor.get('input_field').get('value'),
132
this.editor.getInput(),
133
"The getInput() method should return the same value as " +
134
"the editor's input field's current value.");
137
test_validate_values: function() {
138
Assert.isFalse(this.editor.get('accept_empty'),
139
"The editor shouldn't accept empty values by default.");
141
var prev = this.editor.get('value');
142
this.editor.set('value', null);
145
this.editor.get('value'),
146
"The editor's value should not have changed.");
148
this.editor.set('value', '');
151
this.editor.get('value'),
152
"The editor should not accept the empty string as a " +
153
"value if 'accept_empty' is false.");
155
/* The control can be asked to accept empty values. */
156
this.editor.set('accept_empty', true);
157
this.editor.set('value', '');
160
this.editor.get('value'),
161
"The editor should have accepted the empty string as a " +
162
"valid value if 'accept_empty' is true.");
165
test_validate_empty_editor_input: function() {
166
var ed = this.editor;
168
// A helper to catch the 'save' event.
169
var got_save = false;
170
var after_save = function(ev) { got_save = true; };
171
ed.after('ieditor:save', after_save);
175
Assert.isFalse(ed.hasErrors(),
176
"Sanity check: the editor shouldn't be displaying any " +
178
Assert.isFalse(ed.get('accept_empty'),
179
"Sanity check: the editor shouldn't accept empty inputs.");
181
ed.get('input_field').set('value', '');
184
Assert.isTrue(ed.hasErrors(),
185
"The editor should be displaying an error after the " +
186
"trying to save an empty input.");
187
Assert.isFalse(got_save,
188
"The editor should not have fired a 'save' event.");
191
test_set_and_clear_error_message: function() {
192
this.editor.render();
194
var ed = this.editor,
195
edisplay = ed.get('error_message'),
196
c_hidden = 'yui3-ieditor-errors-hidden';
200
"The editor should have a valid error display node.");
203
edisplay.hasClass(c_hidden),
204
"The error display should start out hidden.");
207
"The editor's 'in_error' attribute should not be set.");
209
var msg = "An error has occured.";
214
edisplay.get('text'),
215
"The error display's text should be set.");
217
edisplay.hasClass(c_hidden),
218
"The error display should be visible when an error is set.");
221
"The editor .hasErrors() method should return true if " +
222
"there are errors being displayed.");
225
"The editor's 'in_error' attribute should be set.");
229
edisplay.hasClass(c_hidden),
230
"The error display should be hidden when the error " +
234
"The editor .hasErrors() method should return false " +
235
"if there are no errors being displayed.");
238
test_save_input_to_editor: function() {
239
var expected_value = 'abc',
248
ed.get('input_field').set('value', expected_value);
254
"The value of the editor's input field should have been " +
255
"saved to the editor's 'value' attribute.");
258
test_focus_method_focuses_editor_input: function() {
259
this.editor.render();
261
var input = this.editor.get('input_field'),
265
Y.on('focus', function() {
271
Assert.isTrue(focused,
272
"The editor's input field should have received focus " +
273
"after calling the editor's focus method.");
276
test_input_receives_focus_after_editor_errors: function() {
277
this.editor.render();
279
var ed = this.editor,
280
input = this.editor.get('input_field'),
285
"Sanity check: the editor should be clear of errors.");
287
ed.get('accept_empty'),
288
"Sanity check: the editor should not accept empty " +
291
// Force an error by setting the editor's input to the
293
input.set('value', '');
296
// Add our focus event listener.
297
Y.on('focus', function() {
304
"Sanity check: the editor should be in an error state " +
305
"after saving an empty value.");
309
"The editor's input field should have the current " +
313
test_widget_has_a_disabled_tabindex_when_focused: function() {
314
// The tabindex attribute appears when the widget is focused.
315
this.editor.render();
318
// Be aware that in IE, get('tabIndex') and getAttribute('tabIndex')
319
// return different values when set to -1. This is due to YUI's
320
// getAttribute() calling dom_node.getAttribute('tabIndex', 2), which
321
// is an IE extension.
322
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
325
this.editor.get('boundingBox').get('tabIndex'),
326
"The widget should have a tabindex of -1 (disabled).");
329
test_enter_key_saves_input: function() {
330
this.editor.render();
332
var ed = this.editor,
333
input_element = Y.Node.getDOMNode(
334
this.editor.get('input_field'));
336
input_element.value = 'abc';
338
// A helper to flag the 'save' event.
340
function saveCheck(e) {
344
ed.after('ieditor:save', saveCheck, this);
346
// Simulate an 'Enter' key event in the editor's input field.
347
Y.Event.simulate(input_element, "keydown", { keyCode: 13 });
349
Assert.isFalse(ed.hasErrors());
351
"Pressing the 'Enter' key inside the editor's input field " +
352
"should save the input.");
355
test_enter_key_ignored_in_multiline: function() {
356
this.editor.set('multiline', true);
357
this.editor.render();
359
var ed = this.editor;
360
var input_element = Y.Node.getDOMNode(this.editor.get('input_field'));
362
input_element.value = 'abc';
364
// A helper to flag the 'save' event.
366
function saveCheck(e) {
370
ed.after('ieditor:save', saveCheck, this);
372
// Simulate an 'Enter' key event in the editor's input field.
373
Y.Event.simulate(input_element, "keydown", { keyCode: 13 });
375
// Restore to previous state.
376
this.editor.set('multiline', false);
378
Assert.isFalse(ed.hasErrors());
379
Assert.isFalse(saved,
380
"Pressing the 'Enter' key in multiline mode " +
381
"should not trigger a save.");
384
test_input_should_be_trimmed_of_whitespace: function() {
385
this.editor.render();
387
var input = this.editor.get('input_field');
389
// Set a whitespace value as the input.
390
input.set('value', ' ');
395
this.editor.hasErrors(),
396
"The editor should be displaying an error after trying to " +
397
"save a whitespace value.");
401
suite.add(new Y.Test.Case({
402
name: 'Initial value',
405
this.editor = make_editor({initial_value_override: 'Initial value'});
408
tearDown: function() {
409
cleanup_widget(this.editor);
412
test_initial_value_override: function() {
413
this.editor.render();
416
this.editor.get('input_field').get('value'),
417
"The editor's input field should have the initial value.");
421
suite.add(new Y.Test.Case({
422
name: 'Editable text initial values',
426
this.etext = make_editable_text(
427
{initial_value_override: 'Initial value'});
430
tearDown: function() {
432
cleanup_widget(this.etext);
435
test_save_initial_value_override: function() {
440
this.etext.editor.get('input_field').get('value'),
441
"The input_field should have been set to the initial value.");
443
this.etext.editor.save();
446
this.etext.editor.get('value'),
447
"The editor's initial value did not get saved.");
450
this.etext.editor.get('initial_value_override'),
451
"The editor's initial_value_override should be null.");
454
test_cancel_does_not_modify_value: function() {
458
'Some editable inline text.',
459
this.etext.editor.get('value'),
460
"The editor's value is not what it should be.");
463
this.etext.editor.get('initial_value_override'),
464
"The editor's initial_value_override is not what it should be.");
466
this.etext.editor.cancel();
468
'Some editable inline text.',
469
this.etext.editor.get('value'),
470
"The editor's value did not get reset.");
473
this.etext.editor.get('initial_value_override'),
474
"The editor's initial_value_override did not get preserved.");
478
suite.add(new Y.Test.Case({
480
name: "Inline editor input sizing for a positive size value",
483
this.expected_size = 32;
484
this.editor = make_editor({size: this.expected_size});
487
tearDown: function() {
488
cleanup_widget(this.editor);
491
test_editor_size_attribute_matches_user_value: function() {
493
this.editor.get('size'),
495
"The editor's 'size' attribute should match the user's " +
499
test_input_field_size_matches_the_editor_size: function() {
500
this.editor.render();
501
var input = this.editor.get('input_field');
503
this.expected_size + 'ex',
504
input.getStyle('width'),
505
"The editor's input field size should have been set from the " +
506
"'size' attribute.");
511
suite.add(new Y.Test.Case({
513
name: "Inline editor input sizing for a null size value",
516
this.editor = make_editor();
517
this.editor.render();
520
tearDown: function() {
521
cleanup_widget(this.editor);
524
test_editor_size_attribute_is_null: function() {
527
this.editor.get('size'),
528
"The editor's 'size' attribute should default to 'null'.");
531
test_editor_input_has_browser_default_size: function() {
532
var input = this.editor.get('input_field');
534
input.hasAttribute('size'),
535
"The editor's input field should have the browser default " +
536
"size if the editor's size is 'null'.");
543
* The following test is just for the attribute validators. Most of this is
544
* made necessary because YUI doesn't publish attribute validation errors.
546
* See ticket http://yuilibrary.com/projects/yui3/ticket/2525946
548
suite.add(new Y.Test.Case({
550
name: "Inline editor size attribute validation",
553
this.initial_size = null;
554
this.editor = make_editor({size: this.initial_size});
557
test_editor_accepts_null_as_size: function() {
558
this.editor.set('size', null);
561
this.editor.get('size'),
562
"The editor should accept a null value for the size attribute.");
565
test_editor_accepts_positive_numbers_as_size: function() {
566
this.editor.set('size', 123);
569
this.editor.get('size'),
570
"The editor should accept a positive number as a valid size.");
573
test_editor_rejects_negative_numbers_for_size: function() {
574
this.editor.set('size', -2);
577
this.editor.get('size'),
578
"The editor should not accept negative numbers for its size.");
581
test_editor_rejects_characters_for_size: function() {
582
this.editor.set('size', 'a');
585
this.editor.get('size'),
586
"The editor should not accept strings for its size.");
591
suite.add(new Y.Test.Case({
593
name: 'editor_save_state_change',
596
this.editor = make_editor();
599
tearDown: function() {
600
cleanup_widget(this.editor);
603
test_ui_initial_state_is_not_waiting: function() {
604
this.editor.render();
606
this.editor.get('boundingBox').hasClass('yui3-ieditor-waiting'),
607
"The editor UI should not start out in the 'waiting' state.");
610
test_set_ui_waiting_state: function() {
611
var ed = this.editor;
617
ed.get('input_field').get('disabled'),
618
"The editor's input should be disabled while in the " +
621
ed.get('boundingBox').hasClass('yui3-ieditor-waiting'),
622
"The editor's UI should reflect the 'waiting' state " +
623
"with an appropriate class.");
626
test_clear_ui_waiting_state: function() {
627
var ed = this.editor;
631
ed._uiClearWaiting();
634
ed.get('input_field').get('disabled'),
635
"The editor's input should be re-enabled when clearing " +
636
"the 'waiting' state.");
638
ed.get('boundingBox').hasClass('yui3-ieditor-waiting'),
639
"The editor's UI should have the 'waiting' state " +
645
suite.add(new Y.Test.Case({
647
name: 'editable_text',
651
this.etext = make_editable_text();
654
tearDown: function() {
655
cleanup_widget(this.etext);
658
test_initial_values_from_DOM: function() {
660
Y.one("#single_text"),
661
this.etext.get('text'),
662
"The editor's text node should have been set from the " +
666
Y.one('#single_edit'),
667
this.etext.get('trigger'),
668
"The editor's trigger node should have been set from " +
672
'Some editable inline text.',
673
this.etext.editor.get('value'),
674
"The editor's initial value should be set from it's " +
678
this.etext.editor.get('value'),
679
this.etext.get('value'),
680
"The editable text's value should be the same as the " +
684
test_show: function() {
685
/* The show() method should display the editor, and hide the
689
this.etext.show_editor();
690
Assert.isTrue(this.etext.editor.get('visible'),
691
"The editor's 'visible' attribute should be true.");
694
test_hide: function() {
695
/* The hide() method should hide the editor, and display the
699
this.etext.show_editor();
700
this.etext.hide_editor();
701
Assert.isFalse(this.etext.editor.get('visible'),
702
"The editor's 'visible' attribute should be False.");
705
test_trigger_edit: function() {
706
/* Clicking on the editable text's "Edit" button should
707
* make the editor visible.
709
Assert.isFalse(this.etext.editor.get('visible'),
710
"Sanity check, the editor should be hidden.");
713
simulate('#single_edit', 'click');
715
Assert.isTrue(this.etext.editor.get('visible'),
716
"The editor should be visible.");
719
test_text_is_updated_to_saved_value: function() {
722
// Grab the normalized text.
723
var expected_value = 'abc';
727
this.etext.get('value'),
730
simulate('#single_edit', 'click');
733
.set('value', expected_value);
735
this.etext.editor.save();
739
this.etext.editor.get('value'),
740
"Sanity check: the editor's value should have been " +
745
this.etext.get('value'),
746
"The editable text's current value should be updated " +
747
"after saving some new text in the editor.");
750
test_text_is_escaped: function() {
753
var input_value = '<i>l33t inject0r d00d</i> 0wnz y00';
754
var shown_value = '<i>l33t inject0r d00d</i> 0wnz y00';
756
simulate('#single_edit', 'click');
757
this.etext.editor.setInput(input_value);
758
this.etext.editor.save();
762
this.etext.get('text').get('innerHTML'),
763
"Input text should be escaped before being inserted in HTML.");
766
this.etext.editor.getInput(),
767
"Input text should be retained verbatim.");
770
test_accept_empty_attribute_passthrough: function() {
774
et.get('accept_empty'),
775
et.editor.get('accept_empty'),
776
"The editor and inline editor's 'accept_empty " +
777
"should start out the same.");
779
et.set('accept_empty', true);
781
et.editor.get('accept_empty'),
782
"The inline editor's 'accept_empty' attribute should " +
783
"also be set to 'true'.");
785
et.get('accept_empty'),
786
"The editor's 'accept_empty' attribute should be true.");
788
et.set('accept_empty', false);
790
et.get('accept_empty'),
791
"The editor's 'accept_empty' attribute should be false.");
793
et.editor.get('accept_empty'),
794
"The inline editor's 'accept_empty' attribute should " +
795
"also be set to 'false'.");
798
test_widget_has_a_disabled_tabindex_when_focused: function() {
799
// The tabindex attribute appears when the widget is focused.
803
// Be aware that in IE, get('tabIndex') and getAttribute('tabIndex')
804
// return different values when set to -1. This is due to YUI's
805
// getAttribute() calling dom_node.getAttribute('tabIndex', 2), which
806
// is an IE extension.
807
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
809
// On IE and KHTML, EditableText._onRender() will prevent the
810
// default widget rendering that would set the tabIndex on the
811
// boundingBox, so this test will fail for those browsers.
814
this.etext.get('boundingBox').get('tabIndex'),
815
"The widget should have a tabindex of -1 (disabled).");
818
test_trigger_is_disabled_if_the_widget_is_not_rendered: function() {
819
var trigger = this.etext.get('trigger');
822
"Sanity check: the editor's trigger should be a valid node.");
824
this.etext.get('rendered'),
825
"Sanity check: the editor should not be rendered.");
827
simulate(trigger, 'click');
828
// Peek inside the box a bit, and check that the nested editor
829
// instance is still invisible. Assume that if it is, then
830
// the show_editor() method was never called.
832
this.etext.editor.get('visible'),
833
"Triggering an unrendered editor should not display the widget.");
837
suite.add(new Y.Test.Case({
839
name: "EditableText single-line/multi-line modes",
843
this.single = make_editable_text({
844
contentBox: '#editable_single_text',
847
this.single.render();
848
this.single.show_editor();
849
this.multi = make_editable_text({
850
contentBox: '#editable_multi_text',
854
this.multi.show_editor();
857
tearDown: function() {
858
cleanup_widget(this.single);
859
cleanup_widget(this.multi);
862
test_multi_line_has_larger_minimum: function() {
863
var single = this.single.editor;
864
var multi = this.multi.editor;
869
var single_height = single.get('input_field').getStyle('height');
870
var multi_height = multi.get('input_field').getStyle('height');
872
single_height = parse_size(single_height);
873
multi_height = parse_size(multi_height);
878
"Multi-line and single-line editors should have different sizes.");
880
multi_height > single_height,
881
"Multi-line editor should start out larger.");
884
test_single_line_top_button_box: function() {
885
var box = this.single.editor.get("top_buttons");
889
"Single-line editor should not have a top button box.");
892
test_multi_line_top_button_box: function() {
893
var box = this.multi.editor.get("top_buttons");
897
"Multi-line editor should have a top button box.");
901
suite.add(new Y.Test.Case({
903
name: "Editor input sizing",
906
this.expected_size = 23;
907
this.editor = make_editor({
908
contentBox: '#editable_single_text',
909
size: this.expected_size
911
this.editor.render();
913
this.long_line = 'mm mmmmm mmmmmmm mm mmm mm mmmmmmm mmmmmmmm mm mmm m';
914
this.long_word = 'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm';
915
this.short_line = 'hi mom';
918
tearDown: function() {
919
cleanup_widget(this.editor);
922
test_size_attribute_passthrough: function() {
923
// create a new editor with the input size set to 23 characters.
926
this.editor.get('size'),
927
"The inline editor widget should have received a size " +
928
"from the EditableText widget.");
931
test_long_text_wraps: function() {
932
var editor = this.editor,
933
input = editor.get('input_field'),
934
original_height = input.getStyle('height');
936
editor.setInput(this.long_line);
937
var new_height = input.getStyle('height');
942
"Inserting a long text should grow the input area.");
945
input.getStyle('overflow'),
946
"Scrollbars should be hidden when no unbreakable lines present.");
948
parse_size(new_height) > parse_size(original_height),
949
"A grown input area should be larger than before.");
952
test_long_words_scroll: function() {
953
var editor = this.editor,
954
input = editor.get('input_field'),
955
original_height = input.getStyle('height');
957
editor.setInput(this.long_word);
958
var new_height = input.getStyle('height');
963
"Long words should add legroom for a horizontal scrollbar.");
965
parse_size(new_height) > parse_size(original_height),
966
"A grown input area should be larger than before.");
969
test_resize_on_growth: function() {
970
var editor = this.editor,
971
input = editor.get('input_field');
975
editor.on('ieditor:resized', function() {
978
input.set('value', this.long_line);
980
Assert.isTrue(resized, "Editor resize event was not fired.");
983
test_resize_on_shrinkage: function() {
984
var editor = this.editor,
985
input = editor.get('input_field');
987
editor.setInput(this.long_line);
991
editor.on('ieditor:resized', function() {
994
input.set('value', this.short_line);
997
Assert.isTrue(resized, "Editor resize event was not fired.");
1000
test_long_text_unwraps: function() {
1001
var editor = this.editor,
1002
input = editor.get('input_field');
1004
editor.setInput(this.short_line);
1005
var original_height = input.getStyle('height');
1007
editor.setInput(this.long_line);
1008
editor.setInput(this.short_line);
1009
var new_height = input.getStyle('height');
1014
"Removing lines of text should shrink the input area.");
1017
test_long_words_unscroll: function() {
1018
var editor = this.editor,
1019
input = editor.get('input_field');
1021
editor.setInput(this.short_line);
1022
var original_height = input.getStyle('height');
1024
editor.setInput(this.long_word);
1025
editor.setInput(this.short_line);
1026
var new_height = input.getStyle('height');
1031
"Removing long words should remove legroom for scrollbar.");
1034
input.getStyle('overflow'),
1035
"Scrollbars should be hidden when long lines are removed.");
1039
suite.add(new Y.Test.Case({
1040
name: "Window resizing",
1043
this.small_size = 5;
1044
this.large_size = 40;
1045
this.short_line = 'i';
1046
// A line that fits in small_size but not in large_size.
1047
this.long_line = 'x xx x xx x xx x xx';
1048
// A word that fits in small_size but not in large_size.
1049
this.long_word = 'xxxxxxxxxxxxxxxxxxx';
1050
this.editor = make_editor();
1051
this.editor.render();
1054
tearDown: function() {
1055
cleanup_widget(this.editor);
1058
// Pretend that a window resize has changed the editor's width to
1059
// the given number of columns. Also lets you set new contents for
1060
// the input box. Returns resulting input box height in pixels.
1061
_pretendResize: function(new_size, new_text) {
1062
var text = (new_text ? new_text : this.editor.getInput());
1063
var content_box = this.editor.get('contentBox');
1065
var old_input = this.editor.get('input_field');
1066
content_box.removeChild(old_input);
1067
this.editor.set('input_field', null);
1069
var old_alter_ego = this.editor.alter_ego;
1070
content_box.removeChild(old_alter_ego);
1071
this.editor.alter_ego = null;
1073
this.editor.set('size', new_size);
1074
this.editor._initInput();
1076
this.editor.setInput(text);
1077
this.editor._windowResize();
1078
return this._getInputBoxHeight();
1081
_getInputBoxHeight: function() {
1082
var input = this.editor.get('input_field');
1083
return parse_size(input.getStyle('height'));
1086
// Helper: assert lower < higher, and print helpful message.
1087
_assertLower: function(lower, higher, failure_text) {
1088
if (!(lower < higher)) {
1089
// Log values in separate statements to avoid infinite recursion
1090
// during ill-typed attempts at string concatenation.
1091
Y.log("Expected the first of these to be lower than the second:");
1095
Assert.isTrue(lower < higher, failure_text);
1098
test_resize_might_not_change_layout: function() {
1099
var roomy = this._pretendResize(this.large_size, this.short_line);
1100
var tight = this._pretendResize(this.small_size);
1104
"If there's enough room, resizing should not affect height.");
1107
test_undersize_adds_lines: function() {
1108
var roomy = this._pretendResize(this.large_size, this.long_line);
1109
var tight = this._pretendResize(this.small_size);
1113
"Undersizing a long line should break it.");
1116
test_oversize_removes_lines: function() {
1117
var tight = this._pretendResize(this.small_size, this.long_line);
1118
var roomy = this._pretendResize(this.large_size);
1122
"Oversizing a long line should unbreak it.");
1125
test_undersize_adds_scrollbar: function() {
1126
// Actually, a scrollbar and/or more lines. The spec leaves it
1127
// all up to the browser, but either way we'll see a higher
1129
var roomy = this._pretendResize(this.large_size, this.long_word);
1130
var tight = this._pretendResize(this.small_size);
1134
"Undersizing a long word should require a taller input box.");
1137
test_oversize_removes_scrollbar: function() {
1138
var tight = this._pretendResize(this.small_size, this.long_word);
1139
var roomy = this._pretendResize(this.large_size);
1143
"Oversizing a long word should reduce input box height.");
1146
test_resize_works_while_hidden: function() {
1147
var roomy = this._pretendResize(this.large_size, this.long_line);
1149
var tight = this._pretendResize(this.small_size);
1151
this.editor.updateSize();
1155
"Editors should notice window resizes even while hidden.");
1160
suite.add(new Y.Test.Case({
1161
name: "EditableText text value",
1164
setup_sample_html();
1165
this.multi = make_editable_text({
1167
contentBox: '#editable_multi_text',
1170
this.multi.render();
1173
tearDown: function() {
1174
cleanup_widget(this.multi);
1177
test_text_value_no_trailing_newlines: function() {
1178
var text = this.multi.get('value');
1180
"Some editable multi-line text.",
1182
"The editor kills trailing whitespace.");
1186
function FailedSavePlugin() {
1187
FailedSavePlugin.superclass.constructor.apply(this, arguments);
1190
FailedSavePlugin.NAME = 'failedsave';
1191
FailedSavePlugin.NS = 'test';
1193
Y.extend(FailedSavePlugin, Y.Plugin.Base, {
1194
initializer: function(config) {
1195
this.doBefore("_saveData", this._altSave);
1198
_altSave: function() {
1199
var host = this.get('host');
1200
// Set the UI 'waiting' status.
1201
host._uiSetWaiting();
1202
host.showError("Some error occurred.");
1203
// Make sure we clear the 'waiting' status.
1204
host._uiClearWaiting();
1205
return new Y.Do.Halt();
1209
suite.add(new Y.Test.Case({
1210
name: "Edit buttons enabled on error",
1213
setup_sample_html();
1214
this.multi = make_editable_text({
1216
contentBox: '#editable_multi_text',
1219
this.multi.render();
1220
this.multi.show_editor();
1223
tearDown: function() {
1224
cleanup_widget(this.multi);
1227
test_error_on_save_enabled_buttons: function() {
1228
var editor = this.multi.editor;
1229
editor.plug({fn:FailedSavePlugin});
1230
// Now saving should invoke an error.
1232
Assert.isTrue(editor.get('in_error'), "Editor should be in error");
1233
// Both the submit and cancel buttons should be visible.
1236
editor.get('submit_button').getStyle('display'),
1237
"Submit should be set to display:inline");
1240
editor.get('cancel_button').getStyle('display'),
1241
"Cancel should be set to display:inline");
1247
Y.lazr.testing.Runner.add(suite);
1248
Y.lazr.testing.Runner.run();