← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wallyworld/launchpad/branch-infotype-portlet2-1040999 into lp:launchpad

 

Ian Booth has proposed merging lp:~wallyworld/launchpad/branch-infotype-portlet2-1040999 into lp:launchpad with lp:~wallyworld/launchpad/branch-infotype-portlet-1040999 as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1040999 in Launchpad itself: "Cannot use branch information type portlet to set type"
  https://bugs.launchpad.net/launchpad/+bug/1040999

For more details, see:
https://code.launchpad.net/~wallyworld/launchpad/branch-infotype-portlet2-1040999/+merge/121527

== Implementation ==

This branch adds the javascript code to provide a popup choice widget for editing branch information type.
There is already similar functionality for editing bug info type, so common code was pulled out and put in a common module which both import and use.

== Tests ==

Add new yui tests for branch info type widget, update existing yui tests for bug info type widget.

== Lint ==

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/app/javascript/information_type.js
  lib/lp/bugs/javascript/information_type_choice.js
  lib/lp/bugs/javascript/tests/test_information_type_choice.html
  lib/lp/bugs/javascript/tests/test_information_type_choice.js
  lib/lp/code/javascript/branch.information_type_choice.js
  lib/lp/code/javascript/tests/test_information_type_choice.html
  lib/lp/code/javascript/tests/test_information_type_choice.js
  lib/lp/code/templates/branch-portlet-privacy.pt

-- 
https://code.launchpad.net/~wallyworld/launchpad/branch-infotype-portlet2-1040999/+merge/121527
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wallyworld/launchpad/branch-infotype-portlet2-1040999 into lp:launchpad.
=== added file 'lib/lp/app/javascript/information_type.js'
--- lib/lp/app/javascript/information_type.js	1970-01-01 00:00:00 +0000
+++ lib/lp/app/javascript/information_type.js	2012-08-28 02:04:19 +0000
@@ -0,0 +1,82 @@
+/* Copyright 2012 Canonical Ltd.  This software is licensed under the
+ * GNU Affero General Public License version 3 (see the file LICENSE).
+ *
+ * Base functionality for displaying Information Type data.
+ */
+
+YUI.add('lp.app.information_type', function(Y) {
+
+var namespace = Y.namespace('lp.app.information_type');
+
+var get_information_type_banner_text = function(value) {
+    var text_template = "This page contains {info_type} information.";
+    var info_type = namespace.information_type_value_from_key(
+            value, 'value', 'name');
+    return Y.Lang.sub(text_template, {'info_type': info_type});
+};
+
+/**
+ * Lookup the information_type property, keyed on the named value.
+ *
+ * @param key the key to lookup
+ * @param key_name the key property name
+ * @param value_name the value property_name
+ * @return {*}
+ */
+namespace.information_type_value_from_key = function(key, key_name,
+                                                value_name) {
+    var data = null;
+    Y.Array.some(LP.cache.information_type_data, function(info_type) {
+        if (info_type[key_name] === key) {
+            data = info_type[value_name];
+            return true;
+        }
+        return false;
+    });
+    return data;
+};
+
+/**
+ * Update the privacy portlet to display the specified information type value.
+ *
+ * @param value
+ */
+namespace.update_privacy_portlet = function(value) {
+    var description = namespace.information_type_value_from_key(
+        value, 'value', 'description');
+    var desc_node = Y.one('#information-type-description');
+    if (Y.Lang.isValue(desc_node)) {
+        desc_node.set('text', description);
+    }
+    var summary = Y.one('#information-type-summary');
+    var private_type =
+            Y.Array.indexOf(LP.cache.private_types, value) >= 0;
+    if (private_type) {
+        summary.replaceClass('public', 'private');
+    } else {
+        summary.replaceClass('private', 'public');
+    }
+};
+
+/**
+ * Update the privacy banner to display the specified information type value.
+ *
+ * @param value
+ */
+namespace.update_privacy_banner = function(value) {
+    var body = Y.one('body');
+    var privacy_banner = Y.lp.app.banner.privacy.getPrivacyBanner();
+    var private_type =
+            Y.Array.indexOf(LP.cache.private_types, value) >= 0;
+    if (private_type) {
+        body.replaceClass('public', 'private');
+        var banner_text = get_information_type_banner_text(value);
+        privacy_banner.updateText(banner_text);
+        privacy_banner.show();
+    } else {
+        body.replaceClass('private', 'public');
+        privacy_banner.hide();
+    }
+};
+
+}, "0.1", {"requires": ["base", "oop", "node", "lp.app.banner.privacy"]});

=== modified file 'lib/lp/bugs/javascript/information_type_choice.js'
--- lib/lp/bugs/javascript/information_type_choice.js	2012-08-24 12:49:00 +0000
+++ lib/lp/bugs/javascript/information_type_choice.js	2012-08-28 02:04:19 +0000
@@ -7,30 +7,12 @@
 YUI.add('lp.bugs.information_type_choice', function(Y) {
 
 var namespace = Y.namespace('lp.bugs.information_type_choice');
+var information_type = Y.namespace('lp.app.information_type');
 
 // For testing.
 var skip_animation = false;
 
 /**
- * Lookup the information_type property, keyed on the named value.
- * @param key the key to lookup
- * @param key_name the key property name
- * @param value_name the value property_name
- * @return {*}
- */
-var information_type_value_from_key = function(key, key_name,
-                                                value_name) {
-    var data = null;
-    Y.Array.some(LP.cache.information_type_data, function(info_type) {
-        if (info_type[key_name] === key) {
-            data = info_type[value_name];
-            return true;
-        }
-    });
-    return data;
-};
-
-/**
  * Save the new information type. If validate_change is true, then a check
  * will be done to ensure the bug will not become invisible. If the bug will
  * become invisible, a confirmation popup is used to confirm the user's
@@ -57,11 +39,11 @@
                     widget, initial_value, lp_client);
             return true;
         }
-        var orig_value = information_type_value_from_key(
+        var orig_value = information_type.information_type_value_from_key(
             LP.cache.bug.information_type, 'name', 'value');
         widget.set('value', orig_value);
         widget._showFailed();
-        update_privacy_portlet(orig_value);
+        information_type.update_privacy_portlet(orig_value);
         return false;
     };
     var submit_url = document.URL + "/+secrecy";
@@ -101,49 +83,13 @@
     lp_client.io_provider.io(submit_url, config);
 };
 
-var update_privacy_portlet = function(value) {
-    var description = information_type_value_from_key(
-        value, 'value', 'description');
-    var desc_node = Y.one('#information-type-description');
-    if (Y.Lang.isValue(desc_node)) {
-        desc_node.set('text', description);
-    }
-    var summary = Y.one('#information-type-summary');
-    var private_type = (Y.Array.indexOf(LP.cache.private_types, value) >= 0);
-    if (private_type) {
-        summary.replaceClass('public', 'private');
-    } else {
-        summary.replaceClass('private', 'public');
-    }
-};
-
-var update_privacy_banner = function(value) {
-    var body = Y.one('body');
-    var privacy_banner = Y.lp.app.banner.privacy.getPrivacyBanner();
-    var private_type = (Y.Array.indexOf(LP.cache.private_types, value) >= 0);
-    if (private_type) {
-        body.replaceClass('public', 'private');
-        var banner_text = namespace.get_information_type_banner_text(value);
-        privacy_banner.updateText(banner_text);
-        privacy_banner.show();
-    } else {
-        body.replaceClass('private', 'public');
-        privacy_banner.hide();
-    }
-};
-
-namespace.get_information_type_banner_text = function(value) {
-    var text_template = "This page contains {info_type} information.";
-    var info_type = information_type_value_from_key(value, 'value', 'name');
-    return Y.Lang.substitute(text_template, {'info_type': info_type});
-};
-
 namespace.information_type_save_success = function(widget, value,
                                                    subscribers_list,
                                                    subscribers_data) {
     LP.cache.bug.information_type =
-        information_type_value_from_key(value, 'value', 'name');
-    update_privacy_banner(value);
+        information_type.information_type_value_from_key(
+                value, 'value', 'name');
+    information_type.update_privacy_banner(value);
     widget._showSucceeded();
     if (Y.Lang.isObject(subscribers_data)) {
         var subscribers = subscribers_data.subscription_data;
@@ -174,7 +120,7 @@
                                                       lp_client) {
     var value = widget.get('value');
     var do_save = function() {
-        update_privacy_portlet(value);
+        information_type.update_privacy_portlet(value);
         namespace.save_information_type(
             widget, initial_value, value, lp_client, false);
     };
@@ -182,7 +128,7 @@
     // change while the confirmation dialog is showing.
     var new_value = widget.get('value');
     widget.set('value', initial_value);
-    update_privacy_portlet(initial_value);
+    information_type.update_privacy_portlet(initial_value);
     var confirm_text_template = [
         '<p class="block-sprite large-warning">',
         '    You are about to mark this bug as ',
@@ -193,13 +139,14 @@
         '    <strong>Please confirm you really want to do this.</strong>',
         '</p>'
         ].join('');
-    var title = information_type_value_from_key(value, 'value', 'name');
+    var title = information_type.information_type_value_from_key(
+            value, 'value', 'name');
     var confirm_text = Y.Lang.sub(confirm_text_template,
             {information_type: title});
     var co = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
         submit_fn: function() {
             widget.set('value', new_value);
-            update_privacy_portlet(new_value);
+            information_type.update_privacy_portlet(new_value);
             do_save();
         },
         form_content: confirm_text,
@@ -211,13 +158,13 @@
 namespace.setup_information_type_choice = function(privacy_link, lp_client,
                                                    skip_anim) {
     skip_animation = skip_anim;
-    var initial_value = information_type_value_from_key(
+    var initial_value = information_type.information_type_value_from_key(
         LP.cache.bug.information_type, 'name', 'value');
-    var information_type = Y.one('#information-type');
+    var information_type_value = Y.one('#information-type');
     var information_type_edit = new Y.ChoiceSource({
         editicon: privacy_link,
         contentBox: Y.one('#privacy'),
-        value_location: information_type,
+        value_location: information_type_value,
         value: initial_value,
         title: "Change information type",
         items: LP.cache.information_type_data,
@@ -228,7 +175,7 @@
     information_type_edit.render();
     information_type_edit.on("save", function(e) {
         var value = information_type_edit.get('value');
-        update_privacy_portlet(value);
+        information_type.update_privacy_portlet(value);
         namespace.save_information_type(
             information_type_edit, initial_value, value, lp_client, true);
 
@@ -238,4 +185,5 @@
 };
 }, "0.1", {"requires": ["base", "oop", "node", "event", "io-base",
                         "lazr.choiceedit", "lp.bugs.bugtask_index",
-                        "lp.app.banner.privacy", "lp.app.choice"]});
+                        "lp.app.banner.privacy", "lp.app.choice",
+                        "lp.app.information_type"]});

=== modified file 'lib/lp/bugs/javascript/tests/test_information_type_choice.html'
--- lib/lp/bugs/javascript/tests/test_information_type_choice.html	2012-07-03 07:06:48 +0000
+++ lib/lp/bugs/javascript/tests/test_information_type_choice.html	2012-08-28 02:04:19 +0000
@@ -30,6 +30,8 @@
       <script type="text/javascript"
           src="../../../../../build/js/lp/app/choice.js"></script>
       <script type="text/javascript"
+          src="../../../../../build/js/lp/app/information_type.js"></script>
+      <script type="text/javascript"
           src="../../../../../build/js/lp/app/testing/mockio.js"></script>
       <script type="text/javascript"
           src="../../../../../build/js/lp/app/client.js"></script>

=== modified file 'lib/lp/bugs/javascript/tests/test_information_type_choice.js'
--- lib/lp/bugs/javascript/tests/test_information_type_choice.js	2012-08-24 12:49:00 +0000
+++ lib/lp/bugs/javascript/tests/test_information_type_choice.js	2012-08-28 02:04:19 +0000
@@ -304,5 +304,5 @@
     }));
 
 }, '0.1', {'requires': ['test', 'console', 'event', 'node-event-simulate',
-        'lp.testing.mockio', 'lp.client','lp.bugs.subscribers',
-        'lp.bugs.information_type_choice']});
+        'lp.testing.mockio', 'lp.client', 'lp.app.informatin_type',
+        'lp.bugs.information_type_choice', 'lp.bugs.subscribers']});

=== added file 'lib/lp/code/javascript/branch.information_type_choice.js'
--- lib/lp/code/javascript/branch.information_type_choice.js	1970-01-01 00:00:00 +0000
+++ lib/lp/code/javascript/branch.information_type_choice.js	2012-08-28 02:04:19 +0000
@@ -0,0 +1,116 @@
+/* Copyright 2012 Canonical Ltd.  This software is licensed under the
+ * GNU Affero General Public License version 3 (see the file LICENSE).
+ *
+ * Information Type choice widget for branch pages.
+ */
+
+YUI.add('lp.code.branch.information_type_choice', function(Y) {
+
+var namespace = Y.namespace('lp.code.branch.information_type_choice');
+var information_type = Y.namespace('lp.app.information_type');
+var superclass = Y.Widget;
+
+namespace.BranchInformationTypeWidget = Y.Base.create(
+    "branchInformationTypeWidget", Y.Widget, [], {
+    initializer: function(cfg) {
+        this.lp_client = new Y.lp.client.Launchpad(cfg);
+    },
+
+    renderUI: function() {
+        superclass.prototype.renderUI.apply(this, arguments);
+        var privacy_link = Y.one('#privacy-link');
+        var initial_value = information_type.information_type_value_from_key(
+            LP.cache.context.information_type, 'name', 'value');
+        var information_type_value = Y.one('#information-type');
+        this.information_type_edit = new Y.ChoiceSource({
+            editicon: privacy_link,
+            contentBox: Y.one('#privacy'),
+            value_location: information_type_value,
+            value: initial_value,
+            title: "Change information type",
+            items: LP.cache.information_type_data,
+            backgroundColor: '#FFFF99',
+            flashEnabled: false
+        });
+        Y.lp.app.choice.hook_up_choicesource_spinner(
+                this.information_type_edit);
+        this.information_type_edit.render();
+        privacy_link.addClass('js-action');
+    },
+
+    bindUI: function() {
+        superclass.prototype.bindUI.apply(this, arguments);
+        var that = this;
+        this.information_type_edit.on("save", function(e) {
+            var value = that.information_type_edit.get('value');
+            information_type.update_privacy_portlet(value);
+            that._save_information_type(value);
+
+        });
+    },
+
+    _save_information_type: function(value) {
+        var that = this;
+        var widget = this.information_type_edit;
+        var error_handler = new Y.lp.client.FormErrorHandler();
+        error_handler.showError = function(error_msg) {
+            Y.lp.app.errors.display_error(
+                Y.one('#information-type'), error_msg);
+        };
+        error_handler.handleError = function() {
+            var orig_value = information_type.information_type_value_from_key(
+                LP.cache.context.information_type, 'name', 'value');
+            widget.set('value', orig_value);
+            if (that.get('use_animation')) {
+                widget._showFailed();
+            }
+            information_type.update_privacy_portlet(orig_value);
+            return false;
+        };
+        var submit_url = document.URL + "/+edit-information-type";
+        var qs = Y.lp.client.append_qs(
+                '', 'field.actions.change', 'Change Branch');
+        qs = Y.lp.client.append_qs(qs, 'field.information_type', value);
+        var config = {
+            method: "POST",
+            headers: {'Accept': 'application/xhtml;application/json'},
+            data: qs,
+            on: {
+                start: function () {
+                    widget._uiSetWaiting();
+                },
+                end: function () {
+                    widget._uiClearWaiting();
+                },
+                success: function (id, response) {
+                    that._information_type_save_success(value);
+                    Y.lp.client.display_notifications(
+                        response.getResponseHeader('X-Lazr-Notifications'));
+                },
+                failure: error_handler.getFailureHandler()
+            }
+        };
+        this.lp_client.io_provider.io(submit_url, config);
+    },
+
+    _information_type_save_success: function(value) {
+        LP.cache.context.information_type =
+            information_type.information_type_value_from_key(
+                    value, 'value', 'name');
+        information_type.update_privacy_banner(value);
+        if (this.get('use_animation')) {
+            this.information_type_edit._showSucceeded();
+        }
+    }
+}, {
+    ATTRS: {
+        // For testing
+        use_animation: {
+            value: true
+        }
+    }
+});
+
+}, "0.1", {"requires": ["base", "oop", "node", "event", "io-base",
+                        "lazr.choiceedit", "lp.app.banner.privacy",
+                        "lp.app.choice", "lp.app.information_type"]});

=== added file 'lib/lp/code/javascript/tests/test_information_type_choice.html'
--- lib/lp/code/javascript/tests/test_information_type_choice.html	1970-01-01 00:00:00 +0000
+++ lib/lp/code/javascript/tests/test_information_type_choice.html	2012-08-28 02:04:19 +0000
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<!--
+Copyright 2012 Canonical Ltd.  This software is licensed under the
+GNU Affero General Public License version 3 (see the file LICENSE).
+-->
+
+<html>
+  <head>
+      <title>lp.code.branch.information_type_choice 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/lp.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/choice.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/information_type.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/testing/mockio.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/client.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/extras/extras.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/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/choiceedit/choiceedit.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/mustache.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/inlineedit/editor.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/formoverlay/formoverlay.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/overlay/overlay.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/expander.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/errors.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/banners/banner.js"></script>
+      <script type="text/javascript"
+          src="../../../../../build/js/lp/app/banners/privacy.js"></script>
+
+      <!-- The module under test. -->
+      <script type="text/javascript" src="../branch.information_type_choice.js"></script>
+
+      <!-- Placeholder for any css asset for this module. -->
+      <!-- <link rel="stylesheet" href="../assets/bugs.information_type_choice-ctest_inforore.css" /> -->
+
+      <!-- The test suite -->
+      <script type="text/javascript" src="test_information_type_choice.js"></script>
+
+    </head>
+    <body class="yui3-skin-sam">
+        <ul id="suites">
+            <li>lp.code.branch.information_type_choice.test</li>
+        </ul>
+        <div id="fixture"></div>
+        <script type="text/x-template" id="portlet-template">
+            <div id="privacy">
+                <div id="privacy-text">
+                    <span id="information-type-summary" class="sprite public">
+                        This report contains
+                        <strong id="information-type">Public</strong>
+                        information
+                    </span>
+                    <a class="sprite edit" id="privacy-link" href="#">edit</a>
+                    <div id="information-type-description">Everyone can see this information.</div>
+                </div>
+            </div>
+        </script>
+    </body>
+</html>

=== added file 'lib/lp/code/javascript/tests/test_information_type_choice.js'
--- lib/lp/code/javascript/tests/test_information_type_choice.js	1970-01-01 00:00:00 +0000
+++ lib/lp/code/javascript/tests/test_information_type_choice.js	2012-08-28 02:04:19 +0000
@@ -0,0 +1,179 @@
+/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
+
+YUI.add('lp.code.branch.information_type_choice.test', function (Y) {
+
+    var tests = Y.namespace('lp.code.branch.information_type_choice.test');
+    var ns = Y.lp.code.branch.information_type_choice;
+    tests.suite = new Y.Test.Suite(
+            'lp.code.branch.information_type_choice Tests');
+
+    tests.suite.add(new Y.Test.Case({
+        name: 'lp.code.branch.information_type_choice_tests',
+
+        setUp: function() {
+            window.LP = {
+                cache: {
+                    context: {
+                        web_link: '',
+                        information_type: 'Public'
+                    },
+                    private_types: ['PROPRIETARY', 'USERDATA'],
+                    information_type_data: [
+                        {'value': 'PUBLIC', 'name': 'Public',
+                            'description': 'Public Description'},
+                        {'value': 'PUBLICSECURITY', 'name': 'Public Security',
+                            'description': 'Public Security Description'},
+                        {'value': 'PROPRIETARY', 'name': 'Proprietary',
+                            'description': 'Private Description'},
+                        {'value': 'USERDATA', 'name': 'Private',
+                            'description': 'Private Description'}
+                    ]
+                }
+            };
+            this.fixture = Y.one('#fixture');
+            var portlet = Y.Node.create(
+                    Y.one('#portlet-template').getContent());
+            this.fixture.appendChild(portlet);
+            this.mockio = new Y.lp.testing.mockio.MockIo();
+        },
+
+        tearDown: function () {
+            if (this.fixture !== null) {
+                this.fixture.empty(true);
+            }
+            delete this.fixture;
+            delete this.mockio;
+            delete window.LP;
+        },
+
+        makeWidget: function() {
+            this.widget = new ns.BranchInformationTypeWidget({
+                io_provider: this.mockio,
+                use_animation: false
+            });
+            this.widget.render();
+        },
+
+        _shim_privacy_banner: function () {
+            var old_func = Y.lp.app.banner.privacy.getPrivacyBanner;
+            Y.lp.app.banner.privacy.getPrivacyBanner = function () {
+                return {
+                    show: function () { Y.fire('test:banner:show'); },
+                    hide: function () { Y.fire('test:banner:hide'); },
+                    updateText: function () { Y.fire('test:banner:update'); }
+                };
+            };
+            return old_func;
+        },
+
+        _unshim_privacy_banner: function (old_func) {
+            Y.lp.app.banner.privacy.getPrivacyBanner = old_func;
+        },
+
+        test_library_exists: function () {
+            Y.Assert.isObject(Y.lp.code.branch.information_type_choice,
+                "Cannot locate the " +
+                "lp.code.branch.information_type_choice module");
+        },
+
+        // The widget is created as expected.
+        test_create_widget: function() {
+            this.makeWidget();
+            Y.Assert.isInstanceOf(
+                ns.BranchInformationTypeWidget, this.widget,
+                "Branch info type widget failed to be instantiated");
+            var privacy_link = Y.one('#privacy-link');
+            Y.Assert.isTrue(privacy_link.hasClass('js-action'));
+        },
+
+        // The save XHR call works as expected.
+        test_save_information_type: function() {
+            this.makeWidget();
+            var save_success_called = false;
+            this.widget._information_type_save_success = function(value) {
+                Y.Assert.areEqual('USERDATA', value);
+                save_success_called = true;
+            };
+            this.widget._save_information_type('USERDATA');
+            this.mockio.success({
+                responseText: '',
+                responseHeaders: {'Content-Type': 'application/json'}});
+            Y.Assert.areEqual(
+                document.URL + '/+edit-information-type',
+                this.mockio.last_request.url);
+            Y.Assert.areEqual(
+                'field.actions.change=Change%20Branch&' +
+                'field.information_type=USERDATA',
+                this.mockio.last_request.config.data);
+            Y.Assert.isTrue(save_success_called);
+        },
+
+        // Setting a private type shows the privacy banner.
+        test_information_type_save_success_private: function() {
+            this.makeWidget();
+            var old_func = this._shim_privacy_banner();
+            var hide_flag = false;
+            var update_flag = false;
+            Y.on('test:banner:show', function() {
+                hide_flag = true;
+            });
+            Y.on('test:banner:update', function() {
+                update_flag = true;
+            });
+
+            this.widget._information_type_save_success('PROPRIETARY');
+            var body = Y.one('body');
+            Y.Assert.isTrue(body.hasClass('private'));
+            Y.Assert.isTrue(hide_flag);
+            Y.Assert.isTrue(update_flag);
+            Y.Assert.areEqual(
+                'Proprietary', LP.cache.context.information_type);
+            this._unshim_privacy_banner(old_func);
+        },
+
+        // Setting a private type hides the privacy banner.
+        test_information_type_save_success_public: function() {
+            this.makeWidget();
+            var old_func = this._shim_privacy_banner();
+            var flag = false;
+            Y.on('test:banner:hide', function() {
+                flag = true;
+            });
+            var summary = Y.one('#information-type-summary');
+            summary.replaceClass('public', 'private');
+
+            this.widget._information_type_save_success('PUBLIC');
+            var body = Y.one('body');
+            Y.Assert.isTrue(body.hasClass('public'));
+            Y.Assert.isTrue(flag);
+            Y.Assert.areEqual('Public', LP.cache.context.information_type);
+            this._unshim_privacy_banner(old_func);
+        },
+
+        // Test error handling when a save fails.
+        test_information_type_save_error: function() {
+            this.makeWidget();
+            this.widget.information_type_edit.set('value', 'USERDATA');
+            this.widget._save_information_type('USERDATA');
+            this.mockio.last_request.respond({
+                status: 500,
+                statusText: 'An error occurred'
+            });
+            // The original info type value from the cache should have been
+            // set back into the widget.
+            Y.Assert.areEqual(
+                    'PUBLIC',
+                    this.widget.information_type_edit.get('value'));
+            var description_node = Y.one('#information-type-description');
+            Y.Assert.areEqual(
+                'Public Description', description_node.get('text'));
+            var summary = Y.one('#information-type-summary');
+            Y.Assert.isTrue(summary.hasClass('public'));
+            // The error was displayed.
+            Y.Assert.isNotNull(Y.one('.yui3-lazr-formoverlay-errors'));
+        }
+    }));
+
+}, '0.1', {'requires': ['test', 'console', 'event', 'node-event-simulate',
+        'lp.testing.mockio', 'lp.client', 'lp.app.information_type',
+        'lp.code.branch.information_type_choice']});

=== modified file 'lib/lp/code/templates/branch-portlet-privacy.pt'
--- lib/lp/code/templates/branch-portlet-privacy.pt	2012-08-28 02:04:19 +0000
+++ lib/lp/code/templates/branch-portlet-privacy.pt	2012-08-28 02:04:19 +0000
@@ -18,3 +18,17 @@
     <div id="information-type-description" style="padding-top: 5px"
          tal:content="view/information_type_description"></div>
 </div>
+
+<tal:script>
+  <script type="text/javascript">
+    LPJS.use('lp.code.branch.information_type_choice', function(Y) {
+        Y.on('domready',
+            function(e) {
+              var widget = new Y.lp.code.branch.information_type_choice.BranchInformationTypeWidget();
+              widget.render();
+            },
+            window);
+    });
+  </script>
+</tal:script>
+


Follow ups