Merge lp:~hatch/juju-gui/bundle-fail-gracefully into lp:juju-gui/experimental

Proposed by Jeff Pihach
Status: Merged
Merged at revision: 1132
Proposed branch: lp:~hatch/juju-gui/bundle-fail-gracefully
Merge into: lp:juju-gui/experimental
Diff against target: 222 lines (+125/-23)
2 files modified
app/subapps/browser/views/bundle.js (+48/-8)
test/test_bundle_details_view.js (+77/-15)
To merge this branch: bzr merge lp:~hatch/juju-gui/bundle-fail-gracefully
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+190769@code.launchpad.net

Description of the change

Bundle topology rendering fails gracefully

If the bundle does not provide proper xy position annotations
on any of the services in its deployer file we do not render
the bundle topology and instead remove the bundle topology
tab, selecting the Charms tab to show the charms the
bundle contains.

Because we don't have any bundles with proper positions right
now I added the flag `strictBundle` to enable this feature.

https://codereview.appspot.com/14502061/

To post a comment you must log in.
Revision history for this message
Jeff Pihach (hatch) wrote :

Reviewers: mp+190769_code.launchpad.net,

Message:
Please take a look.

Description:
Bundle topology rendering fails gracefully

If the bundle does not provide proper xy position annotations
on any of the services in its deployer file we do not render
the bundle topology and instead issue a warning.

Because we don't have any bundles with proper positions right
now I added the flag strictBundle to enable this feature.

https://code.launchpad.net/~hatch/juju-gui/bundle-fail-gracefully/+merge/190769

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/14502061/

Affected files (+119, -23 lines):
   A [revision details]
   M app/subapps/browser/views/bundle.js
   M test/test_bundle_details_view.js

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

Small test change requested, and otherwise code is LGTM. doing qa now.

https://codereview.appspot.com/14502061/diff/1/test/test_bundle_details_view.js
File test/test_bundle_details_view.js (right):

https://codereview.appspot.com/14502061/diff/1/test/test_bundle_details_view.js#newcode188
test/test_bundle_details_view.js:188: 'gui-y': ''
I wonder if we should not allow this either. shrug.

https://codereview.appspot.com/14502061/diff/1/test/test_bundle_details_view.js#newcode208
test/test_bundle_details_view.js:208: view._positionAnnotationsIncluded
= function() {
But this way you are not testing whether _postionAnnotationsIncluded
actually ever can approve something! :-) Can we just adjust the data
instead?

https://codereview.appspot.com/14502061/

1135. By Jeff Pihach

If a bundle topology data is invalid we now don't show the tab at all and instead default to the charms tab

Revision history for this message
Jeff Pihach (hatch) wrote :
Revision history for this message
Jeff Pihach (hatch) wrote :

*** Submitted:

Bundle topology rendering fails gracefully

If the bundle does not provide proper xy position annotations
on any of the services in its deployer file we do not render
the bundle topology and instead remove the bundle topology
tab, selecting the Charms tab to show the charms the
bundle contains.

Because we don't have any bundles with proper positions right
now I added the flag `strictBundle` to enable this feature.

R=gary.poster
CC=
https://codereview.appspot.com/14502061

https://codereview.appspot.com/14502061/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/subapps/browser/views/bundle.js'
--- app/subapps/browser/views/bundle.js 2013-10-11 17:51:10 +0000
+++ app/subapps/browser/views/bundle.js 2013-10-11 22:52:00 +0000
@@ -150,27 +150,67 @@
150 return !/\.svg$/.test(fileName);150 return !/\.svg$/.test(fileName);
151 });151 });
152 var content = this.template(attrs);152 var content = this.template(attrs);
153
154 var node = this.get('container').setHTML(content);153 var node = this.get('container').setHTML(content);
155 var renderTo = this.get('renderTo');154 var renderTo = this.get('renderTo');
156 var options = {size: [480, 360]};155 var options = {size: [480, 360]};
157 this.hideIndicator(renderTo);156 this.hideIndicator(renderTo);
158 this.environment = new views.BundleTopology(Y.mix({157
159 db: this.fakebackend.db,158 var showTopo = true;
160 container: node.one('#bws-bundle'), // Id because of Y.TabView159 // remove the flag in the test(test_bundle_details_view.js)
161 store: this.get('store')160 // when this flag is no longer needed.
162 }, options));161 if (window.flags && window.flags.strictBundle) {
163162 showTopo = this._positionAnnotationsIncluded(attrs.data.services);
164 this.environment.render();163 }
164 if (showTopo) {
165 this.environment = new views.BundleTopology(Y.mix({
166 db: this.fakebackend.db,
167 container: node.one('#bws-bundle'), // Id because of Y.TabView
168 store: this.get('store')
169 }, options));
170 this.environment.render();
171 } else {
172 // Remove the bundle tab so it doesn't get PE'd when
173 // we instantiate the tabview.
174 node.one('#bws-bundle').remove();
175 node.one('a[href=#bws-bundle]').get('parentNode').remove();
176 }
177
165 renderTo.setHTML(node);178 renderTo.setHTML(node);
166179
167 this._setupTabview();180 this._setupTabview();
181 if (!showTopo) {
182 // Select the charms tab as the landing tab if
183 // we aren't showing the bundle topology.
184 this.tabview.selectChild(2);
185 }
168 this._dispatchTabEvents(this.tabview);186 this._dispatchTabEvents(this.tabview);
169187
170 this.set('rendered', true);188 this.set('rendered', true);
171 },189 },
172190
173 /**191 /**
192 Determines if all of the services in the bundle
193 have position annotations.
194
195 @method _positionAnnotationsIncluded
196 @param {Object} services An object of all of the services in the bundle.
197 @return {Boolean} Weather all services have position annotations or not.
198 */
199 _positionAnnotationsIncluded: function(services) {
200 // Some returns true if it's stopped early, this inverts before returning.
201 return !Object.keys(services).some(function(key) {
202 var annotations = services[key].annotations;
203 // If there is no annotations for the position coords
204 // return true stopping the 'some' loop.
205 if (!annotations ||
206 !annotations['gui-x'] ||
207 !annotations['gui-y']) {
208 return true;
209 }
210 });
211 },
212
213 /**
174 Renders the loading indicator into the DOM and then calls214 Renders the loading indicator into the DOM and then calls
175 the _prepareData method to fetch/parse the bundle data for215 the _prepareData method to fetch/parse the bundle data for
176 the real view rendering.216 the real view rendering.
177217
=== modified file 'test/test_bundle_details_view.js'
--- test/test_bundle_details_view.js 2013-10-11 20:13:50 +0000
+++ test/test_bundle_details_view.js 2013-10-11 22:52:00 +0000
@@ -60,6 +60,9 @@
60 entityId: data.id,60 entityId: data.id,
61 renderTo: container61 renderTo: container
62 });62 });
63 view._setupLocalFakebackend = function() {
64 this.fakebackend = utils.makeFakeBackend();
65 };
63 });66 });
6467
65 afterEach(function() {68 afterEach(function() {
@@ -89,9 +92,6 @@
89 });92 });
9093
91 it('displays the bundle data in a tabview', function(done) {94 it('displays the bundle data in a tabview', function(done) {
92 view._setupLocalFakebackend = function() {
93 this.fakebackend = utils.makeFakeBackend();
94 };
95 view.after('renderedChange', function(e) {95 view.after('renderedChange', function(e) {
96 assert.isNotNull(container.one('.yui3-tabview'));96 assert.isNotNull(container.one('.yui3-tabview'));
97 done();97 done();
@@ -112,9 +112,6 @@
112 done();112 done();
113 }113 }
114 });114 });
115 view._setupLocalFakebackend = function() {
116 this.fakebackend = utils.makeFakeBackend();
117 };
118 view.after('renderedChange', function(e) {115 view.after('renderedChange', function(e) {
119 container.one('a.readme').simulate('click');116 container.one('a.readme').simulate('click');
120 });117 });
@@ -134,9 +131,6 @@
134 done();131 done();
135 }132 }
136 });133 });
137 view._setupLocalFakebackend = function() {
138 this.fakebackend = utils.makeFakeBackend();
139 };
140 view.after('renderedChange', function(e) {134 view.after('renderedChange', function(e) {
141 container.one('a.code').simulate('click');135 container.one('a.code').simulate('click');
142 var codeNode = container.one('#bws-code');136 var codeNode = container.one('#bws-code');
@@ -148,9 +142,6 @@
148 });142 });
149143
150 it('renders the proper charm icons into the header', function(done) {144 it('renders the proper charm icons into the header', function(done) {
151 view._setupLocalFakebackend = function() {
152 this.fakebackend = utils.makeFakeBackend();
153 };
154 view.after('renderedChange', function(e) {145 view.after('renderedChange', function(e) {
155 assert.equal(146 assert.equal(
156 container.one('.header .details .charms').all('img').size(),147 container.one('.header .details .charms').all('img').size(),
@@ -161,9 +152,6 @@
161 });152 });
162153
163 it('deploys a bundle when \'add\' button is clicked', function(done) {154 it('deploys a bundle when \'add\' button is clicked', function(done) {
164 view._setupLocalFakebackend = function() {
165 this.fakebackend = utils.makeFakeBackend();
166 };
167 // app.js sets this to its deploy bundle method so155 // app.js sets this to its deploy bundle method so
168 // as long as it's called it's successful.156 // as long as it's called it's successful.
169 view.set('deployBundle', function(data) {157 view.set('deployBundle', function(data) {
@@ -176,4 +164,78 @@
176 view.render();164 view.render();
177 });165 });
178166
167 it('fails gracefully if services don\'t provide xy annotations',
168 function(done) {
169 window.flags = { strictBundle: true };
170 view._parseData = function() {
171 return new Y.Promise(function(resolve) { resolve(); });
172 };
173 view.set('entity', {
174 getAttrs: function() {
175 return {
176 charm_metadata: {},
177 files: [],
178 data: {
179 services: {
180 foo: {
181 annotations: {
182 'gui-x': '',
183 'gui-y': ''
184 }
185 },
186 bar: {}
187 }
188 }
189 };
190 }});
191 view.after('renderedChange', function(e) {
192 assert.isNull(container.one('#bws-bundle'));
193 assert.isNull(container.one('a[href=#bws-bundle]'));
194 // Check that the charms tab is the landing tab
195 assert.equal(view.tabview.get('selection').get('index'), 2);
196 window.flags = {};
197 done();
198 });
199 view.render();
200 });
201
202 it('renders the bundle topology into the view', function(done) {
203 window.flags = { strictBundle: true };
204 view._parseData = function() {
205 return new Y.Promise(function(resolve) { resolve(); });
206 };
207 view.set('entity', {
208 getAttrs: function() {
209 return {
210 charm_metadata: {},
211 files: [],
212 data: {
213 services: {
214 foo: {
215 annotations: {
216 'gui-x': '1',
217 'gui-y': '2'
218 }
219 },
220 bar: {
221 annotations: {
222 'gui-x': '3',
223 'gui-y': '4'
224 }
225 }
226 }
227 }
228 };
229 }});
230 view.after('renderedChange', function(e) {
231 assert.isNotNull(container.one('.topology-canvas'));
232 // Check that the bundle topology tab is the landing tab.
233 assert.equal(view.tabview.get('selection').get('index'), 0);
234 window.flags = {};
235 done();
236 });
237 view.render();
238 });
239
240
179});241});

Subscribers

People subscribed via source and target branches