Merge lp:~gary/juju-gui/nameCheck into lp:juju-gui/experimental

Proposed by Gary Poster
Status: Merged
Merged at revision: 1186
Proposed branch: lp:~gary/juju-gui/nameCheck
Merge into: lp:juju-gui/experimental
Diff against target: 135 lines (+70/-16)
3 files modified
app/views/ghost-inspector.js (+10/-0)
app/views/viewlets/inspector-header.js (+13/-16)
test/test_ghost_inspector.js (+47/-0)
To merge this branch: bzr merge lp:~gary/juju-gui/nameCheck
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+194234@code.launchpad.net

Description of the change

Fix ghost inspector initial name validation

QA: deploy mediawiki with the default name. Make another ghost, and the inspector should correctly show that the default name is invalid.

https://codereview.appspot.com/22500043/

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :
Download full text (5.6 KiB)

Reviewers: mp+194234_code.launchpad.net,

Message:
Please take a look.

Description:
Fix ghost inspector initial name validation

QA: deploy mediawiki with the default name. Make another ghost, and the
inspector should correctly show that the default name is invalid.

Thank you.

https://code.launchpad.net/~gary/juju-gui/nameCheck/+merge/194234

(do not edit description out of merge proposal)

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

Affected files (+60, -16 lines):
   A [revision details]
   M app/views/viewlets/inspector-header.js
   M test/test_ghost_inspector.js

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: <email address hidden>
+New revision: <email address hidden>

Index: test/test_ghost_inspector.js
=== modified file 'test/test_ghost_inspector.js'
--- test/test_ghost_inspector.js 2013-11-05 18:10:05 +0000
+++ test/test_ghost_inspector.js 2013-11-06 21:04:34 +0000
@@ -47,6 +47,7 @@
      conn = new utils.SocketStub();
      db = new models.Database();
      env = juju.newEnvironment({conn: conn});
+ env.connect();
    });

    afterEach(function(done) {
@@ -93,6 +94,52 @@
      return view.createServiceInspector(service, {databinding: {interval:
0}});
    };

+ describe('charm name validity', function() {
+ it('shows when a charm name is invalid initially', function() {
+ db.services.add({id: 'mediawiki', charm: 'cs:precise/mediawiki'});
+ inspector = setUpInspector();
+ var model = inspector.model;
+ var serviceNameInput = Y.one('input[name=service-name]');
+ assert.equal(model.get('displayName'), '(mediawiki)');
+ assert.isTrue(serviceNameInput.hasClass('invalid'));
+ assert.isFalse(serviceNameInput.hasClass('valid'));
+ });
+
+ it('shows when a charm name is valid initially', function() {
+ db.services.add({id: 'mediawiki42', charm: 'cs:precise/mediawiki'});
+ inspector = setUpInspector();
+ var model = inspector.model;
+ var serviceNameInput = Y.one('input[name=service-name]');
+ assert.equal(model.get('displayName'), '(mediawiki)');
+ assert.isFalse(serviceNameInput.hasClass('invalid'));
+ assert.isTrue(serviceNameInput.hasClass('valid'));
+ });
+
+ it('shows when a charm name becomes invalid', function() {
+ db.services.add({id: 'mediawiki42', charm: 'cs:precise/mediawiki'});
+ inspector = setUpInspector();
+ var serviceNameInput = Y.one('input[name=service-name]');
+ // This is usually fired by an event. The event simulation is
broken as
+ // of this writing, and we can do more of a unit test this way.
+ inspector.updateGhostName(
+ {newVal: 'mediawiki42', currentTarget: serviceNameInput});
+ assert.isTrue(serviceNameInput.hasClass('invalid'));
+ assert.isFalse(serviceNameInput.hasClass('valid'));
+ });
+
+ it('shows when a charm name becomes valid', function() {
+ db.services.add({id: 'mediawiki', charm: 'cs:precise/mediawiki'});
+ in...

Read more...

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

LGTM with a small comment request.
QA OK
Thanks for this fix!

https://codereview.appspot.com/22500043/diff/1/app/views/viewlets/inspector-header.js
File app/views/viewlets/inspector-header.js (right):

https://codereview.appspot.com/22500043/diff/1/app/views/viewlets/inspector-header.js#newcode59
app/views/viewlets/inspector-header.js:59: var name =
pojoModel.displayName.match(/^\(([^)]*)\)$/)[1];
I'd love it if there was a quick comment describing what this regex
looks for to make the code easier to scan.

https://codereview.appspot.com/22500043/diff/1/test/test_ghost_inspector.js
File test/test_ghost_inspector.js (right):

https://codereview.appspot.com/22500043/diff/1/test/test_ghost_inspector.js#newcode50
test/test_ghost_inspector.js:50: env.connect();
Ahh the shibboleth of writing environment tests.....you may proceed.

https://codereview.appspot.com/22500043/

lp:~gary/juju-gui/nameCheck updated
1184. By Gary Poster

merge trunk

1185. By Gary Poster

add explanatory comments per review

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

*** Submitted:

Fix ghost inspector initial name validation

QA: deploy mediawiki with the default name. Make another ghost, and the
inspector should correctly show that the default name is invalid.

R=jeff.pihach
CC=
https://codereview.appspot.com/22500043

https://codereview.appspot.com/22500043/

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

On 2013/11/06 21:20:50, jeff.pihach wrote:
...

https://codereview.appspot.com/22500043/diff/1/app/views/viewlets/inspector-header.js#newcode59
> app/views/viewlets/inspector-header.js:59: var name =
> pojoModel.displayName.match(/^\(([^)]*)\)$/)[1];
> I'd love it if there was a quick comment describing what this regex
looks for to
> make the code easier to scan.

You want comments? I'm your man! Done. :-)

Thanks for the review!

https://codereview.appspot.com/22500043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'app/views/ghost-inspector.js'
2--- app/views/ghost-inspector.js 2013-10-15 19:33:04 +0000
3+++ app/views/ghost-inspector.js 2013-11-06 21:41:10 +0000
4@@ -170,6 +170,11 @@
5 @param {Y.EventFacade} e event object from valuechange.
6 */
7 updateGhostName: function(e) {
8+ // This code has a fragile dependency: the inspector-header.js render
9+ // method expects these parentheses around the model displayName. If you
10+ // change this format, or this code, make sure you look at that method
11+ // too. Hopefully the associated tests will catch it as well.
12+ // Also see resetCanvas, below.
13 var name = '(' + e.newVal + ')';
14 this.model.set('displayName', name);
15 this.serviceNameInputStatus(
16@@ -184,6 +189,11 @@
17 @method resetCanvas
18 */
19 resetCanvas: function() {
20+ // This code has a fragile dependency: the inspector-header.js render
21+ // method expects these parentheses around the model displayName. If you
22+ // change this format, or this code, make sure you look at that method
23+ // too. Hopefully the associated tests will catch it as well.
24+ // Also see updateGhostName, above.
25 this.model.set('displayName', '(' + this.model.get('packageName') + ')');
26 this.viewletManager.destroy();
27 },
28
29=== modified file 'app/views/viewlets/inspector-header.js'
30--- app/views/viewlets/inspector-header.js 2013-09-30 15:38:34 +0000
31+++ app/views/viewlets/inspector-header.js 2013-11-06 21:41:10 +0000
32@@ -48,25 +48,22 @@
33 'render': function(model, viewContainerAttrs) {
34 this.container = Y.Node.create(this.templateWrapper);
35 var pojoModel = model.getAttrs();
36- if (model instanceof models.Charm) {
37- pojoModel.ghost = true;
38- pojoModel.charmUrl = pojoModel.id;
39- } else if (model instanceof models.Service) {
40- pojoModel.charmUrl = pojoModel.charm;
41- } else {
42- throw 'Programmer error: unknown model type';
43- }
44+ pojoModel.charmUrl = pojoModel.charm;
45 // Manually add the icon url for the charm since we don't have access to
46 // the browser handlebars helper at this location.
47 pojoModel.icon = viewContainerAttrs.store.iconpath(pojoModel.charmUrl);
48-
49- // Check if there is already a service using the default name to
50- // trigger the name ux.
51- if (utils.checkForExistingService(pojoModel.name,
52- viewContainerAttrs.db)) {
53- pojoModel.invalidName = 'invalid';
54- } else {
55- pojoModel.invalidName = 'valid';
56+ if (pojoModel.pending) {
57+ // Check if there is already a service using the default name to
58+ // trigger the name ux.
59+ // This regex simply removes the outer parentheses from the
60+ // displayName that is set in the ghost-inspector.js updateGhostName
61+ // method. If the regex doesn't match, blow up. It should match.
62+ var name = pojoModel.displayName.match(/^\(([^)]*)\)$/)[1];
63+ if (utils.checkForExistingService(name, viewContainerAttrs.db)) {
64+ pojoModel.invalidName = 'invalid';
65+ } else {
66+ pojoModel.invalidName = 'valid';
67+ }
68 }
69
70 this.container.setHTML(this.template(pojoModel));
71
72=== modified file 'test/test_ghost_inspector.js'
73--- test/test_ghost_inspector.js 2013-11-05 18:10:05 +0000
74+++ test/test_ghost_inspector.js 2013-11-06 21:41:10 +0000
75@@ -47,6 +47,7 @@
76 conn = new utils.SocketStub();
77 db = new models.Database();
78 env = juju.newEnvironment({conn: conn});
79+ env.connect();
80 });
81
82 afterEach(function(done) {
83@@ -93,6 +94,52 @@
84 return view.createServiceInspector(service, {databinding: {interval: 0}});
85 };
86
87+ describe('charm name validity', function() {
88+ it('shows when a charm name is invalid initially', function() {
89+ db.services.add({id: 'mediawiki', charm: 'cs:precise/mediawiki'});
90+ inspector = setUpInspector();
91+ var model = inspector.model;
92+ var serviceNameInput = Y.one('input[name=service-name]');
93+ assert.equal(model.get('displayName'), '(mediawiki)');
94+ assert.isTrue(serviceNameInput.hasClass('invalid'));
95+ assert.isFalse(serviceNameInput.hasClass('valid'));
96+ });
97+
98+ it('shows when a charm name is valid initially', function() {
99+ db.services.add({id: 'mediawiki42', charm: 'cs:precise/mediawiki'});
100+ inspector = setUpInspector();
101+ var model = inspector.model;
102+ var serviceNameInput = Y.one('input[name=service-name]');
103+ assert.equal(model.get('displayName'), '(mediawiki)');
104+ assert.isFalse(serviceNameInput.hasClass('invalid'));
105+ assert.isTrue(serviceNameInput.hasClass('valid'));
106+ });
107+
108+ it('shows when a charm name becomes invalid', function() {
109+ db.services.add({id: 'mediawiki42', charm: 'cs:precise/mediawiki'});
110+ inspector = setUpInspector();
111+ var serviceNameInput = Y.one('input[name=service-name]');
112+ // This is usually fired by an event. The event simulation is broken as
113+ // of this writing, and we can do more of a unit test this way.
114+ inspector.updateGhostName(
115+ {newVal: 'mediawiki42', currentTarget: serviceNameInput});
116+ assert.isTrue(serviceNameInput.hasClass('invalid'));
117+ assert.isFalse(serviceNameInput.hasClass('valid'));
118+ });
119+
120+ it('shows when a charm name becomes valid', function() {
121+ db.services.add({id: 'mediawiki', charm: 'cs:precise/mediawiki'});
122+ inspector = setUpInspector();
123+ var serviceNameInput = Y.one('input[name=service-name]');
124+ // This is usually fired by an event. The event simulation is broken as
125+ // of this writing, and we can do more of a unit test this way.
126+ inspector.updateGhostName(
127+ {newVal: 'mediawiki42', currentTarget: serviceNameInput});
128+ assert.isFalse(serviceNameInput.hasClass('invalid'));
129+ assert.isTrue(serviceNameInput.hasClass('valid'));
130+ });
131+ });
132+
133 it('updates the service name in the topology when changed in the inspector',
134 function(done) {
135 // XXX (Jeff) YUI's simulate can't properly simulate focus or blur in

Subscribers

People subscribed via source and target branches