launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #06292
[Merge] lp:~rharding/launchpad/combo_yui_tests2 into lp:launchpad
Richard Harding has proposed merging lp:~rharding/launchpad/combo_yui_tests2 into lp:launchpad with lp:~rharding/launchpad/combo_yui_tests as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~rharding/launchpad/combo_yui_tests2/+merge/91499
= Summary =
Updating more of the YUI tests to be updated per the new convoy/buid dir setup.
See the first MP for the main details. I'm breaking the changes into multiple MP since this is going to be a giant diff due to touching each JS test file.
https://code.launchpad.net/~rharding/launchpad/combo_yui_tests/+merge/91478
== Tests in this batch ==
lib/lp/app/javascript/choiceedit/tests/test_choiceedit.html
lib/lp/app/javascript/confirmationoverlay/tests/test_confirmationoverlay.html
lib/lp/app/javascript/picker/tests/test_personpicker.html
lib/lp/app/javascript/picker/tests/test_picker.html
lib/lp/app/javascript/picker/tests/test_picker_patcher.html
--
https://code.launchpad.net/~rharding/launchpad/combo_yui_tests2/+merge/91499
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rharding/launchpad/combo_yui_tests2 into lp:launchpad.
=== modified file 'lib/lp/app/javascript/choiceedit/tests/test_choiceedit.html'
--- lib/lp/app/javascript/choiceedit/tests/test_choiceedit.html 2011-08-10 08:43:17 +0000
+++ lib/lp/app/javascript/choiceedit/tests/test_choiceedit.html 2012-02-07 16:00:29 +0000
@@ -1,28 +1,52 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+Copyright 2012 Canonical Ltd. This software is licensed under the
+GNU Affero General Public License version 3 (see the file LICENSE).
+-->
+
<html>
<head>
- <title>Status Editor</title>
-
- <!-- YUI and test setup -->
- <script type="text/javascript"
- src="../../../../../canonical/launchpad/icing/yui/yui/yui.js">
- </script>
- <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
- <script type="text/javascript"
- src="../../../../app/javascript/testing/testrunner.js"></script>
-
- <!-- Dependency -->
- <script type="text/javascript" src="../../lazr/lazr.js"></script>
- <script type="text/javascript" src="../../anim/anim.js"></script>
- <script type="text/javascript" src="../../overlay/overlay.js"></script>
- <script type="text/javascript" src="../../extras/extras.js"></script>
-
- <!-- The module under test -->
- <script type="text/javascript" src="../choiceedit.js"></script>
-
- <!-- The test suite -->
- <script type="text/javascript" src="test_choiceedit.js"></script>
-</head>
-<body class="yui3-skin-sam">
-</body>
+ <title>choiceedit tests</title>
+
+ <!-- YUI and test setup -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/yui/yui/yui.js">
+ </script>
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/console-core.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/skins/sam/console.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
+
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
+
+ <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
+
+ <!-- Dependencies -->
+ <script type="text/javascript" src="../../../../../../build/js/lp/app/lazr/lazr.js"></script>
+ <script type="text/javascript" src="../../../../../../build/js/lp/app/anim/anim.js"></script>
+ <script type="text/javascript" src="../../../../../../build/js/lp/app/overlay/overlay.js"></script>
+ <script type="text/javascript" src="../../../../../../build/js/lp/app/extras/extras.js"></script>
+ <script type="text/javascript" src="../../../../../../build/js/lp/app/choice.js"></script>
+
+
+ <!-- The module under test. -->
+ <script type="text/javascript" src="../choiceedit.js"></script>
+
+ <!-- Any css assert for this module. -->
+ <!-- <link rel="stylesheet" href="../assets/choiceedit-core.css" /> -->
+
+ <!-- The test suite -->
+ <script type="text/javascript" src="test_choiceedit.js"></script>
+
+ </head>
+ <body class="yui3-skin-sam">
+ <ul id="suites">
+ <!-- <li>lp.large_indicator.test</li> -->
+ <li>lp.choiceedit.test</li>
+ </ul>
+ </body>
</html>
=== modified file 'lib/lp/app/javascript/choiceedit/tests/test_choiceedit.js'
--- lib/lp/app/javascript/choiceedit/tests/test_choiceedit.js 2011-08-09 14:18:02 +0000
+++ lib/lp/app/javascript/choiceedit/tests/test_choiceedit.js 2012-02-07 16:00:29 +0000
@@ -1,527 +1,528 @@
-/* Copyright (c) 2008, Canonical Ltd. All rights reserved. */
-
-YUI().use('lp.testing.runner', 'test', 'console', 'node', 'lazr.choiceedit',
- 'event', 'event-simulate', 'widget-stack', function(Y) {
-
-// Local aliases
-var Assert = Y.Assert,
- ArrayAssert = Y.ArrayAssert;
-
-/*
- * A wrapper for the Y.Event.simulate() function. The wrapper accepts
- * CSS selectors and Node instances instead of raw nodes.
- */
-function simulate(widget, selector, evtype, options) {
- var rawnode = Y.Node.getDOMNode(widget.one(selector));
- Y.Event.simulate(rawnode, evtype, options);
-}
-
-/* Helper function to clean up a dynamically added widget instance. */
-function cleanup_widget(widget) {
- // Nuke the boundingBox, but only if we've touched the DOM.
- if (widget.get('rendered')) {
- var bb = widget.get('boundingBox');
- if (Y.Node.getDOMNode(bb)) {
- if (bb.get('parentNode')) {
- bb.get('parentNode').removeChild(bb);
- }
- }
- }
- // Kill the widget itself.
- widget.destroy();
-}
-
-var suite = new Y.Test.Suite("LAZR Choice Edit Tests");
-
-function setUp() {
- // add the in-page HTML
- var inpage = Y.Node.create([
- '<p id="thestatus">',
- 'Status: <span class="value">Unset</span> ',
- '<img class="editicon" src="https://bugs.edge.launchpad.net/@@/edit">',
- '</p>'].join(''));
- Y.one("body").appendChild(inpage);
- this.config = this.make_config();
- this.choice_edit = new Y.ChoiceSource(this.config);
- this.choice_edit.render();
-}
-
-function tearDown() {
- if (this.choice_edit._choice_list) {
- cleanup_widget(this.choice_edit._choice_list);
- }
- var status = Y.one("document").one("#thestatus");
- if (status) {
- status.get("parentNode").removeChild(status);
- }
-}
-
-suite.add(new Y.Test.Case({
-
- name: 'choice_edit_basics',
-
- setUp: setUp,
-
- tearDown: tearDown,
-
- make_config: function() {
- return {
- contentBox: '#thestatus',
- value: 'incomplete',
- title: 'Change status to',
- items: [
- { name: 'New', value: 'new', style: '',
- help: '', disabled: false },
- { name: 'Invalid', value: 'invalid', style: '',
- help: '', disabled: true },
- { name: 'Incomplete', value: 'incomplete', style: '',
- help: '', disabled: false },
- { name: 'Fix Released', value: 'fixreleased', style: '',
- help: '', disabled: false },
- { name: 'Fix Committed', value: 'fixcommitted', style: '',
- help: '', disabled: true },
- { name: 'In Progress', value: 'inprogress', style: '',
- help: '', disabled: false },
- { name: 'Stalled', value: 'stalled', style: '',
- help: '', disabled: false, source_name: 'STALLED' }
- ]
- };
- },
-
- test_can_be_instantiated: function() {
- Assert.isInstanceOf(
- Y.ChoiceSource, this.choice_edit, "ChoiceSource not instantiated.");
- },
-
- test_choicesource_overrides_value_in_page: function() {
- var st = Y.one(document).one("#thestatus");
- // value in page should be set to the config.items.name corresponding to
- // config.value
- Assert.areEqual("Incomplete", st.one(".value").get("innerHTML"),
- "ChoiceSource is not overriding displayed value in HTML");
- },
-
- test_clicking_creates_choicelist: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- Assert.isNotNull(this.choice_edit._choice_list,
- "ChoiceList object is not created");
- Assert.isNotNull(Y.one(document).one(".yui3-ichoicelist"),
- "ChoiceList HTML is not being added to the page");
- },
-
- test_right_clicking_doesnt_create_choicelist: function() {
- simulate(this.choice_edit.get('boundingBox'),
- '.value', 'click', { button: 2 });
- Assert.isNull(Y.one(document).one(".yui3-ichoicelist"),
- "ChoiceList created when the right mouse button was clicked");
- },
-
- test_choicelist_has_correct_values: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- var that = this;
- Y.each(this.config.items, function(configitem) {
- var found = false;
- Y.each(that.choice_edit._choice_list.get("items"), function(choiceitem) {
- if (choiceitem.name == configitem.name) {
- found = true;
- }
- });
- Assert.isTrue(found,
- "Item " + configitem.name + " is passed to ChoiceSource but is " +
- "not in ChoiceList.items");
- });
- var choicelistcount = this.choice_edit._choice_list.get("items").length;
- var configcount = this.config.items.length;
- Assert.areEqual(choicelistcount, configcount,
- "ChoiceList HTML list is a different length (" + choicelistcount +
- ") than config items list (" + configcount + ")");
- },
-
- test_choicelist_html_has_correct_values: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- var configcount = this.config.items.length;
- var choicelist_lis = Y.one(document).all(".yui3-ichoicelist li");
- Assert.areEqual(choicelist_lis.size(), configcount,
- "ChoiceList HTML list is a different length (" + choicelist_lis.size() +
- ") than config items list (" + configcount + ")");
- // confirm that each LI matches with an item
- var that = this;
- choicelist_lis.each(function(li) {
- var text = li.get("text");
- var found = false;
- for (var i=0; i<that.config.items.length; i++) {
- if (that.config.items[i].name == text) {
- found = true;
- break;
- }
- }
- Assert.isTrue(found, "Page LI '" + text +
- "' did not come from a config item");
- });
- },
-
- test_choicelist_html_has_disabled: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- var configcount = this.config.items.length;
- var choicelist_lis = Y.one(document).all(".yui3-ichoicelist li");
- // confirm that disabled LIs are disabled
- var that = this;
- choicelist_lis.each(function(li) {
- var text = li.get("text");
- for (var i=0; i<that.config.items.length; i++) {
- if (that.config.items[i].name == text) {
- if (that.config.items[i].disabled) {
- Assert.isNotNull(li.one("span.disabled"),
- "Page LI '" + text + "' was not disabled");
- }
- break;
- }
- }
- });
- },
-
- test_choicelist_html_has_current: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- var configcount = this.config.items.length;
- var choicelist_lis = Y.one(document).all(".yui3-ichoicelist li");
- // confirm that current value has an LI with current style
- var that = this;
- var asserted = false;
- choicelist_lis.each(function(li) {
- var text = li.get("text");
- for (var i=0; i<that.config.items.length; i++) {
- if (that.config.items[i].name == text) {
- if (that.config.items[i].value == that.config.value) {
- Assert.isNotNull(li.one("span.current"),
- "Page LI '" + text + "' was not marked as current");
- asserted = true;
- }
- break;
- }
- }
- });
- Assert.isTrue(asserted, "There was no current LI item");
- },
-
- test_clicking_choicelist_item_fires_signal: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- var that = this;
- var fired = false;
- this.choice_edit._choice_list.on("valueChosen", function() {
- fired = true;
- });
- // simulate a click on the "fix released" option, which is
- // (a) enabled
- // (b) not the current option
- simulate(this.choice_edit._choice_list.get('boundingBox'),
- 'li a[href$=fixreleased]', 'click');
- Assert.isTrue(fired, "valueChosen signal was not fired");
- },
-
- test_clicking_choicelist_item_does_green_flash: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- var that = this;
- var green_flash = Y.lp.anim.green_flash;
- var flashed = false;
- Y.lp.anim.green_flash = function() {
- return {
- run: function() {
- flashed = true;
- }
- };
- };
- simulate(this.choice_edit._choice_list.get('boundingBox'),
- 'li a[href$=fixreleased]', 'click');
- Assert.isTrue(flashed, "green_flash animation was not fired");
- Y.lp.anim.green_flash = green_flash;
- },
-
- test_clicking_choicelist_item_sets_page_value: function() {
- var st = Y.one(document).one("#thestatus");
- // The page value is set to item.name of the selected item.
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- simulate(this.choice_edit._choice_list.get('boundingBox'),
- 'li a[href$=fixreleased]', 'click');
- Assert.areEqual("Fix Released", st.one(".value").get("innerHTML"),
- "Chosen choicelist item is not displayed in HTML (value is '" +
- st.one(".value").get("innerHTML") + "')");
- },
-
- test_clicking_choicelist_item_sets_page_source_name: function() {
- var st = Y.one(document).one("#thestatus");
- // By default, the page value is set to item.name of the
- // selected item, but this can be overridden by specifying
- // item.source_name.
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- var choice_list_bb = this.choice_edit._choice_list.get('boundingBox');
- var stalled_in_list = choice_list_bb.one('li a[href$=stalled]');
- Assert.areEqual(
- "Stalled", stalled_in_list.get('innerHTML'),
- "ChoiceList item not displayed correctly: " +
- stalled_in_list.get('innerHTML'));
- simulate(choice_list_bb, 'li a[href$=stalled]', 'click');
- Assert.areEqual("STALLED", st.one(".value").get("innerHTML"),
- "Chosen choicelist item is not displayed in HTML (value is '" +
- st.one(".value").get("innerHTML") + "')");
- }
-
-}));
-
-suite.add(new Y.Test.Case({
-
- name: 'choice_edit_non_clickable_content',
-
- setUp: setUp,
-
- tearDown: tearDown,
-
- make_config: function() {
- return {
- contentBox: '#thestatus',
- value: 'incomplete',
- title: 'Change status to',
- items: [
- { name: 'New', value: 'new', style: '',
- help: '', disabled: false },
- { name: 'Invalid', value: 'invalid', style: '',
- help: '', disabled: true },
- { name: 'Incomplete', value: 'incomplete', style: '',
- help: '', disabled: false },
- { name: 'Fix Released', value: 'fixreleased', style: '',
- help: '', disabled: false },
- { name: 'Fix Committed', value: 'fixcommitted', style: '',
- help: '', disabled: true },
- { name: 'In Progress', value: 'inprogress', style: '',
- help: '', disabled: false },
- { name: 'Stalled', value: 'stalled', style: '',
- help: '', disabled: false, source_name: 'STALLED' }
- ],
- clickable_content: false
- };
- },
-
- test_clicking_content_doesnt_create_choicelist: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- Assert.isUndefined(this.choice_edit._choice_list,
- "ChoiceList object is created");
- Assert.isNull(Y.one(document).one(".yui3-ichoicelist"),
- "ChoiceList HTML is being added to the page");
- },
-
- test_clicking_icon_creates_choicelist: function() {
- simulate(this.choice_edit.get('boundingBox'), '.editicon', 'click');
- Assert.isNotUndefined(this.choice_edit._choice_list,
- "ChoiceList object is not being created");
- Assert.isNotNull(Y.one(document).one(".yui3-ichoicelist"),
- "ChoiceList HTML is not being added to the page");
- },
-
-}));
-
-
-/**
- * Tests what happens when config.value does not correspond to any of
- * the items in config.items.
- */
-suite.add(new Y.Test.Case({
-
- name: 'choice_edit_value_item_mismatch',
-
- setUp: setUp,
-
- tearDown: tearDown,
-
- make_config: function() {
- return {
- contentBox: '#thestatus',
+/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
+
+YUI.add('lp.choiceedit.test', function (Y) {
+ var tests = Y.namespace('lp.choiceedit.test');
+ tests.suite = new Y.Test.Suite('choiceedit tests');
+
+ // Local aliases
+ var Assert = Y.Assert,
+ ArrayAssert = Y.ArrayAssert;
+
+ /*
+ * A wrapper for the Y.Event.simulate() function. The wrapper accepts
+ * CSS selectors and Node instances instead of raw nodes.
+ */
+ var simulate = function (widget, selector, evtype, options) {
+ var rawnode = Y.Node.getDOMNode(widget.one(selector));
+ Y.Event.simulate(rawnode, evtype, options);
+ }
+
+ /* Helper function to clean up a dynamically added widget instance. */
+ var cleanup_widget = function (widget) {
+ // Nuke the boundingBox, but only if we've touched the DOM.
+ if (widget.get('rendered')) {
+ var bb = widget.get('boundingBox');
+ if (Y.Node.getDOMNode(bb)) {
+ if (bb.get('parentNode')) {
+ bb.get('parentNode').removeChild(bb);
+ }
+ }
+ }
+ // Kill the widget itself.
+ widget.destroy();
+ }
+
+ var shared_setup = function () {
+ // add the in-page HTML
+ var inpage = Y.Node.create([
+ '<p id="thestatus">',
+ 'Status: <span class="value">Unset</span> ',
+ '<img class="editicon" src="https://bugs.edge.launchpad.net/@@/edit">',
+ '</p>'].join(''));
+ Y.one("body").appendChild(inpage);
+ this.config = this.make_config();
+ this.choice_edit = new Y.ChoiceSource(this.config);
+ this.choice_edit.render();
+ }
+
+ var shared_teardown = function () {
+ if (this.choice_edit._choice_list) {
+ cleanup_widget(this.choice_edit._choice_list);
+ }
+ var status = Y.one("document").one("#thestatus");
+ if (status) {
+ status.get("parentNode").removeChild(status);
+ }
+ }
+
+ tests.suite.add(new Y.Test.Case({
+ name: 'choiceedit_tests',
+
+ setUp: shared_setup,
+ tearDown: shared_teardown,
+
+ test_library_exists: function () {
+ Y.Assert.isObject(Y.ChoiceSource,
+ "We should be able to locate the lazr.choiceedit module");
+ },
+
+ make_config: function() {
+ return {
+ contentBox: '#thestatus',
+ value: 'incomplete',
+ title: 'Change status to',
+ items: [
+ { name: 'New', value: 'new', style: '',
+ help: '', disabled: false },
+ { name: 'Invalid', value: 'invalid', style: '',
+ help: '', disabled: true },
+ { name: 'Incomplete', value: 'incomplete', style: '',
+ help: '', disabled: false },
+ { name: 'Fix Released', value: 'fixreleased', style: '',
+ help: '', disabled: false },
+ { name: 'Fix Committed', value: 'fixcommitted', style: '',
+ help: '', disabled: true },
+ { name: 'In Progress', value: 'inprogress', style: '',
+ help: '', disabled: false },
+ { name: 'Stalled', value: 'stalled', style: '',
+ help: '', disabled: false, source_name: 'STALLED' }
+ ]
+ };
+ },
+
+ test_can_be_instantiated: function() {
+ Assert.isInstanceOf(
+ Y.ChoiceSource, this.choice_edit, "ChoiceSource not instantiated.");
+ },
+
+ test_choicesource_overrides_value_in_page: function() {
+ var st = Y.one(document).one("#thestatus");
+ // value in page should be set to the config.items.name corresponding to
+ // config.value
+ Assert.areEqual("Incomplete", st.one(".value").get("innerHTML"),
+ "ChoiceSource is not overriding displayed value in HTML");
+ },
+
+ test_clicking_creates_choicelist: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ Assert.isNotNull(this.choice_edit._choice_list,
+ "ChoiceList object is not created");
+ Assert.isNotNull(Y.one(document).one(".yui3-ichoicelist"),
+ "ChoiceList HTML is not being added to the page");
+ },
+
+ test_right_clicking_doesnt_create_choicelist: function() {
+ simulate(this.choice_edit.get('boundingBox'),
+ '.value', 'click', { button: 2 });
+ Assert.isNull(Y.one(document).one(".yui3-ichoicelist"),
+ "ChoiceList created when the right mouse button was clicked");
+ },
+
+ test_choicelist_has_correct_values: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ var that = this;
+ Y.each(this.config.items, function(configitem) {
+ var found = false;
+ Y.each(that.choice_edit._choice_list.get("items"), function(choiceitem) {
+ if (choiceitem.name == configitem.name) {
+ found = true;
+ }
+ });
+ Assert.isTrue(found,
+ "Item " + configitem.name + " is passed to ChoiceSource but is " +
+ "not in ChoiceList.items");
+ });
+ var choicelistcount = this.choice_edit._choice_list.get("items").length;
+ var configcount = this.config.items.length;
+ Assert.areEqual(choicelistcount, configcount,
+ "ChoiceList HTML list is a different length (" + choicelistcount +
+ ") than config items list (" + configcount + ")");
+ },
+
+ test_choicelist_html_has_correct_values: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ var configcount = this.config.items.length;
+ var choicelist_lis = Y.one(document).all(".yui3-ichoicelist li");
+ Assert.areEqual(choicelist_lis.size(), configcount,
+ "ChoiceList HTML list is a different length (" + choicelist_lis.size() +
+ ") than config items list (" + configcount + ")");
+ // confirm that each LI matches with an item
+ var that = this;
+ choicelist_lis.each(function(li) {
+ var text = li.get("text");
+ var found = false;
+ for (var i=0; i<that.config.items.length; i++) {
+ if (that.config.items[i].name == text) {
+ found = true;
+ break;
+ }
+ }
+ Assert.isTrue(found, "Page LI '" + text +
+ "' did not come from a config item");
+ });
+ },
+
+ test_choicelist_html_has_disabled: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ var configcount = this.config.items.length;
+ var choicelist_lis = Y.one(document).all(".yui3-ichoicelist li");
+ // confirm that disabled LIs are disabled
+ var that = this;
+ choicelist_lis.each(function(li) {
+ var text = li.get("text");
+ for (var i=0; i<that.config.items.length; i++) {
+ if (that.config.items[i].name == text) {
+ if (that.config.items[i].disabled) {
+ Assert.isNotNull(li.one("span.disabled"),
+ "Page LI '" + text + "' was not disabled");
+ }
+ break;
+ }
+ }
+ });
+ },
+
+ test_choicelist_html_has_current: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ var configcount = this.config.items.length;
+ var choicelist_lis = Y.one(document).all(".yui3-ichoicelist li");
+ // confirm that current value has an LI with current style
+ var that = this;
+ var asserted = false;
+ choicelist_lis.each(function(li) {
+ var text = li.get("text");
+ for (var i=0; i<that.config.items.length; i++) {
+ if (that.config.items[i].name == text) {
+ if (that.config.items[i].value == that.config.value) {
+ Assert.isNotNull(li.one("span.current"),
+ "Page LI '" + text + "' was not marked as current");
+ asserted = true;
+ }
+ break;
+ }
+ }
+ });
+ Assert.isTrue(asserted, "There was no current LI item");
+ },
+
+ test_clicking_choicelist_item_fires_signal: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ var that = this;
+ var fired = false;
+ this.choice_edit._choice_list.on("valueChosen", function() {
+ fired = true;
+ });
+ // simulate a click on the "fix released" option, which is
+ // (a) enabled
+ // (b) not the current option
+ simulate(this.choice_edit._choice_list.get('boundingBox'),
+ 'li a[href$=fixreleased]', 'click');
+ Assert.isTrue(fired, "valueChosen signal was not fired");
+ },
+
+ test_clicking_choicelist_item_does_green_flash: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ var that = this;
+ var green_flash = Y.lp.anim.green_flash;
+ var flashed = false;
+ Y.lp.anim.green_flash = function() {
+ return {
+ run: function() {
+ flashed = true;
+ }
+ };
+ };
+ simulate(this.choice_edit._choice_list.get('boundingBox'),
+ 'li a[href$=fixreleased]', 'click');
+ Assert.isTrue(flashed, "green_flash animation was not fired");
+ Y.lp.anim.green_flash = green_flash;
+ },
+
+ test_clicking_choicelist_item_sets_page_value: function() {
+ var st = Y.one(document).one("#thestatus");
+ // The page value is set to item.name of the selected item.
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ simulate(this.choice_edit._choice_list.get('boundingBox'),
+ 'li a[href$=fixreleased]', 'click');
+ Assert.areEqual("Fix Released", st.one(".value").get("innerHTML"),
+ "Chosen choicelist item is not displayed in HTML (value is '" +
+ st.one(".value").get("innerHTML") + "')");
+ },
+
+ test_clicking_choicelist_item_sets_page_source_name: function() {
+ var st = Y.one(document).one("#thestatus");
+ // By default, the page value is set to item.name of the
+ // selected item, but this can be overridden by specifying
+ // item.source_name.
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ var choice_list_bb = this.choice_edit._choice_list.get('boundingBox');
+ var stalled_in_list = choice_list_bb.one('li a[href$=stalled]');
+ Assert.areEqual(
+ "Stalled", stalled_in_list.get('innerHTML'),
+ "ChoiceList item not displayed correctly: " +
+ stalled_in_list.get('innerHTML'));
+ simulate(choice_list_bb, 'li a[href$=stalled]', 'click');
+ Assert.areEqual("STALLED", st.one(".value").get("innerHTML"),
+ "Chosen choicelist item is not displayed in HTML (value is '" +
+ st.one(".value").get("innerHTML") + "')");
+ }
+ }));
+
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'choice_edit_non_clickable_content',
+
+ setUp: shared_setup,
+ tearDown: shared_teardown,
+
+ make_config: function() {
+ return {
+ contentBox: '#thestatus',
+ value: 'incomplete',
+ title: 'Change status to',
+ items: [
+ { name: 'New', value: 'new', style: '',
+ help: '', disabled: false },
+ { name: 'Invalid', value: 'invalid', style: '',
+ help: '', disabled: true },
+ { name: 'Incomplete', value: 'incomplete', style: '',
+ help: '', disabled: false },
+ { name: 'Fix Released', value: 'fixreleased', style: '',
+ help: '', disabled: false },
+ { name: 'Fix Committed', value: 'fixcommitted', style: '',
+ help: '', disabled: true },
+ { name: 'In Progress', value: 'inprogress', style: '',
+ help: '', disabled: false },
+ { name: 'Stalled', value: 'stalled', style: '',
+ help: '', disabled: false, source_name: 'STALLED' }
+ ],
+ clickable_content: false
+ };
+ },
+
+ test_clicking_content_doesnt_create_choicelist: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ Assert.isUndefined(this.choice_edit._choice_list,
+ "ChoiceList object is created");
+ Assert.isNull(Y.one(document).one(".yui3-ichoicelist"),
+ "ChoiceList HTML is being added to the page");
+ },
+
+ test_clicking_icon_creates_choicelist: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.editicon', 'click');
+ Assert.isNotUndefined(this.choice_edit._choice_list,
+ "ChoiceList object is not being created");
+ Assert.isNotNull(Y.one(document).one(".yui3-ichoicelist"),
+ "ChoiceList HTML is not being added to the page");
+ },
+
+ }));
+
+ /**
+ * Tests what happens when config.value does not correspond to any of
+ * the items in config.items.
+ */
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'choice_edit_value_item_mismatch',
+
+ setUp: shared_setup,
+ tearDown: shared_teardown,
+
+ make_config: function() {
+ return {
+ contentBox: '#thestatus',
+ value: null,
+ title: 'Change status to',
+ items: [
+ { name: 'New', value: 'new', style: '',
+ help: '', disabled: false },
+ { name: 'Invalid', value: 'invalid', style: '',
+ help: '', disabled: true }
+ ]
+ };
+ },
+
+ /**
+ * The value displayed in the page should be left alone if
+ * config.value does not correspond to any item in config.items.
+ */
+ test_choicesource_leaves_value_in_page: function() {
+ var st = Y.one(document).one("#thestatus");
+ Assert.areEqual(
+ "Unset", st.one(".value").get("innerHTML"),
+ "ChoiceSource is overriding displayed value in HTML");
+ },
+
+ test_choicelist_html_has_current: function() {
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ var configcount = this.config.items.length;
+ var choicelist_lis = Y.one(document).all(".yui3-ichoicelist li");
+
+ var that = this;
+ var asserted;
+ var test_li = function(li) {
+ var text = li.get("text");
+ for (var i=0; i < that.config.items.length; i++) {
+ if (that.config.items[i].name == text) {
+ if (that.config.items[i].value == that.choice_edit.get("value")) {
+ Assert.isNotNull(li.one("span.current"),
+ "Page LI '" + text + "' was not marked as current");
+ asserted = true;
+ }
+ break;
+ }
+ }
+ };
+ // When config.value does not correspond to any item in
+ // config.items, no LI in the choice list will be marked with
+ // the "current" style.
+ asserted = false;
+ choicelist_lis.each(test_li);
+ Assert.isFalse(asserted, "There was a current LI item");
+ // Once a choice is made, the current value is marked with the
+ // "current" class in the choice list.
+ simulate(this.choice_edit._choice_list.get('boundingBox'),
+ 'li a[href$=new]', 'click');
+ simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
+ asserted = false;
+ choicelist_lis.refresh();
+ choicelist_lis.each(test_li);
+ Assert.isTrue(asserted, "There was no current LI item");
+ }
+
+ }));
+
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'nullable_choice_edit',
+
+ setUp: function() {
+ // add the in-page HTML
+ var inpage = Y.Node.create([
+ '<p id="nullchoiceedit" style="margin-top: 25px">',
+ ' <img class="addicon" src="https://bugs.edge.launchpad.net/@@/add">',
+ ' <span class="nulltext">Choose something</span>',
+ ' <span class="value" style="display:none" />',
+ ' <img class="editicon" style="display:none" src="https://bugs.edge.launchpad.net/@@/edit">',
+ '</p>'].join(''));
+ Y.one("body").appendChild(inpage);
+ this.null_choice_edit = new Y.NullChoiceSource({
+ contentBox: '#nullchoiceedit',
value: null,
- title: 'Change status to',
+ title: 'Choose something',
items: [
- { name: 'New', value: 'new', style: '',
- help: '', disabled: false },
- { name: 'Invalid', value: 'invalid', style: '',
- help: '', disabled: true }
+ { name: 'Chico', value: 'chico', style: '',
+ help: '', disabled: false },
+ { name: 'Harpo', value: 'harpo', style: '',
+ help: '', disabled: false },
+ { name: 'Groucho', value: 'groucho', style: '',
+ help: '', disabled: false },
+ { name: 'Gummo', value: 'gummo', style: '',
+ help: '', disabled: false },
+ { name: 'Zeppo', value: 'zeppo', style: '',
+ help: '', disabled: false },
+ { name: 'Not funny!', value: null, style: '',
+ help: '', disabled: false }
]
- };
- },
-
- /**
- * The value displayed in the page should be left alone if
- * config.value does not correspond to any item in config.items.
- */
- test_choicesource_leaves_value_in_page: function() {
- var st = Y.one(document).one("#thestatus");
- Assert.areEqual(
- "Unset", st.one(".value").get("innerHTML"),
- "ChoiceSource is overriding displayed value in HTML");
- },
-
- test_choicelist_html_has_current: function() {
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- var configcount = this.config.items.length;
- var choicelist_lis = Y.one(document).all(".yui3-ichoicelist li");
-
- var that = this;
- var asserted;
- var test_li = function(li) {
- var text = li.get("text");
- for (var i=0; i < that.config.items.length; i++) {
- if (that.config.items[i].name == text) {
- if (that.config.items[i].value == that.choice_edit.get("value")) {
- Assert.isNotNull(li.one("span.current"),
- "Page LI '" + text + "' was not marked as current");
- asserted = true;
- }
- break;
+ });
+
+ this.null_choice_edit.render();
+ },
+
+ tearDown: function() {
+ if (this.null_choice_edit._choice_list) {
+ cleanup_widget(this.null_choice_edit._choice_list);
+ }
+ var nullchoiceedit = Y.one("document").one("#nullchoiceedit");
+ if (nullchoiceedit) {
+ nullchoiceedit.get("parentNode").removeChild(nullchoiceedit);
+ }
+ },
+
+ test_can_be_instantiated: function() {
+ Assert.isInstanceOf(
+ Y.NullChoiceSource, this.null_choice_edit,
+ "NullChoiceSource not instantiated.");
+ },
+
+ test_action_icon: function() {
+ var that = this;
+
+ Assert.areEqual(
+ this.null_choice_edit.get('actionicon'),
+ this.null_choice_edit.get('addicon'),
+ 'Action icon is not the add icon like expected.');
+
+ Assert.areEqual(
+ this.null_choice_edit.get('addicon').getStyle('display'),
+ 'inline',
+ 'Add icon is not visible when it should be');
+ Assert.areEqual(
+ this.null_choice_edit.get('editicon').getStyle('display'),
+ 'none',
+ "Edit icon is visible when it shouldn't be");
+
+ simulate(this.null_choice_edit.get('boundingBox'),
+ '.value', 'click');
+ simulate(this.null_choice_edit._choice_list.get('boundingBox'),
+ 'li a[href$=groucho]', 'click');
+ this.null_choice_edit._uiClearWaiting();
+
+ Assert.areEqual(
+ this.null_choice_edit.get('actionicon'),
+ this.null_choice_edit.get('editicon'),
+ 'Action icon is not the add icon like expected.');
+ Assert.areEqual(
+ this.null_choice_edit.get('addicon').getStyle('display'),
+ 'none',
+ "Add icon is visible when it shouldn't be");
+ Assert.areEqual(
+ this.null_choice_edit.get('editicon').getStyle('display'),
+ 'inline',
+ "Edit icon is not visible when it shouldn be");
+ },
+
+ test_null_item_absent: function() {
+ Assert.areEqual(
+ this.null_choice_edit.get('value'),
+ null,
+ "Selected value isn't null");
+
+ simulate(this.null_choice_edit.get('boundingBox'),
+ '.value', 'click');
+ var remove_action_present = false;
+ this.null_choice_edit._choice_list.get(
+ 'boundingBox').all('li a').each(function(item) {
+ if (item._value == null) {
+ remove_action_present = true;
}
- }
- };
- // When config.value does not correspond to any item in
- // config.items, no LI in the choice list will be marked with
- // the "current" style.
- asserted = false;
- choicelist_lis.each(test_li);
- Assert.isFalse(asserted, "There was a current LI item");
- // Once a choice is made, the current value is marked with the
- // "current" class in the choice list.
- simulate(this.choice_edit._choice_list.get('boundingBox'),
- 'li a[href$=new]', 'click');
- simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
- asserted = false;
- choicelist_lis.refresh();
- choicelist_lis.each(test_li);
- Assert.isTrue(asserted, "There was no current LI item");
- }
-
-}));
-
-suite.add(new Y.Test.Case({
-
- name: 'nullable_choice_edit',
-
- setUp: function() {
- // add the in-page HTML
- var inpage = Y.Node.create([
- '<p id="nullchoiceedit" style="margin-top: 25px">',
- ' <img class="addicon" src="https://bugs.edge.launchpad.net/@@/add">',
- ' <span class="nulltext">Choose something</span>',
- ' <span class="value" style="display:none" />',
- ' <img class="editicon" style="display:none" src="https://bugs.edge.launchpad.net/@@/edit">',
- '</p>'].join(''));
- Y.one("body").appendChild(inpage);
- this.null_choice_edit = new Y.NullChoiceSource({
- contentBox: '#nullchoiceedit',
- value: null,
- title: 'Choose something',
- items: [
- { name: 'Chico', value: 'chico', style: '',
- help: '', disabled: false },
- { name: 'Harpo', value: 'harpo', style: '',
- help: '', disabled: false },
- { name: 'Groucho', value: 'groucho', style: '',
- help: '', disabled: false },
- { name: 'Gummo', value: 'gummo', style: '',
- help: '', disabled: false },
- { name: 'Zeppo', value: 'zeppo', style: '',
- help: '', disabled: false },
- { name: 'Not funny!', value: null, style: '',
- help: '', disabled: false }
- ]
- });
-
- this.null_choice_edit.render();
- },
-
- tearDown: function() {
- if (this.null_choice_edit._choice_list) {
- cleanup_widget(this.null_choice_edit._choice_list);
- }
- var nullchoiceedit = Y.one("document").one("#nullchoiceedit");
- if (nullchoiceedit) {
- nullchoiceedit.get("parentNode").removeChild(nullchoiceedit);
- }
- },
-
- test_can_be_instantiated: function() {
- Assert.isInstanceOf(
- Y.NullChoiceSource, this.null_choice_edit,
- "NullChoiceSource not instantiated.");
- },
-
- test_action_icon: function() {
- var that = this;
-
- Assert.areEqual(
- this.null_choice_edit.get('actionicon'),
- this.null_choice_edit.get('addicon'),
- 'Action icon is not the add icon like expected.');
-
- Assert.areEqual(
- this.null_choice_edit.get('addicon').getStyle('display'),
- 'inline',
- 'Add icon is not visible when it should be');
- Assert.areEqual(
- this.null_choice_edit.get('editicon').getStyle('display'),
- 'none',
- "Edit icon is visible when it shouldn't be");
-
- simulate(this.null_choice_edit.get('boundingBox'),
- '.value', 'click');
- simulate(this.null_choice_edit._choice_list.get('boundingBox'),
- 'li a[href$=groucho]', 'click');
- this.null_choice_edit._uiClearWaiting();
-
- Assert.areEqual(
- this.null_choice_edit.get('actionicon'),
- this.null_choice_edit.get('editicon'),
- 'Action icon is not the add icon like expected.');
- Assert.areEqual(
- this.null_choice_edit.get('addicon').getStyle('display'),
- 'none',
- "Add icon is visible when it shouldn't be");
- Assert.areEqual(
- this.null_choice_edit.get('editicon').getStyle('display'),
- 'inline',
- "Edit icon is not visible when it shouldn be");
- },
-
- test_null_item_absent: function() {
- Assert.areEqual(
- this.null_choice_edit.get('value'),
- null,
- "Selected value isn't null");
-
- simulate(this.null_choice_edit.get('boundingBox'),
- '.value', 'click');
- var remove_action_present = false;
- this.null_choice_edit._choice_list.get(
- 'boundingBox').all('li a').each(function(item) {
- if (item._value == null) {
- remove_action_present = true;
- }
- });
- Assert.isFalse(
- remove_action_present,
- 'Remove item is present even when the current value is null.');
- },
-
- test_get_input_for_null: function() {
- this.null_choice_edit.set('value', 'groucho');
- Assert.areEqual(
- 'groucho',
- this.null_choice_edit.getInput(),
- "getInput() did not return the current value");
- // Simulate choosing a null value and check that getInput()
- // returns the new value.
- this.null_choice_edit.onClick({button: 1, halt: function(){}});
- this.null_choice_edit._choice_list.fire('valueChosen', null);
- Assert.areEqual(
- null,
- this.null_choice_edit.getInput(),
- "getInput() did not return the current (null) value");
- }
-}));
-
-Y.lp.testing.Runner.run(suite);
-
+ });
+ Assert.isFalse(
+ remove_action_present,
+ 'Remove item is present even when the current value is null.');
+ },
+
+ test_get_input_for_null: function() {
+ this.null_choice_edit.set('value', 'groucho');
+ Assert.areEqual(
+ 'groucho',
+ this.null_choice_edit.getInput(),
+ "getInput() did not return the current value");
+ // Simulate choosing a null value and check that getInput()
+ // returns the new value.
+ this.null_choice_edit.onClick({button: 1, halt: function(){}});
+ this.null_choice_edit._choice_list.fire('valueChosen', null);
+ Assert.areEqual(
+ null,
+ this.null_choice_edit.getInput(),
+ "getInput() did not return the current (null) value");
+ }
+ }));
+
+
+
+}, '0.1', {
+ 'requires': ['test', 'console', 'lp.choiceedit', 'node', 'event',
+ 'event-simulate', 'widget-stack', 'lp.app.choice']
});
=== modified file 'lib/lp/app/javascript/confirmationoverlay/tests/test_confirmationoverlay.html'
--- lib/lp/app/javascript/confirmationoverlay/tests/test_confirmationoverlay.html 2011-08-30 15:06:11 +0000
+++ lib/lp/app/javascript/confirmationoverlay/tests/test_confirmationoverlay.html 2012-02-07 16:00:29 +0000
@@ -1,39 +1,60 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+Copyright 2012 Canonical Ltd. This software is licensed under the
+GNU Affero General Public License version 3 (see the file LICENSE).
+-->
+
<html>
<head>
- <title>Confirmation Overlay</title>
-
- <!-- YUI and test setup -->
- <script type="text/javascript"
- src="../../../../../canonical/launchpad/icing/yui/yui/yui.js">
- </script>
- <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
- <script type="text/javascript"
- src="../../../../app/javascript/testing/testrunner.js"></script>
-
- <!-- dependent modules from lazr-->
- <script type="text/javascript" src="../../lazr/lazr.js"></script>
- <script type="text/javascript" src="../../overlay/overlay.js"></script>
- <script type="text/javascript" src="../../formoverlay/formoverlay.js"></script>
-
- <!-- The module under test -->
- <script type="text/javascript" src="../confirmationoverlay.js"></script>
-
- <!-- The test suite -->
- <script type="text/javascript" src="test_confirmationoverlay.js"></script>
-
-</head>
-<body class="yui3-skin-sam">
- <div id="placeholder" style="display:none;">
- </div>
-
- <script type="text/x-template" id="form-template">
- <span id="test">content</span>
- <form name="my-form">
- <input type="checkbox" name="checkbox" value="checkbox" />
- <input id="submit" type="submit" name="submit_name" value="submit_value"/>
- </form>
- </script>
-
-</body>
+ <title>Indicator confirmationoverlay</title>
+
+ <!-- YUI and test setup -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/yui/yui/yui.js">
+ </script>
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/console-core.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/skins/sam/console.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
+
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
+
+ <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
+
+ <!-- Dependencies -->
+ <script type="text/javascript" src="../../../../../../build/js/lp/app/lazr/lazr.js"></script>
+ <script type="text/javascript" src="../../../../../../build/js/lp/app/overlay/overlay.js"></script>
+ <script type="text/javascript" src="../../../../../../build/js/lp/app/formoverlay/formoverlay.js"></script>
+
+ <!-- The module under test. -->
+ <script type="text/javascript" src="../confirmationoverlay.js"></script>
+
+ <!-- Any css assert for this module. -->
+ <!-- <link rel="stylesheet" href="../assets/confirmationoverlay-core.css" /> -->
+
+ <!-- The test suite. -->
+ <script type="text/javascript" src="test_confirmationoverlay.js"></script>
+
+ </head>
+ <body class="yui3-skin-sam">
+ <ul id="suites">
+ <!-- <li>lp.large_indicator.test</li> -->
+ <li>lp.app.confirmationoverlay.test</li>
+ </ul>
+
+ <div id="placeholder" style="display:none;">
+ </div>
+
+ <script type="text/x-template" id="form-template">
+ <span id="test">content</span>
+ <form name="my-form">
+ <input type="checkbox" name="checkbox" value="checkbox" />
+ <input id="submit" type="submit" name="submit_name" value="submit_value"/>
+ </form>
+ </script>
+ </body>
</html>
=== modified file 'lib/lp/app/javascript/confirmationoverlay/tests/test_confirmationoverlay.js'
--- lib/lp/app/javascript/confirmationoverlay/tests/test_confirmationoverlay.js 2011-09-13 10:58:15 +0000
+++ lib/lp/app/javascript/confirmationoverlay/tests/test_confirmationoverlay.js 2012-02-07 16:00:29 +0000
@@ -1,226 +1,229 @@
-/* Copyright (c) 2011, Canonical Ltd. All rights reserved. */
-
-YUI().use('lp.testing.runner', 'test', 'dump', 'console', 'node',
- 'lp.app.confirmationoverlay', 'event', 'event-simulate',
- 'node-event-simulate', function(Y) {
-
-var suite = new Y.Test.Suite("Confirmation Overlay Tests");
-
-var form_html = Y.one('#form-template').getContent();
-
-suite.add(new Y.Test.Case({
-
- name: 'confirmation_overlay_basics',
-
- setUp: function() {
- Y.one("#placeholder")
- .empty()
- .append(Y.Node.create(form_html));
- this.button = Y.one('#submit');
- this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay(
- {button: this.button});
- },
-
- tearDown: function() {
- this.overlay.destroy();
- },
-
- test_button_set: function() {
- Y.ObjectAssert.areEqual(this.button, this.overlay.get('button'));
- },
-
- test_form_set: function() {
- var form = Y.one("#placeholder").one('form');
- Y.ObjectAssert.areEqual(form, this.overlay.get('submit_form'));
- },
-
- test_not_visible_by_default: function() {
- Y.Assert.isFalse(this.overlay.get('visible'));
- },
-
- test_shown_when_button_clicked: function() {
- this.button.simulate('click');
- Y.Assert.isTrue(this.overlay.get('visible'));
- },
-
- test_hidden_field_added_on_ok: function() {
- // When 'ok' (i.e. confirmation) is clicked, the Confirmation Overlay
- // adds an additional field to the form to simulate the click on the
- // right button.
- this.button.simulate('click');
-
- this.overlay.form_node.one('.ok-btn').simulate('click');
- var hidden_input = this.overlay.get(
- 'submit_form').one('input.hidden-input');
- var real_input = this.overlay.get('submit_form').one('input#submit');
-
- Y.Assert.areEqual(
- real_input.get('name'),
- hidden_input.get('name'));
- Y.Assert.areEqual(
- real_input.get('value'),
- hidden_input.get('value'));
- },
-
- test_call_submit_on_ok: function() {
- // When 'ok' (i.e. confirmation) is clicked, the Confirmation Overlay
- // submits the form.
- // (Since we don't use YUI to make the request, we have to patch the
- // form object to test it's submission (and prevent the form to be
- // actually submitted.)
- this.button.simulate('click');
-
- var mockForm = Y.Mock();
- Y.Mock.expect(mockForm, {
- method: "submit"
- });
- Y.Mock.expect(mockForm, {
- method: "append",
- args: [Y.Mock.Value.Object]
- });
- this.overlay.set('submit_form', mockForm);
- this.overlay.form_node.one('.ok-btn').simulate('click');
-
- Y.Mock.verify(mockForm);
- }
-
-}));
-
-suite.add(new Y.Test.Case({
-
- name: 'confirmation_overlay_content_functions',
-
- setUp: function() {
- Y.one("#placeholder")
- .empty()
- .append(Y.Node.create(form_html));
- this.button = Y.one('#submit');
- this.getTestContent = function() {
- return Y.one('span#test').get('text');
- };
- this.isTestNotEmpty = function() {
- return Y.one('span#test').get('text') !== '';
- };
- this.overlay = null;
- },
-
- tearDown: function() {
- // Each test is responsible for creating it's own overlay
- // but the cleanup is done in a centralized fashion.
- if (this.overlay !== null) {
- this.overlay.destroy();
- }
- },
-
- test_form_content_fn: function() {
- this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
- button: this.button,
- form_content_fn: this.getTestContent
- });
-
- Y.one('span#test').set('innerHTML', 'random content');
- Y.Assert.areEqual('', this.overlay.get('form_content'));
- this.button.simulate('click');
- Y.Assert.areEqual('random content', this.overlay.get('form_content'));
- },
-
- test_header_content_fn: function() {
- this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
- button: this.button,
- header_content_fn: this.getTestContent
- });
-
- Y.one('span#test').set('innerHTML', 'random content');
- Y.Assert.areEqual('', this.overlay.get('form_header'));
- this.button.simulate('click');
- Y.Assert.areEqual(
- 'random content',
- this.overlay.get('headerContent').get('text').join(''));
- },
-
- test_do_not_display_fn: function() {
- // The parameter display_confirmation_fn can be used
- // to prevent the Confirmation Overlay from popping up.
- this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
- button: this.button,
- display_confirmation_fn: this.isTestNotEmpty
- });
-
- // Hack the form to prevent real submission.
- Y.one('form').on('submit', function(e) {
- e.preventDefault();
- });
-
- Y.one('span#test').set('innerHTML', '');
- Y.Assert.isFalse(this.overlay.get('visible'));
- this.button.simulate('click');
-
- // The Overlay was not displayed.
- Y.Assert.isFalse(this.overlay.get('visible'));
- },
-
- test_callback_called: function() {
- // If submit_fn is passed to the constructor, call this function
- // when the 'ok' is clicked instead of submitting the form.
- var called = false;
- var callback = function() {
- called = true;
- };
- // Hack the form to record form submission.
- var form_submitted = false;
- Y.one('form').on('submit', function(e) {
- form_submitted = true;
- e.preventDefault();
- });
-
- this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
- button: this.button,
- submit_fn: callback
- });
- this.button.simulate('click');
- Y.Assert.isTrue(this.overlay.get('visible'));
- this.overlay.form_node.one('.ok-btn').simulate('click');
- Y.Assert.isFalse(this.overlay.get('visible'));
- // The callback has been called.
- Y.Assert.isTrue(called);
- // The form has not been submitted.
- Y.Assert.isFalse(form_submitted);
- }
-
-}));
-
-suite.add(new Y.Test.Case({
-
- name: 'confirmation_overlay_buttonless',
-
- tearDown: function() {
- if (this.overlay !== null) {
- this.overlay.destroy();
- }
- },
-
- test_callback_called: function() {
- // A ConfirmationOverlay can be constructed without passing a button.
- // The creator is responsible for calling show() manually.
- var called = false;
- var callback = function() {
- called = true;
- };
-
- this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
- submit_fn: callback
- });
- Y.Assert.isFalse(this.overlay.get('visible'));
- this.overlay.show();
- Y.Assert.isTrue(this.overlay.get('visible'));
- this.overlay.form_node.one('.ok-btn').simulate('click');
- Y.Assert.isFalse(this.overlay.get('visible'));
- // The callback has been called.
- Y.Assert.isTrue(called);
- }
-
-}));
-
-Y.lp.testing.Runner.run(suite);
-
+/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
+
+YUI.add('lp.app.confirmationoverlay.test', function (Y) {
+
+ var tests = Y.namespace('lp.app.confirmationoverlay.test');
+ tests.suite = new Y.Test.Suite('app.confirmationoverlay Tests');
+
+ var form_html = Y.one('#form-template').getContent();
+
+ tests.suite.add(new Y.Test.Case({
+ name: 'app.confirmationoverlay_tests',
+
+ setUp: function() {
+ Y.one("#placeholder")
+ .empty()
+ .append(Y.Node.create(form_html));
+ this.button = Y.one('#submit');
+ this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay(
+ {button: this.button});
+ },
+
+ tearDown: function() {
+ this.overlay.destroy();
+ },
+
+ test_library_exists: function () {
+ Y.Assert.isObject(Y.lp.app.confirmationoverlay,
+ "We should be able to locate the lp.app.confirmationoverlay module");
+ },
+
+ test_button_set: function() {
+ Y.ObjectAssert.areEqual(this.button, this.overlay.get('button'));
+ },
+
+ test_form_set: function() {
+ var form = Y.one("#placeholder").one('form');
+ Y.ObjectAssert.areEqual(form, this.overlay.get('submit_form'));
+ },
+
+ test_not_visible_by_default: function() {
+ Y.Assert.isFalse(this.overlay.get('visible'));
+ },
+
+ test_shown_when_button_clicked: function() {
+ this.button.simulate('click');
+ Y.Assert.isTrue(this.overlay.get('visible'));
+ },
+
+ test_hidden_field_added_on_ok: function() {
+ // When 'ok' (i.e. confirmation) is clicked, the Confirmation Overlay
+ // adds an additional field to the form to simulate the click on the
+ // right button.
+ this.button.simulate('click');
+
+ this.overlay.form_node.one('.ok-btn').simulate('click');
+ var hidden_input = this.overlay.get(
+ 'submit_form').one('input.hidden-input');
+ var real_input = this.overlay.get('submit_form').one('input#submit');
+
+ Y.Assert.areEqual(
+ real_input.get('name'),
+ hidden_input.get('name'));
+ Y.Assert.areEqual(
+ real_input.get('value'),
+ hidden_input.get('value'));
+ },
+
+ test_call_submit_on_ok: function() {
+ // When 'ok' (i.e. confirmation) is clicked, the Confirmation Overlay
+ // submits the form.
+ // (Since we don't use YUI to make the request, we have to patch the
+ // form object to test it's submission (and prevent the form to be
+ // actually submitted.)
+ this.button.simulate('click');
+
+ var mockForm = Y.Mock();
+ Y.Mock.expect(mockForm, {
+ method: "submit"
+ });
+ Y.Mock.expect(mockForm, {
+ method: "append",
+ args: [Y.Mock.Value.Object]
+ });
+ this.overlay.set('submit_form', mockForm);
+ this.overlay.form_node.one('.ok-btn').simulate('click');
+
+ Y.Mock.verify(mockForm);
+ }
+ }));
+
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'confirmation_overlay_content_functions',
+
+ setUp: function() {
+ Y.one("#placeholder")
+ .empty()
+ .append(Y.Node.create(form_html));
+ this.button = Y.one('#submit');
+ this.getTestContent = function() {
+ return Y.one('span#test').get('text');
+ };
+ this.isTestNotEmpty = function() {
+ return Y.one('span#test').get('text') !== '';
+ };
+ this.overlay = null;
+ },
+
+ tearDown: function() {
+ // Each test is responsible for creating it's own overlay
+ // but the cleanup is done in a centralized fashion.
+ if (this.overlay !== null) {
+ this.overlay.destroy();
+ }
+ },
+
+ test_form_content_fn: function() {
+ this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
+ button: this.button,
+ form_content_fn: this.getTestContent
+ });
+
+ Y.one('span#test').set('innerHTML', 'random content');
+ Y.Assert.areEqual('', this.overlay.get('form_content'));
+ this.button.simulate('click');
+ Y.Assert.areEqual('random content', this.overlay.get('form_content'));
+ },
+
+ test_header_content_fn: function() {
+ this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
+ button: this.button,
+ header_content_fn: this.getTestContent
+ });
+
+ Y.one('span#test').set('innerHTML', 'random content');
+ Y.Assert.areEqual('', this.overlay.get('form_header'));
+ this.button.simulate('click');
+ Y.Assert.areEqual(
+ 'random content',
+ this.overlay.get('headerContent').get('text').join(''));
+ },
+
+ test_do_not_display_fn: function() {
+ // The parameter display_confirmation_fn can be used
+ // to prevent the Confirmation Overlay from popping up.
+ this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
+ button: this.button,
+ display_confirmation_fn: this.isTestNotEmpty
+ });
+
+ // Hack the form to prevent real submission.
+ Y.one('form').on('submit', function(e) {
+ e.preventDefault();
+ });
+
+ Y.one('span#test').set('innerHTML', '');
+ Y.Assert.isFalse(this.overlay.get('visible'));
+ this.button.simulate('click');
+
+ // The Overlay was not displayed.
+ Y.Assert.isFalse(this.overlay.get('visible'));
+ },
+
+ test_callback_called: function() {
+ // If submit_fn is passed to the constructor, call this function
+ // when the 'ok' is clicked instead of submitting the form.
+ var called = false;
+ var callback = function() {
+ called = true;
+ };
+ // Hack the form to record form submission.
+ var form_submitted = false;
+ Y.one('form').on('submit', function(e) {
+ form_submitted = true;
+ e.preventDefault();
+ });
+
+ this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
+ button: this.button,
+ submit_fn: callback
+ });
+ this.button.simulate('click');
+ Y.Assert.isTrue(this.overlay.get('visible'));
+ this.overlay.form_node.one('.ok-btn').simulate('click');
+ Y.Assert.isFalse(this.overlay.get('visible'));
+ // The callback has been called.
+ Y.Assert.isTrue(called);
+ // The form has not been submitted.
+ Y.Assert.isFalse(form_submitted);
+ }
+
+ }));
+
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'confirmation_overlay_buttonless',
+
+ tearDown: function() {
+ if (this.overlay !== null) {
+ this.overlay.destroy();
+ }
+ },
+
+ test_callback_called: function() {
+ // A ConfirmationOverlay can be constructed without passing a button.
+ // The creator is responsible for calling show() manually.
+ var called = false;
+ var callback = function() {
+ called = true;
+ };
+
+ this.overlay = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
+ submit_fn: callback
+ });
+ Y.Assert.isFalse(this.overlay.get('visible'));
+ this.overlay.show();
+ Y.Assert.isTrue(this.overlay.get('visible'));
+ this.overlay.form_node.one('.ok-btn').simulate('click');
+ Y.Assert.isFalse(this.overlay.get('visible'));
+ // The callback has been called.
+ Y.Assert.isTrue(called);
+ }
+
+ }));
+
+}, '0.1', {
+ 'requires': ['test', 'console', 'lp.app.confirmationoverlay',
+ 'dump', 'node', 'event', 'event-simulate', 'node-event-simulate']
});
=== modified file 'lib/lp/app/javascript/picker/tests/test_personpicker.html'
--- lib/lp/app/javascript/picker/tests/test_personpicker.html 2011-08-10 13:33:26 +0000
+++ lib/lp/app/javascript/picker/tests/test_personpicker.html 2012-02-07 16:00:29 +0000
@@ -1,50 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+Copyright 2012 Canonical Ltd. This software is licensed under the
+GNU Affero General Public License version 3 (see the file LICENSE).
+-->
+
<html>
<head>
- <title>Launchpad PersonPicker</title>
-
- <!-- YUI and test setup -->
- <script type="text/javascript"
- src="../../../../../canonical/launchpad/icing/yui/yui/yui.js">
- </script>
- <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
- <script type="text/javascript"
- src="../../../../app/javascript/testing/testrunner.js"></script>
-
- <!-- Some required dependencies -->
- <script type="text/javascript" src="../../client.js"></script>
- <script type="text/javascript" src="../../lp.js"></script>
- <script type="text/javascript" src="../../activator/activator.js"></script>
- <script type="text/javascript" src="../../anim/anim.js"></script>
- <script type="text/javascript" src="../../lazr/lazr.js"></script>
- <script type="text/javascript" src="../../overlay/overlay.js"></script>
- <script type="text/javascript" src="../../effects/effects.js"></script>
- <script type="text/javascript" src="../../extras/extras.js"></script>
- <script type="text/javascript" src="../../expander.js"></script>
- <script type="text/javascript" src="../picker.js"></script>
- <script type="text/javascript" src="../picker_patcher.js"></script>
-
- <!-- The module under test -->
- <script type="text/javascript" src="../person_picker.js"></script>
-
- <!-- The test suite -->
- <script type="text/javascript" src="test_personpicker.js"></script>
- </head>
-<body class="yui3-skin-sam">
- <div class="yui3-widget yui3-activator yui3-activator-focused">
- <span id="picker_id" class="yui3-activator-content yui3-activator-success">
- <span id="pickertest">
- <span>
- A picker widget test
- <button id="edit-pickertest-btn"
- class="lazr-btn yui3-activator-act yui3-activator-hidden">
- Edit
- </button>
- </span>
- <span class="yui3-activator-data-box">
- </span>
- <span class="yui3-activator-message-box yui3-activator-hidden"></span>
- </span>
- </span>
- </div>
-</body>
+ <title>test person_picker</title>
+
+ <!-- YUI and test setup -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/yui/yui/yui.js">
+ </script>
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/console-core.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/skins/sam/console.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
+
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
+
+ <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
+
+ <!-- Dependencies -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/client.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/lp.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/activator/activator.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/anim/anim.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/lazr/lazr.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/overlay/overlay.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/effects/effect.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/expander.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/picker/picker.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/picker/picker_patcher.js"></script>
+
+
+ <!-- The module under test. -->
+ <script type="text/javascript" src="../person_picker.js"></script>
+
+ <!-- Any css assert for this module. -->
+ <!-- <link rel="stylesheet" href="../assets/person_picker-core.css" /> -->
+
+ <!-- The test suite. -->
+ <script type="text/javascript" src="test_personpicker.js"></script>
+
+ </head>
+ <body class="yui3-skin-sam">
+ <ul id="suites">
+ <!-- <li>lp.large_indicator.test</li> -->
+ <li>lp.person_picker.test</li>
+ </ul>
+
+ <div class="yui3-widget yui3-activator yui3-activator-focused">
+ <span id="picker_id" class="yui3-activator-content yui3-activator-success">
+ <span id="pickertest">
+ <span>
+ A picker widget test
+ <button id="edit-pickertest-btn"
+ class="lazr-btn yui3-activator-act yui3-activator-hidden">
+ Edit
+ </button>
+ </span>
+ <span class="yui3-activator-data-box">
+ </span>
+ <span class="yui3-activator-message-box yui3-activator-hidden"></span>
+ </span>
+ </span>
+ </div>
+
+ </body>
</html>
=== modified file 'lib/lp/app/javascript/picker/tests/test_personpicker.js'
--- lib/lp/app/javascript/picker/tests/test_personpicker.js 2011-09-19 00:35:49 +0000
+++ lib/lp/app/javascript/picker/tests/test_personpicker.js 2012-02-07 16:00:29 +0000
@@ -6,473 +6,477 @@
'lazr.picker', 'lazr.person-picker', 'lp.app.picker',
'node-event-simulate', function(Y) {
-var Assert = Y.Assert;
-
-/* Helper function to clean up a dynamically added widget instance. */
-function cleanup_widget(widget) {
- // Nuke the boundingBox, but only if we've touched the DOM.
- if (widget.get('rendered')) {
- var bb = widget.get('boundingBox');
- bb.get('parentNode').removeChild(bb);
- }
- // Kill the widget itself.
- widget.destroy();
- var data_box = Y.one('#picker_id .yui3-activator-data-box');
- var link = data_box.one('a');
- if (link) {
- link.get('parentNode').removeChild(link);
- }
-}
-
-/*
- * A wrapper for the Y.Event.simulate() function. The wrapper accepts
- * CSS selectors and Node instances instead of raw nodes.
- */
-function simulate(widget, selector, evtype, options) {
- var rawnode = Y.Node.getDOMNode(widget.one(selector));
- Y.Event.simulate(rawnode, evtype, options);
-}
-
-var suite = new Y.Test.Suite("PersonPicker Tests");
-
-/*
- * Test cases for person picker functionality.
- */
-var commonPersonPickerTests = {
-
- name: 'common_person_picker',
-
- setUp: function() {
- this.ME = '/~me';
- window.LP = {
- links: {me: this.ME},
- cache: {}
- };
- this.vocabulary = [
- {
- "value": "me",
- "metadata": "person",
- "title": "Me",
- "css": "sprite-person",
- "description": "me@xxxxxxxxxxx",
- "api_uri": "/~me"
- },
- {
- "value": "someteam",
- "metadata": "team",
- "title": "Some Team",
- "css": "sprite-team",
- "description": "someone@xxxxxxxxxxx",
- "api_uri": "/~someteam"
- }
- ];
-
- // We patch Launchpad client to return some fake data for the patch
- // operation.
- Y.lp.client.Launchpad = function() {};
- Y.lp.client.Launchpad.prototype.patch =
- function(uri, representation, config, headers) {
- // our setup assumes success, so we just do the success
- // callback.
- var entry_repr = {
- 'test_link': representation.test_link,
- 'lp_html': {
- 'test_link':
- '<a href="' + representation.test_link +
- '">Content</a>'}
- };
- var result = new Y.lp.client.Entry(
- null, entry_repr, "a_self_link");
- config.on.success(result);
- };
- },
-
- tearDown: function() {
- cleanup_widget(this.picker);
- delete window.LP;
- },
-
- _picker_params: function(
- show_assign_me_button, show_remove_button,
- selected_value, selected_value_metadata) {
- return {
- "show_assign_me_button": show_assign_me_button,
- "show_remove_button": show_remove_button,
- "selected_value": selected_value,
- "selected_value_metadata": selected_value_metadata
- };
- },
-
- _check_button_state: function(btn_class, is_visible) {
- var assign_me_button = Y.one(btn_class);
- Assert.isNotNull(assign_me_button);
- if (is_visible) {
- Assert.isFalse(
- assign_me_button.hasClass('yui3-picker-hidden'),
- btn_class + " should be visible but is hidden");
- } else {
- Assert.isTrue(
- assign_me_button.hasClass('yui3-picker-hidden'),
- btn_class + " should be hidden but is visible");
- }
- },
-
- _check_assign_me_button_state: function(is_visible) {
- this._check_button_state('.yui-picker-assign-me-button', is_visible);
- },
-
- _check_remove_button_state: function(is_visible) {
- this._check_button_state('.yui-picker-remove-button', is_visible);
- },
-
- test_min_search_chars: function() {
- // The minimum search term is 2 characters.
- this.create_picker(this._picker_params(true, true));
- Assert.areEqual(2, this.picker.get('min_search_chars'));
- },
-
- test_search_field_focus: function () {
- // The search field has focus when the picker is shown.
- this.create_picker(this._picker_params(true, true));
- this.picker.render();
- this.picker.hide();
-
- var got_focus = false;
- this.picker._search_input.on('focus', function(e) {
- got_focus = true;
- });
- this.picker.show();
- Y.Assert.isTrue(got_focus, "search input did not get focus.");
- },
-
- test_buttons_save: function () {
- // The assign/remove links save the correct values.
- this.create_picker(this._picker_params(true, true));
- this.picker.render();
- this.picker.show();
-
- // Patch the picker so the assign_me and remove methods can be
- // tested.
- var data = null;
- this.picker.on('save', function (result) {
- data = result.value;
- });
- var remove = Y.one('.yui-picker-remove-button');
- remove.simulate('click');
- Y.Assert.areEqual(null, data);
-
- var assign_me = Y.one('.yui-picker-assign-me-button');
- assign_me.simulate('click');
- Y.Assert.areEqual('me', data);
- },
-
- test_picker_assign_me_button_text: function() {
- // The assign me button text is correct.
- this.create_picker(this._picker_params(true, true));
- this.picker.render();
- var assign_me_button = Y.one('.yui-picker-assign-me-button');
- Assert.areEqual('Assign Moi', assign_me_button.get('innerHTML'));
- },
-
- test_picker_assign_me_button_not_shown_when_not_logged_in: function() {
- // The assign me button is hidden when the user is not logged-in.
- delete window.LP.links.me; // Log-out.
- this.create_picker(this._picker_params(true, true));
- this.picker.render();
- var assign_me_button = Y.one('.yui-picker-assign-me-button');
- Assert.isNull(assign_me_button);
- },
-
- test_picker_remove_person_button_text: function() {
- // The remove button text is correct.
- this.create_picker(this._picker_params(true, true, "fred", "person"));
- this.picker.render();
- var remove_button = Y.one('.yui-picker-remove-button');
- Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
- },
-
- test_picker_remove_team_button_text: function() {
- // The remove button text is correct.
- this.create_picker(this._picker_params(true, true, "cats", "team"));
- this.picker.render();
- var remove_button = Y.one('.yui-picker-remove-button');
- Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
- },
-
- test_picker_has_assign_me_button: function() {
- // The assign me button is shown.
- this.create_picker(this._picker_params(true, true));
- this.picker.render();
- this._check_assign_me_button_state(true);
- },
-
- test_picker_no_assign_me_button_unless_configured: function() {
- // The assign me button is only rendered if show_assign_me_button
- // config setting is true.
- this.create_picker(this._picker_params(false, true));
- this.picker.render();
- Assert.isNull(Y.one('.yui-picker-assign-me-button'));
- },
-
- test_picker_no_assign_me_button_if_value_is_me: function() {
- // The assign me button is not shown if the picker is created for a
- // field where the value is "me".
- this.create_picker(this._picker_params(true, true, "me"), this.ME);
- this.picker.render();
- this._check_assign_me_button_state(false);
- },
-
- test_picker_no_remove_button_if_null_value: function() {
- // The remove button is not shown if the picker is created for a field
- // which has a null value.
- this.create_picker(this._picker_params(true, true));
- this.picker.render();
- this._check_remove_button_state(false);
- },
-
- test_picker_has_remove_button_if_value: function() {
- // The remove button is shown if the picker is created for a field
- // which has a value.
- this.create_picker(this._picker_params(true, true, "me"), this.ME);
- this.picker.render();
- this._check_remove_button_state(true);
- },
-
- test_picker_no_remove_button_unless_configured: function() {
- // The remove button is only rendered if show_remove_button setting is
- // true.
- this.create_picker(this._picker_params(true, false, "me"), this.ME);
- this.picker.render();
- Assert.isNull(Y.one('.yui-picker-remove-button'));
- }
-};
-
-/*
- * Test cases for person picker functionality when created using
- * addPickerPatcher.
- */
-var pickerPatcherPersonPickerTests = {
-
- name: 'picker_patcher_person_picker',
-
- create_picker: function(params, field_value) {
- if (field_value !== undefined) {
- var data_box = Y.one('#picker_id .yui3-activator-data-box');
- data_box.appendChild(Y.Node.create('<a>Content</a>'));
- data_box.one('a').set('href', field_value);
- }
-
- var config = {
- "picker_type": "person",
- "step_title": "Choose someone",
- "header": "Pick Someone",
- "validate_callback": null,
- "show_search_box": true,
- "show_assign_me_button": params.show_assign_me_button,
- "show_remove_button": params.show_remove_button,
- "selected_value": params.selected_value,
- "selected_value_metadata": params.selected_value_metadata,
- "assign_me_text": "Assign Moi",
- "remove_person_text": "Remove someone",
- "remove_team_text": "Remove some team"
- };
- this.picker = Y.lp.app.picker.addPickerPatcher(
- this.vocabulary,
- "foo/bar",
- "test_link",
- "picker_id",
- config);
- },
-
- test_picker_assign_me_button_hide_on_save: function() {
- // The assign me button is shown initially but hidden if the picker
- // saves a value equal to 'me'.
- this.create_picker(this._picker_params(true, true));
- this._check_assign_me_button_state(true);
- this.picker.set('results', this.vocabulary);
- this.picker.render();
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(1)', 'click');
- this._check_assign_me_button_state(false);
- },
-
- test_picker_remove_button_clicked: function() {
- // The remove button is hidden once a picker value has been removed.
- // And the assign me button is shown.
- this.create_picker(this._picker_params(true, true, "me"), this.ME);
- this.picker.render();
- this._check_assign_me_button_state(false);
- var remove = Y.one('.yui-picker-remove-button');
- remove.simulate('click');
- this._check_remove_button_state(false);
- this._check_assign_me_button_state(true);
- },
-
- test_picker_assign_me_button_clicked: function() {
- // The assign me button is hidden once it is clicked.
- // And the remove button is shown.
- this.create_picker(this._picker_params(true, true));
- this.picker.render();
- var assign_me = Y.one('.yui-picker-assign-me-button');
- assign_me.simulate('click');
- this._check_remove_button_state(true);
- this._check_assign_me_button_state(false);
- },
-
- test_picker_assign_me_updates_remove_text: function() {
- // When Assign me is used, the Remove button text is updated from
- // the team removal text to the person removal text.
- this.create_picker(this._picker_params(true, true, "cats", "team"));
- this.picker.render();
- var remove_button = Y.one('.yui-picker-remove-button');
- Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
- var assign_me = Y.one('.yui-picker-assign-me-button');
- assign_me.simulate('click');
- Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
- },
-
- test_picker_save_updates_remove_text: function() {
- // When save is called, the Remove button text is updated according to
- // the newly saved value.
- this.create_picker(this._picker_params(true, true, "me"), this.ME);
- var remove_button = Y.one('.yui-picker-remove-button');
- Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
- this.picker.set('results', this.vocabulary);
- this.picker.render();
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
- }
-};
-
-/*
- * Test cases for person picker functionality when created using
- * addPickerPatcher.
- */
-var createDirectPersonPickerTests = {
-
- name: 'create_direct_person_picker',
-
- tearDown: function() {
- cleanup_widget(this.picker);
- this.search_input.remove();
- delete window.LP;
- },
-
- create_picker: function(params, field_value) {
- var associated_field_id;
- this.search_input = Y.Node.create(
- '<input id="field_initval" value="foo"/>');
- Y.one(document.body).appendChild(this.search_input);
- associated_field_id = 'field_initval';
- var text_field = Y.one('#field_initval');
- if (field_value !== undefined) {
- text_field.set('text', field_value);
- }
- var config = {
- "picker_type": "person",
- "associated_field_id": associated_field_id,
- "show_assign_me_button": params.show_assign_me_button,
- "show_remove_button": params.show_remove_button,
- "selected_value": params.selected_value,
- "selected_value_metadata": params.selected_value_metadata,
- "assign_me_text": "Assign Moi",
- "remove_person_text": "Remove someone",
- "remove_team_text": "Remove some team"
- };
- this.picker = Y.lp.app.picker.create(
- this.vocabulary, config, associated_field_id);
- },
-
- test_picker_assign_me_button_hide_on_save: function() {
- // The assign me button is shown initially but hidden if the picker
- // saves a value equal to 'me'.
- this.create_picker(this._picker_params(true, true));
- this._check_assign_me_button_state(true);
- this.picker.set('results', this.vocabulary);
- this.picker.render();
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(1)', 'click');
- this._check_assign_me_button_state(false);
- },
-
- test_picker_remove_button_clicked: function() {
- // The remove button is hidden once a picker value has been removed.
- // And the assign me button is shown.
- this.create_picker(this._picker_params(true, true, "me"), this.ME);
- this.picker.render();
- this._check_assign_me_button_state(false);
- var remove = Y.one('.yui-picker-remove-button');
- remove.simulate('click');
- this._check_remove_button_state(false);
- this._check_assign_me_button_state(true);
- },
-
- test_picker_assign_me_button_clicked: function() {
- // The assign me button is hidden once it is clicked.
- // And the remove button is shown.
- this.create_picker(this._picker_params(true, true));
- this.picker.render();
- var assign_me = Y.one('.yui-picker-assign-me-button');
- assign_me.simulate('click');
- this._check_remove_button_state(true);
- this._check_assign_me_button_state(false);
- },
-
- test_picker_assign_me_updates_remove_text: function() {
- // When Assign me is used, the Remove button text is updated from
- // the team removal text to the person removal text.
- this.create_picker(this._picker_params(true, true, "cats", "team"));
- this.picker.render();
- var remove_button = Y.one('.yui-picker-remove-button');
- Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
- var assign_me = Y.one('.yui-picker-assign-me-button');
- assign_me.simulate('click');
- Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
- },
-
- test_picker_save_updates_remove_text: function() {
- // When save is called, the Remove button text is updated according to
- // the newly saved value.
- this.create_picker(this._picker_params(true, true, "me"), this.ME);
- var remove_button = Y.one('.yui-picker-remove-button');
- Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
- this.picker.set('results', this.vocabulary);
- this.picker.render();
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
- }
-};
-
-suite.add(new Y.Test.Case(
- Y.merge(
- commonPersonPickerTests,
- pickerPatcherPersonPickerTests)
-));
-
-suite.add(new Y.Test.Case(
- Y.merge(
- commonPersonPickerTests,
- createDirectPersonPickerTests)
-));
-
-// Hook for the test runner to get test results.
-var handle_complete = function(data) {
- window.status = '::::' + JSON.stringify(data);
-};
-Y.Test.Runner.on('complete', handle_complete);
-Y.Test.Runner.add(suite);
-
-var console = new Y.Console({newestOnTop: false});
-console.render('#log');
-
-Y.on('domready', function() {
- Y.Test.Runner.run();
-});
+ var Assert = Y.Assert;
+
+ /* Helper function to clean up a dynamically added widget instance. */
+ function cleanup_widget(widget) {
+ // Nuke the boundingBox, but only if we've touched the DOM.
+ if (widget.get('rendered')) {
+ var bb = widget.get('boundingBox');
+ bb.get('parentNode').removeChild(bb);
+ }
+ // Kill the widget itself.
+ widget.destroy();
+ var data_box = Y.one('#picker_id .yui3-activator-data-box');
+ var link = data_box.one('a');
+ if (link) {
+ link.get('parentNode').removeChild(link);
+ }
+ }
+
+ /*
+ * A wrapper for the Y.Event.simulate() function. The wrapper accepts
+ * CSS selectors and Node instances instead of raw nodes.
+ */
+ function simulate(widget, selector, evtype, options) {
+ var rawnode = Y.Node.getDOMNode(widget.one(selector));
+ Y.Event.simulate(rawnode, evtype, options);
+ }
+
+ var suite = new Y.Test.Suite("PersonPicker Tests");
+
+ /*
+ * Test cases for person picker functionality.
+ */
+ var commonPersonPickerTests = {
+
+ name: 'common_person_picker',
+
+ setUp: function() {
+ this.ME = '/~me';
+ window.LP = {
+ links: {me: this.ME},
+ cache: {}
+ };
+ this.vocabulary = [
+ {
+ "value": "me",
+ "metadata": "person",
+ "title": "Me",
+ "css": "sprite-person",
+ "description": "me@xxxxxxxxxxx",
+ "api_uri": "/~me"
+ },
+ {
+ "value": "someteam",
+ "metadata": "team",
+ "title": "Some Team",
+ "css": "sprite-team",
+ "description": "someone@xxxxxxxxxxx",
+ "api_uri": "/~someteam"
+ }
+ ];
+
+ // We patch Launchpad client to return some fake data for the patch
+ // operation.
+ Y.lp.client.Launchpad = function() {};
+ Y.lp.client.Launchpad.prototype.patch =
+ function(uri, representation, config, headers) {
+ // our setup assumes success, so we just do the success
+ // callback.
+ var entry_repr = {
+ 'test_link': representation.test_link,
+ 'lp_html': {
+ 'test_link':
+ '<a href="' + representation.test_link +
+ '">Content</a>'}
+ };
+ var result = new Y.lp.client.Entry(
+ null, entry_repr, "a_self_link");
+ config.on.success(result);
+ };
+ },
+
+ tearDown: function() {
+ cleanup_widget(this.picker);
+ delete window.LP;
+ },
+
+ _picker_params: function(
+ show_assign_me_button, show_remove_button,
+ selected_value, selected_value_metadata) {
+ return {
+ "show_assign_me_button": show_assign_me_button,
+ "show_remove_button": show_remove_button,
+ "selected_value": selected_value,
+ "selected_value_metadata": selected_value_metadata
+ };
+ },
+
+ _check_button_state: function(btn_class, is_visible) {
+ var assign_me_button = Y.one(btn_class);
+ Assert.isNotNull(assign_me_button);
+ if (is_visible) {
+ Assert.isFalse(
+ assign_me_button.hasClass('yui3-picker-hidden'),
+ btn_class + " should be visible but is hidden");
+ } else {
+ Assert.isTrue(
+ assign_me_button.hasClass('yui3-picker-hidden'),
+ btn_class + " should be hidden but is visible");
+ }
+ },
+
+ _check_assign_me_button_state: function(is_visible) {
+ this._check_button_state('.yui-picker-assign-me-button',
+ is_visible);
+ },
+
+ _check_remove_button_state: function(is_visible) {
+ this._check_button_state('.yui-picker-remove-button', is_visible);
+ },
+
+ test_min_search_chars: function() {
+ // The minimum search term is 2 characters.
+ this.create_picker(this._picker_params(true, true));
+ Assert.areEqual(2, this.picker.get('min_search_chars'));
+ },
+
+ test_search_field_focus: function () {
+ // The search field has focus when the picker is shown.
+ this.create_picker(this._picker_params(true, true));
+ this.picker.render();
+ this.picker.hide();
+
+ var got_focus = false;
+ this.picker._search_input.on('focus', function(e) {
+ got_focus = true;
+ });
+ this.picker.show();
+ Y.Assert.isTrue(got_focus, "search input did not get focus.");
+ },
+
+ test_buttons_save: function () {
+ // The assign/remove links save the correct values.
+ this.create_picker(this._picker_params(true, true));
+ this.picker.render();
+ this.picker.show();
+
+ // Patch the picker so the assign_me and remove methods can be
+ // tested.
+ var data = null;
+ this.picker.on('save', function (result) {
+ data = result.value;
+ });
+ var remove = Y.one('.yui-picker-remove-button');
+ remove.simulate('click');
+ Y.Assert.areEqual(null, data);
+
+ var assign_me = Y.one('.yui-picker-assign-me-button');
+ assign_me.simulate('click');
+ Y.Assert.areEqual('me', data);
+ },
+
+ test_picker_assign_me_button_text: function() {
+ // The assign me button text is correct.
+ this.create_picker(this._picker_params(true, true));
+ this.picker.render();
+ var assign_me_button = Y.one('.yui-picker-assign-me-button');
+ Assert.areEqual('Assign Moi', assign_me_button.get('innerHTML'));
+ },
+
+ test_picker_assign_me_button_not_shown_when_not_logged_in: function() {
+ // The assign me button is hidden when the user is not logged-in.
+ delete window.LP.links.me; // Log-out.
+ this.create_picker(this._picker_params(true, true));
+ this.picker.render();
+ var assign_me_button = Y.one('.yui-picker-assign-me-button');
+ Assert.isNull(assign_me_button);
+ },
+
+ test_picker_remove_person_button_text: function() {
+ // The remove button text is correct.
+ this.create_picker(this._picker_params(true,
+ true,
+ "fred",
+ "person"));
+ this.picker.render();
+ var remove_button = Y.one('.yui-picker-remove-button');
+ Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
+ },
+
+ test_picker_remove_team_button_text: function() {
+ // The remove button text is correct.
+ this.create_picker(this._picker_params(true, true, "cats", "team"));
+ this.picker.render();
+ var remove_button = Y.one('.yui-picker-remove-button');
+ Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
+ },
+
+ test_picker_has_assign_me_button: function() {
+ // The assign me button is shown.
+ this.create_picker(this._picker_params(true, true));
+ this.picker.render();
+ this._check_assign_me_button_state(true);
+ },
+
+ test_picker_no_assign_me_button_unless_configured: function() {
+ // The assign me button is only rendered if show_assign_me_button
+ // config setting is true.
+ this.create_picker(this._picker_params(false, true));
+ this.picker.render();
+ Assert.isNull(Y.one('.yui-picker-assign-me-button'));
+ },
+
+ test_picker_no_assign_me_button_if_value_is_me: function() {
+ // The assign me button is not shown if the picker is created for a
+ // field where the value is "me".
+ this.create_picker(this._picker_params(true, true, "me"), this.ME);
+ this.picker.render();
+ this._check_assign_me_button_state(false);
+ },
+
+ test_picker_no_remove_button_if_null_value: function() {
+ // The remove button is not shown if the picker is created for a
+ // field which has a null value.
+ this.create_picker(this._picker_params(true, true));
+ this.picker.render();
+ this._check_remove_button_state(false);
+ },
+
+ test_picker_has_remove_button_if_value: function() {
+ // The remove button is shown if the picker is created for a field
+ // which has a value.
+ this.create_picker(this._picker_params(true, true, "me"), this.ME);
+ this.picker.render();
+ this._check_remove_button_state(true);
+ },
+
+ test_picker_no_remove_button_unless_configured: function() {
+ // The remove button is only rendered if show_remove_button
+ // setting is true.
+ this.create_picker(this._picker_params(true, false, "me"), this.ME);
+ this.picker.render();
+ Assert.isNull(Y.one('.yui-picker-remove-button'));
+ }
+ };
+
+ /*
+ * Test cases for person picker functionality when created using
+ * addPickerPatcher.
+ */
+ var pickerPatcherPersonPickerTests = {
+
+ name: 'picker_patcher_person_picker',
+
+ create_picker: function(params, field_value) {
+ if (field_value !== undefined) {
+ var data_box = Y.one('#picker_id .yui3-activator-data-box');
+ data_box.appendChild(Y.Node.create('<a>Content</a>'));
+ data_box.one('a').set('href', field_value);
+ }
+
+ var config = {
+ "picker_type": "person",
+ "step_title": "Choose someone",
+ "header": "Pick Someone",
+ "validate_callback": null,
+ "show_search_box": true,
+ "show_assign_me_button": params.show_assign_me_button,
+ "show_remove_button": params.show_remove_button,
+ "selected_value": params.selected_value,
+ "selected_value_metadata": params.selected_value_metadata,
+ "assign_me_text": "Assign Moi",
+ "remove_person_text": "Remove someone",
+ "remove_team_text": "Remove some team"
+ };
+ this.picker = Y.lp.app.picker.addPickerPatcher(
+ this.vocabulary,
+ "foo/bar",
+ "test_link",
+ "picker_id",
+ config);
+ },
+
+ test_picker_assign_me_button_hide_on_save: function() {
+ // The assign me button is shown initially but hidden if the picker
+ // saves a value equal to 'me'.
+ this.create_picker(this._picker_params(true, true));
+ this._check_assign_me_button_state(true);
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(1)', 'click');
+ this._check_assign_me_button_state(false);
+ },
+
+ test_picker_remove_button_clicked: function() {
+ // The remove button is hidden once a picker value has been removed.
+ // And the assign me button is shown.
+ this.create_picker(this._picker_params(true, true, "me"), this.ME);
+ this.picker.render();
+ this._check_assign_me_button_state(false);
+ var remove = Y.one('.yui-picker-remove-button');
+ remove.simulate('click');
+ this._check_remove_button_state(false);
+ this._check_assign_me_button_state(true);
+ },
+
+ test_picker_assign_me_button_clicked: function() {
+ // The assign me button is hidden once it is clicked.
+ // And the remove button is shown.
+ this.create_picker(this._picker_params(true, true));
+ this.picker.render();
+ var assign_me = Y.one('.yui-picker-assign-me-button');
+ assign_me.simulate('click');
+ this._check_remove_button_state(true);
+ this._check_assign_me_button_state(false);
+ },
+
+ test_picker_assign_me_updates_remove_text: function() {
+ // When Assign me is used, the Remove button text is updated from
+ // the team removal text to the person removal text.
+ this.create_picker(this._picker_params(true, true, "cats", "team"));
+ this.picker.render();
+ var remove_button = Y.one('.yui-picker-remove-button');
+ Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
+ var assign_me = Y.one('.yui-picker-assign-me-button');
+ assign_me.simulate('click');
+ Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
+ },
+
+ test_picker_save_updates_remove_text: function() {
+ // When save is called, the Remove button text is updated
+ // according to the newly saved value.
+ this.create_picker(this._picker_params(true, true, "me"), this.ME);
+ var remove_button = Y.one('.yui-picker-remove-button');
+ Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
+ }
+ };
+
+ /*
+ * Test cases for person picker functionality when created using
+ * addPickerPatcher.
+ */
+ var createDirectPersonPickerTests = {
+
+ name: 'create_direct_person_picker',
+
+ tearDown: function() {
+ cleanup_widget(this.picker);
+ this.search_input.remove();
+ delete window.LP;
+ },
+
+ create_picker: function(params, field_value) {
+ var associated_field_id;
+ this.search_input = Y.Node.create(
+ '<input id="field_initval" value="foo"/>');
+ Y.one(document.body).appendChild(this.search_input);
+ associated_field_id = 'field_initval';
+ var text_field = Y.one('#field_initval');
+ if (field_value !== undefined) {
+ text_field.set('text', field_value);
+ }
+ var config = {
+ "picker_type": "person",
+ "associated_field_id": associated_field_id,
+ "show_assign_me_button": params.show_assign_me_button,
+ "show_remove_button": params.show_remove_button,
+ "selected_value": params.selected_value,
+ "selected_value_metadata": params.selected_value_metadata,
+ "assign_me_text": "Assign Moi",
+ "remove_person_text": "Remove someone",
+ "remove_team_text": "Remove some team"
+ };
+ this.picker = Y.lp.app.picker.create(
+ this.vocabulary, config, associated_field_id);
+ },
+
+ test_picker_assign_me_button_hide_on_save: function() {
+ // The assign me button is shown initially but hidden if the picker
+ // saves a value equal to 'me'.
+ this.create_picker(this._picker_params(true, true));
+ this._check_assign_me_button_state(true);
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(1)', 'click');
+ this._check_assign_me_button_state(false);
+ },
+
+ test_picker_remove_button_clicked: function() {
+ // The remove button is hidden once a picker value has been removed.
+ // And the assign me button is shown.
+ this.create_picker(this._picker_params(true, true, "me"), this.ME);
+ this.picker.render();
+ this._check_assign_me_button_state(false);
+ var remove = Y.one('.yui-picker-remove-button');
+ remove.simulate('click');
+ this._check_remove_button_state(false);
+ this._check_assign_me_button_state(true);
+ },
+
+ test_picker_assign_me_button_clicked: function() {
+ // The assign me button is hidden once it is clicked.
+ // And the remove button is shown.
+ this.create_picker(this._picker_params(true, true));
+ this.picker.render();
+ var assign_me = Y.one('.yui-picker-assign-me-button');
+ assign_me.simulate('click');
+ this._check_remove_button_state(true);
+ this._check_assign_me_button_state(false);
+ },
+
+ test_picker_assign_me_updates_remove_text: function() {
+ // When Assign me is used, the Remove button text is updated from
+ // the team removal text to the person removal text.
+ this.create_picker(this._picker_params(true, true, "cats", "team"));
+ this.picker.render();
+ var remove_button = Y.one('.yui-picker-remove-button');
+ Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
+ var assign_me = Y.one('.yui-picker-assign-me-button');
+ assign_me.simulate('click');
+ Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
+ },
+
+ test_picker_save_updates_remove_text: function() {
+ // When save is called, the Remove button text is updated
+ // according to the newly saved value.
+ this.create_picker(this._picker_params(true, true, "me"), this.ME);
+ var remove_button = Y.one('.yui-picker-remove-button');
+ Assert.areEqual('Remove someone', remove_button.get('innerHTML'));
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ Assert.areEqual('Remove some team', remove_button.get('innerHTML'));
+ }
+ };
+
+ suite.add(new Y.Test.Case(
+ Y.merge(
+ commonPersonPickerTests,
+ pickerPatcherPersonPickerTests)
+ ));
+
+ suite.add(new Y.Test.Case(
+ Y.merge(
+ commonPersonPickerTests,
+ createDirectPersonPickerTests)
+ ));
+
+ // Hook for the test runner to get test results.
+ var handle_complete = function(data) {
+ window.status = '::::' + JSON.stringify(data);
+ };
+ Y.Test.Runner.on('complete', handle_complete);
+ Y.Test.Runner.add(suite);
+
+ var console = new Y.Console({newestOnTop: false});
+ console.render('#log');
+
+ Y.on('domready', function() {
+ Y.Test.Runner.run();
+ });
});
=== modified file 'lib/lp/app/javascript/picker/tests/test_picker.html'
--- lib/lp/app/javascript/picker/tests/test_picker.html 2011-08-10 08:43:17 +0000
+++ lib/lp/app/javascript/picker/tests/test_picker.html 2012-02-07 16:00:29 +0000
@@ -1,29 +1,108 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
- <head>
- <title>Picker</title>
-
- <!-- YUI and test setup -->
- <script type="text/javascript"
- src="../../../../../canonical/launchpad/icing/yui/yui/yui.js">
- </script>
- <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
- <script type="text/javascript"
- src="../../../../app/javascript/testing/testrunner.js"></script>
-
- <!-- The module under test -->
- <script type="text/javascript" src="../../overlay/overlay.js"></script>
- <script type="text/javascript" src="../picker.js"></script>
- <script type="text/javascript" src="../../expander.js"></script>
- <script type="text/javascript" src="../../anim/anim.js"></script>
- <script type="text/javascript" src="../../effects/effects.js"></script>
- <script type="text/javascript" src="../../lazr/lazr.js"></script>
- <script type="text/javascript" src="../../extras/extras.js"></script>
-
- <!-- The test suite -->
- <script type="text/javascript" src="test_picker.js"></script>
-</head>
-<body class="yui3-skin-sam">
-</body>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+Copyright 2012 Canonical Ltd. This software is licensed under the
+GNU Affero General Public License version 3 (see the file LICENSE).
+-->
+
+<html>
+ <head>
+ <title>Indicator ${LIBRARY}</title>
+
+ <!-- YUI and test setup -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/yui/yui/yui.js">
+ </script>
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/console-core.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/skins/sam/console.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
+
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
+
+ <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
+
+ <!-- Dependencies -->
+ <!-- <script type="text/javascript" src="../../../../../../build/js/lp/..."></script> -->
+
+ <!-- The module under test. -->
+ <script type="text/javascript" src="../${LIBRARY}.js"></script>
+
+ <!-- Any css assert for this module. -->
+ <!-- <link rel="stylesheet" href="../assets/${LIBRARY}-core.css" /> -->
+
+ <!-- The test suite. -->
+ <script type="text/javascript" src="test_${LIBRARY}.js"></script>
+
+ </head>
+ <body class="yui3-skin-sam">
+ <ul id="suites">
+ <!-- <li>lp.large_indicator.test</li> -->
+ <li>lp.${LIBRARY}.test</li>
+ </ul>
+ </body>
+</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+Copyright 2012 Canonical Ltd. This software is licensed under the
+GNU Affero General Public License version 3 (see the file LICENSE).
+-->
+
+<html>
+ <head>
+ <title>test picker</title>
+
+ <!-- YUI and test setup -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/yui/yui/yui.js">
+ </script>
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/console-core.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/skins/sam/console.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
+
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
+
+ <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
+
+ <!-- Dependencies -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/overlay/overlay.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/picker/picker.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/expander.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/anim/anim.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/effects/effects.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/lazr/lazr.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/extras/extras.js"></script>
+
+
+ <!-- The module under test. -->
+ <script type="text/javascript" src="../picker.js"></script>
+
+ <!-- Any css assert for this module. -->
+ <!-- <link rel="stylesheet" href="../assets/picker-core.css" /> -->
+
+ <!-- The test suite. -->
+ <script type="text/javascript" src="test_picker.js"></script>
+
+ </head>
+ <body class="yui3-skin-sam">
+ <ul id="suites">
+ <!-- <li>lp.large_indicator.test</li> -->
+ <li>lp.picker.test</li>
+ </ul>
+ </body>
</html>
=== modified file 'lib/lp/app/javascript/picker/tests/test_picker.js'
--- lib/lp/app/javascript/picker/tests/test_picker.js 2011-09-16 16:12:22 +0000
+++ lib/lp/app/javascript/picker/tests/test_picker.js 2012-02-07 16:00:29 +0000
@@ -1,1419 +1,1448 @@
-/* Copyright (c) 2009, Canonical Ltd. All rights reserved. */
-
-YUI().use('lp.testing.runner', 'test', 'console', 'node', 'lazr.picker',
- 'event', 'node-event-simulate', 'dump', function(Y) {
-
-// Local aliases
-var Assert = Y.Assert,
- ArrayAssert = Y.ArrayAssert;
-
-var module = Y.lazr.picker;
-
-/*
- * A wrapper for the Y.Event.simulate() function. The wrapper accepts
- * CSS selectors and Node instances instead of raw nodes.
- */
-function simulate(widget, selector, evtype, options) {
- var rawnode = Y.Node.getDOMNode(widget.one(selector));
- Y.Event.simulate(rawnode, evtype, options);
-}
-
-/* Helper function to clean up a dynamically added widget instance. */
-function cleanup_widget(widget) {
- // Nuke the boundingBox, but only if we've touched the DOM.
- if (widget.get('rendered')) {
- var bb = widget.get('boundingBox');
- bb.get('parentNode').removeChild(bb);
- }
- // Kill the widget itself.
- widget.destroy();
-}
-
-var suite = new Y.Test.Suite("LAZR Picker Tests");
-
-suite.add(new Y.Test.Case({
-
- name: 'picker_basics',
-
- setUp: function() {
- this.picker = new Y.lazr.picker.Picker({
- "selected_value": 'foo',
- "selected_value_metadata": 'foobar'
- });
- },
-
- tearDown: function() {
- cleanup_widget(this.picker);
- },
-
- test_picker_can_be_instantiated: function() {
- Assert.isInstanceOf(
- Y.lazr.picker.Picker, this.picker,
- "Picker failed to be instantiated");
- },
-
- test_picker_initialisation: function() {
- Assert.areEqual('foo', this.picker.get('selected_value'));
- Assert.areEqual('foobar', this.picker.get('selected_value_metadata'));
- },
-
- test_picker_is_stackable: function() {
- // We should probably define an Assert.hasExtension.
- Assert.areSame(
- Y.WidgetStack.prototype.sizeShim, this.picker.sizeShim,
- "Picker should be stackable.");
- Assert.areSame(
- Y.WidgetPositionAlign.prototype.align, this.picker.align,
- "Picker should be positionable.");
- },
-
- test_picker_has_elements: function () {
- /**
- * Test that renderUI() adds search box, an error container and a
- * results container to the widget.
- * */
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- Assert.isNotNull(
- bb.one('.yui3-picker-search'),
- "Missing search box.");
- Assert.isNotNull(
- bb.one('.lazr-search.lazr-btn'),
- "Missing search button.");
- Assert.isNotNull(
- bb.one('.yui3-picker-results'),
- "Missing search results.");
- Assert.isNotNull(
- bb.one('.yui3-picker-error'), "Missing error box.");
- },
-
- test_set_results_updates_display: function () {
- this.picker.render();
- var image_url = '../../lazr/assets/skins/sam/search.png';
- this.picker.set('results', [
- {
- image: image_url,
- css: 'yui3-blah-blue',
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var li = bb.one('.yui3-picker-results li');
- Assert.isNotNull(li, "Results not found");
- Assert.isTrue(li.hasClass('yui3-blah-blue'), "Missing class name.");
- Assert.isNotNull(li.one('img'), "Missing image.");
- Assert.areEqual(
- image_url, li.one('img').getAttribute('src'),
- "Unexpected image url");
- var title_el = li.one('.yui3-picker-result-title');
- Assert.isNotNull(title_el, "Missing title element");
- Assert.areEqual(
- 'Joe Schmo', title_el.get('text'), 'Unexpected title value.');
- var description_el = li.one('.yui3-picker-result-description');
- Assert.isNotNull(description_el, "Missing description element.");
- Assert.areEqual(
- 'joe@xxxxxxxxxxx', description_el.get('text'),
- 'Unexpected description value.');
- },
-
- test_alternate_title_text: function () {
- this.picker.render();
- this.picker.set('results', [
- {
- css: 'yui3-blah-blue',
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx',
- alt_title: 'Another Joe'
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var li = bb.one('.yui3-picker-results li');
- var title_el = li.one('.yui3-picker-result-title');
- Assert.isNotNull(title_el, "Missing title element");
- Assert.areEqual('A', title_el.get('tagName'), 'Tab key is broken.');
- Assert.isTrue(title_el.hasClass('js-action'));
- Assert.areEqual(
- 'Joe Schmo\u00a0(Another Joe)', title_el.get('text'),
- 'Unexpected title value.');
- },
-
- test_title_links: function () {
- this.picker.render();
- this.picker.set('results', [
- {
- css: 'yui3-blah-blue',
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx',
- alt_title: 'Joe Again <foo></foo>',
- title_link: 'http://somewhere.com',
- alt_title_link: 'http://somewhereelse.com',
- link_css: 'cool-style',
- details: ['Member since 2007']
- }
- ]);
-
- function check_link(picker, link_selector, title, href) {
- var bb = picker.get('boundingBox');
- var link_clicked = false;
- var link_node = bb.one(link_selector);
-
- Assert.areEqual(title, link_node.get('text'));
- Assert.areEqual(href, link_node.get('href'));
-
- Y.on('click', function(e) {
- link_clicked = true;
- }, link_node);
- simulate(bb, link_selector, 'click');
- Assert.isTrue(link_clicked,
- link_selector + ' link was not clicked');
- }
- check_link(
- this.picker, 'a.cool-style:nth-child(1)', 'Joe Schmo',
- 'http://somewhere.com/');
- check_link(
- this.picker, 'a.cool-style:last-child', 'View details',
- 'http://somewhereelse.com/');
- var alt_text_node = this.picker.get('boundingBox')
- .one('.yui3-picker-result-title span');
- Assert.areEqual('Joe Again <foo></foo>', alt_text_node.get('text'));
- },
-
- test_details: function () {
- // The details of the li is the content node of the expander.
- this.picker.render();
- this.picker.set('results', [
- {
- css: 'yui3-blah-blue',
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx',
- details: ['joe on irc.freenode.net', 'Member since 2007'],
- alt_title_link: '/~jschmo'
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var li = bb.one('.yui3-picker-results li');
- var expander_action = li.expander.icon_node.get('firstChild');
- Assert.areEqual(
- 'A', expander_action.get('tagName'), 'Tab key is broken.');
- var details = li.expander.content_node;
- Assert.areEqual(
- 'joe on irc.freenode.net<br>Member since 2007',
- details.one('div').getContent());
- Assert.areEqual(
- 'Select Joe Schmo', details.one('ul li:first-child').get('text'));
- Assert.areEqual(
- 'View details', details.one('ul li:last-child').get('text'));
- },
-
- test_details_escaping: function () {
- // The content of details is escaped.
- this.picker.render();
- this.picker.set('results', [
- {
- css: 'yui3-blah-blue',
- value: 'jschmo',
- title: 'Joe <Schmo>',
- description: 'joe@xxxxxxxxxxx',
- details: ['<joe> on irc.freenode.net', 'f<nor>d maintainer'],
- alt_title_link: '/~jschmo'
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var li = bb.one('.yui3-picker-results li');
- var details = li.expander.content_node;
- Assert.areEqual(
- '<joe> on irc.freenode.net<br>f<nor>d maintainer',
- details.one('div').getContent());
- Assert.areEqual(
- 'Select Joe <Schmo>',
- details.one('ul li:first-child a').getContent('text'));
- },
-
- test_expander_only_one_open: function() {
- // Only one expanded details entry should be open at any time.
- this.picker.render();
- this.picker.set('results', [
- {
- value: 'jschmo',
- title: 'Joe Schmo',
- details: ['detail 1', 'detail 2']
- },
- {
- value: 'jsmith',
- title: 'Joe Smith',
- details: ['detail 1', 'detail 2']
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var first_entry = bb.one('.yui3-picker-results li');
- var first_expander = first_entry.expander;
- var second_entry = bb.one('.yui3-picker-results li.yui3-lazr-odd');
- var second_expander = second_entry.expander;
- first_expander.icon_node.simulate('click');
- Y.Assert.isTrue(first_expander.isExpanded());
- Y.Assert.isFalse(second_expander.isExpanded());
-
- // Open the other expander and check that the first one has closed.
- second_expander.icon_node.simulate('click');
- Y.Assert.isFalse(first_expander.isExpanded());
- Y.Assert.isTrue(second_expander.isExpanded());
- },
-
- test_expander_multiple_pickers: function() {
- // Expanders for one picker should not interfere with those for
- // another picker. ie if Picker A expander is opened, any open
- // expanders on Picker B should remain open.
- var results = [
- {
- value: 'jschmo',
- title: 'Joe Schmo',
- details: ['detail 1', 'detail 2']
- },
- {
- value: 'jsmith',
- title: 'Joe Smith',
- details: ['detail 1', 'detail 2']
- }
- ];
- this.picker.render();
- this.picker.set('results', results);
-
- var another_picker = new Y.lazr.picker.Picker();
- another_picker.render();
- another_picker.set('results', results);
-
- var bb = this.picker.get('boundingBox');
- var picker_entry = bb.one('.yui3-picker-results li');
- var picker_expander = picker_entry.expander;
- picker_expander.icon_node.simulate('click');
-
- bb = another_picker.get('boundingBox');
- var another_picker_entry = bb.one('.yui3-picker-results li');
- var another_picker_expander = another_picker_entry.expander;
- another_picker_expander.icon_node.simulate('click');
-
- Y.Assert.isTrue(picker_expander.isExpanded());
- Y.Assert.isTrue(another_picker_expander.isExpanded());
- cleanup_widget(another_picker);
- },
-
- test_details_save_link: function () {
- // The select link the li's details saves the selection.
- this.picker.render();
- this.picker.set('results', [
- {
- css: 'yui3-blah-blue',
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx',
- alt_title_link: 'http://somewhereelse.com',
- link_css: 'cool-style',
- details: ['Member since 2007']
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var link_node = bb.one('a.save');
- Assert.areEqual('Select Joe Schmo', link_node.get('text'));
- Assert.isTrue(link_node.get('href').indexOf(window.location) === 0);
- var selected_value = null;
- this.picker.subscribe('save', function(e) {
- selected_value = e.details[0].value;
- }, this);
- simulate(bb, 'a.save', 'click');
- Assert.areEqual('jschmo', selected_value);
- },
-
- test_title_badges: function () {
- this.picker.render();
- var badge_info = [
- {
- url: '../../lazr/assets/skins/sam/search.png',
- label: 'product 1',
- role: 'driver'},
- { url: '../../lazr/assets/skins/sam/spinner.png',
- label: 'product 2',
- role: 'maintainer'},
- { url: '../../lazr/assets/skins/sam/spinner.png',
- label: 'product 2',
- role: 'driver'
- }];
- this.picker.set('results', [
- {
- badges: badge_info,
- css: 'yui3-blah-blue',
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var li = bb.one('.yui3-picker-results li');
- var i;
- for (i=0; i<badge_info.length; i++) {
- var img_node = li.one(
- 'div.badge img.badge:nth-child(' + (i + 1) + ')');
- // Check that duplicate badge urls are not displayed.
- if (i===2) {
- Assert.isNull(img_node);
- break;
- }
- Assert.areEqual(
- badge_info[i].url, img_node.getAttribute('src'),
- 'Unexpected badge url');
- var badge_text = badge_info[i].label + ' ' + badge_info[i].role;
- Assert.areEqual(
- badge_text, img_node.get('alt'),
- 'Unexpected badge alt text');
- }
- },
-
- test_details_badges: function () {
- // The affiliation details are rendered correctly in the content node
- // of the expander.
- this.picker.render();
- var badge_info = [
- {
- url: '../../lazr/assets/skins/sam/spinner.png',
- label: 'product 1',
- role: 'maintainer'},
- {
- url: '../../lazr/assets/skins/sam/search.png',
- label: 'product 2',
- role: 'driver'}];
- this.picker.set('results', [
- {
- badges: badge_info,
- css: 'yui3-blah-blue',
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var li = bb.one('.yui3-picker-results li');
- var details = li.expander.content_node;
- var affiliation_header = details.one('div.affiliation:nth-child(1)');
- Assert.areEqual('Affiliation', affiliation_header.get('text'));
- var badge_img = affiliation_header.one('img');
- Assert.areEqual('product 1 maintainer', badge_img.get('alt'));
- Assert.areEqual(
- '../../lazr/assets/skins/sam/spinner.png',
- badge_img.getAttribute('src'));
- affiliation_header = details.one('div.affiliation:nth-child(3)');
- badge_img = affiliation_header.one('img');
- Assert.areEqual('product 2 driver', badge_img.get('alt'));
- Assert.areEqual(
- '../../lazr/assets/skins/sam/search.png',
- badge_img.getAttribute('src'));
- var affiliation_text = details.one(
- 'div.affiliation-text:nth-child(2)');
- Assert.areEqual(
- 'product 1 maintainer', affiliation_text.get('innerHTML'));
- affiliation_text = details.one('div.affiliation-text:nth-child(4)');
- Assert.areEqual(
- 'product 2 driver', affiliation_text.get('innerHTML'));
- },
-
- test_results_display_escaped: function () {
- this.picker.render();
- this.picker.set('results', [
- {
- image: '<script>throw "back";</script>',
- css: 'yui3-blah-blue',
- value: '<script>throw "wobbly";</script>',
- title: '<script>throw "toys out of pram";</script>',
- description: '<script>throw "up";</script>'
- }
- ]);
- var bb = this.picker.get('boundingBox');
- var li = bb.one('.yui3-picker-results li');
- var image_el = li.one('img');
- Assert.areEqual(
- '<script>throw "back";</script>', image_el.getAttribute('src'),
- "Unexpected image url");
- var title_el = li.one('.yui3-picker-result-title');
- Assert.areEqual(
- '<script>throw "toys out of pram";</script>',
- title_el.get('innerHTML'), 'Unexpected title value.');
- var description_el = li.one('.yui3-picker-result-description');
- Assert.areEqual(
- '<script>throw "up";</script>',
- description_el.get('innerHTML'), 'Unexpected description value.');
- },
-
- test_results_updates_display_with_missing_data: function () {
- this.picker.render();
- var image_url = '../../lazr/assets/skins/sam/search.png';
- this.picker.set('results', [
- { value: 'jschmo', title: 'Joe Schmo' }
- ]);
- var bb = this.picker.get('boundingBox');
- var li = bb.one('.yui3-picker-results li');
- Assert.isNotNull(li, "Results not found.");
- Assert.areEqual(Y.lazr.ui.CSS_EVEN, li.getAttribute('class'));
- Assert.isNull(li.one('img'), "Unexpected image.");
- var description_el = li.one('.yui3-picker-result-description.');
- Assert.isNull(description_el, "Unexpected description element.");
- },
-
- test_render_displays_initial_results: function () {
- this.picker.set('results', [
- {'title': 'Title 1'},
- {'title': 'Title 2'}
- ]);
- this.picker.render();
- var bb = this.picker.get('boundingBox');
- var results = bb.all('.yui3-picker-results li');
- Assert.isNotNull(results, "Results not found.");
- Assert.areEqual(2, results.size());
- },
-
- test_resetting_results_removes_previous_results: function () {
- this.picker.render();
- var bb = this.picker.get('boundingBox');
-
- // First time setting the results.
- this.picker.set('results', [
- {'title': 'Title 1'},
- {'title': 'Title 2'}
- ]);
- var results = bb.all('.yui3-picker-results li');
- Assert.isNotNull(results, "Results not found.");
- Assert.areEqual(2, results.size());
-
- // Second time setting the results.
- this.picker.set('results', [
- {'title': 'Title 1'}
- ]);
- results = bb.all('.yui3-picker-results li');
- Assert.isNotNull(results, "Results not found");
- Assert.areEqual(1, results.size());
- },
-
- test_updateResultsDisplay_adds_even_odd_class: function () {
- this.picker.set('results', [
- {'title': 'Title 1'},
- {'title': 'Title 2'},
- {'title': 'Title 1'},
- {'title': 'Title 2'}
- ]);
- this.picker.render();
- var bb = this.picker.get('boundingBox');
- var results = bb.all('.yui3-picker-results li');
- Assert.isNotNull(results, "Results not found.");
- ArrayAssert.itemsAreEqual(
- [true, false, true, false], results.hasClass(Y.lazr.ui.CSS_EVEN));
- ArrayAssert.itemsAreEqual(
- [false, true, false, true], results.hasClass(Y.lazr.ui.CSS_ODD));
- },
-
- test_clicking_search_button_fires_search_event: function () {
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- var input = bb.one('.yui3-picker-search');
- input.set('value', 'a search');
- var event_has_fired = false;
- this.picker.subscribe('search', function(e) {
- event_has_fired = true;
- Assert.areEqual(
- 'a search', e.details[0],
- 'Search event is missing the search string.');
- }, this);
- simulate(
- this.picker.get('boundingBox'), '.lazr-search.lazr-btn', 'click');
- Assert.isTrue(event_has_fired, "search event wasn't fired");
- },
-
- test_set_search_mode_disables_search_button: function () {
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- this.picker.set('search_mode', true);
- Assert.isTrue(
- bb.one('.lazr-search.lazr-btn').get('disabled'),
- "Search button wasn't disabled.");
- this.picker.set('search_mode', false);
- Assert.isFalse(
- bb.one('.lazr-search.lazr-btn').get('disabled'),
- "Search button wasn't re-enabled.");
- },
-
- test_hitting_enter_in_search_input_fires_search_event: function () {
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- var input = bb.one('.yui3-picker-search');
- input.set('value', 'a search');
- var event_has_fired = false;
- this.picker.subscribe('search', function() {
- event_has_fired = true;
- }, this);
- simulate(
- this.picker.get('boundingBox'), '.yui3-picker-search', 'keydown',
- {keyCode: 13});
- Assert.isTrue(event_has_fired, "search event wasn't fired");
- },
-
- test_search_event_sets_the_in_search_mode: function () {
- this.picker.render();
-
- Assert.isFalse(
- this.picker.get('search_mode'),
- "Widget shouldn't be in search mode.");
- this.picker.fire('search');
- Assert.isTrue(
- this.picker.get('search_mode'),
- "Widget should be in search mode.");
- },
-
- test_search_event_resets_the_current_batch: function () {
- this.picker.render();
- this.picker.set('batches', [
- {value: 'batch1', name: 'Batch 1'},
- {value: 'batch2', name: 'Batch 2'}
- ]);
- this.picker.set('selected_batch', 1);
- Assert.areEqual(1, this.picker.get('selected_batch'));
- this.picker._search_input.set('value', 'bar');
- simulate(
- this.picker.get('boundingBox'), '.lazr-search.lazr-btn', 'click');
-
- // An initial search resets the batch.
- Assert.areEqual(0, this.picker.get('selected_batch'));
-
- // Batch is reset if search term has changed.
- this.picker.set('search_mode', false);
- this.picker.set('selected_batch', 1);
- this.picker._search_input.set('value', 'foo');
- simulate(
- this.picker.get('boundingBox'), '.lazr-search.lazr-btn', 'click');
- Assert.areEqual(0, this.picker.get('selected_batch'));
-
- // Batch is not reset if search term hasn't changed.
- this.picker.set('search_mode', false);
- this.picker.set('selected_batch', 1);
- simulate(
- this.picker.get('boundingBox'), '.lazr-search.lazr-btn', 'click');
- Assert.areEqual(1, this.picker.get('selected_batch'));
- },
-
- test_setting_search_mode: function () {
- // Setting search_mode adds a CSS class and disables the search box.
-
- this.picker.render();
-
- this.picker.set('search_mode', true);
- var bb = this.picker.get('boundingBox');
- Assert.isTrue(
- bb.one('.yui3-picker-search').get('disabled'),
- "Search box should be disabled.");
- Assert.isTrue(
- bb.hasClass('yui3-picker-search-mode'),
- 'Missing CSS class on widget.');
- },
-
- test_unsetting_search_mode: function () {
-
- this.picker.render();
-
- this.picker.set('search_mode', true);
- this.picker.set('search_mode', false);
- var bb = this.picker.get('boundingBox');
- Assert.isFalse(
- bb.one('.yui3-picker-search').get('disabled'),
- "Search input should be enabled.");
- Assert.isFalse(
- bb.hasClass('yui3-picker-search-mode'),
- 'CSS class should be removed from the widget.');
- },
-
- test_set_results_remove_search_mode: function () {
- this.picker.render();
-
- this.picker.set('search_mode', true);
- this.picker.set('results', []);
-
- Assert.isFalse(
- this.picker.get('search_mode'),
- "Widget should be out of search_mode.");
- },
-
- test_set_error: function () {
- // Setting the error property displays the string in the
- // error box and puts an in-error CSS class on the widget.
- this.picker.render();
-
- var error_msg = 'Sorry an <error> occured.';
- this.picker.set('error', error_msg);
-
- var bb = this.picker.get('boundingBox');
- Assert.areEqual(
- error_msg, bb.one('.yui3-picker-error').get('text'),
- "Error message wasn't displayed.");
- Assert.isTrue(
- bb.hasClass('yui3-picker-error-mode'),
- "Missing error-mode class.");
- },
-
- test_set_error_null_clears_ui: function () {
- this.picker.render();
-
- this.picker.set('error', 'Sorry an error occured.');
- this.picker.set('error', null);
- var bb = this.picker.get('boundingBox');
- Assert.areEqual('', bb.one('.yui3-picker-error').get('text'),
- "Error message wasn't cleared.");
- Assert.isFalse(
- bb.hasClass('yui3-picker-error-mode'),
- "error-mode class should be removed.");
- },
-
- test_small_search_sets_error: function () {
- this.picker.render();
- this.picker.set('min_search_chars', 4);
- var bb = this.picker.get('boundingBox');
- var input = bb.one('.yui3-picker-search');
- input.set('value', ' 1 3 '); // 3 characters after trim.
- simulate(
- this.picker.get('boundingBox'), '.lazr-search.lazr-btn', 'click');
- Assert.areEqual(
- "Please enter at least 4 characters.",
- this.picker.get('error'),
- "Error message wasn't displayed.");
- },
-
- test_click_on_result_fire_save_event: function () {
- this.picker.set('results', [
- {'title': 'Object 1', value: 'first'},
- {'title': 'Object 2', value: 'second'}
- ]);
-
- this.picker.render();
-
- var event_has_fired = false;
- this.picker.subscribe('save', function(e) {
- event_has_fired = true;
- Assert.areEqual(
- 'first', e.details[0].value,
- "The event value of the clicked li is wrong.");
- Assert.areEqual(
- 'Object 1', e.details[0].title,
- "The event title of the clicked li is wrong.");
- }, this);
- simulate(
- this.picker.get('boundingBox'),
- '.yui3-picker-results li', 'click');
- Assert.isTrue(event_has_fired, "save event wasn't fired.");
- },
-
- test_cancel_event_hides_widget: function () {
- this.picker.render();
-
- this.picker.fire('cancel', 'bogus');
- Assert.isFalse(
- this.picker.get('visible'), "The widget should be hidden.");
- },
-
- test_cancel_event_resets_search_mode: function () {
- this.picker.render();
- this.picker.set('search_mode', true);
- Assert.isTrue(this.picker.get('search_mode'));
- this.picker.fire('cancel', 'bogus');
- Assert.isFalse(this.picker.get('search_mode'));
- },
-
- test_save_event_hides_widget: function () {
- this.picker.render();
-
- this.picker.fire('save', 'bogus');
- Assert.isFalse(
- this.picker.get('visible'), "The widget should be hidden.");
- },
-
- test_save_event_clears_widget_by_default: function () {
- this.picker.render();
-
- this.picker._search_input.set('value', 'foo');
- this.picker.fire('save', 'bogus');
- Assert.areEqual(
- '', this.picker._search_input.get('value'),
- "The widget hasn't been cleared");
- },
-
- test_save_does_not_clear_widget_when_clear_on_save_is_false: function () {
- picker = new Y.lazr.picker.Picker({clear_on_save: false});
- picker.render();
-
- picker._search_input.set('value', 'foo');
- picker.fire('save', 'bogus');
- Assert.areEqual(
- 'foo', picker._search_input.get('value'),
- "The widget has been cleared but it should not");
- },
-
- test_cancel_event_does_not_clear_widget_by_default: function () {
- this.picker.render();
-
- this.picker._search_input.set('value', 'foo');
- this.picker.fire('cancel', 'bogus');
- Assert.areEqual(
- 'foo', this.picker._search_input.get('value'),
- "The widget has been cleared but it should not");
- },
-
- test_cancel_event_clears_widget_when_clear_on_cancel_true: function () {
- picker = new Y.lazr.picker.Picker({clear_on_cancel: true});
- picker.render();
-
- picker._search_input.set('value', 'foo');
- picker.fire('cancel', 'bogus');
- Assert.areEqual(
- '', picker._search_input.get('value'),
- "The widget hasn't been cleared");
- },
-
- test_search_clears_any_eror: function () {
- this.picker.render();
- this.picker.set('error', "An error");
-
- this.picker.fire('search');
-
- Assert.isNull(
- this.picker.get('error'), 'Error should be cleared.');
-
- },
-
- test_no_search_result_msg: function () {
- this.picker.render();
-
- this.picker.set(
- 'no_results_search_message', "Your query '{query}' sucked.");
- var bb = this.picker.get('boundingBox');
- bb.one('.yui3-picker-search').set('value', 'my <search> string');
- this.picker.set('results', []);
-
- var search_results = bb.one('.yui3-picker-results');
- Assert.areEqual(
- "Your query 'my <search> string' sucked.",
- search_results.get('text'),
- "Empty results message wasn't displayed.");
- Assert.isTrue(
- search_results.hasClass('yui3-picker-no-results'),
- "Missing no-results CSS class.");
- },
-
- test_search_results_clear_no_results_css: function () {
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- bb.one('.yui3-picker-search').set('value', 'my search string');
- this.picker.set('results', []);
-
- this.picker.set('results', [{title: 'Title 1'}, {title: 'Title 2'}]);
- Assert.isFalse(
- bb.one('.yui3-picker-results').hasClass('yui3-picker-no-results'),
- "The no-results CSS class should have been removed.");
- },
-
- test_setting_search_slot_updates_ui: function () {
- this.picker.render();
- var filler = '<span>hello</span>';
- this.picker.set('search_slot', Y.Node.create(filler));
- var bb = this.picker.get('boundingBox');
- var div = bb.one('.yui3-picker-search-slot');
-
- Assert.isNotNull(div, 'Container for form extras not found.');
- Assert.areEqual(filler, div.get('innerHTML'));
- },
-
- test_setting_footer_slot_updates_ui: function () {
- this.picker.render();
- var filler = '<span>foobar</span>';
- this.picker.set('footer_slot', Y.Node.create(filler));
- var bb = this.picker.get('boundingBox');
- var div = bb.one('.yui3-picker-footer-slot');
-
- Assert.isNotNull(div, 'Container for form extras not found.');
- Assert.areEqual(filler, div.get('innerHTML'));
- },
-
- test_setting_batches_updates_ui: function () {
- this.picker.render();
- this.picker.set('batches', [
- {value: 'new', name: 'New'},
- {value: 'assigned', name: 'Assigned'}
- ]);
- var bb = this.picker.get('boundingBox');
- Assert.isNotNull(
- bb.one('.yui3-picker-batches span'),
- "Container for batches not found.");
- var batches = bb.all('.yui3-picker-batches span');
- Assert.isNotNull(batches, "Batches not found");
- Assert.areEqual(2, batches.size());
- ArrayAssert.itemsAreEqual(
- ['New', 'Assigned'],
- batches.get('text'),
- "Batches don't contain batch names.");
- ArrayAssert.itemsAreEqual(
- [true, false],
- batches.hasClass('yui3-picker-selected-batch'),
- "Selected batches missing CSS class.");
-
- Assert.isNotNull(
- bb.one('.yui3-picker-batches .lazr-prev'),
- "There should be a previous button.");
- Assert.isNotNull(
- bb.one('.yui3-picker-batches .lazr-next'),
- "There should be a next button.");
- },
-
- test_simplified_batching_interface: function () {
- this.picker.render();
- this.picker.set('batch_count', 4);
- this.picker.set('results', [
- { value: 'aardvark', title: 'Aardvarks' },
- { value: 'bats', title: 'Bats' },
- { value: 'cats', title: 'Cats' },
- { value: 'dogs', title: 'Dogs' },
- { value: 'emus', title: 'Emus' },
- { value: 'frogs', title: 'Frogs' },
- { value: 'gerbils', title: 'Gerbils' }
- ]);
- var bb = this.picker.get('boundingBox');
- Assert.isNotNull(
- bb.one('.yui3-picker-batches span'),
- "Container for batches not found.");
- var batches = bb.all('.yui3-picker-batches span');
- Assert.isNotNull(batches, "Batches not found");
- Assert.areEqual(4, batches.size());
- ArrayAssert.itemsAreEqual(
- ['1', '2', '3', '4'],
- batches.get('text'),
- "Batches don't contain batch names.");
- ArrayAssert.itemsAreEqual(
- [true, false, false, false],
- batches.hasClass('yui3-picker-selected-batch'),
- "Selected batches missing CSS class.");
-
- Assert.isNotNull(
- bb.one('.yui3-picker-batches .lazr-prev'),
- "There should be a previous button.");
- Assert.isNotNull(
- bb.one('.yui3-picker-batches .lazr-next'),
- "There should be a next button.");
- },
-
- test_clicking_a_batch_item_fires_search_event: function () {
- this.picker.set('current_search_string', 'search');
- this.picker.set('batches', [
- {value: 'item1', name: 'Item 1'},
- {value: 'item2', name: 'Item 2'}
- ]);
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- var event_has_fired = false;
- this.picker.subscribe('search', function(e) {
- event_has_fired = true;
- ArrayAssert.itemsAreEqual(
- ['search', 'item1'], e.details,
- "Search event details should contain search" +
- "string and selected batch");
- }, this);
- simulate(
- this.picker.get('boundingBox'),
- '.yui3-picker-batches span', 'click');
- Assert.isTrue(event_has_fired, "search event wasn't fired.");
- },
-
- test_clicking_a_batch_item_sets_selected_batch: function () {
- this.picker.set('current_search_string', 'search');
- this.picker.set('batches', [
- {value: 'item1', name: 'Item 1'},
- {value: 'item2', name: 'Item 2'}
- ]);
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- Assert.areEqual(
- 0, this.picker.get('selected_batch'),
- "First batch should be selected.");
- simulate(
- this.picker.get('boundingBox'),
- '.yui3-picker-batches span:nth-last-child(2)', 'click');
- Assert.areEqual(
- 1, this.picker.get('selected_batch'),
- "selected_batch should have been updated.");
- },
-
- test_set_selected_batch_updates_css: function () {
- this.picker.render();
- this.picker.set('batches', [
- {value: 'item1', name: '1'},
- {value: 'item2', name: '2'}
- ]);
- Assert.areEqual(
- 0, this.picker.get('selected_batch'),
- "Expected first batch to be selected by default.");
- this.picker.set('selected_batch', 1);
-
- var bb = this.picker.get('boundingBox');
- var batches = bb.all('.yui3-picker-batches span');
- ArrayAssert.itemsAreEqual(
- [false, true],
- batches.hasClass('yui3-picker-selected-batch'),
- "Selected batch missing CSS class.");
- },
-
- test_set_selected_batch_validator: function () {
- this.picker.render();
- this.picker.set('batches', [
- {value: 'item1', name: '1'},
- {value: 'item2', name: '2'}
- ]);
-
- this.picker.set('selected_batch', -1);
- Assert.areEqual(
- 0, this.picker.get('selected_batch'),
- "Negative index shouldn't update selected_batch.");
-
- this.picker.set('selected_batch', 3);
- Assert.areEqual(
- 0, this.picker.get('selected_batch'),
- "Index greather than last batch item shouldn't " +
- "update selected_batch.");
-
- this.picker.set('selected_batch', 'one');
- Assert.areEqual(
- 0, this.picker.get('selected_batch'),
- "Non-integere shouldn't update selected_batch.");
- },
-
- test_prev_button_is_disabled_only_on_first_batch: function () {
- this.picker.set('batches', [
- {value: 'item1', name: '1'},
- {value: 'item2', name: '2'}
- ]);
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- Assert.isTrue(
- bb.one('.lazr-prev').get('disabled'),
- "Previous button should be disabled on first batch.");
-
- this.picker.set('selected_batch', 1);
- Assert.isFalse(
- bb.one('.lazr-prev').get('disabled'),
- "Previous button shouldn't be disabled on last batch.");
- },
-
- test_next_button_is_disabled_only_on_last_batch: function () {
- this.picker.set('batches', [
- {value: 'item1', name: '1'},
- {value: 'item2', name: '2'}
- ]);
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- Assert.isFalse(
- bb.one('.lazr-next').get('disabled'),
- "Next button shouldn't be disabled on first batch.");
-
- this.picker.set('selected_batch', 1);
- Assert.isTrue(
- bb.one('.lazr-next').get('disabled'),
- "Previous button should be disabled on last batch.");
- },
-
- test_click_on_next_button_selects_next_batch: function () {
- this.picker.set('batches', [
- {value: 'item1', name: '1'},
- {value: 'item2', name: '2'},
- {value: 'item3', name: '3'}
- ]);
- this.picker.set('selected_batch', 1);
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- simulate(
- this.picker.get('boundingBox'), '.lazr-next.lazr-btn', 'click');
- Assert.areEqual(
- 2, this.picker.get('selected_batch'),
- "Next batch should have been selected.");
- },
-
- test_click_on_next_button_fires_search_event: function () {
- this.picker.set('current_search_string', 'search');
- this.picker.set('batches', [
- {value: 'item1', name: 'Item 1'},
- {value: 'item2', name: 'Item 2'}
- ]);
- this.picker.render();
-
- var event_has_fired = false;
- this.picker.subscribe('search', function(e) {
- event_has_fired = true;
- ArrayAssert.itemsAreEqual(
- ['search', 'item2'], e.details,
- "Search event details should contain search" +
- "string and selected batch");
- }, this);
- simulate(
- this.picker.get('boundingBox'),
- '.yui3-picker-batches .lazr-next', 'click');
- Assert.isTrue(event_has_fired, "search event wasn't fired.");
- },
-
- test_click_on_prev_button_selects_prev_batch: function () {
- this.picker.set('batches', [
- {value: 'item1', name: '1'},
- {value: 'item2', name: '2'},
- {value: 'item3', name: '3'}
- ]);
- this.picker.set('selected_batch', 1);
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- simulate(
- this.picker.get('boundingBox'), '.lazr-prev.lazr-btn', 'click');
- Assert.areEqual(
- 0, this.picker.get('selected_batch'),
- "Previous batch should have been selected.");
- },
-
- test_click_on_prev_button_fires_search_event: function () {
- this.picker.set('current_search_string', 'search');
- this.picker.set('batches', [
- {value: 'item1', name: 'Item 1'},
- {value: 'item2', name: 'Item 2'}
- ]);
- this.picker.set('selected_batch', 1);
- this.picker.render();
-
- var event_has_fired = false;
- this.picker.subscribe('search', function(e) {
- event_has_fired = true;
- ArrayAssert.itemsAreEqual(
- ['search', 'item1'], e.details,
- "Search event details should contain search" +
- "string and selected batch");
- }, this);
- simulate(
- this.picker.get('boundingBox'),
- '.yui3-picker-batches .lazr-prev', 'click');
- Assert.isTrue(event_has_fired, "search event wasn't fired.");
- },
-
- test_buttons_are_displayed_only_if_there_are_batches: function () {
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- Assert.isNull(
- bb.one('.yui3-picker-batches .lazr-prev'),
- "There should be no previous button.");
- Assert.isNull(
- bb.one('.yui3-picker-batches .lazr-next'),
- "There should be no next button.");
- },
-
- test_text_input_on_footer_can_be_focused: function () {
- this.picker.render();
- this.picker.set('footer_slot', Y.Node.create(
- '<input class="extra-input" name="extra_input" type="text" />'));
- var extra_input = this.picker.get('boundingBox').one('.extra-input');
- var got_focus = false;
- extra_input.on('focus', function(e) {
- got_focus = true;
- });
- extra_input.focus();
- Assert.isTrue(got_focus, "focus didn't go to the extra input.");
- },
-
- test_overlay_progress_value: function () {
- // Setting the progress attribute controls the overlay's
- // green progress bar.
- this.picker.render();
- Assert.areEqual(
- 50,
- this.picker.get('progress'),
- "The picker should start out with progress at 50%.");
-
- this.picker.set('results', [
- {
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- Assert.areEqual(
- 100,
- this.picker.get('progress'),
- "The picker progress should be 100% with results.");
-
- this.picker.set('results', []);
- Assert.areEqual(
- 50,
- this.picker.get('progress'),
- "The picker progress should be 50% without results.");
- },
-
- test_exiting_search_mode_focus_search_box: function () {
- this.picker.render();
- this.picker.set('search_mode', true);
-
- var bb = this.picker.get('boundingBox');
- var search_input = bb.one('.yui3-picker-search');
- var got_focus = false;
- search_input.on('focus', function(e) {
- got_focus = true;
- });
- this.picker.set('search_mode', false);
- Assert.isTrue(got_focus, "focus didn't go to the search input.");
- }
-}));
-
-suite.add(new Y.Test.Case({
-
- name: 'picker_with_filter',
-
- setUp: function() {
- this.picker = new Y.lazr.picker.Picker({
- "selected_value": 'foo',
- "selected_value_metadata": 'foobar',
- "filter_options": [
- {'name': 'ALL',
- 'title': 'All',
- 'description': 'Display all'},
- {'name': 'PROJECT',
- 'title': 'Product',
- 'description': 'Display products'}
- ]
- });
- },
-
- tearDown: function() {
- cleanup_widget(this.picker);
- },
-
- test_picker_has_elements: function () {
- // Test renderUI() adds filter container container to the widget.
- this.picker.render();
-
- var bb = this.picker.get('boundingBox');
- Assert.isNotNull(
- bb.one('.yui3-picker-filter'),
- "Missing filter box.");
- },
-
- _check_filter: function (filter_data) {
- // Check the expected filter links are rendered with the correct data.
- var filter_div = this.picker.get('boundingBox')
- .one('.yui3-picker-filter');
- var i;
- for (i=0; i<filter_data.length; i++) {
- var link = filter_div.one('a:nth-child(' + (i + 1) + ')');
- Assert.isTrue(link.hasClass(filter_data[i].css));
- Assert.areEqual(link.get('text'), filter_data[i].title);
- Assert.areEqual(link.get('title'), filter_data[i].description);
- }
- },
-
- test_no_results_does_not_render_filter: function () {
- // Rendering empty results doesn't render the filter and clears it
- // if it is already visible.
- this.picker.render();
- this.picker._search_input.set('value', 'Joe');
- var filter_div = this.picker.get('boundingBox')
- .one('.yui3-picker-filter');
- // Make the filter visible by rendering some results.
- this.picker.set('results', [
- {
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- Assert.areNotEqual('', filter_div.get('innerHTML'));
- // Reset and render empty results.
- this.picker.set('current_filter_value', null);
- this.picker.set('results', []);
- Assert.areEqual('', filter_div.get('innerHTML'));
- },
-
- test_set_results_renders_filter: function () {
- // Rendering results also renders the filter elements.
- this.picker.render();
- this.picker._search_input.set('value', 'Joe');
- this.picker.set('results', [
- {
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- var filter_div = this.picker.get('boundingBox')
- .one('.yui3-picker-filter');
- Assert.isNotNull(filter_div, "Filter not found");
- Assert.areEqual('Showing All matches for "Joe".' +
- 'Filter by:\u00A0All,\u00A0or\u00A0Product',
- filter_div.get('textContent'));
- this._check_filter([
- {css: 'invalid-link', title: 'All', description: 'Display all'},
- {css: 'js-action', title: 'Product',
- description: 'Display products'}
- ]);
- },
-
- test_filter_search: function () {
- // When a filter link is clicked a new search is performed and the
- // filter is updated.
- this.picker.render();
- this.picker._search_input.set('value', 'Joe');
- this.picker.set('results', [
- {
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- var search_ok = false;
- var picker = this.picker;
- this.picker.subscribe('search', function(e) {
- var search_string = e.details[0];
- var filter_name = e.details[3];
- Assert.areEqual('Joe', search_string);
- Assert.areEqual('PROJECT', filter_name);
- Assert.areEqual('Product', picker.get('current_filter_value'));
- search_ok = true;
- picker.set('results', [
- {
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- });
- var filter_div = this.picker.get('boundingBox')
- .one('.yui3-picker-filter');
- var filter_link = filter_div.one('a:nth-child(2)');
- filter_link.simulate('click');
- Assert.isTrue(search_ok);
- this._check_filter([
- {css: 'js-action', title: 'All', description: 'Display all'},
- {css: 'invalid-link', title: 'Product',
- description: 'Display products'}
- ]);
- },
-
- test_filter_search_no_results: function () {
- // When a filter link is clicked and no results are returned, the
- // filter is still visible.
- this.picker.render();
- this.picker._search_input.set('value', 'Joe');
- this.picker.set('results', [
- {
- value: 'jschmo',
- title: 'Joe Schmo',
- description: 'joe@xxxxxxxxxxx'
- }
- ]);
- var search_ok = false;
- var picker = this.picker;
- this.picker.subscribe('search', function(e) {
- var search_string = e.details[0];
- var filter_name = e.details[3];
- Assert.areEqual('Joe', search_string);
- Assert.areEqual('PROJECT', filter_name);
- Assert.areEqual('Product', picker.get('current_filter_value'));
- search_ok = true;
- picker.set('results', []);
- });
- var filter_div = this.picker.get('boundingBox')
- .one('.yui3-picker-filter');
- var filter_link = filter_div.one('a:nth-child(2)');
- filter_link.simulate('click');
- Assert.isTrue(search_ok);
- this._check_filter([
- {css: 'js-action', title: 'All', description: 'Display all'},
- {css: 'invalid-link', title: 'Product',
- description: 'Display products'}
- ]);
- },
-
- test_search_resets_filter: function () {
- // When a new search is performed the current filter is reset.
- this.picker.render();
- var picker = this.picker;
- var search_ok = false;
- this.picker.set('current_filter_value', 'Product');
- this.picker._search_input.set('value', 'Joe');
- this.picker.subscribe('search', function(e) {
- var search_string = e.details[0];
- var filter_name = e.details[3];
- Assert.areEqual('Joe', search_string);
- Assert.isFalse(Y.Lang.isValue(filter_name));
- Assert.isFalse(
- Y.Lang.isValue(picker.get('current_filter_value')));
- search_ok = true;
- });
- this.picker._search_button.simulate('click');
- Assert.isTrue(search_ok);
- }
-}));
-
-suite.add(new Y.Test.Case({
-
- name: 'picker_text_field_plugin',
-
- setUp: function() {
- this.search_input = Y.Node.create(
- '<input id="field.initval" value="foo"/>');
- Y.one(document.body).appendChild(this.search_input);
- this.picker = new Y.lazr.picker.Picker({
- associated_field_id: 'field.initval'
- });
- },
-
- tearDown: function() {
- cleanup_widget(this.picker);
- this.search_input.remove();
- },
-
- test_TextFieldPickerPlugin_initial_value: function () {
- this.picker.render();
- this.picker.show();
- Assert.areEqual('foo', this.picker._search_input.get('value'));
- },
-
- test_TextFieldPickerPlugin_selected_item_is_saved: function () {
- this.picker.set('results', [{
- 'title': 'Object 1', value: 'first', metadata: 'new_metadata'}]);
- this.picker.render();
- var got_focus = false;
- this.search_input.on('focus', function(e) {
- got_focus = true;
- });
- simulate(
- this.picker.get('boundingBox'),
- '.yui3-picker-results li', 'click');
- Assert.areEqual(
- 'first', Y.one('[id="field.initval"]').get("value"));
- Assert.areEqual(
- 'new_metadata', this.picker.get('selected_value_metadata'));
- Assert.areEqual(
- 'first', this.picker.get('selected_value'));
- Assert.isTrue(got_focus, "focus didn't go to the search input.");
- }
-
-}));
-
-Y.lp.testing.Runner.run(suite);
-
+/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
+
+YUI.add('lp.picker.test', function (Y) {
+ var tests = Y.namespace('lp.picker.test');
+ tests.suite = new Y.Test.Suite('picker Tests');
+
+ // Local aliases
+ var Assert = Y.Assert,
+ ArrayAssert = Y.ArrayAssert;
+
+ /*
+ * A wrapper for the Y.Event.simulate() function. The wrapper accepts
+ * CSS selectors and Node instances instead of raw nodes.
+ */
+ function simulate(widget, selector, evtype, options) {
+ var rawnode = Y.Node.getDOMNode(widget.one(selector));
+ Y.Event.simulate(rawnode, evtype, options);
+ }
+
+ /* Helper function to clean up a dynamically added widget instance. */
+ function cleanup_widget(widget) {
+ // Nuke the boundingBox, but only if we've touched the DOM.
+ if (widget.get('rendered')) {
+ var bb = widget.get('boundingBox');
+ bb.get('parentNode').removeChild(bb);
+ }
+ // Kill the widget itself.
+ widget.destroy();
+ }
+
+ tests.suite.add(new Y.Test.Case({
+ name: 'picker_tests',
+
+ setUp: function() {
+ this.picker = new Y.lazr.picker.Picker({
+ "selected_value": 'foo',
+ "selected_value_metadata": 'foobar'
+ });
+ },
+
+ tearDown: function() {
+ cleanup_widget(this.picker);
+ },
+
+ test_library_exists: function () {
+ Y.Assert.isObject(Y.lazr.picker,
+ "We should be able to locate the lazr.picker module");
+ },
+
+ test_picker_can_be_instantiated: function() {
+ Assert.isInstanceOf(
+ Y.lazr.picker.Picker, this.picker,
+ "Picker failed to be instantiated");
+ },
+
+ test_picker_initialisation: function() {
+ Assert.areEqual('foo', this.picker.get('selected_value'));
+ Assert.areEqual('foobar',
+ this.picker.get('selected_value_metadata'));
+ },
+
+ test_picker_is_stackable: function() {
+ // We should probably define an Assert.hasExtension.
+ Assert.areSame(
+ Y.WidgetStack.prototype.sizeShim, this.picker.sizeShim,
+ "Picker should be stackable.");
+ Assert.areSame(
+ Y.WidgetPositionAlign.prototype.align, this.picker.align,
+ "Picker should be positionable.");
+ },
+
+ test_picker_has_elements: function () {
+ /**
+ * Test that renderUI() adds search box, an error container and a
+ * results container to the widget.
+ * */
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ Assert.isNotNull(
+ bb.one('.yui3-picker-search'),
+ "Missing search box.");
+ Assert.isNotNull(
+ bb.one('.lazr-search.lazr-btn'),
+ "Missing search button.");
+ Assert.isNotNull(
+ bb.one('.yui3-picker-results'),
+ "Missing search results.");
+ Assert.isNotNull(
+ bb.one('.yui3-picker-error'), "Missing error box.");
+ },
+
+ test_set_results_updates_display: function () {
+ this.picker.render();
+ var image_url = '../../lazr/assets/skins/sam/search.png';
+ this.picker.set('results', [
+ {
+ image: image_url,
+ css: 'yui3-blah-blue',
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var li = bb.one('.yui3-picker-results li');
+ Assert.isNotNull(li, "Results not found");
+ Assert.isTrue(li.hasClass('yui3-blah-blue'), "Missing class name.");
+ Assert.isNotNull(li.one('img'), "Missing image.");
+ Assert.areEqual(
+ image_url, li.one('img').getAttribute('src'),
+ "Unexpected image url");
+ var title_el = li.one('.yui3-picker-result-title');
+ Assert.isNotNull(title_el, "Missing title element");
+ Assert.areEqual(
+ 'Joe Schmo', title_el.get('text'), 'Unexpected title value.');
+ var description_el = li.one('.yui3-picker-result-description');
+ Assert.isNotNull(description_el, "Missing description element.");
+ Assert.areEqual(
+ 'joe@xxxxxxxxxxx', description_el.get('text'),
+ 'Unexpected description value.');
+ },
+
+ test_alternate_title_text: function () {
+ this.picker.render();
+ this.picker.set('results', [
+ {
+ css: 'yui3-blah-blue',
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx',
+ alt_title: 'Another Joe'
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var li = bb.one('.yui3-picker-results li');
+ var title_el = li.one('.yui3-picker-result-title');
+ Assert.isNotNull(title_el, "Missing title element");
+ Assert.areEqual('A', title_el.get('tagName'), 'Tab key is broken.');
+ Assert.isTrue(title_el.hasClass('js-action'));
+ Assert.areEqual(
+ 'Joe Schmo\u00a0(Another Joe)', title_el.get('text'),
+ 'Unexpected title value.');
+ },
+
+ test_title_links: function () {
+ this.picker.render();
+ this.picker.set('results', [
+ {
+ css: 'yui3-blah-blue',
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx',
+ alt_title: 'Joe Again <foo></foo>',
+ title_link: 'http://somewhere.com',
+ alt_title_link: 'http://somewhereelse.com',
+ link_css: 'cool-style',
+ details: ['Member since 2007']
+ }
+ ]);
+
+ function check_link(picker, link_selector, title, href) {
+ var bb = picker.get('boundingBox');
+ var link_clicked = false;
+ var link_node = bb.one(link_selector);
+
+ Assert.areEqual(title, link_node.get('text'));
+ Assert.areEqual(href, link_node.get('href'));
+
+ Y.on('click', function(e) {
+ link_clicked = true;
+ }, link_node);
+ simulate(bb, link_selector, 'click');
+ Assert.isTrue(link_clicked,
+ link_selector + ' link was not clicked');
+ }
+ check_link(
+ this.picker, 'a.cool-style:nth-child(1)', 'Joe Schmo',
+ 'http://somewhere.com/');
+ check_link(
+ this.picker, 'a.cool-style:last-child', 'View details',
+ 'http://somewhereelse.com/');
+ var alt_text_node = this.picker.get('boundingBox')
+ .one('.yui3-picker-result-title span');
+ Assert.areEqual('Joe Again <foo></foo>', alt_text_node.get('text'));
+ },
+
+ test_details: function () {
+ // The details of the li is the content node of the expander.
+ this.picker.render();
+ this.picker.set('results', [
+ {
+ css: 'yui3-blah-blue',
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx',
+ details: ['joe on irc.freenode.net', 'Member since 2007'],
+ alt_title_link: '/~jschmo'
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var li = bb.one('.yui3-picker-results li');
+ var expander_action = li.expander.icon_node.get('firstChild');
+ Assert.areEqual(
+ 'A', expander_action.get('tagName'), 'Tab key is broken.');
+ var details = li.expander.content_node;
+ Assert.areEqual(
+ 'joe on irc.freenode.net<br>Member since 2007',
+ details.one('div').getContent());
+ Assert.areEqual(
+ 'Select Joe Schmo',
+ details.one('ul li:first-child').get('text'));
+ Assert.areEqual(
+ 'View details', details.one('ul li:last-child').get('text'));
+ },
+
+ test_details_escaping: function () {
+ // The content of details is escaped.
+ this.picker.render();
+ this.picker.set('results', [
+ {
+ css: 'yui3-blah-blue',
+ value: 'jschmo',
+ title: 'Joe <Schmo>',
+ description: 'joe@xxxxxxxxxxx',
+ details: ['<joe> on irc.freenode.net',
+ 'f<nor>d maintainer'],
+ alt_title_link: '/~jschmo'
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var li = bb.one('.yui3-picker-results li');
+ var details = li.expander.content_node;
+ Assert.areEqual(
+ '<joe> on irc.freenode.net<br>f<nor>d maintainer',
+ details.one('div').getContent());
+ Assert.areEqual(
+ 'Select Joe <Schmo>',
+ details.one('ul li:first-child a').getContent('text'));
+ },
+
+ test_expander_only_one_open: function() {
+ // Only one expanded details entry should be open at any time.
+ this.picker.render();
+ this.picker.set('results', [
+ {
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ details: ['detail 1', 'detail 2']
+ },
+ {
+ value: 'jsmith',
+ title: 'Joe Smith',
+ details: ['detail 1', 'detail 2']
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var first_entry = bb.one('.yui3-picker-results li');
+ var first_expander = first_entry.expander;
+ var second_entry = bb.one('.yui3-picker-results li.yui3-lazr-odd');
+ var second_expander = second_entry.expander;
+ first_expander.icon_node.simulate('click');
+ Y.Assert.isTrue(first_expander.isExpanded());
+ Y.Assert.isFalse(second_expander.isExpanded());
+
+ // Open the other expander and check that the first one has closed.
+ second_expander.icon_node.simulate('click');
+ Y.Assert.isFalse(first_expander.isExpanded());
+ Y.Assert.isTrue(second_expander.isExpanded());
+ },
+
+ test_expander_multiple_pickers: function() {
+ // Expanders for one picker should not interfere with those for
+ // another picker. ie if Picker A expander is opened, any open
+ // expanders on Picker B should remain open.
+ var results = [
+ {
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ details: ['detail 1', 'detail 2']
+ },
+ {
+ value: 'jsmith',
+ title: 'Joe Smith',
+ details: ['detail 1', 'detail 2']
+ }
+ ];
+ this.picker.render();
+ this.picker.set('results', results);
+
+ var another_picker = new Y.lazr.picker.Picker();
+ another_picker.render();
+ another_picker.set('results', results);
+
+ var bb = this.picker.get('boundingBox');
+ var picker_entry = bb.one('.yui3-picker-results li');
+ var picker_expander = picker_entry.expander;
+ picker_expander.icon_node.simulate('click');
+
+ bb = another_picker.get('boundingBox');
+ var another_picker_entry = bb.one('.yui3-picker-results li');
+ var another_picker_expander = another_picker_entry.expander;
+ another_picker_expander.icon_node.simulate('click');
+
+ Y.Assert.isTrue(picker_expander.isExpanded());
+ Y.Assert.isTrue(another_picker_expander.isExpanded());
+ cleanup_widget(another_picker);
+ },
+
+ test_details_save_link: function () {
+ // The select link the li's details saves the selection.
+ this.picker.render();
+ this.picker.set('results', [
+ {
+ css: 'yui3-blah-blue',
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx',
+ alt_title_link: 'http://somewhereelse.com',
+ link_css: 'cool-style',
+ details: ['Member since 2007']
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var link_node = bb.one('a.save');
+ Assert.areEqual('Select Joe Schmo', link_node.get('text'));
+ Assert.isTrue(link_node.get('href').indexOf(window.location) === 0);
+ var selected_value = null;
+ this.picker.subscribe('save', function(e) {
+ selected_value = e.details[0].value;
+ }, this);
+ simulate(bb, 'a.save', 'click');
+ Assert.areEqual('jschmo', selected_value);
+ },
+
+ test_title_badges: function () {
+ this.picker.render();
+ var badge_info = [
+ {
+ url: '../../lazr/assets/skins/sam/search.png',
+ label: 'product 1',
+ role: 'driver'},
+ { url: '../../lazr/assets/skins/sam/spinner.png',
+ label: 'product 2',
+ role: 'maintainer'},
+ { url: '../../lazr/assets/skins/sam/spinner.png',
+ label: 'product 2',
+ role: 'driver'
+ }];
+ this.picker.set('results', [
+ {
+ badges: badge_info,
+ css: 'yui3-blah-blue',
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var li = bb.one('.yui3-picker-results li');
+ var i;
+ for (i=0; i<badge_info.length; i++) {
+ var img_node = li.one(
+ 'div.badge img.badge:nth-child(' + (i + 1) + ')');
+ // Check that duplicate badge urls are not displayed.
+ if (i===2) {
+ Assert.isNull(img_node);
+ break;
+ }
+ Assert.areEqual(
+ badge_info[i].url, img_node.getAttribute('src'),
+ 'Unexpected badge url');
+ var badge_text = badge_info[i].label + ' ' + badge_info[i].role;
+ Assert.areEqual(
+ badge_text, img_node.get('alt'),
+ 'Unexpected badge alt text');
+ }
+ },
+
+ test_details_badges: function () {
+ // The affiliation details are rendered correctly in the content
+ // node of the expander.
+ this.picker.render();
+ var badge_info = [
+ {
+ url: '../../lazr/assets/skins/sam/spinner.png',
+ label: 'product 1',
+ role: 'maintainer'},
+ {
+ url: '../../lazr/assets/skins/sam/search.png',
+ label: 'product 2',
+ role: 'driver'}];
+ this.picker.set('results', [
+ {
+ badges: badge_info,
+ css: 'yui3-blah-blue',
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var li = bb.one('.yui3-picker-results li');
+ var details = li.expander.content_node;
+ var affiliation_header =
+ details.one('div.affiliation:nth-child(1)');
+ Assert.areEqual('Affiliation', affiliation_header.get('text'));
+ var badge_img = affiliation_header.one('img');
+ Assert.areEqual('product 1 maintainer', badge_img.get('alt'));
+ Assert.areEqual(
+ '../../lazr/assets/skins/sam/spinner.png',
+ badge_img.getAttribute('src'));
+ affiliation_header = details.one('div.affiliation:nth-child(3)');
+ badge_img = affiliation_header.one('img');
+ Assert.areEqual('product 2 driver', badge_img.get('alt'));
+ Assert.areEqual(
+ '../../lazr/assets/skins/sam/search.png',
+ badge_img.getAttribute('src'));
+ var affiliation_text = details.one(
+ 'div.affiliation-text:nth-child(2)');
+ Assert.areEqual(
+ 'product 1 maintainer', affiliation_text.get('innerHTML'));
+ affiliation_text = details.one('div.affiliation-text:nth-child(4)');
+ Assert.areEqual(
+ 'product 2 driver', affiliation_text.get('innerHTML'));
+ },
+
+ test_results_display_escaped: function () {
+ this.picker.render();
+ this.picker.set('results', [
+ {
+ image: '<script>throw "back";</script>',
+ css: 'yui3-blah-blue',
+ value: '<script>throw "wobbly";</script>',
+ title: '<script>throw "toys out of pram";</script>',
+ description: '<script>throw "up";</script>'
+ }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var li = bb.one('.yui3-picker-results li');
+ var image_el = li.one('img');
+ Assert.areEqual(
+ '<script>throw "back";</script>', image_el.getAttribute('src'),
+ "Unexpected image url");
+ var title_el = li.one('.yui3-picker-result-title');
+ Assert.areEqual(
+ '<script>throw "toys out of pram";</script>',
+ title_el.get('innerHTML'), 'Unexpected title value.');
+ var description_el = li.one('.yui3-picker-result-description');
+ Assert.areEqual(
+ '<script>throw "up";</script>',
+ description_el.get('innerHTML'),
+ 'Unexpected description value.');
+ },
+
+ test_results_updates_display_with_missing_data: function () {
+ this.picker.render();
+ var image_url = '../../lazr/assets/skins/sam/search.png';
+ this.picker.set('results', [
+ { value: 'jschmo', title: 'Joe Schmo' }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ var li = bb.one('.yui3-picker-results li');
+ Assert.isNotNull(li, "Results not found.");
+ Assert.areEqual(Y.lazr.ui.CSS_EVEN, li.getAttribute('class'));
+ Assert.isNull(li.one('img'), "Unexpected image.");
+ var description_el = li.one('.yui3-picker-result-description.');
+ Assert.isNull(description_el, "Unexpected description element.");
+ },
+
+ test_render_displays_initial_results: function () {
+ this.picker.set('results', [
+ {'title': 'Title 1'},
+ {'title': 'Title 2'}
+ ]);
+ this.picker.render();
+ var bb = this.picker.get('boundingBox');
+ var results = bb.all('.yui3-picker-results li');
+ Assert.isNotNull(results, "Results not found.");
+ Assert.areEqual(2, results.size());
+ },
+
+ test_resetting_results_removes_previous_results: function () {
+ this.picker.render();
+ var bb = this.picker.get('boundingBox');
+
+ // First time setting the results.
+ this.picker.set('results', [
+ {'title': 'Title 1'},
+ {'title': 'Title 2'}
+ ]);
+ var results = bb.all('.yui3-picker-results li');
+ Assert.isNotNull(results, "Results not found.");
+ Assert.areEqual(2, results.size());
+
+ // Second time setting the results.
+ this.picker.set('results', [
+ {'title': 'Title 1'}
+ ]);
+ results = bb.all('.yui3-picker-results li');
+ Assert.isNotNull(results, "Results not found");
+ Assert.areEqual(1, results.size());
+ },
+
+ test_updateResultsDisplay_adds_even_odd_class: function () {
+ this.picker.set('results', [
+ {'title': 'Title 1'},
+ {'title': 'Title 2'},
+ {'title': 'Title 1'},
+ {'title': 'Title 2'}
+ ]);
+ this.picker.render();
+ var bb = this.picker.get('boundingBox');
+ var results = bb.all('.yui3-picker-results li');
+ Assert.isNotNull(results, "Results not found.");
+ ArrayAssert.itemsAreEqual(
+ [true, false, true, false],
+ results.hasClass(Y.lazr.ui.CSS_EVEN));
+ ArrayAssert.itemsAreEqual(
+ [false, true, false, true],
+ results.hasClass(Y.lazr.ui.CSS_ODD));
+ },
+
+ test_clicking_search_button_fires_search_event: function () {
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ var input = bb.one('.yui3-picker-search');
+ input.set('value', 'a search');
+ var event_has_fired = false;
+ this.picker.subscribe('search', function(e) {
+ event_has_fired = true;
+ Assert.areEqual(
+ 'a search', e.details[0],
+ 'Search event is missing the search string.');
+ }, this);
+ simulate(
+ this.picker.get('boundingBox'),
+ '.lazr-search.lazr-btn',
+ 'click');
+ Assert.isTrue(event_has_fired, "search event wasn't fired");
+ },
+
+ test_set_search_mode_disables_search_button: function () {
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ this.picker.set('search_mode', true);
+ Assert.isTrue(
+ bb.one('.lazr-search.lazr-btn').get('disabled'),
+ "Search button wasn't disabled.");
+ this.picker.set('search_mode', false);
+ Assert.isFalse(
+ bb.one('.lazr-search.lazr-btn').get('disabled'),
+ "Search button wasn't re-enabled.");
+ },
+
+ test_hitting_enter_in_search_input_fires_search_event: function () {
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ var input = bb.one('.yui3-picker-search');
+ input.set('value', 'a search');
+ var event_has_fired = false;
+ this.picker.subscribe('search', function() {
+ event_has_fired = true;
+ }, this);
+ simulate(
+ this.picker.get('boundingBox'),
+ '.yui3-picker-search',
+ 'keydown',
+ {keyCode: 13});
+ Assert.isTrue(event_has_fired, "search event wasn't fired");
+ },
+
+ test_search_event_sets_the_in_search_mode: function () {
+ this.picker.render();
+
+ Assert.isFalse(
+ this.picker.get('search_mode'),
+ "Widget shouldn't be in search mode.");
+ this.picker.fire('search');
+ Assert.isTrue(
+ this.picker.get('search_mode'),
+ "Widget should be in search mode.");
+ },
+
+ test_search_event_resets_the_current_batch: function () {
+ this.picker.render();
+ this.picker.set('batches', [
+ {value: 'batch1', name: 'Batch 1'},
+ {value: 'batch2', name: 'Batch 2'}
+ ]);
+ this.picker.set('selected_batch', 1);
+ Assert.areEqual(1, this.picker.get('selected_batch'));
+ this.picker._search_input.set('value', 'bar');
+ simulate(
+ this.picker.get('boundingBox'),
+ '.lazr-search.lazr-btn',
+ 'click');
+
+ // An initial search resets the batch.
+ Assert.areEqual(0, this.picker.get('selected_batch'));
+
+ // Batch is reset if search term has changed.
+ this.picker.set('search_mode', false);
+ this.picker.set('selected_batch', 1);
+ this.picker._search_input.set('value', 'foo');
+ simulate(
+ this.picker.get('boundingBox'),
+ '.lazr-search.lazr-btn',
+ 'click');
+ Assert.areEqual(0, this.picker.get('selected_batch'));
+
+ // Batch is not reset if search term hasn't changed.
+ this.picker.set('search_mode', false);
+ this.picker.set('selected_batch', 1);
+ simulate(
+ this.picker.get('boundingBox'),
+ '.lazr-search.lazr-btn',
+ 'click');
+ Assert.areEqual(1, this.picker.get('selected_batch'));
+ },
+
+ test_setting_search_mode: function () {
+ // Setting search_mode adds a CSS class and disables the search box.
+
+ this.picker.render();
+
+ this.picker.set('search_mode', true);
+ var bb = this.picker.get('boundingBox');
+ Assert.isTrue(
+ bb.one('.yui3-picker-search').get('disabled'),
+ "Search box should be disabled.");
+ Assert.isTrue(
+ bb.hasClass('yui3-picker-search-mode'),
+ 'Missing CSS class on widget.');
+ },
+
+ test_unsetting_search_mode: function () {
+
+ this.picker.render();
+
+ this.picker.set('search_mode', true);
+ this.picker.set('search_mode', false);
+ var bb = this.picker.get('boundingBox');
+ Assert.isFalse(
+ bb.one('.yui3-picker-search').get('disabled'),
+ "Search input should be enabled.");
+ Assert.isFalse(
+ bb.hasClass('yui3-picker-search-mode'),
+ 'CSS class should be removed from the widget.');
+ },
+
+ test_set_results_remove_search_mode: function () {
+ this.picker.render();
+
+ this.picker.set('search_mode', true);
+ this.picker.set('results', []);
+
+ Assert.isFalse(
+ this.picker.get('search_mode'),
+ "Widget should be out of search_mode.");
+ },
+
+ test_set_error: function () {
+ // Setting the error property displays the string in the
+ // error box and puts an in-error CSS class on the widget.
+ this.picker.render();
+
+ var error_msg = 'Sorry an <error> occured.';
+ this.picker.set('error', error_msg);
+
+ var bb = this.picker.get('boundingBox');
+ Assert.areEqual(
+ error_msg, bb.one('.yui3-picker-error').get('text'),
+ "Error message wasn't displayed.");
+ Assert.isTrue(
+ bb.hasClass('yui3-picker-error-mode'),
+ "Missing error-mode class.");
+ },
+
+ test_set_error_null_clears_ui: function () {
+ this.picker.render();
+
+ this.picker.set('error', 'Sorry an error occured.');
+ this.picker.set('error', null);
+ var bb = this.picker.get('boundingBox');
+ Assert.areEqual('', bb.one('.yui3-picker-error').get('text'),
+ "Error message wasn't cleared.");
+ Assert.isFalse(
+ bb.hasClass('yui3-picker-error-mode'),
+ "error-mode class should be removed.");
+ },
+
+ test_small_search_sets_error: function () {
+ this.picker.render();
+ this.picker.set('min_search_chars', 4);
+ var bb = this.picker.get('boundingBox');
+ var input = bb.one('.yui3-picker-search');
+ input.set('value', ' 1 3 '); // 3 characters after trim.
+ simulate(
+ this.picker.get('boundingBox'),
+ '.lazr-search.lazr-btn',
+ 'click');
+ Assert.areEqual(
+ "Please enter at least 4 characters.",
+ this.picker.get('error'),
+ "Error message wasn't displayed.");
+ },
+
+ test_click_on_result_fire_save_event: function () {
+ this.picker.set('results', [
+ {'title': 'Object 1', value: 'first'},
+ {'title': 'Object 2', value: 'second'}
+ ]);
+
+ this.picker.render();
+
+ var event_has_fired = false;
+ this.picker.subscribe('save', function(e) {
+ event_has_fired = true;
+ Assert.areEqual(
+ 'first', e.details[0].value,
+ "The event value of the clicked li is wrong.");
+ Assert.areEqual(
+ 'Object 1', e.details[0].title,
+ "The event title of the clicked li is wrong.");
+ }, this);
+ simulate(
+ this.picker.get('boundingBox'),
+ '.yui3-picker-results li', 'click');
+ Assert.isTrue(event_has_fired, "save event wasn't fired.");
+ },
+
+ test_cancel_event_hides_widget: function () {
+ this.picker.render();
+
+ this.picker.fire('cancel', 'bogus');
+ Assert.isFalse(
+ this.picker.get('visible'), "The widget should be hidden.");
+ },
+
+ test_cancel_event_resets_search_mode: function () {
+ this.picker.render();
+ this.picker.set('search_mode', true);
+ Assert.isTrue(this.picker.get('search_mode'));
+ this.picker.fire('cancel', 'bogus');
+ Assert.isFalse(this.picker.get('search_mode'));
+ },
+
+ test_save_event_hides_widget: function () {
+ this.picker.render();
+
+ this.picker.fire('save', 'bogus');
+ Assert.isFalse(
+ this.picker.get('visible'), "The widget should be hidden.");
+ },
+
+ test_save_event_clears_widget_by_default: function () {
+ this.picker.render();
+
+ this.picker._search_input.set('value', 'foo');
+ this.picker.fire('save', 'bogus');
+ Assert.areEqual(
+ '', this.picker._search_input.get('value'),
+ "The widget hasn't been cleared");
+ },
+
+ test_save_does_not_clear_widget_when_clear_on_save_is_false: function () {
+ picker = new Y.lazr.picker.Picker({clear_on_save: false});
+ picker.render();
+
+ picker._search_input.set('value', 'foo');
+ picker.fire('save', 'bogus');
+ Assert.areEqual(
+ 'foo', picker._search_input.get('value'),
+ "The widget has been cleared but it should not");
+ },
+
+ test_cancel_event_does_not_clear_widget_by_default: function () {
+ this.picker.render();
+
+ this.picker._search_input.set('value', 'foo');
+ this.picker.fire('cancel', 'bogus');
+ Assert.areEqual(
+ 'foo', this.picker._search_input.get('value'),
+ "The widget has been cleared but it should not");
+ },
+
+ test_cancel_event_clears_widget_when_clear_on_cancel_true: function () {
+ picker = new Y.lazr.picker.Picker({clear_on_cancel: true});
+ picker.render();
+
+ picker._search_input.set('value', 'foo');
+ picker.fire('cancel', 'bogus');
+ Assert.areEqual(
+ '', picker._search_input.get('value'),
+ "The widget hasn't been cleared");
+ },
+
+ test_search_clears_any_eror: function () {
+ this.picker.render();
+ this.picker.set('error', "An error");
+
+ this.picker.fire('search');
+
+ Assert.isNull(
+ this.picker.get('error'), 'Error should be cleared.');
+
+ },
+
+ test_no_search_result_msg: function () {
+ this.picker.render();
+
+ this.picker.set(
+ 'no_results_search_message', "Your query '{query}' sucked.");
+ var bb = this.picker.get('boundingBox');
+ bb.one('.yui3-picker-search').set('value', 'my <search> string');
+ this.picker.set('results', []);
+
+ var search_results = bb.one('.yui3-picker-results');
+ Assert.areEqual(
+ "Your query 'my <search> string' sucked.",
+ search_results.get('text'),
+ "Empty results message wasn't displayed.");
+ Assert.isTrue(
+ search_results.hasClass('yui3-picker-no-results'),
+ "Missing no-results CSS class.");
+ },
+
+ test_search_results_clear_no_results_css: function () {
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ bb.one('.yui3-picker-search').set('value', 'my search string');
+ this.picker.set('results', []);
+
+ this.picker.set('results',
+ [{title: 'Title 1'},
+ {title: 'Title 2'}]);
+ Assert.isFalse(
+ bb.one('.yui3-picker-results').
+ hasClass('yui3-picker-no-results'),
+ "The no-results CSS class should have been removed.");
+ },
+
+ test_setting_search_slot_updates_ui: function () {
+ this.picker.render();
+ var filler = '<span>hello</span>';
+ this.picker.set('search_slot', Y.Node.create(filler));
+ var bb = this.picker.get('boundingBox');
+ var div = bb.one('.yui3-picker-search-slot');
+
+ Assert.isNotNull(div, 'Container for form extras not found.');
+ Assert.areEqual(filler, div.get('innerHTML'));
+ },
+
+ test_setting_footer_slot_updates_ui: function () {
+ this.picker.render();
+ var filler = '<span>foobar</span>';
+ this.picker.set('footer_slot', Y.Node.create(filler));
+ var bb = this.picker.get('boundingBox');
+ var div = bb.one('.yui3-picker-footer-slot');
+
+ Assert.isNotNull(div, 'Container for form extras not found.');
+ Assert.areEqual(filler, div.get('innerHTML'));
+ },
+
+ test_setting_batches_updates_ui: function () {
+ this.picker.render();
+ this.picker.set('batches', [
+ {value: 'new', name: 'New'},
+ {value: 'assigned', name: 'Assigned'}
+ ]);
+ var bb = this.picker.get('boundingBox');
+ Assert.isNotNull(
+ bb.one('.yui3-picker-batches span'),
+ "Container for batches not found.");
+ var batches = bb.all('.yui3-picker-batches span');
+ Assert.isNotNull(batches, "Batches not found");
+ Assert.areEqual(2, batches.size());
+ ArrayAssert.itemsAreEqual(
+ ['New', 'Assigned'],
+ batches.get('text'),
+ "Batches don't contain batch names.");
+ ArrayAssert.itemsAreEqual(
+ [true, false],
+ batches.hasClass('yui3-picker-selected-batch'),
+ "Selected batches missing CSS class.");
+
+ Assert.isNotNull(
+ bb.one('.yui3-picker-batches .lazr-prev'),
+ "There should be a previous button.");
+ Assert.isNotNull(
+ bb.one('.yui3-picker-batches .lazr-next'),
+ "There should be a next button.");
+ },
+
+ test_simplified_batching_interface: function () {
+ this.picker.render();
+ this.picker.set('batch_count', 4);
+ this.picker.set('results', [
+ { value: 'aardvark', title: 'Aardvarks' },
+ { value: 'bats', title: 'Bats' },
+ { value: 'cats', title: 'Cats' },
+ { value: 'dogs', title: 'Dogs' },
+ { value: 'emus', title: 'Emus' },
+ { value: 'frogs', title: 'Frogs' },
+ { value: 'gerbils', title: 'Gerbils' }
+ ]);
+ var bb = this.picker.get('boundingBox');
+ Assert.isNotNull(
+ bb.one('.yui3-picker-batches span'),
+ "Container for batches not found.");
+ var batches = bb.all('.yui3-picker-batches span');
+ Assert.isNotNull(batches, "Batches not found");
+ Assert.areEqual(4, batches.size());
+ ArrayAssert.itemsAreEqual(
+ ['1', '2', '3', '4'],
+ batches.get('text'),
+ "Batches don't contain batch names.");
+ ArrayAssert.itemsAreEqual(
+ [true, false, false, false],
+ batches.hasClass('yui3-picker-selected-batch'),
+ "Selected batches missing CSS class.");
+
+ Assert.isNotNull(
+ bb.one('.yui3-picker-batches .lazr-prev'),
+ "There should be a previous button.");
+ Assert.isNotNull(
+ bb.one('.yui3-picker-batches .lazr-next'),
+ "There should be a next button.");
+ },
+
+ test_clicking_a_batch_item_fires_search_event: function () {
+ this.picker.set('current_search_string', 'search');
+ this.picker.set('batches', [
+ {value: 'item1', name: 'Item 1'},
+ {value: 'item2', name: 'Item 2'}
+ ]);
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ var event_has_fired = false;
+ this.picker.subscribe('search', function(e) {
+ event_has_fired = true;
+ ArrayAssert.itemsAreEqual(
+ ['search', 'item1'], e.details,
+ "Search event details should contain search" +
+ "string and selected batch");
+ }, this);
+ simulate(
+ this.picker.get('boundingBox'),
+ '.yui3-picker-batches span', 'click');
+ Assert.isTrue(event_has_fired, "search event wasn't fired.");
+ },
+
+ test_clicking_a_batch_item_sets_selected_batch: function () {
+ this.picker.set('current_search_string', 'search');
+ this.picker.set('batches', [
+ {value: 'item1', name: 'Item 1'},
+ {value: 'item2', name: 'Item 2'}
+ ]);
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ Assert.areEqual(
+ 0, this.picker.get('selected_batch'),
+ "First batch should be selected.");
+ simulate(
+ this.picker.get('boundingBox'),
+ '.yui3-picker-batches span:nth-last-child(2)', 'click');
+ Assert.areEqual(
+ 1, this.picker.get('selected_batch'),
+ "selected_batch should have been updated.");
+ },
+
+ test_set_selected_batch_updates_css: function () {
+ this.picker.render();
+ this.picker.set('batches', [
+ {value: 'item1', name: '1'},
+ {value: 'item2', name: '2'}
+ ]);
+ Assert.areEqual(
+ 0, this.picker.get('selected_batch'),
+ "Expected first batch to be selected by default.");
+ this.picker.set('selected_batch', 1);
+
+ var bb = this.picker.get('boundingBox');
+ var batches = bb.all('.yui3-picker-batches span');
+ ArrayAssert.itemsAreEqual(
+ [false, true],
+ batches.hasClass('yui3-picker-selected-batch'),
+ "Selected batch missing CSS class.");
+ },
+
+ test_set_selected_batch_validator: function () {
+ this.picker.render();
+ this.picker.set('batches', [
+ {value: 'item1', name: '1'},
+ {value: 'item2', name: '2'}
+ ]);
+
+ this.picker.set('selected_batch', -1);
+ Assert.areEqual(
+ 0, this.picker.get('selected_batch'),
+ "Negative index shouldn't update selected_batch.");
+
+ this.picker.set('selected_batch', 3);
+ Assert.areEqual(
+ 0, this.picker.get('selected_batch'),
+ "Index greather than last batch item shouldn't " +
+ "update selected_batch.");
+
+ this.picker.set('selected_batch', 'one');
+ Assert.areEqual(
+ 0, this.picker.get('selected_batch'),
+ "Non-integere shouldn't update selected_batch.");
+ },
+
+ test_prev_button_is_disabled_only_on_first_batch: function () {
+ this.picker.set('batches', [
+ {value: 'item1', name: '1'},
+ {value: 'item2', name: '2'}
+ ]);
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ Assert.isTrue(
+ bb.one('.lazr-prev').get('disabled'),
+ "Previous button should be disabled on first batch.");
+
+ this.picker.set('selected_batch', 1);
+ Assert.isFalse(
+ bb.one('.lazr-prev').get('disabled'),
+ "Previous button shouldn't be disabled on last batch.");
+ },
+
+ test_next_button_is_disabled_only_on_last_batch: function () {
+ this.picker.set('batches', [
+ {value: 'item1', name: '1'},
+ {value: 'item2', name: '2'}
+ ]);
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ Assert.isFalse(
+ bb.one('.lazr-next').get('disabled'),
+ "Next button shouldn't be disabled on first batch.");
+
+ this.picker.set('selected_batch', 1);
+ Assert.isTrue(
+ bb.one('.lazr-next').get('disabled'),
+ "Previous button should be disabled on last batch.");
+ },
+
+ test_click_on_next_button_selects_next_batch: function () {
+ this.picker.set('batches', [
+ {value: 'item1', name: '1'},
+ {value: 'item2', name: '2'},
+ {value: 'item3', name: '3'}
+ ]);
+ this.picker.set('selected_batch', 1);
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ simulate(
+ this.picker.get('boundingBox'), '.lazr-next.lazr-btn', 'click');
+ Assert.areEqual(
+ 2, this.picker.get('selected_batch'),
+ "Next batch should have been selected.");
+ },
+
+ test_click_on_next_button_fires_search_event: function () {
+ this.picker.set('current_search_string', 'search');
+ this.picker.set('batches', [
+ {value: 'item1', name: 'Item 1'},
+ {value: 'item2', name: 'Item 2'}
+ ]);
+ this.picker.render();
+
+ var event_has_fired = false;
+ this.picker.subscribe('search', function(e) {
+ event_has_fired = true;
+ ArrayAssert.itemsAreEqual(
+ ['search', 'item2'], e.details,
+ "Search event details should contain search" +
+ "string and selected batch");
+ }, this);
+ simulate(
+ this.picker.get('boundingBox'),
+ '.yui3-picker-batches .lazr-next', 'click');
+ Assert.isTrue(event_has_fired, "search event wasn't fired.");
+ },
+
+ test_click_on_prev_button_selects_prev_batch: function () {
+ this.picker.set('batches', [
+ {value: 'item1', name: '1'},
+ {value: 'item2', name: '2'},
+ {value: 'item3', name: '3'}
+ ]);
+ this.picker.set('selected_batch', 1);
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ simulate(
+ this.picker.get('boundingBox'), '.lazr-prev.lazr-btn', 'click');
+ Assert.areEqual(
+ 0, this.picker.get('selected_batch'),
+ "Previous batch should have been selected.");
+ },
+
+ test_click_on_prev_button_fires_search_event: function () {
+ this.picker.set('current_search_string', 'search');
+ this.picker.set('batches', [
+ {value: 'item1', name: 'Item 1'},
+ {value: 'item2', name: 'Item 2'}
+ ]);
+ this.picker.set('selected_batch', 1);
+ this.picker.render();
+
+ var event_has_fired = false;
+ this.picker.subscribe('search', function(e) {
+ event_has_fired = true;
+ ArrayAssert.itemsAreEqual(
+ ['search', 'item1'], e.details,
+ "Search event details should contain search" +
+ "string and selected batch");
+ }, this);
+ simulate(
+ this.picker.get('boundingBox'),
+ '.yui3-picker-batches .lazr-prev', 'click');
+ Assert.isTrue(event_has_fired, "search event wasn't fired.");
+ },
+
+ test_buttons_are_displayed_only_if_there_are_batches: function () {
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ Assert.isNull(
+ bb.one('.yui3-picker-batches .lazr-prev'),
+ "There should be no previous button.");
+ Assert.isNull(
+ bb.one('.yui3-picker-batches .lazr-next'),
+ "There should be no next button.");
+ },
+
+ test_text_input_on_footer_can_be_focused: function () {
+ this.picker.render();
+ this.picker.set('footer_slot', Y.Node.create(
+ '<input class="extra-input" name="extra_input" type="text" />'));
+ var extra_input =
+ this.picker.get('boundingBox').one('.extra-input');
+ var got_focus = false;
+ extra_input.on('focus', function(e) {
+ got_focus = true;
+ });
+ extra_input.focus();
+ Assert.isTrue(got_focus, "focus didn't go to the extra input.");
+ },
+
+ test_overlay_progress_value: function () {
+ // Setting the progress attribute controls the overlay's
+ // green progress bar.
+ this.picker.render();
+ Assert.areEqual(
+ 50,
+ this.picker.get('progress'),
+ "The picker should start out with progress at 50%.");
+
+ this.picker.set('results', [
+ {
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ Assert.areEqual(
+ 100,
+ this.picker.get('progress'),
+ "The picker progress should be 100% with results.");
+
+ this.picker.set('results', []);
+ Assert.areEqual(
+ 50,
+ this.picker.get('progress'),
+ "The picker progress should be 50% without results.");
+ },
+
+ test_exiting_search_mode_focus_search_box: function () {
+ this.picker.render();
+ this.picker.set('search_mode', true);
+
+ var bb = this.picker.get('boundingBox');
+ var search_input = bb.one('.yui3-picker-search');
+ var got_focus = false;
+ search_input.on('focus', function(e) {
+ got_focus = true;
+ });
+ this.picker.set('search_mode', false);
+ Assert.isTrue(got_focus, "focus didn't go to the search input.");
+ }
+ }));
+
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'picker_with_filter',
+
+ setUp: function() {
+ this.picker = new Y.lazr.picker.Picker({
+ "selected_value": 'foo',
+ "selected_value_metadata": 'foobar',
+ "filter_options": [
+ {'name': 'ALL',
+ 'title': 'All',
+ 'description': 'Display all'},
+ {'name': 'PROJECT',
+ 'title': 'Product',
+ 'description': 'Display products'}
+ ]
+ });
+ },
+
+ tearDown: function() {
+ cleanup_widget(this.picker);
+ },
+
+ test_picker_has_elements: function () {
+ // Test renderUI() adds filter container container to the widget.
+ this.picker.render();
+
+ var bb = this.picker.get('boundingBox');
+ Assert.isNotNull(
+ bb.one('.yui3-picker-filter'),
+ "Missing filter box.");
+ },
+
+ _check_filter: function (filter_data) {
+ // Check the expected filter links are rendered with the correct
+ // data.
+ var filter_div = this.picker.get('boundingBox')
+ .one('.yui3-picker-filter');
+ var i;
+ for (i=0; i<filter_data.length; i++) {
+ var link = filter_div.one('a:nth-child(' + (i + 1) + ')');
+ Assert.isTrue(link.hasClass(filter_data[i].css));
+ Assert.areEqual(link.get('text'), filter_data[i].title);
+ Assert.areEqual(link.get('title'), filter_data[i].description);
+ }
+ },
+
+ test_no_results_does_not_render_filter: function () {
+ // Rendering empty results doesn't render the filter and clears it
+ // if it is already visible.
+ this.picker.render();
+ this.picker._search_input.set('value', 'Joe');
+ var filter_div = this.picker.get('boundingBox')
+ .one('.yui3-picker-filter');
+ // Make the filter visible by rendering some results.
+ this.picker.set('results', [
+ {
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ Assert.areNotEqual('', filter_div.get('innerHTML'));
+ // Reset and render empty results.
+ this.picker.set('current_filter_value', null);
+ this.picker.set('results', []);
+ Assert.areEqual('', filter_div.get('innerHTML'));
+ },
+
+ test_set_results_renders_filter: function () {
+ // Rendering results also renders the filter elements.
+ this.picker.render();
+ this.picker._search_input.set('value', 'Joe');
+ this.picker.set('results', [
+ {
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ var filter_div = this.picker.get('boundingBox')
+ .one('.yui3-picker-filter');
+ Assert.isNotNull(filter_div, "Filter not found");
+ Assert.areEqual('Showing All matches for "Joe".' +
+ 'Filter by:\u00A0All,\u00A0or\u00A0Product',
+ filter_div.get('textContent'));
+ this._check_filter([
+ {css: 'invalid-link', title: 'All', description: 'Display all'},
+ {css: 'js-action', title: 'Product',
+ description: 'Display products'}
+ ]);
+ },
+
+ test_filter_search: function () {
+ // When a filter link is clicked a new search is performed and the
+ // filter is updated.
+ this.picker.render();
+ this.picker._search_input.set('value', 'Joe');
+ this.picker.set('results', [
+ {
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ var search_ok = false;
+ var picker = this.picker;
+ this.picker.subscribe('search', function(e) {
+ var search_string = e.details[0];
+ var filter_name = e.details[3];
+ Assert.areEqual('Joe', search_string);
+ Assert.areEqual('PROJECT', filter_name);
+ Assert.areEqual('Product', picker.get('current_filter_value'));
+ search_ok = true;
+ picker.set('results', [
+ {
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ });
+ var filter_div = this.picker.get('boundingBox')
+ .one('.yui3-picker-filter');
+ var filter_link = filter_div.one('a:nth-child(2)');
+ filter_link.simulate('click');
+ Assert.isTrue(search_ok);
+ this._check_filter([
+ {css: 'js-action', title: 'All', description: 'Display all'},
+ {css: 'invalid-link', title: 'Product',
+ description: 'Display products'}
+ ]);
+ },
+
+ test_filter_search_no_results: function () {
+ // When a filter link is clicked and no results are returned, the
+ // filter is still visible.
+ this.picker.render();
+ this.picker._search_input.set('value', 'Joe');
+ this.picker.set('results', [
+ {
+ value: 'jschmo',
+ title: 'Joe Schmo',
+ description: 'joe@xxxxxxxxxxx'
+ }
+ ]);
+ var search_ok = false;
+ var picker = this.picker;
+ this.picker.subscribe('search', function(e) {
+ var search_string = e.details[0];
+ var filter_name = e.details[3];
+ Assert.areEqual('Joe', search_string);
+ Assert.areEqual('PROJECT', filter_name);
+ Assert.areEqual('Product', picker.get('current_filter_value'));
+ search_ok = true;
+ picker.set('results', []);
+ });
+ var filter_div = this.picker.get('boundingBox')
+ .one('.yui3-picker-filter');
+ var filter_link = filter_div.one('a:nth-child(2)');
+ filter_link.simulate('click');
+ Assert.isTrue(search_ok);
+ this._check_filter([
+ {css: 'js-action', title: 'All', description: 'Display all'},
+ {css: 'invalid-link', title: 'Product',
+ description: 'Display products'}
+ ]);
+ },
+
+ test_search_resets_filter: function () {
+ // When a new search is performed the current filter is reset.
+ this.picker.render();
+ var picker = this.picker;
+ var search_ok = false;
+ this.picker.set('current_filter_value', 'Product');
+ this.picker._search_input.set('value', 'Joe');
+ this.picker.subscribe('search', function(e) {
+ var search_string = e.details[0];
+ var filter_name = e.details[3];
+ Assert.areEqual('Joe', search_string);
+ Assert.isFalse(Y.Lang.isValue(filter_name));
+ Assert.isFalse(
+ Y.Lang.isValue(picker.get('current_filter_value')));
+ search_ok = true;
+ });
+ this.picker._search_button.simulate('click');
+ Assert.isTrue(search_ok);
+ }
+ }));
+
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'picker_text_field_plugin',
+
+ setUp: function() {
+ this.search_input = Y.Node.create(
+ '<input id="field.initval" value="foo"/>');
+ Y.one(document.body).appendChild(this.search_input);
+ this.picker = new Y.lazr.picker.Picker({
+ associated_field_id: 'field.initval'
+ });
+ },
+
+ tearDown: function() {
+ cleanup_widget(this.picker);
+ this.search_input.remove();
+ },
+
+ test_TextFieldPickerPlugin_initial_value: function () {
+ this.picker.render();
+ this.picker.show();
+ Assert.areEqual('foo', this.picker._search_input.get('value'));
+ },
+
+ test_TextFieldPickerPlugin_selected_item_is_saved: function () {
+ this.picker.set('results', [{
+ title: 'Object 1',
+ value: 'first',
+ metadata: 'new_metadata'}]
+ );
+ this.picker.render();
+ var got_focus = false;
+ this.search_input.on('focus', function(e) {
+ got_focus = true;
+ });
+ simulate(
+ this.picker.get('boundingBox'),
+ '.yui3-picker-results li', 'click');
+ Assert.areEqual(
+ 'first', Y.one('[id="field.initval"]').get("value"));
+ Assert.areEqual(
+ 'new_metadata', this.picker.get('selected_value_metadata'));
+ Assert.areEqual(
+ 'first', this.picker.get('selected_value'));
+ Assert.isTrue(got_focus, "focus didn't go to the search input.");
+ }
+
+ }));
+
+}, '0.1', {
+ 'requires': ['test', 'console', 'lazr.picker', 'event',
+ 'node-event-simulate', 'dump']
});
=== modified file 'lib/lp/app/javascript/picker/tests/test_picker_patcher.html'
--- lib/lp/app/javascript/picker/tests/test_picker_patcher.html 2011-08-10 08:43:17 +0000
+++ lib/lp/app/javascript/picker/tests/test_picker_patcher.html 2012-02-07 16:00:29 +0000
@@ -1,52 +1,83 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+Copyright 2012 Canonical Ltd. This software is licensed under the
+GNU Affero General Public License version 3 (see the file LICENSE).
+-->
+
<html>
<head>
- <title>Launchpad Picker</title>
-
- <!-- YUI and test setup -->
- <script type="text/javascript"
- src="../../../../../canonical/launchpad/icing/yui/yui/yui.js">
- </script>
- <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
- <script type="text/javascript"
- src="../../../../app/javascript/testing/testrunner.js"></script>
-
- <!-- Some required dependencies -->
- <script type="text/javascript" src="../../activator/activator.js"></script>
- <script type="text/javascript" src="../../overlay/overlay.js"></script>
- <script type="text/javascript" src="../../anim/anim.js"></script>
- <script type="text/javascript" src="../../lazr/lazr.js"></script>
- <script type="text/javascript" src="../../client.js"></script>
- <script type="text/javascript" src="../../extras/extras.js"></script>
- <script type="text/javascript" src="../picker_patcher.js"></script>
-
- <!-- The module under test -->
- <script type="text/javascript" src="../picker.js"></script>
- <script type="text/javascript" src="../person_picker.js"></script>
-
- <!-- Testing helpers -->
- <script type="text/javascript" src="../../testing/mockio.js"></script>
-
- <!-- The test suite -->
- <script type="text/javascript" src="test_picker_patcher.js"></script>
-</head>
-<body class="yui3-skin-sam">
- <div class="yui3-widget yui3-activator yui3-activator-focused">
- <span id="picker_id" class="yui3-activator-content yui3-activator-success">
- <span id="pickertest">
- <span>
- A picker widget test
- <button id="edit-pickertest-btn"
- class="lazr-btn yui3-activator-act yui3-activator-hidden">
- Edit
- </button>
- </span>
- <span class="yui3-activator-data-box">
- </span>
- <span class="yui3-activator-message-box yui3-activator-hidden"></span>
- </span>
- </span>
- </div>
-</body>
+ <title>Indicator picker_patcher</title>
+
+ <!-- YUI and test setup -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/yui/yui/yui.js">
+ </script>
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/console-core.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/console/assets/skins/sam/console.css" />
+ <link rel="stylesheet"
+ href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
+
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
+
+ <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
+
+ <!-- Dependencies -->
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/activator/activator.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/overlay/overlay.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/extras/extras.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/anim/anim.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/lazr/lazr.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/client.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/lazr/lazr.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/picker/picker.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/picker/person_picker.js"></script>
+ <script type="text/javascript"
+ src="../../../../../../build/js/lp/app/testing/mockio.js"></script>
+
+ <!-- The module under test. -->
+ <script type="text/javascript" src="../picker_patcher.js"></script>
+
+ <!-- Any css assert for this module. -->
+ <!-- <link rel="stylesheet" href="../assets/picker_patcher-core.css" /> -->
+
+ <!-- The test suite. -->
+ <script type="text/javascript" src="test_picker_patcher.js"></script>
+
+ </head>
+ <body class="yui3-skin-sam">
+ <ul id="suites">
+ <!-- <li>lp.large_indicator.test</li> -->
+ <li>lp.app.picker.test</li>
+ </ul>
+
+ <div class="yui3-widget yui3-activator yui3-activator-focused">
+ <span id="picker_id" class="yui3-activator-content yui3-activator-success">
+ <span id="pickertest">
+ <span>
+ A picker widget test
+ <button id="edit-pickertest-btn"
+ class="lazr-btn yui3-activator-act yui3-activator-hidden">
+ Edit
+ </button>
+ </span>
+ <span class="yui3-activator-data-box">
+ </span>
+ <span class="yui3-activator-message-box yui3-activator-hidden"></span>
+ </span>
+ </span>
+ </div>
+ </body>
</html>
=== modified file 'lib/lp/app/javascript/picker/tests/test_picker_patcher.js'
--- lib/lp/app/javascript/picker/tests/test_picker_patcher.js 2012-02-01 23:40:45 +0000
+++ lib/lp/app/javascript/picker/tests/test_picker_patcher.js 2012-02-07 16:00:29 +0000
@@ -1,636 +1,635 @@
-/* Copyright (c) 2011, Canonical Ltd. All rights reserved. */
-
-YUI().use('lp.testing.runner', 'test', 'console', 'node', 'lp', 'lp.client',
- 'event-focus', 'event-simulate', 'lazr.picker', 'lazr.person-picker',
- 'lp.app.picker', 'node-event-simulate', 'escape', 'event',
- 'lp.testing.mockio',
- function(Y) {
-
-var Assert = Y.Assert;
-
-/*
- * A wrapper for the Y.Event.simulate() function. The wrapper accepts
- * CSS selectors and Node instances instead of raw nodes.
- */
-function simulate(widget, selector, evtype, options) {
- var rawnode = Y.Node.getDOMNode(widget.one(selector));
- Y.Event.simulate(rawnode, evtype, options);
-}
-
-/* Helper function to clean up a dynamically added widget instance. */
-function cleanup_widget(widget) {
- // Nuke the boundingBox, but only if we've touched the DOM.
- if (widget.get('rendered')) {
- var bb = widget.get('boundingBox');
- bb.get('parentNode').removeChild(bb);
- }
- // Kill the widget itself.
- widget.destroy();
- var data_box = Y.one('#picker_id .yui3-activator-data-box');
- var link = data_box.one('a');
- if (link) {
- link.get('parentNode').removeChild(link);
- }
-}
-
-var suite = new Y.Test.Suite("Launchpad Picker Tests");
-
-/*
-* Test cases for a picker with a yesno validation callback.
-*/
-suite.add(new Y.Test.Case({
-
- name: 'picker_yesyno_validation',
-
- setUp: function() {
- this.vocabulary = [
- {"value": "fred", "title": "Fred", "css": "sprite-person",
- "description": "fred@xxxxxxxxxxx", "api_uri": "~/fred",
- "metadata": "person"},
- {"value": "frieda", "title": "Frieda", "css": "sprite-team",
- "description": "frieda@xxxxxxxxxxx", "api_uri": "~/frieda",
- "metadata": "team"}
- ];
- this.picker = null;
- this.text_input = null;
- this.select_menu = null;
- this.saved_picker_value = null;
- this.validation_namespace =
- Y.namespace('lp.app.picker.validation');
- },
-
- tearDown: function() {
- if (this.select_menu !== null) {
- Y.one('body').removeChild(this.select_menu);
- }
- if (this.text_input !== null) {
- Y.one('body').removeChild(this.text_input);
- }
- if (this.picker !== null) {
+/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
+
+YUI.add('lp.app.picker.test', function (Y) {
+
+ var tests = Y.namespace('lp.app.picker.test');
+ var Assert = Y.Assert;
+ tests.suite = new Y.Test.Suite('picker patcher Tests');
+
+ /*
+ * A wrapper for the Y.Event.simulate() function. The wrapper accepts
+ * CSS selectors and Node instances instead of raw nodes.
+ */
+ function simulate(widget, selector, evtype, options) {
+ var rawnode = Y.Node.getDOMNode(widget.one(selector));
+ Y.Event.simulate(rawnode, evtype, options);
+ }
+
+ /* Helper function to clean up a dynamically added widget instance. */
+ function cleanup_widget(widget) {
+ // Nuke the boundingBox, but only if we've touched the DOM.
+ if (widget.get('rendered')) {
+ var bb = widget.get('boundingBox');
+ bb.get('parentNode').removeChild(bb);
+ }
+ // Kill the widget itself.
+ widget.destroy();
+ var data_box = Y.one('#picker_id .yui3-activator-data-box');
+ var link = data_box.one('a');
+ if (link) {
+ link.get('parentNode').removeChild(link);
+ }
+ }
+
+ tests.suite.add(new Y.Test.Case({
+ name: 'picker_yesyno_validation',
+
+ setUp: function() {
+ this.vocabulary = [
+ {"value": "fred", "title": "Fred", "css": "sprite-person",
+ "description": "fred@xxxxxxxxxxx", "api_uri": "~/fred",
+ "metadata": "person"},
+ {"value": "frieda", "title": "Frieda", "css": "sprite-team",
+ "description": "frieda@xxxxxxxxxxx", "api_uri": "~/frieda",
+ "metadata": "team"}
+ ];
+ this.picker = null;
+ this.text_input = null;
+ this.select_menu = null;
+ this.saved_picker_value = null;
+ this.validation_namespace =
+ Y.namespace('lp.app.picker.validation');
+ },
+
+ tearDown: function() {
+ if (this.select_menu !== null) {
+ Y.one('body').removeChild(this.select_menu);
+ }
+ if (this.text_input !== null) {
+ Y.one('body').removeChild(this.text_input);
+ }
+ if (this.picker !== null) {
+ cleanup_widget(this.picker);
+ }
+ this.validation_namespace.show_picker_id = undefined;
+ },
+
+ test_library_exists: function () {
+ Y.Assert.isObject(Y.lp.app.picker,
+ "We should be able to locate the lp.app.picker module");
+ },
+
+ create_picker: function(validate_callback, extra_config) {
+ var config = {
+ "step_title": "Choose someone",
+ "header": "Pick Someone",
+ "null_display_value": "No one",
+ "show_widget_id": "show_picker_id",
+ "validate_callback": validate_callback
+ };
+ if (extra_config !== undefined) {
+ config = Y.merge(extra_config, config);
+ }
+ this.picker = Y.lp.app.picker.addPickerPatcher(
+ this.vocabulary,
+ "foo/bar",
+ "test_link",
+ "picker_id",
+ config);
+ var self = this;
+ this.picker.subscribe('save', function(e) {
+ self.saved_picker_value =
+ e.details[Y.lazr.picker.Picker.SAVE_RESULT].api_uri;
+ });
+ },
+
+ create_picker_direct: function(associated_field) {
+ this.picker = Y.lp.app.picker.create(
+ this.vocabulary,
+ undefined,
+ associated_field);
+ var self = this;
+ this.picker.subscribe('save', function(e) {
+ self.saved_picker_value =
+ e.details[Y.lazr.picker.Picker.SAVE_RESULT].api_uri;
+ });
+ },
+
+ test_picker_can_be_instantiated: function() {
+ // The picker can be instantiated.
+ this.create_picker();
+ Assert.isInstanceOf(
+ Y.lazr.picker.Picker, this.picker,
+ "Picker failed to be instantiated");
+ },
+
+ // A validation callback stub. Instead of going to the server to see if
+ // a picker value requires confirmation, we compare it to a known value.
+ yesno_validate_callback: function(expected_value) {
+ return function(picker, value, save_fn, cancel_fn) {
+ Assert.areEqual(
+ expected_value, value.api_uri, "unexpected picker value");
+ if (value === null) {
+ return true;
+ }
+ var requires_confirmation = value.api_uri !== "~/fred";
+ if (requires_confirmation) {
+ var yesno_content = "<p>Confirm selection</p>";
+ Y.lp.app.picker.yesno_save_confirmation(
+ picker, yesno_content, "Yes", "No",
+ save_fn, cancel_fn);
+ } else {
+ save_fn();
+ }
+ };
+ },
+
+ test_no_confirmation_required: function() {
+ // The picker saves the selected value if no confirmation
+ // is required.
+ this.create_picker(this.yesno_validate_callback("~/fred"));
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(1)', 'click');
+ Assert.areEqual('~/fred', this.saved_picker_value);
+ },
+
+ test_TextFieldPickerPlugin_selected_item_is_saved: function () {
+ // The picker saves the selected value to its associated
+ // textfield if one is defined.
+ this.text_input = Y.Node.create(
+ '<input id="field.testfield" value="foo" />');
+ Y.one(document.body).appendChild(this.text_input);
+ this.create_picker_direct('field.testfield');
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+ var got_focus = false;
+ this.text_input.on('focus', function(e) {
+ got_focus = true;
+ });
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ Assert.areEqual(
+ 'frieda', Y.one('[id="field.testfield"]').get("value"));
+ Assert.areEqual('team', this.picker.get('selected_value_metadata'));
+ Assert.isTrue(got_focus, "focus didn't go to the search input.");
+ },
+
+ test_navigation_renders_after_results: function () {
+ // We modify the base picker to show the batch navigation below the
+ // picker results.
+ this.create_picker();
+ this.picker.set('results', this.vocabulary);
+ var results_box = this.picker._results_box;
+ var batch_box = this.picker._batches_box;
+ Assert.areEqual(results_box.next(), batch_box);
+ },
+
+ test_extra_no_results_message: function () {
+ // If "extra_no_results_message" is defined, it is rendered in the
+ // footer slot when there are no results.
+ this.create_picker(
+ undefined, {'extra_no_results_message': 'message'});
+ this.picker.set('results', []);
+ var footer_slot = this.picker.get('footer_slot');
+ Assert.areEqual('message', footer_slot.get('text'));
+ },
+
+ test_footer_node_preserved_without_extra_no_results_message: function () {
+ // If "extra_no_results_message" is not defined, the footer slot node
+ // should be preserved.
+ this.create_picker();
+ var footer_node = Y.Node.create("<span>foobar</span>");
+ this.picker.set('footer_slot', footer_node);
+ this.picker.set('results', []);
+ var footer_slot = this.picker.get('footer_slot');
+ Assert.areEqual('foobar', footer_slot.get('text'));
+ },
+
+ test_confirmation_yes: function() {
+ // The picker saves the selected value if the user answers
+ // "Yes" to a confirmation request.
+ // The validator is specified using the picker's config object.
+ this.create_picker(this.yesno_validate_callback("~/frieda"));
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
+
+ simulate(
+ yesno, 'button:nth-child(1)', 'click');
+ Assert.areEqual('~/frieda', this.saved_picker_value);
+ },
+
+ test_confirmation_yes_namespace_validator: function() {
+ // The picker saves the selected value if the user answers
+ // "Yes" to a confirmation request.
+ // The validator is specified using the validation namespace.
+ this.validation_namespace.show_picker_id =
+ [this.yesno_validate_callback("~/frieda")];
+
+ this.create_picker();
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
+
+ simulate(
+ yesno, 'button:nth-child(1)', 'click');
+ Assert.areEqual('~/frieda', this.saved_picker_value);
+ },
+
+ test_confirmation_no: function() {
+ // The picker doesn't save the selected value if the user answers
+ // "No" to a confirmation request.
+ this.create_picker(this.yesno_validate_callback("~/frieda"));
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
+ simulate(
+ yesno, 'button:nth-child(2)', 'click');
+ Assert.isNull(this.saved_picker_value);
+ },
+
+ // Helper function for multiple (2) validators.
+ choose_all_yes: function() {
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
+ // Click the Yes button.
+ simulate(yesno, 'button:nth-child(1)', 'click');
+ yesno = this.picker.get('contentBox').one('.extra-form-buttons');
+ // Click the Yes button.
+ simulate(yesno, 'button:nth-child(1)', 'click');
+ Assert.areEqual('~/frieda', this.saved_picker_value);
+ },
+
+ test_multi_validators_config_and_ns_all_yes: function() {
+ // Set up a picker with 2 validators, one via the config and one via
+ // the namespace.
+
+ // The picker saves the selected value if the user answers
+ // "Yes" to all confirmation request.
+ this.validation_namespace.show_picker_id =
+ this.yesno_validate_callback("~/frieda");
+ this.create_picker(this.yesno_validate_callback("~/frieda"));
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+ this.choose_all_yes();
+ },
+
+ test_multi_validators_via_ns_all_yes: function() {
+ // Set up a picker with 2 validators, both configured via the
+ // namespace.
+
+ // The picker saves the selected value if the user answers
+ // "Yes" to all confirmation request.
+ this.validation_namespace.show_picker_id = [
+ this.yesno_validate_callback("~/frieda"),
+ this.yesno_validate_callback("~/frieda")
+ ];
+ this.create_picker();
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+ this.choose_all_yes();
+ },
+
+ test_multi_validators_via_config_all_yes: function() {
+ // Set up a picker with 2 validators, both configured via the picker
+ // config.
+
+ // The picker saves the selected value if the user answers
+ // "Yes" to all confirmation request.
+ var validators = [
+ this.yesno_validate_callback("~/frieda"),
+ this.yesno_validate_callback("~/frieda")
+ ];
+ this.create_picker(validators);
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+ this.choose_all_yes();
+ },
+
+ test_chained_validators_one_no: function() {
+ // The picker doesn't save the selected value if the user answers
+ // "No" to any one of the confirmation requests.
+ this.validation_namespace.show_picker_id = [
+ this.yesno_validate_callback("~/frieda"),
+ this.yesno_validate_callback("~/frieda")];
+
+ this.create_picker();
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
+ // Click the Yes button.
+ simulate(yesno, 'button:nth-child(1)', 'click');
+ yesno = this.picker.get('contentBox').one('.extra-form-buttons');
+ // Click the No button.
+ simulate(yesno, 'button:nth-child(2)', 'click');
+ Assert.isNull(this.saved_picker_value);
+ },
+
+ test_connect_select_menu: function() {
+ // connect_select_menu() connects the select menu's onchange event to
+ // copy the selected value to the text input field.
+ this.text_input = Y.Node.create(
+ '<input id="field.testfield" value="foo" />');
+ var node = Y.one(document.body).appendChild(this.text_input);
+ this.select_menu = Y.Node.create(
+ '<select id="field.testfield-suggestions"> ' +
+ ' <option value="">Did you mean...</option>' +
+ ' <option value="fnord">Fnord Snarf (fnord)</option>' +
+ '</select>');
+ Y.one('body').appendChild(this.select_menu);
+ var select_menu = Y.DOM.byId('field.testfield-suggestions');
+ var text_input = Y.DOM.byId('field.testfield');
+ Y.lp.app.picker.connect_select_menu(select_menu, text_input);
+ select_menu.selectedIndex = 1;
+ Y.Event.simulate(select_menu, 'change');
+ Assert.areEqual(
+ 'fnord', text_input.value,
+ "Select menu's onchange handler failed.");
+ },
+
+ test_privacy_warning: function () {
+ //tests that the specific public_private warning version of yesno
+ //works.
+ var overridden_privacy_callback = function (
+ picker, value, save_fn, cancel_fn) {
+ window.LP = { cache: {} };
+ LP.cache.context = { private: false };
+ Y.lp.client.Launchpad = function() {};
+ Y.lp.client.Launchpad.prototype.get = function(uri, config) {
+ var person = {
+ get: function (key) {
+ return true;
+ }
+ };
+ config.on.success(person);
+ };
+
+ Y.lp.app.picker.public_private_warning(
+ picker, value, save_fn, cancel_fn);
+ };
+
+ this.create_picker(overridden_privacy_callback);
+ this.picker.set('results', this.vocabulary);
+ this.picker.render();
+
+ simulate(
+ this.picker.get('boundingBox').one('.yui3-picker-results'),
+ 'li:nth-child(2)', 'click');
+ // expected_text is a little weird since breaks between p tags and
+ // buttons are lost.
+ var expected_text = 'This action will reveal this team\'s name to ' +
+ 'the public.ContinueChoose Again';
+ var text = Y.one(".validation-node").get('text');
+ Assert.areEqual(expected_text, text);
+ }
+
+ }));
+
+ /*
+ * Test cases for a picker with a large vocabulary.
+ */
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'picker_large_vocabulary',
+
+ setUp: function() {
+ var i;
+ this.vocabulary = new Array(121);
+ for (i = 0; i < 121; i++) {
+ this.vocabulary[i] = {
+ "value": "value-" + i,
+ "title": "title-" + i,
+ "css": "sprite-person",
+ "description": "description-" + i,
+ "api_uri": "~/fred-" + i};
+ }
+ },
+
+ tearDown: function() {
cleanup_widget(this.picker);
- }
- this.validation_namespace.show_picker_id = undefined;
- },
+ },
- create_picker: function(validate_callback, extra_config) {
- var config = {
+ create_picker: function(show_search_box, extra_config) {
+ var config = {
"step_title": "Choose someone",
"header": "Pick Someone",
- "null_display_value": "No one",
- "show_widget_id": "show_picker_id",
- "validate_callback": validate_callback
- };
- if (extra_config !== undefined) {
- config = Y.merge(extra_config, config);
- }
- this.picker = Y.lp.app.picker.addPickerPatcher(
- this.vocabulary,
- "foo/bar",
- "test_link",
- "picker_id",
- config);
- var self = this;
- this.picker.subscribe('save', function(e) {
- self.saved_picker_value =
- e.details[Y.lazr.picker.Picker.SAVE_RESULT].api_uri;
- });
- },
-
- create_picker_direct: function(associated_field) {
- this.picker = Y.lp.app.picker.create(
- this.vocabulary,
- undefined,
- associated_field);
- var self = this;
- this.picker.subscribe('save', function(e) {
- self.saved_picker_value =
- e.details[Y.lazr.picker.Picker.SAVE_RESULT].api_uri;
- });
- },
-
- test_picker_can_be_instantiated: function() {
- // The picker can be instantiated.
- this.create_picker();
- Assert.isInstanceOf(
- Y.lazr.picker.Picker, this.picker,
- "Picker failed to be instantiated");
- },
-
- // A validation callback stub. Instead of going to the server to see if
- // a picker value requires confirmation, we compare it to a known value.
- yesno_validate_callback: function(expected_value) {
- return function(picker, value, save_fn, cancel_fn) {
- Assert.areEqual(
- expected_value, value.api_uri, "unexpected picker value");
- if (value === null) {
- return true;
- }
- var requires_confirmation = value.api_uri !== "~/fred";
- if (requires_confirmation) {
- var yesno_content = "<p>Confirm selection</p>";
- Y.lp.app.picker.yesno_save_confirmation(
- picker, yesno_content, "Yes", "No",
- save_fn, cancel_fn);
- } else {
- save_fn();
- }
- };
- },
-
- test_no_confirmation_required: function() {
- // The picker saves the selected value if no confirmation
- // is required.
- this.create_picker(this.yesno_validate_callback("~/fred"));
- this.picker.set('results', this.vocabulary);
- this.picker.render();
-
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(1)', 'click');
- Assert.areEqual('~/fred', this.saved_picker_value);
- },
-
- test_TextFieldPickerPlugin_selected_item_is_saved: function () {
- // The picker saves the selected value to its associated
- // textfield if one is defined.
- this.text_input = Y.Node.create(
- '<input id="field.testfield" value="foo" />');
- Y.one(document.body).appendChild(this.text_input);
- this.create_picker_direct('field.testfield');
- this.picker.set('results', this.vocabulary);
- this.picker.render();
- var got_focus = false;
- this.text_input.on('focus', function(e) {
- got_focus = true;
- });
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- Assert.areEqual(
- 'frieda', Y.one('[id="field.testfield"]').get("value"));
- Assert.areEqual('team', this.picker.get('selected_value_metadata'));
- Assert.isTrue(got_focus, "focus didn't go to the search input.");
- },
-
- test_navigation_renders_after_results: function () {
- // We modify the base picker to show the batch navigation below the
- // picker results.
- this.create_picker();
- this.picker.set('results', this.vocabulary);
- var results_box = this.picker._results_box;
- var batch_box = this.picker._batches_box;
- Assert.areEqual(results_box.next(), batch_box);
- },
-
- test_extra_no_results_message: function () {
- // If "extra_no_results_message" is defined, it is rendered in the
- // footer slot when there are no results.
- this.create_picker(
- undefined, {'extra_no_results_message': 'message'});
- this.picker.set('results', []);
- var footer_slot = this.picker.get('footer_slot');
- Assert.areEqual('message', footer_slot.get('text'));
- },
-
- test_footer_node_preserved_without_extra_no_results_message: function () {
- // If "extra_no_results_message" is not defined, the footer slot node
- // should be preserved.
- this.create_picker();
- var footer_node = Y.Node.create("<span>foobar</span>");
- this.picker.set('footer_slot', footer_node);
- this.picker.set('results', []);
- var footer_slot = this.picker.get('footer_slot');
- Assert.areEqual('foobar', footer_slot.get('text'));
- },
-
- test_confirmation_yes: function() {
- // The picker saves the selected value if the user answers
- // "Yes" to a confirmation request.
- // The validator is specified using the picker's config object.
- this.create_picker(this.yesno_validate_callback("~/frieda"));
- this.picker.set('results', this.vocabulary);
- this.picker.render();
-
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
-
- simulate(
- yesno, 'button:nth-child(1)', 'click');
- Assert.areEqual('~/frieda', this.saved_picker_value);
- },
-
- test_confirmation_yes_namespace_validator: function() {
- // The picker saves the selected value if the user answers
- // "Yes" to a confirmation request.
- // The validator is specified using the validation namespace.
- this.validation_namespace.show_picker_id =
- [this.yesno_validate_callback("~/frieda")];
-
- this.create_picker();
- this.picker.set('results', this.vocabulary);
- this.picker.render();
-
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
-
- simulate(
- yesno, 'button:nth-child(1)', 'click');
- Assert.areEqual('~/frieda', this.saved_picker_value);
- },
-
- test_confirmation_no: function() {
- // The picker doesn't save the selected value if the user answers
- // "No" to a confirmation request.
- this.create_picker(this.yesno_validate_callback("~/frieda"));
- this.picker.set('results', this.vocabulary);
- this.picker.render();
-
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
- simulate(
- yesno, 'button:nth-child(2)', 'click');
- Assert.isNull(this.saved_picker_value);
- },
-
- // Helper function for multiple (2) validators.
- choose_all_yes: function() {
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
- // Click the Yes button.
- simulate(yesno, 'button:nth-child(1)', 'click');
- yesno = this.picker.get('contentBox').one('.extra-form-buttons');
- // Click the Yes button.
- simulate(yesno, 'button:nth-child(1)', 'click');
- Assert.areEqual('~/frieda', this.saved_picker_value);
- },
-
- test_multi_validators_config_and_ns_all_yes: function() {
- // Set up a picker with 2 validators, one via the config and one via
- // the namespace.
-
- // The picker saves the selected value if the user answers
- // "Yes" to all confirmation request.
- this.validation_namespace.show_picker_id =
- this.yesno_validate_callback("~/frieda");
- this.create_picker(this.yesno_validate_callback("~/frieda"));
- this.picker.set('results', this.vocabulary);
- this.picker.render();
- this.choose_all_yes();
- },
-
- test_multi_validators_via_ns_all_yes: function() {
- // Set up a picker with 2 validators, both configured via the
- // namespace.
-
- // The picker saves the selected value if the user answers
- // "Yes" to all confirmation request.
- this.validation_namespace.show_picker_id = [
- this.yesno_validate_callback("~/frieda"),
- this.yesno_validate_callback("~/frieda")
- ];
- this.create_picker();
- this.picker.set('results', this.vocabulary);
- this.picker.render();
- this.choose_all_yes();
- },
-
- test_multi_validators_via_config_all_yes: function() {
- // Set up a picker with 2 validators, both configured via the picker
- // config.
-
- // The picker saves the selected value if the user answers
- // "Yes" to all confirmation request.
- var validators = [
- this.yesno_validate_callback("~/frieda"),
- this.yesno_validate_callback("~/frieda")
- ];
- this.create_picker(validators);
- this.picker.set('results', this.vocabulary);
- this.picker.render();
- this.choose_all_yes();
- },
-
- test_chained_validators_one_no: function() {
- // The picker doesn't save the selected value if the user answers
- // "No" to any one of the confirmation requests.
- this.validation_namespace.show_picker_id = [
- this.yesno_validate_callback("~/frieda"),
- this.yesno_validate_callback("~/frieda")];
-
- this.create_picker();
- this.picker.set('results', this.vocabulary);
- this.picker.render();
-
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- var yesno = this.picker.get('contentBox').one('.extra-form-buttons');
- // Click the Yes button.
- simulate(yesno, 'button:nth-child(1)', 'click');
- yesno = this.picker.get('contentBox').one('.extra-form-buttons');
- // Click the No button.
- simulate(yesno, 'button:nth-child(2)', 'click');
- Assert.isNull(this.saved_picker_value);
- },
-
- test_connect_select_menu: function() {
- // connect_select_menu() connects the select menu's onchange event to
- // copy the selected value to the text input field.
- this.text_input = Y.Node.create(
- '<input id="field.testfield" value="foo" />');
- var node = Y.one(document.body).appendChild(this.text_input);
- this.select_menu = Y.Node.create(
- '<select id="field.testfield-suggestions"> ' +
- ' <option value="">Did you mean...</option>' +
- ' <option value="fnord">Fnord Snarf (fnord)</option>' +
- '</select>');
- Y.one('body').appendChild(this.select_menu);
- var select_menu = Y.DOM.byId('field.testfield-suggestions');
- var text_input = Y.DOM.byId('field.testfield');
- Y.lp.app.picker.connect_select_menu(select_menu, text_input);
- select_menu.selectedIndex = 1;
- Y.Event.simulate(select_menu, 'change');
- Assert.areEqual(
- 'fnord', text_input.value,
- "Select menu's onchange handler failed.");
- },
-
- test_privacy_warning: function () {
- //tests that the specific public_private warning version of yesno
- //works.
- var overridden_privacy_callback = function (
- picker, value, save_fn, cancel_fn) {
- window.LP = { cache: {} };
- LP.cache.context = { private: false };
- Y.lp.client.Launchpad = function() {};
- Y.lp.client.Launchpad.prototype.get = function(uri, config) {
- var person = {
- get: function (key) {
- return true;
+ "validate_callback": null
+ };
+ if (show_search_box !== undefined) {
+ config.show_search_box = show_search_box;
+ }
+ if (extra_config !== undefined) {
+ config = Y.merge(extra_config, config);
+ }
+ this.picker = Y.lp.app.picker.addPickerPatcher(
+ this.vocabulary,
+ "foo/bar",
+ "test_link",
+ "picker_id",
+ config);
+ },
+
+ test_filter_options_initialisation: function() {
+ // Filter options are correctly used to set up the picker.
+ this.picker = Y.lp.app.picker.create(
+ this.vocabulary, undefined, undefined, ['a', 'b', 'c']);
+ Y.ArrayAssert.itemsAreEqual(
+ ['a', 'b', 'c'], this.picker.get('filter_options'));
+ },
+
+ test_picker_displays_empty_list: function() {
+ // With too many results, the results will be empty.
+ this.create_picker(true);
+ this.picker.render();
+ this.picker.set('min_search_chars', 0);
+ this.picker.fire('search', '');
+ var result_text = this.picker.get('contentBox')
+ .one('.yui3-picker-results').get('text');
+ Assert.areEqual('', result_text);
+ },
+
+ test_picker_displays_warning: function() {
+ // With a search box the picker will refuse to display more than
+ // 120 values.
+ this.create_picker(true);
+ this.picker.set('min_search_chars', 0);
+ this.picker.fire('search', '');
+ Assert.areEqual(
+ 'Too many matches. Please try to narrow your search.',
+ this.picker.get('error'));
+ },
+
+ test_picker_displays_warning_by_default: function() {
+ // If show_search_box is not supplied in config, it defaults to true.
+ // Thus the picker will refuse to display more than 120 values.
+ this.create_picker();
+ this.picker.set('min_search_chars', 0);
+ this.picker.fire('search', '');
+ Assert.areEqual(
+ 'Too many matches. Please try to narrow your search.',
+ this.picker.get('error'));
+ },
+
+ test_picker_no_warning: function() {
+ // Without a search box the picker will also display more than
+ // 120 values.
+ this.create_picker(false);
+ this.picker.set('min_search_chars', 0);
+ this.picker.fire('search', '');
+ Assert.areEqual(null, this.picker.get('error'));
+ },
+
+ test_vocab_filter_config: function () {
+ // The vocab filter config is correctly used to create the picker.
+ var filters = [{name: 'ALL', title: 'All', description: 'All'}];
+ this.create_picker(undefined, {'vocabulary_filters': filters});
+ var filter_options = this.picker.get('filter_options');
+ Assert.areEqual(filters, filter_options);
+ }
+ }));
+
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'picker_error_handling',
+
+ setUp: function() {
+ this.create_picker();
+ this.picker.fire('search', 'foo');
+ },
+
+ tearDown: function() {
+ cleanup_widget(this.picker);
+ },
+
+ create_picker: function() {
+ this.mock_io = new Y.lp.testing.mockio.MockIo();
+ this.picker = Y.lp.app.picker.addPickerPatcher(
+ "Foo",
+ "foo/bar",
+ "test_link",
+ "picker_id",
+ {yio: this.mock_io});
+ },
+
+ get_oops_headers: function(oops) {
+ var headers = {};
+ headers['X-Lazr-OopsId'] = oops;
+ return headers;
+ },
+
+ test_oops: function() {
+ // A 500 (ISE) with an OOPS ID informs the user that we've
+ // logged it, and gives them the OOPS ID.
+ this.mock_io.failure(
+ {responseHeaders: this.get_oops_headers('OOPS')});
+ Assert.areEqual(
+ "Sorry, something went wrong with your search. We've recorded " +
+ "what happened, and we'll fix it as soon as possible. " +
+ "(Error ID: OOPS)",
+ this.picker.get('error'));
+ },
+
+ test_timeout: function() {
+ // A 503 (timeout) or 502/504 (proxy error) informs the user
+ // that they should retry, and gives them the OOPS ID.
+ this.mock_io.failure(
+ {status: 503, responseHeaders: this.get_oops_headers('OOPS')});
+ Assert.areEqual(
+ "Sorry, something went wrong with your search. Trying again " +
+ "in a couple of minutes might work. (Error ID: OOPS)",
+ this.picker.get('error'));
+ },
+
+ test_other_error: function() {
+ // Any other type of error just displays a generic failure
+ // message, with no OOPS ID.
+ this.mock_io.failure({status: 400});
+ Assert.areEqual(
+ "Sorry, something went wrong with your search.",
+ this.picker.get('error'));
+ }
+ }));
+
+ tests.suite.add(new Y.Test.Case({
+
+ name: 'picker_automated_search',
+
+ create_picker: function(yio) {
+ var config = {yio: yio};
+ return Y.lp.app.picker.addPickerPatcher(
+ "Foo",
+ "foo/bar",
+ "test_link",
+ "picker_id",
+ config);
+ },
+
+ make_response: function(status, oops, responseText) {
+ if (oops === undefined) {
+ oops = null;
+ }
+ return {
+ status: status,
+ responseText: responseText,
+ getResponseHeader: function(header) {
+ if (header === 'X-Lazr-OopsId') {
+ return oops;
}
- };
- config.on.success(person);
- };
-
- Y.lp.app.picker.public_private_warning(
- picker, value, save_fn, cancel_fn);
- };
-
- this.create_picker(overridden_privacy_callback);
- this.picker.set('results', this.vocabulary);
- this.picker.render();
-
- simulate(
- this.picker.get('boundingBox').one('.yui3-picker-results'),
- 'li:nth-child(2)', 'click');
- // expected_text is a little weird since breaks between p tags and
- // buttons are lost.
- var expected_text = 'This action will reveal this team\'s name to ' +
- 'the public.ContinueChoose Again';
- var text = Y.one(".validation-node").get('text');
- Assert.areEqual(expected_text, text);
- }
-}));
-
-/*
- * Test cases for a picker with a large vocabulary.
- */
-suite.add(new Y.Test.Case({
-
- name: 'picker_large_vocabulary',
-
- setUp: function() {
- var i;
- this.vocabulary = new Array(121);
- for (i = 0; i < 121; i++) {
- this.vocabulary[i] = {
- "value": "value-" + i,
- "title": "title-" + i,
- "css": "sprite-person",
- "description": "description-" + i,
- "api_uri": "~/fred-" + i};
- }
- },
-
- tearDown: function() {
- cleanup_widget(this.picker);
- },
-
- create_picker: function(show_search_box, extra_config) {
- var config = {
- "step_title": "Choose someone",
- "header": "Pick Someone",
- "validate_callback": null
- };
- if (show_search_box !== undefined) {
- config.show_search_box = show_search_box;
- }
- if (extra_config !== undefined) {
- config = Y.merge(extra_config, config);
- }
- this.picker = Y.lp.app.picker.addPickerPatcher(
- this.vocabulary,
- "foo/bar",
- "test_link",
- "picker_id",
- config);
- },
-
- test_filter_options_initialisation: function() {
- // Filter options are correctly used to set up the picker.
- this.picker = Y.lp.app.picker.create(
- this.vocabulary, undefined, undefined, ['a', 'b', 'c']);
- Y.ArrayAssert.itemsAreEqual(
- ['a', 'b', 'c'], this.picker.get('filter_options'));
- },
-
- test_picker_displays_empty_list: function() {
- // With too many results, the results will be empty.
- this.create_picker(true);
- this.picker.render();
- this.picker.set('min_search_chars', 0);
- this.picker.fire('search', '');
- var result_text = this.picker.get('contentBox')
- .one('.yui3-picker-results').get('text');
- Assert.areEqual('', result_text);
- },
-
- test_picker_displays_warning: function() {
- // With a search box the picker will refuse to display more than
- // 120 values.
- this.create_picker(true);
- this.picker.set('min_search_chars', 0);
- this.picker.fire('search', '');
- Assert.areEqual(
- 'Too many matches. Please try to narrow your search.',
- this.picker.get('error'));
- },
-
- test_picker_displays_warning_by_default: function() {
- // If show_search_box is not supplied in config, it defaults to true.
- // Thus the picker will refuse to display more than 120 values.
- this.create_picker();
- this.picker.set('min_search_chars', 0);
- this.picker.fire('search', '');
- Assert.areEqual(
- 'Too many matches. Please try to narrow your search.',
- this.picker.get('error'));
- },
-
- test_picker_no_warning: function() {
- // Without a search box the picker will also display more than
- // 120 values.
- this.create_picker(false);
- this.picker.set('min_search_chars', 0);
- this.picker.fire('search', '');
- Assert.areEqual(null, this.picker.get('error'));
- },
-
- test_vocab_filter_config: function () {
- // The vocab filter config is correctly used to create the picker.
- var filters = [{name: 'ALL', title: 'All', description: 'All'}];
- this.create_picker(undefined, {'vocabulary_filters': filters});
- var filter_options = this.picker.get('filter_options');
- Assert.areEqual(filters, filter_options);
- }
-}));
-
-suite.add(new Y.Test.Case({
-
- name: 'picker_error_handling',
-
- setUp: function() {
- this.create_picker();
- this.picker.fire('search', 'foo');
- },
-
- tearDown: function() {
- cleanup_widget(this.picker);
- },
-
- create_picker: function() {
- this.mock_io = new Y.lp.testing.mockio.MockIo();
- this.picker = Y.lp.app.picker.addPickerPatcher(
- "Foo",
- "foo/bar",
- "test_link",
- "picker_id",
- {yio: this.mock_io});
- },
-
- get_oops_headers: function(oops) {
- var headers = {};
- headers['X-Lazr-OopsId'] = oops;
- return headers;
- },
-
- test_oops: function() {
- // A 500 (ISE) with an OOPS ID informs the user that we've
- // logged it, and gives them the OOPS ID.
- this.mock_io.failure(
- {responseHeaders: this.get_oops_headers('OOPS')});
- Assert.areEqual(
- "Sorry, something went wrong with your search. We've recorded " +
- "what happened, and we'll fix it as soon as possible. " +
- "(Error ID: OOPS)",
- this.picker.get('error'));
- },
-
- test_timeout: function() {
- // A 503 (timeout) or 502/504 (proxy error) informs the user
- // that they should retry, and gives them the OOPS ID.
- this.mock_io.failure(
- {status: 503, responseHeaders: this.get_oops_headers('OOPS')});
- Assert.areEqual(
- "Sorry, something went wrong with your search. Trying again " +
- "in a couple of minutes might work. (Error ID: OOPS)",
- this.picker.get('error'));
- },
-
- test_other_error: function() {
- // Any other type of error just displays a generic failure
- // message, with no OOPS ID.
- this.mock_io.failure({status: 400});
- Assert.areEqual(
- "Sorry, something went wrong with your search.",
- this.picker.get('error'));
- }
-}));
-
-suite.add(new Y.Test.Case({
-
- name: 'picker_automated_search',
-
- create_picker: function(yio) {
- var config = {yio: yio};
- return Y.lp.app.picker.addPickerPatcher(
- "Foo",
- "foo/bar",
- "test_link",
- "picker_id",
- config);
- },
-
- make_response: function(status, oops, responseText) {
- if (oops === undefined) {
- oops = null;
- }
- return {
- status: status,
- responseText: responseText,
- getResponseHeader: function(header) {
- if (header === 'X-Lazr-OopsId') {
- return oops;
}
- }
- };
- },
-
- test_automated_search_results_ignored_if_user_has_searched: function() {
- // If an automated search (like loading branch suggestions) returns
- // results and the user has submitted a search, then the results of
- // the automated search are ignored so as not to confuse the user.
- var mock_io = new Y.lp.testing.mockio.MockIo();
- var picker = this.create_picker(mock_io);
- // First an automated search is run.
- picker.fire('search', 'guess', undefined, true);
- // Then the user initiates their own search.
- picker.fire('search', 'test');
- // Two requests have been sent out.
- Y.Assert.areEqual(2, mock_io.requests.length);
- // Respond to the automated request.
- mock_io.requests[0].respond({responseText: '{"entries": 1}'});
- // ... the results are ignored.
- Assert.areNotEqual(1, picker.get('results'));
- // Respond to the user request.
- mock_io.requests[1].respond({responseText: '{"entries": 2}'});
- Assert.areEqual(2, picker.get('results'));
- cleanup_widget(picker);
- },
-
- test_automated_search_error_ignored_if_user_has_searched: function() {
- // If an automated search (like loading branch suggestions) returns an
- // error and the user has submitted a search, then the error from the
- // automated search is ignored so as not to confuse the user.
- var mock_io = new Y.lp.testing.mockio.MockIo();
- var picker = this.create_picker(mock_io);
- picker.fire('search', 'test');
- picker.fire('search', 'guess', undefined, true);
- mock_io.failure();
- Assert.areEqual(null, picker.get('error'));
- cleanup_widget(picker);
- }
-
-}));
-
-Y.lp.testing.Runner.run(suite);
-
-});
+ };
+ },
+
+ test_automated_search_results_ignored_if_user_has_searched: function() {
+ // If an automated search (like loading branch suggestions) returns
+ // results and the user has submitted a search, then the results of
+ // the automated search are ignored so as not to confuse the user.
+ var mock_io = new Y.lp.testing.mockio.MockIo();
+ var picker = this.create_picker(mock_io);
+ // First an automated search is run.
+ picker.fire('search', 'guess', undefined, true);
+ // Then the user initiates their own search.
+ picker.fire('search', 'test');
+ // Two requests have been sent out.
+ Y.Assert.areEqual(2, mock_io.requests.length);
+ // Respond to the automated request.
+ mock_io.requests[0].respond({responseText: '{"entries": 1}'});
+ // ... the results are ignored.
+ Assert.areNotEqual(1, picker.get('results'));
+ // Respond to the user request.
+ mock_io.requests[1].respond({responseText: '{"entries": 2}'});
+ Assert.areEqual(2, picker.get('results'));
+ cleanup_widget(picker);
+ },
+
+ test_automated_search_error_ignored_if_user_has_searched: function() {
+ // If an automated search (like loading branch suggestions) returns an
+ // error and the user has submitted a search, then the error from the
+ // automated search is ignored so as not to confuse the user.
+ var mock_io = new Y.lp.testing.mockio.MockIo();
+ var picker = this.create_picker(mock_io);
+ picker.fire('search', 'test');
+ picker.fire('search', 'guess', undefined, true);
+ mock_io.failure();
+ Assert.areEqual(null, picker.get('error'));
+ cleanup_widget(picker);
+ }
+
+ }));
+
+}, '0.1', {'requires': ['test', 'console', 'lp.pickert', 'node', 'lp', 'lp.client',
+ 'event-focus', 'event-simulate', 'lazr.picker', 'lazr.person-picker',
+ 'lp.app.picker', 'node-event-simulate', 'escape', 'event',
+ 'lp.testing.mockio',]});