Merge lp:~benji/juju-gui/bug-1103477 into lp:juju-gui/experimental

Proposed by Benji York
Status: Merged
Merged at revision: 345
Proposed branch: lp:~benji/juju-gui/bug-1103477
Merge into: lp:juju-gui/experimental
Diff against target: 374 lines (+92/-68)
6 files modified
app/store/env.js (+13/-10)
app/views/service.js (+2/-2)
app/views/topology/relation.js (+9/-14)
test/test_application_notifications.js (+24/-34)
test/test_env.js (+9/-6)
test/test_topology_relation.js (+35/-2)
To merge this branch: bzr merge lp:~benji/juju-gui/bug-1103477
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+144594@code.launchpad.net

Description of the change

Add a test for the fix for bug 1103204

This branch also includes some refactoring of where relation names are
calculated in an effort to DRY it up as well as make testing a tad easier.

https://codereview.appspot.com/7206047/

To post a comment you must log in.
Revision history for this message
Madison Scott-Clary (makyo) wrote :

Land as is after landing parent branch, looks good to me with the change
involved in the parent.

https://codereview.appspot.com/7206047/

Revision history for this message
Gary Poster (gary) wrote :

Land with changes.

Extremely nice branch, Benji. Thank you.

Gary

https://codereview.appspot.com/7206047/diff/1/app/views/topology/relation.js
File app/views/topology/relation.js (right):

https://codereview.appspot.com/7206047/diff/1/app/views/topology/relation.js#newcode834
app/views/topology/relation.js:834: relationClick: function(d, self) {
I expected you to change this "d" argument to "relation" like your other
nice changes. Would be nice. :-)

https://codereview.appspot.com/7206047/diff/1/app/views/utils.js
File app/views/utils.js (right):

https://codereview.appspot.com/7206047/diff/1/app/views/utils.js#newcode827
app/views/utils.js:827: * Decorate a relation with some related/derrived
data.
typo: derived

https://codereview.appspot.com/7206047/

lp:~benji/juju-gui/bug-1103477 updated
346. By Benji York

merge from trunk

347. By Benji York

give a parameter a better name

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/store/env.js'
--- app/store/env.js 2013-01-24 14:14:45 +0000
+++ app/store/env.js 2013-01-24 19:23:21 +0000
@@ -13,6 +13,9 @@
13 Environment.superclass.constructor.apply(this, arguments);13 Environment.superclass.constructor.apply(this, arguments);
14 }14 }
1515
16 var endpointToName = function(endpoint) {
17 return endpoint[0] + ':' + endpoint[1].name;
18 };
1619
17 Environment.NAME = 'env';20 Environment.NAME = 'env';
18 Environment.ATTRS = {21 Environment.ATTRS = {
@@ -204,19 +207,19 @@
204 * Add a relation between two services.207 * Add a relation between two services.
205 *208 *
206 * @method add_relation209 * @method add_relation
207 * @param {String} endpoint_a A string `service:interface` representing210 * @param {Object} endpointA An array of [service, interface] representing
208 the first endpoint to connect.211 the first endpoint to connect.
209 * @param {String} endpoint_b A string `service:interface` representing212 * @param {Object} endpointB An array of [service, interface] representing
210 the second endpoint to connect.213 the second endpoint to connect.
211 * @param {Function} callback A callable that must be called once the214 * @param {Function} callback A callable that must be called once the
212 operation is performed.215 operation is performed.
213 * @return {undefined} Sends a message to the server only.216 * @return {undefined} Sends a message to the server only.
214 */217 */
215 add_relation: function(endpoint_a, endpoint_b, callback) {218 add_relation: function(endpointA, endpointB, callback) {
216 this._send_rpc({219 this._send_rpc({
217 'op': 'add_relation',220 'op': 'add_relation',
218 'endpoint_a': endpoint_a,221 'endpoint_a': endpointToName(endpointA),
219 'endpoint_b': endpoint_b}, callback, true);222 'endpoint_b': endpointToName(endpointB)}, callback, true);
220 },223 },
221224
222 get_charm: function(charm_url, callback) {225 get_charm: function(charm_url, callback) {
@@ -311,19 +314,19 @@
311 * Remove a relation between two services.314 * Remove a relation between two services.
312 *315 *
313 * @method remove_relation316 * @method remove_relation
314 * @param {String} endpoint_a A string `service:interface` representing317 * @param {Object} endpointA An array of [service, interface] representing
315 the first endpoint to disconnect.318 the first endpoint to disconnect.
316 * @param {String} endpoint_b A string `service:interface` representing319 * @param {Object} endpointB An array of [service, interface] representing
317 the second endpoint to disconnect.320 the second endpoint to disconnect.
318 * @param {Function} callback A callable that must be called once the321 * @param {Function} callback A callable that must be called once the
319 operation is performed.322 operation is performed.
320 * @return {undefined} Sends a message to the server only.323 * @return {undefined} Sends a message to the server only.
321 */324 */
322 remove_relation: function(endpoint_a, endpoint_b, callback) {325 remove_relation: function(endpointA, endpointB, callback) {
323 this._send_rpc({326 this._send_rpc({
324 'op': 'remove_relation',327 'op': 'remove_relation',
325 'endpoint_a': endpoint_a,328 'endpoint_a': endpointToName(endpointA),
326 'endpoint_b': endpoint_b}, callback, true);329 'endpoint_b': endpointToName(endpointB)}, callback, true);
327 },330 },
328331
329 /**332 /**
330333
=== modified file 'app/views/service.js'
--- app/views/service.js 2013-01-24 14:14:45 +0000
+++ app/views/service.js 2013-01-24 19:23:21 +0000
@@ -445,14 +445,14 @@
445 service = this.get('model'),445 service = this.get('model'),
446 relation = db.relations.getById(rel_id),446 relation = db.relations.getById(rel_id),
447 endpoints = relation.get('endpoints'),447 endpoints = relation.get('endpoints'),
448 endpoint_a = endpoints[0][0] + ':' + endpoints[0][1].name,448 endpoint_a = endpoints[0],
449 endpoint_b;449 endpoint_b;
450450
451 if (endpoints.length === 1) {451 if (endpoints.length === 1) {
452 // For a peer relationship, both endpoints are the same.452 // For a peer relationship, both endpoints are the same.
453 endpoint_b = endpoint_a;453 endpoint_b = endpoint_a;
454 } else {454 } else {
455 endpoint_b = endpoints[1][0] + ':' + endpoints[1][1].name;455 endpoint_b = endpoints[1];
456 }456 }
457457
458 ev.target.set('disabled', true);458 ev.target.set('disabled', true);
459459
=== modified file 'app/views/topology/relation.js'
--- app/views/topology/relation.js 2013-01-24 19:02:40 +0000
+++ app/views/topology/relation.js 2013-01-24 19:23:21 +0000
@@ -445,19 +445,16 @@
445 self.addRelation(); // Will clear the state.445 self.addRelation(); // Will clear the state.
446 }446 }
447 },447 },
448 removeRelation: function(d, view, confirmButton) {448 removeRelation: function(relation, view, confirmButton) {
449 var env = this.get('component').get('env');449 var env = this.get('component').get('env');
450 var endpoints = d.endpoints;
451 var relationId = d.relation_id;
452 // At this time, relations may have been redrawn, so here we have to450 // At this time, relations may have been redrawn, so here we have to
453 // retrieve the relation DOM element again.451 // retrieve the relation DOM element again.
454 var relationElement = view.get('container').one('#' + relationId);452 var relationElement = view.get('container')
453 .one('#' + relation.relation_id);
455 utils.addSVGClass(relationElement, 'to-remove pending-relation');454 utils.addSVGClass(relationElement, 'to-remove pending-relation');
456 env.remove_relation(455 env.remove_relation(relation.endpoints[0], relation.endpoints[1],
457 endpoints[0][0] + ':' + endpoints[0][1].name,
458 endpoints[1][0] + ':' + endpoints[1][1].name,
459 Y.bind(this._removeRelationCallback, this, view,456 Y.bind(this._removeRelationCallback, this, view,
460 relationElement, relationId, confirmButton));457 relationElement, relation.relation_id, confirmButton));
461 },458 },
462459
463 _removeRelationCallback: function(view,460 _removeRelationCallback: function(view,
@@ -722,9 +719,7 @@
722719
723 // Fire event to add relation in juju.720 // Fire event to add relation in juju.
724 // This needs to specify interface in the future.721 // This needs to specify interface in the future.
725 env.add_relation(722 env.add_relation(endpoints[0], endpoints[1],
726 endpoints[0][0] + ':' + endpoints[0][1].name,
727 endpoints[1][0] + ':' + endpoints[1][1].name,
728 Y.bind(this._addRelationCallback, this, view, relation_id)723 Y.bind(this._addRelationCallback, this, view, relation_id)
729 );724 );
730 view.set('currentServiceClickAction', 'hideServiceMenu');725 view.set('currentServiceClickAction', 'hideServiceMenu');
@@ -838,8 +833,8 @@
838 'active');833 'active');
839 },834 },
840835
841 relationClick: function(d, self) {836 relationClick: function(relation self) {
842 if (d.isSubordinate) {837 if (relation.isSubordinate) {
843 var subRelDialog = views.createModalPanel(838 var subRelDialog = views.createModalPanel(
844 'You may not remove a subordinate relation.',839 'You may not remove a subordinate relation.',
845 '#rmsubrelation-modal-panel');840 '#rmsubrelation-modal-panel');
@@ -861,7 +856,7 @@
861 subRelDialog.get('boundingBox').all('.yui3-button')856 subRelDialog.get('boundingBox').all('.yui3-button')
862 .removeClass('yui3-button');857 .removeClass('yui3-button');
863 } else {858 } else {
864 self.removeRelationConfirm(d, this, self);859 self.removeRelationConfirm(relation, this, self);
865 }860 }
866 }861 }
867862
868863
=== modified file 'test/test_application_notifications.js'
--- test/test_application_notifications.js 2013-01-17 16:19:17 +0000
+++ test/test_application_notifications.js 2013-01-24 19:23:21 +0000
@@ -2,7 +2,7 @@
22
3describe('juju application notifications', function() {3describe('juju application notifications', function() {
4 var _setTimeout, _viewsHighlightRow, db, ERR_EV, juju, models, NO_OP,4 var _setTimeout, _viewsHighlightRow, db, ERR_EV, juju, models, NO_OP,
5 viewContainer, views, Y;5 viewContainer, views, Y, willError;
66
7 before(function(done) {7 before(function(done) {
8 Y = YUI(GlobalConfig).use(['node',8 Y = YUI(GlobalConfig).use(['node',
@@ -22,6 +22,18 @@
22 ERR_EV = {22 ERR_EV = {
23 err: true23 err: true
24 };24 };
25
26 /**
27 * A function that accepts a callback as its last (rightmost) argument and
28 * calls that callback with a synthetic error event.
29 */
30 willError = function() {
31 // The last argument is the callback. We do not care what the
32 // other arguments are or if they change in the future.
33 var callback = arguments[arguments.length - 1];
34 callback(ERR_EV);
35 };
36
25 NO_OP = function() {};37 NO_OP = function() {};
26 });38 });
2739
@@ -91,12 +103,8 @@
91 },103 },
92 db: db,104 db: db,
93 env: {105 env: {
94 add_unit: function(serviceId, delta, callback) {106 add_unit: willError,
95 callback(ERR_EV);107 remove_units: willError
96 },
97 remove_units: function(param, callback) {
98 callback(ERR_EV);
99 }
100 },108 },
101 model: {109 model: {
102 getAttrs: NO_OP,110 getAttrs: NO_OP,
@@ -140,9 +148,8 @@
140 { err: true,148 { err: true,
141 unit_names: ['aaa']});149 unit_names: ['aaa']});
142 },150 },
143 resolved: function(unit_name, relation_name, retry, callback) {151 resolved: willError
144 callback(ERR_EV);152 },
145 }},
146 unit: {},153 unit: {},
147 querystring: {}154 querystring: {}
148 });155 });
@@ -257,10 +264,7 @@
257 }},264 }},
258 getModelURL: NO_OP,265 getModelURL: NO_OP,
259 db: db,266 db: db,
260 env:267 env: {set_constraints: willError},
261 { set_constraints: function(id, values, callback) {
262 callback(ERR_EV);
263 }},
264 container: viewContainer}).render();268 container: viewContainer}).render();
265269
266 view.updateConstraints();270 view.updateConstraints();
@@ -274,15 +278,9 @@
274 var view = new views.service_config(278 var view = new views.service_config(
275 { db: db,279 { db: db,
276 env: {280 env: {
277 set_config: function(id, newValues, callback) {281 set_config: willError,
278 callback(ERR_EV);282 expose: willError,
279 },283 unexpose: willError
280 expose: function(id, callback) {
281 callback(ERR_EV);
282 },
283 unexpose: function(id, callback) {
284 callback({err: true, service_name: '1234'});
285 }
286 },284 },
287 getModelURL: NO_OP,285 getModelURL: NO_OP,
288 model: {286 model: {
@@ -329,11 +327,7 @@
329327
330 var view = new views.service_relations(328 var view = new views.service_relations(
331 { db: db,329 { db: db,
332 env: {330 env: {remove_relation: willError},
333 remove_relation: function(id, newValues, callback) {
334 callback(ERR_EV);
335 }
336 },
337 getModelURL: NO_OP,331 getModelURL: NO_OP,
338 container: viewContainer});332 container: viewContainer});
339333
@@ -388,11 +382,7 @@
388 return {get: NO_OP};382 return {get: NO_OP};
389 }383 }
390 },384 },
391 env = {385 env = {deploy: willError},
392 deploy: function(charmUrl, serviceName, config, callback) {
393 callback(ERR_EV);
394 }
395 },
396 mockView = {386 mockView = {
397 fire: NO_OP,387 fire: NO_OP,
398 _deployCallback: function() {388 _deployCallback: function() {
@@ -418,7 +408,7 @@
418 }408 }
419 };409 };
420410
421 views.charm.prototype.on_charm_deploy.apply(mockView, [ERR_EV]);411 views.charm.prototype.on_charm_deploy.call(mockView, ERR_EV);
422 assert.isTrue(notified);412 assert.isTrue(notified);
423 });413 });
424414
425415
=== modified file 'test/test_env.js'
--- test/test_env.js 2013-01-24 04:11:52 +0000
+++ test/test_env.js 2013-01-24 19:23:21 +0000
@@ -10,7 +10,7 @@
10 var Y;10 var Y;
1111
12 describe('Juju environment', function() {12 describe('Juju environment', function() {
13 var juju, conn, env, msg, testUtils;13 var juju, conn, env, msg, testUtils, endpoint1, endpoint2;
1414
15 before(function(done) {15 before(function(done) {
16 Y = YUI(GlobalConfig).use(16 Y = YUI(GlobalConfig).use(
@@ -26,9 +26,13 @@
26 });26 });
27 });27 });
2828
29 after(function(done) {29 beforeEach(function() {
30 endpoint1 = ['service1', {name: 'relation-name-1'}];
31 endpoint2 = ['service2', {name: 'relation-name-2'}];
32 });
33
34 after(function() {
30 env.destroy();35 env.destroy();
31 done();
32 });36 });
3337
34 it('can deploy a service', function() {38 it('can deploy a service', function() {
@@ -217,7 +221,7 @@
217 };221 };
218222
219 it('denies adding a relation if the GUI is read-only', function() {223 it('denies adding a relation if the GUI is read-only', function() {
220 assertOperationDenied('add_relation', ['haproxy:http', 'django:http']);224 assertOperationDenied('add_relation', [endpoint1, endpoint2]);
221 });225 });
222226
223 it('denies adding a unit if the GUI is read-only', function() {227 it('denies adding a unit if the GUI is read-only', function() {
@@ -242,8 +246,7 @@
242 });246 });
243247
244 it('denies removing a relation if the GUI is read-only', function() {248 it('denies removing a relation if the GUI is read-only', function() {
245 assertOperationDenied(249 assertOperationDenied('remove_relation', [endpoint1, endpoint2]);
246 'remove_relation', ['haproxy:http', 'django:http']);
247 });250 });
248251
249 it('denies removing units if the GUI is read-only', function() {252 it('denies removing units if the GUI is read-only', function() {
250253
=== modified file 'test/test_topology_relation.js'
--- test/test_topology_relation.js 2013-01-23 16:46:40 +0000
+++ test/test_topology_relation.js 2013-01-24 19:23:21 +0000
@@ -39,12 +39,12 @@
3939
40 it('fires a "clearState" event if a drag line is clicked', function() {40 it('fires a "clearState" event if a drag line is clicked', function() {
41 var firedEventName;41 var firedEventName;
42 var fauxTopo = {42 var topo = {
43 fire: function(eventName) {43 fire: function(eventName) {
44 firedEventName = eventName;44 firedEventName = eventName;
45 }45 }
46 };46 };
47 view.set('component', fauxTopo);47 view.set('component', topo);
48 view.draglineClicked(undefined, view);48 view.draglineClicked(undefined, view);
49 assert.equal(firedEventName, 'clearState');49 assert.equal(firedEventName, 'clearState');
50 });50 });
@@ -57,4 +57,37 @@
57 assert.equal(view.render(), view);57 assert.equal(view.render(), view);
58 });58 });
5959
60 it('retrieves the current relation DOM element when removing', function() {
61 var requestedSelector;
62 var container = {
63 one: function(selector) {
64 requestedSelector = selector;
65 }
66 };
67 var env = {
68 remove_relation: function() {}
69 };
70 var topo = {
71 get: function() {
72 return env;
73 }
74 };
75 var fauxView = {
76 get: function(name) {
77 if (name === 'component') {
78 return topo;
79 } else if (name === 'container') {
80 return container;
81 }
82 }
83 };
84 var relationId = 'the ID of this relation';
85 var relation = {
86 relation_id: relationId,
87 endpoints: [null, null]
88 };
89 view.removeRelation.call(fauxView, relation, fauxView, undefined);
90 assert.equal(requestedSelector, '#' + relationId);
91 });
92
60});93});

Subscribers

People subscribed via source and target branches