← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~benji/launchpad/add-edit-tests-2 into lp:launchpad

 

Benji York has proposed merging lp:~benji/launchpad/add-edit-tests-2 into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~benji/launchpad/add-edit-tests-2/+merge/56831

This branch adds workflow tests for adding bug notification
subscriptions, editing them, and unsubscribing from them.  The intent is
to test the basic workflow in each scenario as well as provide a good
framework for more tests in the future.

The tests can be run by loading
lib/lp/registry/javascript/tests/test_structural_subscription.html in a
browser.

There is not lint reported for the added/changed lines but there is
quite a bit for the pre-existing lines.  Fixes for those are in a
forthcoming branch in order to keep this branch sane.
-- 
https://code.launchpad.net/~benji/launchpad/add-edit-tests-2/+merge/56831
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~benji/launchpad/add-edit-tests-2 into lp:launchpad.
=== modified file 'lib/lp/registry/javascript/structural-subscription.js'
--- lib/lp/registry/javascript/structural-subscription.js	2011-04-07 14:16:39 +0000
+++ lib/lp/registry/javascript/structural-subscription.js	2011-04-07 19:46:28 +0000
@@ -1050,6 +1050,17 @@
     };
 }
 
+// If set, this will be used instead of Y.io.  This is for testing.
+namespace._Y_io_hook = null;
+
+function do_io(link, config) {
+    var yio = Y.io;
+    if (namespace._Y_io_hook) {
+        yio = namespace._Y_io_hook;
+    }
+    yio(link, config);
+}
+
 /**
  * Construct a handler for an unsubscribe link.
  */
@@ -1082,7 +1093,7 @@
                 failure: error_handler.getFailureHandler()
             }
         };
-        Y.io(filter.self_link, y_config);
+        do_io(filter.self_link, y_config);
     };
 }
 

=== modified file 'lib/lp/registry/javascript/tests/test_structural_subscription.js'
--- lib/lp/registry/javascript/tests/test_structural_subscription.js	2011-04-07 14:14:03 +0000
+++ lib/lp/registry/javascript/tests/test_structural_subscription.js	2011-04-07 19:46:28 +0000
@@ -5,7 +5,7 @@
     filter: 'raw',
     combine: false,
     fetchCSS: false
-    }).use('test', 'console', 'node', 'lp.client',
+    }).use('test', 'console', 'node', 'node-event-simulate', 'lp.client',
         'lp.registry.structural_subscription', function(Y) {
 
     var suite = new Y.Test.Suite("Structural subscription overlay tests");
@@ -22,6 +22,10 @@
     var content_box_name = 'ss-content-box';
     var content_box_id = '#' + content_box_name;
 
+    // Listing node.
+    var subscription_listing_name = 'subscription-listing';
+    var subscription_listing_id = '#' + subscription_listing_name;
+
     var target_link_class = '.menu-link-subscribe_to_bug_mail';
 
     function array_compare(a,b) {
@@ -36,11 +40,17 @@
         return true;
     }
 
-    function create_test_node() {
-        return Y.Node.create(
-                '<div id="test-content">' +
-                '  <div id="' + content_box_name + '"></div>' +
-                '</div>');
+    function create_test_node(include_listing) {
+        var test_node = Y.Node.create('<div id="test-content">')
+            .append(Y.Node.create('<div></div>')
+                .set('id', content_box_name))
+
+        if (include_listing) {
+            test_node.append(Y.Node.create('<div style="width: 50%"></div>')
+                .set('id', subscription_listing_name));
+        }
+
+        return test_node;
     }
 
     function remove_test_node() {
@@ -58,6 +68,61 @@
         return true;
     }
 
+    function monkeypatch_LP() {
+          // Monkeypatch LP to avoid network traffic and to allow
+          // insertion of test data.
+          var original_lp = window.LP
+          window.LP = {
+            links: {},
+            cache: {}
+          };
+
+          LP.cache.context = {
+            title: 'Test Project',
+            self_link: 'https://launchpad.dev/api/test_project'
+          };
+          LP.cache.administratedTeams = [];
+          LP.cache.importances = ['Unknown', 'Critical', 'High', 'Medium',
+                                  'Low', 'Wishlist', 'Undecided'];
+          LP.cache.statuses = ['New', 'Incomplete', 'Opinion',
+                               'Invalid', 'Won\'t Fix', 'Expired',
+                               'Confirmed', 'Triaged', 'In Progress',
+                               'Fix Committed', 'Fix Released', 'Unknown'];
+          LP.links.me = 'https://launchpad.dev/api/~someone';
+          return original_lp;
+    }
+
+    function LPClient(){
+        if (!(this instanceof arguments.callee))
+            throw new Error("Constructor called as a function");
+        this.received = []
+        // We create new functions every time because we allow them to be
+        // configured.
+        this.named_post = function(url, func, config) {
+            this._call('named_post', config, arguments);
+        };
+        this.patch = function(bug_filter, data, config) {
+            this._call('patch', config, arguments);
+        }
+    };
+    LPClient.prototype._call = function(name, config, args) {
+        this.received.push(
+            [name, Array.prototype.slice.call(args)]);
+        if (!Y.Lang.isValue(args.callee.args))
+            throw new Error("Set call_args on "+name);
+        if (Y.Lang.isValue(args.callee.fail) && args.callee.fail) {
+            config.on.failure.apply(undefined, args.callee.args);
+        } else {
+            config.on.success.apply(undefined, args.callee.args);
+        }
+    };
+    // DELETE uses Y.io directly as of this writing, so we cannot stub it
+    // here.
+
+    function make_lp_client_stub() {
+        return new LPClient();
+    }
+
     test_case = new Y.Test.Case({
         name: 'structural_subscription_overlay',
 
@@ -481,28 +546,11 @@
         setUp: function() {
           // Monkeypatch LP to avoid network traffic and to allow
           // insertion of test data.
-          window.LP = {
-            links: {},
-            cache: {}
-          };
-
-          LP.cache.context = {
-            title: 'Test Project',
-            self_link: 'https://launchpad.dev/api/test_project'
-          };
-          LP.cache.administratedTeams = [];
-          LP.cache.importances = ['Unknown', 'Critical', 'High', 'Medium',
-                                  'Low', 'Wishlist', 'Undecided'];
-          LP.cache.statuses = ['New', 'Incomplete', 'Opinion',
-                               'Invalid', 'Won\'t Fix', 'Expired',
-                               'Confirmed', 'Triaged', 'In Progress',
-                               'Fix Committed', 'Fix Released', 'Unknown'];
-          LP.links.me = 'https://launchpad.dev/api/~someone';
-
-          var lp_client = function() {};
+          this.original_lp = monkeypatch_LP();
+
           this.configuration = {
               content_box: content_box_id,
-              lp_client: lp_client
+              lp_client: make_lp_client_stub()
           };
 
           this.content_node = create_test_node();
@@ -510,17 +558,16 @@
         },
 
         tearDown: function() {
-          remove_test_node();
-          delete this.content_node;
+            window.LP = this.original_lp;
+            remove_test_node();
+            delete this.content_node;
         },
 
         test_overlay_error_handling_adding: function() {
             // Verify that errors generated during adding of a filter are
             // displayed to the user.
-            this.configuration.lp_client.named_post =
-                function(url, func, config) {
-                config.on.failure(true, true);
-                };
+            this.configuration.lp_client.named_post.fail = true;
+            this.configuration.lp_client.named_post.args = [true, true];
             module.setup(this.configuration);
             module._show_add_overlay(this.configuration);
             // After the setup the overlay should be in the DOM.
@@ -540,17 +587,10 @@
             // displayed to the user.
             var original_delete_filter = module._delete_filter;
             module._delete_filter = function() {};
-            this.configuration.lp_client.patch =
-                function(bug_filter, data, config) {
-                    config.on.failure(true, true);
-                };
-            var bug_filter = {
-                'getAttrs': function() { return {}; }
-            };
-            this.configuration.lp_client.named_post =
-                function(url, func, config) {
-                    config.on.success(bug_filter);
-                };
+            this.configuration.lp_client.patch.fail = true;
+            this.configuration.lp_client.patch.args = [true, true];
+            this.configuration.lp_client.named_post.args = [
+                {'getAttrs': function() { return {}; }}];
             module.setup(this.configuration);
             module._show_add_overlay(this.configuration);
             // After the setup the overlay should be in the DOM.
@@ -808,6 +848,7 @@
 
     }));
 
+<<<<<<< TREE
     suite.add(new Y.Test.Case({
         name: 'Add a subscription from +subscriptions page',
 
@@ -971,6 +1012,250 @@
         },
     }));
 
+=======
+    suite.add(new Y.Test.Case({
+        name: 'Structural Subscription: add subcription workflow',
+
+        _should: {error: {}},
+
+        setUp: function() {
+            var TestBugFilter = function() {};
+            TestBugFilter.prototype = {
+                'getAttrs': function () {
+                    return {};
+                }
+            };
+            // We need an lp_client that will appear to succesfully create the
+            // bug filter.
+            var TestClient = function() {};
+            TestClient.prototype = {
+                named_post: function (uri, operation_name, config) {
+                    config.on.success(new TestBugFilter());
+                    this.post_called = true;
+                },
+                patch: function(uri, representation, config, headers) {
+                    config.on.success();
+                    this.patch_called = true;
+                },
+                post_called: false,
+                patch_called: false
+            };
+
+            this.original_lp = monkeypatch_LP();
+
+            this.configuration = {
+                content_box: content_box_id,
+                lp_client: new TestClient()
+            };
+            this.content_node = create_test_node();
+            Y.one('body').appendChild(this.content_node);
+        },
+
+        tearDown: function() {
+            window.LP = this.original_lp;
+            remove_test_node();
+            delete this.content_node;
+        },
+
+        test_simple_add_workflow: function() {
+            // Clicking on the "Subscribe to bug mail" link and then clicking
+            // on the overlay form's "OK" button results in a filter being
+            // created and PATCHed.
+            module.setup(this.configuration);
+            Y.one('a.menu-link-subscribe_to_bug_mail').simulate('click');
+            Assert.isFalse(module.lp_client.post_called);
+            Assert.isFalse(module.lp_client.patch_called);
+            var button = Y.one('.yui3-lazr-formoverlay-actions button');
+            Assert.areEqual(button.get('text'), 'OK');
+            button.simulate('click');
+            Assert.isTrue(module.lp_client.post_called);
+            Assert.isTrue(module.lp_client.patch_called);
+        },
+
+        test_simple_add_workflow_cancled: function() {
+            // Clicking on the "Subscribe to bug mail" link and then clicking
+            // on the overlay form's cancel button results in no filter being
+            // created or PATCHed.
+            module.setup(this.configuration);
+            Y.one('a.menu-link-subscribe_to_bug_mail').simulate('click');
+            Assert.isFalse(module.lp_client.post_called);
+            Assert.isFalse(module.lp_client.patch_called);
+            var button = Y.one(
+                '.yui3-lazr-formoverlay-actions button+button');
+            Assert.areEqual(button.get('text'), 'Cancel');
+            button.simulate('click');
+            Assert.isFalse(module.lp_client.post_called);
+            Assert.isFalse(module.lp_client.patch_called);
+        }
+
+    }));
+
+    suite.add(new Y.Test.Case({
+        name: 'Structural Subscription: edit subcription workflow',
+
+        _should: {error: {}},
+
+        setUp: function() {
+            var TestBugFilter = function(data) {
+                if (data !== undefined) {
+                    this._data = data;
+                } else {
+                    this._data = {};
+                }
+            };
+            TestBugFilter.prototype = {
+                'getAttrs': function () {
+                    return this._data;
+                }
+            };
+            // We need an lp_client that will appear to succesfully create the
+            // bug filter.
+            var TestClient = function() {
+                this.post_called = false;
+                this.patch_called = false;
+            };
+            TestClient.prototype = {
+                named_post: function (uri, operation_name, config) {
+                    config.on.success(new TestBugFilter());
+                    this.post_called = true;
+                },
+                patch: function(uri, representation, config, headers) {
+                    config.on.success(new TestBugFilter(representation));
+                    this.patch_called = true;
+                }
+            };
+
+            this.original_lp = monkeypatch_LP();
+
+            LP.cache.subscription_info = [{
+                target_url: 'http://example.com',
+                target_title:'Example project',
+                filters: [{
+                    filter: {
+                        description: 'DESCRIPTION',
+                        statuses: [],
+                        importances: [],
+                        tags: [],
+                        find_all_tags: true,
+                        bug_notification_level: 'Discussion',
+                        self_link: 'http://example.com/a_filter'
+                        },
+                    can_mute: true,
+                    is_muted: false,
+                    subscriber_is_team: false,
+                    subscriber_url: 'http://example.com/subscriber',
+                    subscriber_title: 'Thidwick',
+                    user_is_team_admin: false
+                }]
+            }];
+
+
+            this.configuration = {
+                content_box: content_box_id,
+                lp_client: new TestClient()
+            };
+            this.content_node = create_test_node(true);
+            Y.one('body').appendChild(this.content_node);
+        },
+
+        tearDown: function() {
+            window.LP = this.original_lp;
+            remove_test_node();
+            delete this.content_node;
+        },
+
+        test_simple_edit_workflow: function() {
+            module.setup_bug_subscriptions(this.configuration);
+
+            // Editing a value via the edit link and dialog causes the
+            // subscription list to reflect the new value.
+            var label = Y.one('.filter-name span').get('text');
+            Assert.isTrue(label.indexOf('DESCRIPTION') !== -1);
+
+            // No PATCHing has happened yet.
+            Assert.isFalse(module.lp_client.patch_called);
+
+            // Click the edit link.
+            Y.one('a.edit-subscription').simulate('click');
+
+            // Set a new name (description) and click OK.
+            Y.one('input[name="name"]').set('value', 'NEW VALUE');
+            var button = Y.one('.yui3-lazr-formoverlay-actions button');
+            Assert.areEqual(button.get('text'), 'OK');
+            button.simulate('click');
+
+            // Clicking OK resulted in the bug filter being PATCHed.
+            Assert.isTrue(module.lp_client.patch_called);
+            // And the new value is reflected in the subscription listing.
+            label = Y.one('.filter-name span').get('text');
+            Assert.isTrue(label.indexOf('NEW VALUE') !== -1);
+        }
+
+    }));
+
+    suite.add(new Y.Test.Case({
+        name: 'Structural Subscription: unsubscribing',
+
+        _should: {error: {}},
+
+        setUp: function() {
+            var TestClient = function() {};
+            this.original_lp = monkeypatch_LP();
+
+            LP.cache.subscription_info = [{
+                target_url: 'http://example.com',
+                target_title:'Example project',
+                filters: [{
+                    filter: {
+                        description: 'DESCRIPTION',
+                        statuses: [],
+                        importances: [],
+                        tags: [],
+                        find_all_tags: true,
+                        bug_notification_level: 'Discussion',
+                        self_link: 'http://example.com/a_filter'
+                        },
+                    can_mute: true,
+                    is_muted: false,
+                    subscriber_is_team: false,
+                    subscriber_url: 'http://example.com/subscriber',
+                    subscriber_title: 'Thidwick',
+                    user_is_team_admin: false
+                }]
+            }];
+
+            this.configuration = {
+                content_box: content_box_id,
+                lp_client: new TestClient()
+            };
+            this.content_node = create_test_node(true);
+            Y.one('body').appendChild(this.content_node);
+        },
+
+        tearDown: function() {
+            window.LP = this.original_lp;
+            remove_test_node();
+            delete this.content_node;
+        },
+
+        test_simple_unsubscribe: function() {
+            // Clicking on the unsubscribe link will result in a DELETE being
+            // sent and the filter description being removed.
+
+            var DELETE_performed = false;
+            // Fake a DELETE that succeeds.
+            module._Y_io_hook = function (link, config) {
+                DELETE_performed = true;
+                config.on.success();
+            };
+
+            module.setup_bug_subscriptions(this.configuration);
+            Y.one('a.delete-subscription').simulate('click');
+            Assert.isTrue(DELETE_performed);
+        }
+
+    }));
+>>>>>>> MERGE-SOURCE
     // Lock, stock, and two smoking barrels.
     var handle_complete = function(data) {
         var status_node = Y.Node.create(