Merge lp:~hatch/juju-gui/auth-routes into lp:juju-gui/experimental

Proposed by Jeff Pihach
Status: Merged
Merged at revision: 662
Proposed branch: lp:~hatch/juju-gui/auth-routes
Merge into: lp:juju-gui/experimental
Diff against target: 927 lines (+207/-176)
13 files modified
app/app.js (+37/-44)
app/index.html (+1/-1)
app/store/env/go.js (+1/-1)
app/store/env/python.js (+1/-0)
docs/unit-testing.rst (+20/-0)
lib/views/stylesheet.less (+2/-1)
test/index.html (+1/-0)
test/test_app.js (+101/-111)
test/test_app_hotkeys.js (+3/-2)
test/test_browser_charm_details.js (+14/-14)
test/test_endpoints.js (+3/-1)
test/test_env_go.js (+20/-1)
test/test_notifications.js (+3/-0)
To merge this branch: bzr merge lp:~hatch/juju-gui/auth-routes
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+163732@code.launchpad.net

Description of the change

Converted login/logout to use routes

Login/Logout is now controlled via the routing system
this caused a number of issues with the order of
operations for the auth system so I would love
another QA using all three back ends please.

https://codereview.appspot.com/9415043/

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

Reviewers: mp+163732_code.launchpad.net,

Message:
Please take a look.

Description:
Converted login/logout to use routes

Login/Logout is now controlled via the routing system
this caused a number of issues with the order of
operations for the auth system so I would love
another QA using all three back ends please.

https://code.launchpad.net/~hatch/juju-gui/auth-routes/+merge/163732

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   M app/app.js
   M app/config-debug.js
   M app/index.html
   M app/store/env/go.js
   M app/store/env/python.js
   M test/index.html
   M test/test_app.js
   M test/test_app_hotkeys.js
   M test/test_endpoints.js
   M test/test_env_go.js
   M test/test_notifications.js

lp:~hatch/juju-gui/auth-routes updated
656. By Jeff Pihach

fixing tests

657. By Jeff Pihach

refactored app tests

658. By Jeff Pihach

lint

659. By Jeff Pihach

fixed go auth test

660. By Jeff Pihach

merged trunk

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

QA Issues

1) Improv + large.json
2) View a service
3) Logout
4) Get /login/:gui:/... url resulting in a blank page

Need to clear the namespace on login/logout navigation

https://codereview.appspot.com/9415043/

lp:~hatch/juju-gui/auth-routes updated
661. By Jeff Pihach

fixed namespace logout issue

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

LGTM

We may want a note in HACKING about having to disable navigate for
testing as this happens quite a few places and people are likely to hit
it again.

https://codereview.appspot.com/9415043/

lp:~hatch/juju-gui/auth-routes updated
662. By Jeff Pihach

added docs to outline unit testing issues

Revision history for this message
Jeff Pihach (hatch) wrote :
Revision history for this message
Madison Scott-Clary (makyo) wrote :

Code LGTM - no QA for now, but might get to it later.

https://codereview.appspot.com/9415043/diff/16001/app/app.js
File app/app.js (right):

https://codereview.appspot.com/9415043/diff/16001/app/app.js#newcode825
app/app.js:825: this.showRootView();
What does this mean for the story of getting pasted a link by a
coworker, then having to log in and losing the link? As long as this is
acceptable, cool.

https://codereview.appspot.com/9415043/diff/16001/app/app.js#newcode875
app/app.js:875: @param {function} next callable for the next route Rin
the chain.
Revert.

https://codereview.appspot.com/9415043/diff/16001/test/test_app.js
File test/test_app.js (right):

https://codereview.appspot.com/9415043/diff/16001/test/test_app.js#newcode171
test/test_app.js:171: // app = new Y.juju.App(
Do we need this?

https://codereview.appspot.com/9415043/diff/16001/test/test_app.js#newcode349
test/test_app.js:349: it('login method hanlder is called after
successful login', function(done) {
Not a huge fan of the wording, since the 'it' is intended to be part of
the test name. However we haven't been sticking to this very well, so
I'll defer and create a card.

https://codereview.appspot.com/9415043/

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

Thanks for the reviews guys - I will await the QA from you Matt before I
merge just to be safe.

https://codereview.appspot.com/9415043/diff/16001/app/app.js
File app/app.js (right):

https://codereview.appspot.com/9415043/diff/16001/app/app.js#newcode825
app/app.js:825: this.showRootView();
I was wondering the same - I have created a card to discuss Friday

https://codereview.appspot.com/9415043/diff/16001/app/app.js#newcode875
app/app.js:875: @param {function} next callable for the next route Rin
the chain.
On 2013/05/14 23:24:54, matthew.scott wrote:
> Revert.

Done.

https://codereview.appspot.com/9415043/diff/16001/test/test_app.js
File test/test_app.js (right):

https://codereview.appspot.com/9415043/diff/16001/test/test_app.js#newcode171
test/test_app.js:171: // app = new Y.juju.App(
Nope removed.

https://codereview.appspot.com/9415043/

lp:~hatch/juju-gui/auth-routes updated
663. By Jeff Pihach

fixes from review

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

*** Submitted:

Converted login/logout to use routes

Login/Logout is now controlled via the routing system
this caused a number of issues with the order of
operations for the auth system so I would love
another QA using all three back ends please.

R=bcsaller, matthew.scott
CC=
https://codereview.appspot.com/9415043

https://codereview.appspot.com/9415043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'app/app.js'
2--- app/app.js 2013-05-14 15:09:07 +0000
3+++ app/app.js 2013-05-15 00:00:36 +0000
4@@ -169,7 +169,7 @@
5 },
6 'A-e': {
7 callback: function(evt) {
8- this.fire('navigateTo', {url: '/:gui:/'});
9+ this.fire('navigateTo', { url: '/:gui:/' });
10 },
11 help: 'Navigate to the Environment overview.'
12 },
13@@ -412,7 +412,6 @@
14 if (credentials && credentials.areAvailable) {
15 this.env.login();
16 }
17- this.dispatch();
18 }
19 }, this);
20
21@@ -456,6 +455,8 @@
22 }, this);
23 }
24
25+ Y.one('#logout-trigger').on('click', this.logout, this);
26+
27 // Attach SubApplications
28 // The subapps should share the same db.
29 cfg.db = this.db;
30@@ -563,8 +564,8 @@
31 level: 'error'
32 })
33 );
34- self.fire('navigateTo', {url: self.nsRouter.url(
35- {gui: '/service/' + serviceId})});
36+ self.navigate(self.nsRouter.url(
37+ {gui: '/service/' + serviceId}));
38 }
39 },
40 // If there is no service available then there definitely is no unit
41@@ -579,7 +580,7 @@
42 level: 'error'
43 })
44 );
45- self.fire('navigateTo', {url: self.nsRouter.url({gui: '/'})});
46+ self.navigate(self.nsRouter.url({gui: '/'}));
47 });
48 },
49
50@@ -698,10 +699,10 @@
51 /**
52 * Show the login screen.
53 *
54- * @method show_login
55+ * @method showLogin
56 * @return {undefined} Nothing.
57 */
58- show_login: function() {
59+ showLogin: function() {
60 this.showView('login', {
61 env: this.env,
62 help_text: this.get('login_help')
63@@ -721,11 +722,15 @@
64 * @return {undefined} Nothing.
65 */
66 logout: function(req) {
67+ // Clears out the topology local database on log out
68+ // because we clear out the environment database as well.
69+ // The order of these is important because we need to tell
70+ // the env to log out after it's navigated to make sure that
71+ // it always shows the login screen
72+ this.views.environment.instance.topo.update();
73+ this.navigate('/login/', { overrideAllNamespaces: true });
74 this.env.logout();
75- this.show_login();
76- // This flag will trigger a URL reset in check_user_credentials as the
77- // routing finishes.
78- this.loggingOut = true;
79+ return;
80 },
81
82 // Persistent Views
83@@ -755,13 +760,13 @@
84 /**
85 * Ensure that the current user has authenticated.
86 *
87- * @method check_user_credentials
88+ * @method checkUserCredentials
89 * @param {Object} req The request.
90 * @param {Object} res ???
91 * @param {Object} next The next route handler.
92 *
93 */
94- check_user_credentials: function(req, res, next) {
95+ checkUserCredentials: function(req, res, next) {
96 // If the Juju environment is not connected, exit without letting the
97 // route dispatch proceed. On env connection change, the app will
98 // re-dispatch and this route callback will be executed again.
99@@ -775,26 +780,12 @@
100 // form was never shown - this handles that edge case.
101 var noCredentials = !(credentials && credentials.areAvailable);
102 if (noCredentials) {
103- // If there are no stored credentials, the user is prompted for some.
104- this.show_login();
105- }
106- if (!this.env.userIsAuthenticated) {
107- // If there has not been a successful login attempt, do not let the
108- // route dispatch proceed.
109- if (noCredentials && this.loggingOut) {
110- // Handle logging out.
111- this.loggingOut = false;
112- this.showRootView();
113+ // If there are no stored credentials redirect to the login page
114+ if (req.path !== '/login/') {
115+ this.navigate('/login/');
116+ return;
117 }
118- // At this point, there can be credentials available, but there has not
119- // been a successful login attempt. Assuming this can happen only
120- // at the beginning of the auth process, and that the auth process
121- // always starts right after the environment is connected, we can just
122- // return here, because the connectedChange subscriber should take
123- // care of performing a login attempt.
124- return;
125 }
126- // The route dispatch can proceed if the user is authenticated.
127 next();
128 },
129
130@@ -830,17 +821,11 @@
131 */
132 onLogin: function(evt) {
133 if (evt.data.result) {
134- var mask = Y.one('#full-screen-mask');
135- if (mask) {
136- mask.hide();
137- // Stop the animated loading spinner.
138- if (spinner) {
139- spinner.stop();
140- }
141- }
142- this.dispatch();
143+ // Navigates to / overriding all namespaces
144+ this.showRootView();
145+ return;
146 } else {
147- this.show_login();
148+ this.showLogin();
149 }
150 },
151
152@@ -928,6 +913,14 @@
153 if (!this.renderEnvironment) {
154 next(); return;
155 }
156+ var mask = Y.one('#full-screen-mask');
157+ if (mask) {
158+ mask.hide();
159+ // Stop the animated loading spinner.
160+ if (spinner) {
161+ spinner.stop();
162+ }
163+ }
164 var self = this,
165 view = this.getViewInfo('environment'),
166 options = {
167@@ -1110,7 +1103,7 @@
168 routes: {
169 value: [
170 // Called on each request.
171- { path: '*', callbacks: 'check_user_credentials'},
172+ { path: '*', callbacks: 'checkUserCredentials'},
173 { path: '*', callbacks: 'show_notifications_view'},
174 { path: '*', callbacks: 'toggleStaticViews'},
175 { path: '*', callbacks: 'show_environment'},
176@@ -1154,8 +1147,8 @@
177 namespace: 'gui'},
178 // Feature flags.
179 { path: '*', callbacks: 'featureFlags', namespace: 'flags' },
180- // Logout.
181- { path: '/logout/', callbacks: 'logout'}
182+ // Authorization
183+ { path: '/login/', callbacks: 'showLogin' }
184 ]
185 }
186 }
187
188=== modified file 'app/index.html'
189--- app/index.html 2013-05-13 16:58:10 +0000
190+++ app/index.html 2013-05-15 00:00:36 +0000
191@@ -99,7 +99,7 @@
192 </span>
193 <span class="nav-container">
194 <span class="nav-section active-border">
195- <a href="/logout/" id="logout-trigger">Logout</a>
196+ <div id="logout-trigger">Logout</div>
197 </span>
198 </span>
199 <span class="nav-container" id="charm-search-trigger-container">
200
201=== modified file 'app/store/env/go.js'
202--- app/store/env/go.js 2013-04-18 21:30:29 +0000
203+++ app/store/env/go.js 2013-05-15 00:00:36 +0000
204@@ -227,7 +227,7 @@
205 /**
206 * React to the results of sending a login message to the server.
207 *
208- * @method handleLoginEvent
209+ * @method handleLogin
210 * @param {Object} data The response returned by the server.
211 * @return {undefined} Nothing.
212 */
213
214=== modified file 'app/store/env/python.js'
215--- app/store/env/python.js 2013-05-02 20:13:10 +0000
216+++ app/store/env/python.js 2013-05-15 00:00:36 +0000
217@@ -297,6 +297,7 @@
218 login: function() {
219 // If the user is already authenticated there is nothing to do.
220 if (this.userIsAuthenticated) {
221+ this.fire('login', { data: { result: true }});
222 return;
223 }
224 var credentials = this.getCredentials();
225
226=== added file 'docs/unit-testing.rst'
227--- docs/unit-testing.rst 1970-01-01 00:00:00 +0000
228+++ docs/unit-testing.rst 2013-05-15 00:00:36 +0000
229@@ -0,0 +1,20 @@
230+==========
231+Unit Tests
232+==========
233+
234+The JUJU GUI project uses the `mocha.js`__ test framework for its unit tests.
235+As the application complexity grows there are a number of 'gotchas' in the
236+application which can result in huge headaches when trying to write or modify
237+the unit tests. This document is the go-to resource to document these and should
238+be read thoroughly before you modify or write additional tests.
239+
240+__ http://visionmedia.github.io/mocha/
241+
242+noop app.navigate() when instantiating app
243+------------------------------------------
244+
245+Because the login system now automatically dispatches depending on the users
246+credentials, saved or otherwise, navigate() needs to be noop'ed when
247+instantiating app to stop it from navigating during tests::
248+
249+ app.navigate = function() {};
250
251=== modified file 'lib/views/stylesheet.less'
252--- lib/views/stylesheet.less 2013-05-04 21:16:56 +0000
253+++ lib/views/stylesheet.less 2013-05-15 00:00:36 +0000
254@@ -149,6 +149,7 @@
255 cursor: pointer;
256 }
257 #logout-trigger {
258+ cursor: pointer;
259 display: inline-block;
260 padding: 5px 0 8px 5px;
261 }
262@@ -289,7 +290,7 @@
263 padding: 1em;
264 .create-border-radius('black');
265 .create-box-shadow(-2px 4px 4px 0 rgba(0, 0, 0, 0.5));
266-
267+
268 background-color: black;
269 color: white;
270
271
272=== modified file 'test/index.html'
273--- test/index.html 2013-05-10 23:25:01 +0000
274+++ test/index.html 2013-05-15 00:00:36 +0000
275@@ -109,6 +109,7 @@
276
277 <body>
278 <div id="shortcut-help" style="display: none"></div>
279+ <div id="logout-trigger" style="display: none"></div>
280 <div id="main" class="container"></div>
281 <div id="mocha"></div>
282 </body>
283
284=== modified file 'test/test_app.js'
285--- test/test_app.js 2013-05-06 00:49:09 +0000
286+++ test/test_app.js 2013-05-15 00:00:36 +0000
287@@ -38,7 +38,7 @@
288
289 before(function(done) {
290 Y = YUI(GlobalConfig).use(
291- ['juju-gui', 'juju-tests-utils', 'juju-view-utils'],
292+ ['juju-gui', 'juju-tests-utils', 'juju-view-utils', 'juju-views'],
293 function(Y) {
294 utils = Y.namespace('juju-tests.utils');
295 juju = Y.namespace('juju');
296@@ -56,70 +56,84 @@
297 .append(Y.Node.create('<span/>')
298 .addClass('provider-type'))
299 .hide();
300- conn = new utils.SocketStub();
301- env = juju.newEnvironment({conn: conn});
302- env.connect();
303- app = new Y.juju.App({
304- container: container,
305- viewContainer: container,
306- env: env
307+
308+ });
309+
310+ afterEach(function(done) {
311+ app.after('destroy', function() {
312+ container.remove(true);
313+ sessionStorage.setItem('credentials', null);
314+ done();
315 });
316+
317+ app.destroy();
318+ });
319+
320+ function constructAppInstance(config) {
321+ config = config || {};
322+ if (config.env && config.env.connect) {
323+ config.env.connect();
324+ }
325+ config.container = container;
326+ config.viewContainer = container;
327+
328+ app = new Y.juju.App(config);
329+ app.navigate = function() {};
330 app.showView(new Y.View());
331 injectData(app);
332- });
333-
334- afterEach(function() {
335- app.destroy();
336- container.remove(true);
337- sessionStorage.setItem('credentials', null);
338- });
339+ return app;
340+ }
341
342 it('should not have login credentials if missing from the configuration',
343 function() {
344- app.render();
345+ constructAppInstance({
346+ env: juju.newEnvironment({ conn: new utils.SocketStub() })
347+ });
348 assert.equal(app.env.get('user'), undefined);
349 assert.equal(app.env.get('password'), undefined);
350 });
351
352 it('should propagate login credentials from the configuration',
353- function() {
354+ function(done) {
355 var the_username = 'nehi';
356 var the_password = 'moonpie';
357- // Replace the existing app.
358- app.destroy();
359 app = new Y.juju.App(
360 { container: container,
361 user: the_username,
362 password: the_password,
363 viewContainer: container,
364 conn: {close: function() {}}});
365- app.showView(new Y.View());
366- var credentials = app.env.getCredentials();
367- credentials.user.should.equal(the_username);
368- credentials.password.should.equal(the_password);
369+ app.after('ready', function() {
370+ var credentials = app.env.getCredentials();
371+ credentials.user.should.equal(the_username);
372+ credentials.password.should.equal(the_password);
373+ done();
374+ });
375 });
376
377 it('propagates the readOnly option from the configuration', function() {
378- // Replace the existing app.
379- app.destroy();
380 app = new Y.juju.App({
381 container: container,
382 readOnly: true,
383 viewContainer: container,
384 conn: {close: function() {}}
385 });
386- app.showView(new Y.View());
387 assert.isTrue(app.env.get('readOnly'));
388 });
389
390 it('should produce a valid index', function() {
391+ constructAppInstance({
392+ env: juju.newEnvironment({ conn: new utils.SocketStub() })
393+ });
394 var container = app.get('container');
395- app.render();
396 container.getAttribute('id').should.equal('test-container');
397 container.getAttribute('class').should.include('container');
398 });
399
400 it('should be able to route objects to internal URLs', function() {
401+ constructAppInstance({
402+ env: juju.newEnvironment({ conn: new utils.SocketStub() })
403+ });
404 // Take handles to database objects and ensure we can route to the view
405 // needed to show them.
406 var wordpress = app.db.services.getById('wordpress'),
407@@ -145,13 +159,15 @@
408
409 it('should display the configured environment name', function() {
410 var environment_name = 'This is the environment name. Deal with it.';
411- app.destroy();
412- app = new Y.juju.App(
413- { container: container,
414- viewContainer: container,
415- environment_name: environment_name,
416- conn: {close: function() {}}});
417- app.showView(new Y.View());
418+ constructAppInstance({
419+ env: juju.newEnvironment({
420+ conn: {
421+ send: function() {},
422+ close: function() {}
423+ }
424+ }),
425+ environment_name: environment_name
426+ });
427 assert.equal(
428 container.one('#environment-name').get('text'),
429 environment_name);
430@@ -159,18 +175,23 @@
431
432 it('should show a generic environment name if none configured',
433 function() {
434- app.destroy();
435- app = new Y.juju.App(
436- { container: container,
437- viewContainer: container,
438- conn: {close: function() {}}});
439- app.showView(new Y.View());
440+ constructAppInstance({
441+ env: juju.newEnvironment({
442+ conn: {
443+ send: function() {},
444+ close: function() {}
445+ }
446+ })
447+ });
448 assert.equal(
449 container.one('#environment-name').get('text'),
450 'Environment');
451 });
452
453 it('should show the provider type, when available', function() {
454+ constructAppInstance({
455+ env: juju.newEnvironment({ conn: new utils.SocketStub() })
456+ });
457 var providerType = 'excellent provider';
458 // Since no provider type has been set yet, none is displayed.
459 assert.equal('', container.one('.provider-type').get('text'));
460@@ -183,10 +204,13 @@
461 });
462
463 it('hides the browser subapp on some urls', function() {
464- var app = new Y.juju.App({
465- container: container,
466- viewContainer: container,
467- conn: {close: function() {}}
468+ constructAppInstance({
469+ env: juju.newEnvironment({
470+ conn: {
471+ send: function() {},
472+ close: function() {}
473+ }
474+ })
475 });
476
477 var checkUrls = [{
478@@ -215,7 +239,6 @@
479 app.toggleStaticViews(req, undefined, next);
480 app.get('subApps').charmstore.hidden.should.eql(check.hidden);
481 });
482- app.destroy();
483 });
484
485 });
486@@ -259,11 +282,17 @@
487 });
488
489 // Create and return a new app. If connect is True, also connect the env.
490- var makeApp = function(connect) {
491- var app = new Y.juju.App({env: env, viewContainer: container});
492- var fakeView = new Y.View();
493- fakeView.name = FAKE_VIEW_NAME;
494- app.showView(fakeView);
495+ var makeApp = function(connect, fakeview) {
496+ var app = new Y.juju.App({
497+ env: env,
498+ viewContainer: container,
499+ consoleEnabled: true
500+ });
501+ if (fakeview) {
502+ var fakeView = new Y.View();
503+ fakeView.name = FAKE_VIEW_NAME;
504+ app.showView(fakeView);
505+ }
506 if (connect) {
507 env.connect();
508 }
509@@ -275,7 +304,6 @@
510 var app = makeApp(false); // Create a disconnected app.
511 app.after('ready', function() {
512 assert.equal(0, conn.messages.length);
513- assert.equal(FAKE_VIEW_NAME, app.get('activeView').name);
514 done();
515 });
516 });
517@@ -285,7 +313,6 @@
518 app.after('ready', function() {
519 assert.equal(1, conn.messages.length);
520 assert.equal('login', conn.last_message().op);
521- assert.equal(FAKE_VIEW_NAME, app.get('activeView').name);
522 done();
523 });
524 });
525@@ -293,9 +320,10 @@
526 it('avoids trying to login without credentials', function(done) {
527 env.setCredentials(null);
528 var app = makeApp(true); // Create a connected app.
529+ app.navigate = function() { return; };
530 app.after('ready', function() {
531- assert.equal(0, conn.messages.length);
532- assert.equal(LOGIN_VIEW_NAME, app.get('activeView').name);
533+ assert.equal(app.env.getCredentials(), null);
534+ assert.equal(conn.messages.length, 0);
535 done();
536 });
537 });
538@@ -312,40 +340,29 @@
539 });
540 });
541
542- it('displays the env view if credentials are valid', function(done) {
543- var app = makeApp(true); // Create a connected app.
544- app.after('ready', function() {
545- // Mimic a login successful response.
546- conn.msg({op: 'login', result: true});
547- assert.equal(1, conn.messages.length);
548- assert.equal('login', conn.last_message().op);
549- assert.equal(ENV_VIEW_NAME, app.get('activeView').name);
550+ it('login method hanlder is called after successful login', function(done) {
551+ var oldOnLogin = Y.juju.App.onLogin;
552+ Y.juju.App.prototype.onLogin = function(e) {
553+ assert.equal(conn.messages.length, 1);
554+ assert.equal(conn.last_message().op, 'login');
555+ assert.equal(e.data.result, true);
556+ Y.juju.App.onLogin = oldOnLogin;
557 done();
558- });
559+ };
560+ var app = new Y.juju.App({ env: env, viewContainer: container });
561+ env.connect();
562+ app.env.userIsAuthenticated = true;
563+ app.env.login();
564+ app.destroy(true);
565 });
566
567 it('tries to log in on first connection', function(done) {
568 // This is the case when credential are stashed.
569- var app = makeApp(false); // Create a disconnected app.
570+ var app = makeApp(true); // Create a disconnected app.
571 app.after('ready', function() {
572- assert.equal(FAKE_VIEW_NAME, app.get('activeView').name);
573 env.connect();
574 assert.equal(1, conn.messages.length);
575 assert.equal('login', conn.last_message().op);
576- assert.equal(FAKE_VIEW_NAME, app.get('activeView').name);
577- done();
578- });
579- });
580-
581- it('displays the login view on first connection', function(done) {
582- // This is the case when credential are not stashed.
583- env.setCredentials(null);
584- var app = makeApp(false); // Create a disconnected app.
585- app.after('ready', function() {
586- assert.equal(FAKE_VIEW_NAME, app.get('activeView').name);
587- env.connect();
588- assert.equal(0, conn.messages.length);
589- assert.equal(LOGIN_VIEW_NAME, app.get('activeView').name);
590 done();
591 });
592 });
593@@ -361,22 +378,6 @@
594 Y.each(conn.messages, function(message) {
595 assert.equal('login', message.op);
596 });
597- assert.equal(FAKE_VIEW_NAME, app.get('activeView').name);
598- done();
599- });
600- });
601-
602- it('displays the login view on disconnections', function(done) {
603- // This is the case when credential are not stashed.
604- env.setCredentials(null);
605- var app = makeApp(true); // Create a connected app.
606- app.after('ready', function() {
607- conn.msg({op: 'login', result: true});
608- assert.equal(ENV_VIEW_NAME, app.get('activeView').name);
609- conn.transient_close();
610- conn.open();
611- assert.equal(0, conn.messages.length);
612- assert.equal(LOGIN_VIEW_NAME, app.get('activeView').name);
613 done();
614 });
615 });
616@@ -388,20 +389,9 @@
617 assert.equal(null, env.getCredentials());
618 });
619
620- it('displays the login view after logging out', function(done) {
621- var app = makeApp(true); // Create a connected app.
622- app.after('ready', function() {
623- conn.msg({op: 'login', result: true});
624- assert.equal(ENV_VIEW_NAME, app.get('activeView').name);
625- app.logout();
626- assert.equal(LOGIN_VIEW_NAME, app.get('activeView').name);
627- done();
628- });
629- });
630 });
631 })();
632
633-
634 (function() {
635
636 describe('Application Connection State', function() {
637@@ -418,7 +408,7 @@
638
639 it('should be able to handle env connection status changes', function() {
640 var juju = Y.namespace('juju'),
641- conn = new(Y.namespace('juju-tests.utils')).SocketStub(),
642+ conn = new Y['juju-tests'].utils.SocketStub(),
643 env = juju.newEnvironment({
644 conn: conn,
645 user: 'user',
646@@ -460,18 +450,17 @@
647 conn.open();
648 // We need to fake the connection event.
649 reset_called.should.equal(true);
650- dispatch_called.should.equal(true);
651+ //dispatch_called.should.equal(true);
652 login_called.should.equal(true);
653
654 // Trigger a second time and verify.
655 conn.transient_close();
656 reset_called = false;
657- dispatch_called = false;
658 login_called = false;
659 conn.open();
660 reset_called.should.equal(true);
661- dispatch_called.should.equal(true);
662- login_called.should.equal(true);
663+ //dispatch_called.should.equal(true);
664+ app.destroy();
665 });
666
667 });
668@@ -621,3 +610,4 @@
669
670 });
671 })();
672+
673
674=== modified file 'test/test_app_hotkeys.js'
675--- test/test_app_hotkeys.js 2013-05-06 16:18:15 +0000
676+++ test/test_app_hotkeys.js 2013-05-15 00:00:36 +0000
677@@ -59,7 +59,7 @@
678 assert.equal(searchInput, Y.one(document.activeElement));
679 });
680
681- it('should listen for alt-E events', function() {
682+ it('should listen for alt-E events', function(done) {
683 var altEtriggered = false;
684 app.on('navigateTo', function(ev) {
685 if (ev && ev.url === '/:gui:/') {
686@@ -67,12 +67,13 @@
687 }
688 // Avoid URL change performed by additional listeners.
689 ev.stopImmediatePropagation();
690+ assert.isTrue(altEtriggered);
691+ done();
692 });
693 windowNode.simulate('keydown', {
694 keyCode: 69, // "E" key.
695 altKey: true
696 });
697- assert.isTrue(altEtriggered);
698 });
699
700 });
701
702=== modified file 'test/test_browser_charm_details.js'
703--- test/test_browser_charm_details.js 2013-05-13 18:43:47 +0000
704+++ test/test_browser_charm_details.js 2013-05-15 00:00:36 +0000
705@@ -286,7 +286,7 @@
706 });
707
708 it('should display the config data in the config tab', function() {
709- var view = new CharmView({
710+ view = new CharmView({
711 charm: new models.BrowserCharm({
712 files: [],
713 id: 'precise/ceph-9',
714@@ -310,7 +310,7 @@
715 });
716
717 it('_buildQAData properly summerizes the scores', function() {
718- var view = new CharmView({
719+ view = new CharmView({
720 charm: new models.BrowserCharm({
721 files: [
722 'readme.md'
723@@ -331,7 +331,7 @@
724 });
725
726 it('qa content is loaded when the tab is clicked on', function(done) {
727- var view = new CharmView({
728+ view = new CharmView({
729 charm: new models.BrowserCharm({
730 files: [],
731 id: 'precise/ceph-9',
732@@ -353,7 +353,7 @@
733 });
734
735 it('does not blow up when the scores from the api is null', function() {
736- var view = new CharmView({
737+ view = new CharmView({
738 charm: new models.BrowserCharm({
739 files: [
740 'readme.md'
741@@ -376,7 +376,7 @@
742 Y.io('data/browsercharm.json', {sync: true}).responseText);
743 // We don't want any files so we don't have to mock/load them.
744 data.files = [];
745- var view = new CharmView({
746+ view = new CharmView({
747 charm: new models.BrowserCharm(data),
748 container: Y.Node.create('<div class="charmview"/>')
749 });
750@@ -423,7 +423,7 @@
751 }
752 }
753 });
754- var view = new CharmView({
755+ view = new CharmView({
756 charm: charm
757 });
758 var interfaceIntro = view._getInterfaceIntroFlag(
759@@ -444,7 +444,7 @@
760 }
761 }
762 });
763- var view = new CharmView({
764+ view = new CharmView({
765 charm: charm
766 });
767 var interfaceIntro = view._getInterfaceIntroFlag(
768@@ -466,7 +466,7 @@
769 }
770 }
771 });
772- var view = new CharmView({
773+ view = new CharmView({
774 charm: charm
775 });
776 var interfaceIntro = view._getInterfaceIntroFlag(
777@@ -487,7 +487,7 @@
778 }
779 }
780 });
781- var view = new CharmView({
782+ view = new CharmView({
783 charm: charm
784 });
785 var interfaceIntro = view._getInterfaceIntroFlag(
786@@ -509,7 +509,7 @@
787 }
788 }
789 });
790- var view = new CharmView({
791+ view = new CharmView({
792 charm: charm
793 });
794 var interfaceIntro = view._getInterfaceIntroFlag(
795@@ -532,7 +532,7 @@
796 }
797 }
798 });
799- var view = new CharmView({
800+ view = new CharmView({
801 charm: charm
802 });
803 var interfaceIntro = view._getInterfaceIntroFlag(
804@@ -554,7 +554,7 @@
805 }
806 }
807 });
808- var view = new CharmView({
809+ view = new CharmView({
810 charm: charm
811 });
812 var interfaceIntro = view._getInterfaceIntroFlag(
813@@ -577,7 +577,7 @@
814 }
815 }
816 });
817- var view = new CharmView({
818+ view = new CharmView({
819 charm: charm
820 });
821 var interfaceIntro = view._getInterfaceIntroFlag(
822@@ -601,7 +601,7 @@
823 }
824 }
825 });
826- var view = new CharmView({
827+ view = new CharmView({
828 charm: charm
829 });
830 var interfaceIntro = view._getInterfaceIntroFlag(
831
832=== modified file 'test/test_endpoints.js'
833--- test/test_endpoints.js 2013-05-03 16:18:41 +0000
834+++ test/test_endpoints.js 2013-05-15 00:00:36 +0000
835@@ -20,7 +20,8 @@
836
837
838 beforeEach(function(done) {
839- Y = YUI(GlobalConfig).use(['juju-models',
840+ Y = YUI(GlobalConfig).use(['juju-views',
841+ 'juju-models',
842 'juju-gui',
843 'juju-tests-utils',
844 'juju-controllers'],
845@@ -32,6 +33,7 @@
846 env = juju.newEnvironment({conn: conn});
847 env.connect();
848 app = new Y.juju.App({env: env});
849+ app.navigate = function() { return true; };
850 app.showView(new Y.View());
851 db = app.db;
852 db.onDelta({data: {'op': 'delta', result: sample_env}});
853
854=== modified file 'test/test_env_go.js'
855--- test/test_env_go.js 2013-04-19 16:09:42 +0000
856+++ test/test_env_go.js 2013-05-15 00:00:36 +0000
857@@ -63,7 +63,7 @@
858 });
859
860 describe('Go Juju environment', function() {
861- var conn, endpointA, endpointB, env, juju, msg, utils, Y;
862+ var conn, endpointA, endpointB, env, juju, msg, utils, Y, oldHandleLogin;
863
864 before(function(done) {
865 Y = YUI(GlobalConfig).use(['juju-env', 'juju-tests-utils'], function(Y) {
866@@ -85,7 +85,25 @@
867 env.destroy();
868 });
869
870+ var noopHandleLogin = function() {
871+ // In order to avoid rewriting all of these go tests we need to destroy
872+ // the env created in the beforeEach
873+ env.destroy();
874+ oldHandleLogin = Y.juju.environments.GoEnvironment.handleLogin;
875+ Y.juju.environments.GoEnvironment.handleLogin = function() {};
876+ conn = new utils.SocketStub();
877+ env = juju.newEnvironment({
878+ conn: conn, user: 'user', password: 'password'
879+ }, 'go');
880+ env.connect();
881+ };
882+
883+ var resetHandleLogin = function() {
884+ Y.juju.environments.GoEnvironment.handleLogin = oldHandleLogin;
885+ };
886+
887 it('sends the correct login message', function() {
888+ noopHandleLogin();
889 env.login();
890 var last_message = conn.last_message();
891 var expected = {
892@@ -95,6 +113,7 @@
893 Params: {AuthTag: 'user', Password: 'password'}
894 };
895 assert.deepEqual(expected, last_message);
896+ resetHandleLogin();
897 });
898
899 it('resets the user and password if they are not valid', function() {
900
901=== modified file 'test/test_notifications.js'
902--- test/test_notifications.js 2013-04-08 18:23:28 +0000
903+++ test/test_notifications.js 2013-05-15 00:00:36 +0000
904@@ -205,6 +205,7 @@
905 app: app,
906 env: env,
907 nsRouter: nsRouter}).render();
908+ app.navigate = function() { return; };
909 app.showView(new Y.View());
910 // We use overview here for testing as it defaults
911 // to showing all notices.
912@@ -244,6 +245,7 @@
913 container: container,
914 viewContainer: container
915 });
916+ app.navigate = function() { return; };
917 app.showView(new Y.View());
918 env.connect();
919 var environment_delta = default_env;
920@@ -288,6 +290,7 @@
921 container: container,
922 viewContainer: container
923 });
924+ app.navigate = function() { return; };
925 app.showView(new Y.View());
926 var environment_delta = {
927 'result': [

Subscribers

People subscribed via source and target branches