Merge lp:~benji/juju-gui/bug-1104105-browser-compatability-warning-3 into lp:juju-gui/experimental

Proposed by Benji York
Status: Merged
Merged at revision: 377
Proposed branch: lp:~benji/juju-gui/bug-1104105-browser-compatability-warning-3
Merge into: lp:juju-gui/experimental
Diff against target: 499 lines (+215/-53)
12 files modified
.bzrignore (+2/-0)
Makefile (+33/-15)
app/app.js (+1/-1)
app/index.html (+85/-8)
app/templates/login.handlebars (+3/-3)
app/views/login.js (+4/-4)
lib/merge-files.js (+4/-1)
lib/views/stylesheet.less (+19/-18)
test/index.html (+1/-0)
test/test_login.js (+3/-3)
test/test_startup.js.bottom (+50/-0)
test/test_startup.js.top (+10/-0)
To merge this branch: bzr merge lp:~benji/juju-gui/bug-1104105-browser-compatability-warning-3
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+147448@code.launchpad.net

Description of the change

Add a warning about unsupported browsers.

The tests for the code are a bit unusual in that the code under test is
embedded in an HTML file, so it must be extracted and the test file built my
the Makefile so it can be tested. I don't think this approach is too heinous.

https://codereview.appspot.com/7299071/

To post a comment you must log in.
383. By Benji York

merge trunk and resolve conflict

Revision history for this message
Brad Crittenden (bac) wrote :

The branch looks good, thanks Benji. One change to make before landing.

https://codereview.appspot.com/7299071/diff/3001/app/index.html
File app/index.html (right):

https://codereview.appspot.com/7299071/diff/3001/app/index.html#newcode41
app/index.html:41: Your browser not fully supported.</span>
Please change to: Your browser is not fully supported.

https://codereview.appspot.com/7299071/

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

Hi Benji. Interesting test approach that is cool. Will think about it
more.

I raised the concern on IRC last week that make prod appears to be
broken. Here are some other review comments. I'll re-review when you
have these addressed and make prod fixed.

Thank you

Gary

https://codereview.appspot.com/7299071/diff/3001/Makefile
File Makefile (right):

https://codereview.appspot.com/7299071/diff/3001/Makefile#newcode523
Makefile:523: server spritegen test test-debug test-prod undocumented \
test-prep too, yeah?

https://codereview.appspot.com/7299071/diff/3001/app/index.html
File app/index.html (right):

https://codereview.appspot.com/7299071/diff/3001/app/index.html#newcode41
app/index.html:41: Your browser not fully supported.</span>
add an "is" in there please.

On IE 10 this is two lines, even without the is, which is a shame. It
would be nice if the panel were wider. I might mess with that.

https://codereview.appspot.com/7299071/diff/3001/app/index.html#newcode50
app/index.html:50: <a href="http://www.google.com/chrome">Chrome</a> to
be fully
I think we ought to say Firefox here too. Maybe we wait for CI for
that. If so, please make a bug about this ("Firefox is not regularly
tested" with description mentioning that CI is fix for this bug, and
that this message should be updated when it is).

https://codereview.appspot.com/7299071/diff/3001/app/index.html#newcode113
app/index.html:113: startTheApp = function() {
Unless someone corrects me, I'll assert that is a matter of good
practice to always use var declarations, even at the top level where
they technically are equivalent to what you have written here. Unless
someone argues against them, please add var statements here and below.
(see pastebin from next comment)

https://codereview.appspot.com/7299071/diff/3001/app/index.html#newcode150
app/index.html:150: </script>
This ordering does not accomplish the workflow we want, described in the
graphic assets. The browser warning should be shown before we load the
JS. I think this is one approach to get what we want:
http://pastebin.ubuntu.com/1636315/ . I suspect there are more elegant
ones.

https://codereview.appspot.com/7299071/diff/3001/lib/views/stylesheet.less
File lib/views/stylesheet.less (right):

https://codereview.appspot.com/7299071/diff/3001/lib/views/stylesheet.less#newcode1433
lib/views/stylesheet.less:1433: width: 300px;
I'd like to see what this looks like expanded a bit. The goal would be
to have the text fit in a single line at the top, while still looking
good for login.

https://codereview.appspot.com/7299071/

384. By Benji York

fix prod and tweak widths to reduce line breaks

385. By Benji York

review fixes

386. By Benji York

fix lint

387. By Benji York

fix lint

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

Land with changes, unless you argue against the changes.

Cool, thank you, and thanks for the source fix. Works well for me.
What was the make prod problem?

The box is still not wide enough for me on FF, but is fine on IE. could
you push ".centered-column div" and ".centered-column .panel
input[type="submit"]" out from 260px to 280px, and ".centered-column
.panel input" out to 270px, unless you disagree? I think the design
folks might want to tweak, but not breaking the header text across lines
is more important than the arguably less attractive proportions of the
wider box, IMO.

https://codereview.appspot.com/7299071/diff/3002/app/index.html
File app/index.html (right):

https://codereview.appspot.com/7299071/diff/3002/app/index.html#newcode108
app/index.html:108: <script id="app-startup">
You could protect all of these functions in a function(){[CODE]}()
namespace hack to keep them out of the global namespace. startTheApp is
the only one that would need to be global.

https://codereview.appspot.com/7299071/diff/3002/app/index.html#newcode109
app/index.html:109: isBrowserSupported = function(agent) {
Suggest "var isBrowserSupported = function(agent) {"

This is nicer for variable definition, and would work as desired within
the namespace hack I mention.

OTOH, if you don't use var, "function isBrowserSupported(agent) {" is
identical in semantics, at least as clear, and more concise.

https://codereview.appspot.com/7299071/diff/3002/app/index.html#newcode114
app/index.html:114: getDocument = function() {
Same var discussion

https://codereview.appspot.com/7299071/diff/3002/app/index.html#newcode118
app/index.html:118: displayBrowserWarning = function() {
Same var discussion

https://codereview.appspot.com/7299071/diff/3002/app/index.html#newcode123
app/index.html:123: continueWithCurrentBrowser = function() {
Same var discussion

https://codereview.appspot.com/7299071/diff/3002/app/index.html#newcode130
app/index.html:130: startTheApp = function() {
Same var discussion, except that it needs to be global as you've
implemented it here.

https://codereview.appspot.com/7299071/diff/3002/app/index.html#newcode136
app/index.html:136: window.setTimeout('startTheApp', 100);
Heh. Yeah, I considered this approach too. My global flag was grody in
my book, but so was this. I leaned toward the global flag, then, but
<shrug>.

https://codereview.appspot.com/7299071/diff/3002/app/index.html#newcode139
app/index.html:139: go = function() {
Same var discussion

https://codereview.appspot.com/7299071/diff/3002/lib/merge-files.js
File lib/merge-files.js (right):

https://codereview.appspot.com/7299071/diff/3002/lib/merge-files.js#newcode50
lib/merge-files.js:50: result.code += '\n//@ sourceMappingURL=' +
sourceMapName;
Good catch. Seems silly that we have to do this.

https://codereview.appspot.com/7299071/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2013-02-01 20:27:02 +0000
3+++ .bzrignore 2013-02-11 17:53:23 +0000
4@@ -20,3 +20,5 @@
5 build-debug
6 bin/py
7 python-shelltoolbox
8+test/test_startup.js
9+test/extracted_startup_code
10
11=== modified file 'Makefile'
12--- Makefile 2013-02-08 17:46:45 +0000
13+++ Makefile 2013-02-11 17:53:23 +0000
14@@ -33,12 +33,13 @@
15 -e '^server.js$$')
16 THIRD_PARTY_JS=app/assets/javascripts/reconnecting-websocket.js
17 NODE_TARGETS=node_modules/chai node_modules/cryptojs node_modules/d3 \
18- node_modules/expect.js node_modules/express node_modules/graceful-fs \
19- node_modules/grunt node_modules/jshint node_modules/less \
20- node_modules/minimatch node_modules/mocha node_modules/node-markdown \
21- node_modules/node-minify node_modules/node-spritesheet \
22- node_modules/rimraf node_modules/should node_modules/yui \
23- node_modules/yuidocjs node_modules/recess
24+ node_modules/expect.js node_modules/express \
25+ node_modules/graceful-fs node_modules/grunt node_modules/jshint \
26+ node_modules/less node_modules/minimatch node_modules/mocha \
27+ node_modules/node-markdown node_modules/node-minify \
28+ node_modules/node-spritesheet node_modules/recess \
29+ node_modules/rimraf node_modules/should node_modules/uglify-js \
30+ node_modules/yui node_modules/yuidocjs
31 EXPECTED_NODE_TARGETS=$(shell echo "$(NODE_TARGETS)" | tr ' ' '\n' | sort \
32 | tr '\n' ' ')
33
34@@ -251,7 +252,7 @@
35 # below without the grep to get recess' report.
36 node_modules/recess/bin/recess lib/views/stylesheet.less --config recess.json | grep -q Perfect
37
38-lint: gjslint jshint recess yuidoc-lint
39+lint: test-prep gjslint jshint recess yuidoc-lint
40
41 virtualenv/bin/python:
42 virtualenv virtualenv
43@@ -271,7 +272,7 @@
44 ln -sf "$(PWD)/node_modules/yui/assets/skins/sam/rail-x.png" \
45 build-shared/juju-ui/assets/combined-css/rail-x.png
46 bin/merge-files
47- mv *-source-map build-shared/juju-ui/assets/
48+ mv *.js.map build-shared/juju-ui/assets/
49
50 build-files: $(BUILD_FILES)
51
52@@ -349,7 +350,7 @@
53 $(LINK_PROD_FILES):
54 $(call link-files,prod)
55 ln -sf "$(PWD)/build-shared/juju-ui/assets/all-yui.js" build-prod/juju-ui/assets/
56- ln -sf "$(PWD)"/build-shared/juju-ui/assets/*-source-map build-prod/juju-ui/assets/
57+ ln -sf "$(PWD)"/build-shared/juju-ui/assets/*.js.map build-prod/juju-ui/assets/
58 # Link in the application source code so source maps work.
59 mkdir -p $(PWD)/build-prod/juju-ui/assets/source
60 ln -s $(PWD)/app $(PWD)/build-prod/juju-ui/assets/source
61@@ -357,13 +358,30 @@
62
63 prep: beautify lint
64
65-test-debug: build-debug
66+test/extracted_startup_code: app/index.html
67+ # Pull the JS out of the index so we can run tests against it.
68+ cat app/index.html | \
69+ sed -n '/<script id="app-startup">/,/<\/script>/p'| \
70+ head -n-1 | tail -n+2 > test/extracted_startup_code
71+
72+test/test_startup.js: test/test_startup.js.top test/test_startup.js.bottom \
73+ test/extracted_startup_code
74+ # Stitch together the test file for app start-up.
75+ echo "// THIS IS A GENERATED FILE. DO NOT EDIT." > $@
76+ echo "// See the Makefile for details." >> $@
77+ cat test/test_startup.js.top >> $@
78+ cat test/extracted_startup_code >> $@
79+ cat test/test_startup.js.bottom >> $@
80+
81+test-prep: test/test_startup.js
82+
83+test-debug: build-debug test-prep
84 ./test-server.sh debug
85
86-test-prod: build-prod
87+test-prod: build-prod test-prep
88 ./test-server.sh prod
89
90-test-server: build-debug
91+test-server: build-debug test-prep
92 ./test-server.sh debug true
93
94 test-misc:
95@@ -500,9 +518,9 @@
96
97 # targets are alphabetically sorted, they like it that way :-)
98 .PHONY: appcache-force appcache-touch beautify build build-files \
99- build-devel clean clean-all clean-deps clean-docs code-doc \
100- debug devel docs dist gjslint help jshint lint main-doc prep prod \
101- recess server spritegen test test-debug test-prod undocumented \
102+ build-devel clean clean-all clean-deps clean-docs code-doc debug \
103+ devel docs dist gjslint help jshint lint main-doc prep prod recess \
104+ server spritegen test test-debug test-prep test-prod undocumented \
105 view-code-doc view-docs view-main-doc yuidoc-lint
106
107 .DEFAULT_GOAL := all
108
109=== modified file 'app/app.js'
110--- app/app.js 2013-02-08 17:36:58 +0000
111+++ app/app.js 2013-02-11 17:53:23 +0000
112@@ -638,7 +638,7 @@
113 * @private
114 */
115 onLogin: function() {
116- Y.one('body > #login-mask').hide();
117+ Y.one('body > #full-screen-mask').hide();
118 this.dispatch();
119 },
120
121
122=== added file 'app/assets/images/alert_icon2.png'
123Binary files app/assets/images/alert_icon2.png 1970-01-01 00:00:00 +0000 and app/assets/images/alert_icon2.png 2013-02-11 17:53:23 +0000 differ
124=== modified file 'app/index.html'
125--- app/index.html 2013-02-07 21:04:01 +0000
126+++ app/index.html 2013-02-11 17:53:23 +0000
127@@ -30,7 +30,32 @@
128 </head>
129
130 <body>
131- <div id="login-mask" class="crosshatch-background"></div>
132+ <div id="full-screen-mask" class="crosshatch-background">
133+ <div id="browser-warning" class="centered-column"
134+ style="display:none;">
135+ <i class="sprite juju_logo" title="Juju GUI"></i>
136+ <div class="panel">
137+ <div class="header">
138+ <div class="error">
139+ <span><i class="sprite alert_icon2"></i>
140+ Your browser is not fully supported.</span>
141+ </div>
142+ </div>
143+ <p>
144+ If you continue to use Juju with your current browser your
145+ experience may not be as good as we would like it to be.
146+ </p>
147+ <p>
148+ Please use the latest version of
149+ <a href="http://www.google.com/chrome">Chrome</a> to be fully
150+ supported.
151+ </p>
152+ <form onsubmit="return continueWithCurrentBrowser();">
153+ <input type="submit" value="Continue"/>
154+ </form>
155+ </div>
156+ </div>
157+ </div>
158 <div id="notifier-box"></div>
159 <div id="viewport-wrapper">
160 <div id="vp-left-border"></div>
161@@ -80,17 +105,69 @@
162 </div>
163 <div id="vp-right-border"></div>
164 </div>
165- <!-- javascript away -->
166+ <script id="app-startup">
167+ isBrowserSupported = function(agent) {
168+ // At the moment, only Chrome is supported.
169+ return (/Chrome/.test(agent));
170+ };
171+
172+ getDocument = function() {
173+ return document;
174+ };
175+
176+ displayBrowserWarning = function() {
177+ getDocument()
178+ .getElementById('browser-warning').style.display = 'block';
179+ };
180+
181+ continueWithCurrentBrowser = function() {
182+ getDocument()
183+ .getElementById('browser-warning').style.display = 'none';
184+ startTheApp();
185+ return false;
186+ };
187+
188+ startTheApp = function() {
189+ // This function will be redefined when all the app's JavaScript is
190+ // loaded. We want to keep trying until that happens.
191+
192+ // Tell jslint that we really do want to evaluate a string:
193+ /*jslint evil: true */
194+ window.setTimeout('startTheApp', 100);
195+ };
196+
197+ go = function() {
198+ if (isBrowserSupported(navigator.userAgent)) {
199+ startTheApp();
200+ } else {
201+ displayBrowserWarning();
202+ }
203+ };
204+ </script>
205+ <!--
206+ Load the (potentially slow to download) core of the app. We do this here
207+ because we want the browser warning to execute before spending the time
208+ to download an app the user might not be able to use anyway.
209+ -->
210 <script src="/juju-ui/assets/all-yui.js"></script>
211 <script src="/juju-ui/assets/modules.js"></script>
212 <script src="/juju-ui/assets/config.js"></script>
213 <script>
214- YUI(GlobalConfig).use(["juju-gui"], function(Y) {
215- app = new Y.juju.App(juju_config);
216- // We need to activate the hotkeys when running the application
217- // in production. Unit tests should call it manually.
218- app.activateHotkeys();
219- });
220+ // Now that all of the above JS is loaded we can define the real start
221+ // function which will be picked up by the setTimeout and the app will
222+ // start.
223+ startTheApp = function() {
224+ YUI(GlobalConfig).use(['juju-gui'], function(Y) {
225+ app = new Y.juju.App(juju_config);
226+ // We need to activate the hotkeys when running the application
227+ // in production. Unit tests should call it manually.
228+ app.activateHotkeys();
229+ });
230+ };
231+ // This call is here instead of in the "app-startup" script tag above
232+ // because we extract that JS in order to test it. This bit here is just
233+ // to bootstrap the app when actually loaded into a browser.
234+ go();
235 </script>
236 </body>
237 </html>
238
239=== modified file 'app/templates/login.handlebars'
240--- app/templates/login.handlebars 2013-01-10 10:25:55 +0000
241+++ app/templates/login.handlebars 2013-02-11 17:53:23 +0000
242@@ -1,7 +1,7 @@
243-<div id="login-column">
244+<div class="centered-column">
245 <i class="sprite juju_logo" title="Juju GUI"></i>
246- <div id="login-form">
247- <div id="login-header">
248+ <div id="login-form" class="panel">
249+ <div class="header">
250 {{environment_name}} <span class="provider-type">{{provider_type}}</span>
251 </div>
252 <form>
253
254=== modified file 'app/views/login.js'
255--- app/views/login.js 2013-02-08 17:36:58 +0000
256+++ app/views/login.js 2013-02-11 17:53:23 +0000
257@@ -56,12 +56,12 @@
258 // In order to have the mask cover everything, it needs to be an
259 // immediate child of the body. In order for it to render immediately
260 // when the app loads, it needs to be in index.html.
261- var loginMask = Y.one('body > #login-mask');
262- if (!loginMask) {
263- // No login mask in the DOM, as is the case in tests.
264+ var mask = Y.one('body > #full-screen-mask');
265+ if (!mask) {
266+ // No mask in the DOM, as is the case in tests.
267 return this;
268 }
269- loginMask.show();
270+ mask.show();
271 var env = this.get('env');
272 var environment_name_node = Y.one('#environment-name');
273 var provider_type_node = Y.one('#provider-type');
274
275=== modified file 'lib/merge-files.js'
276--- lib/merge-files.js 2013-02-06 17:37:02 +0000
277+++ lib/merge-files.js 2013-02-11 17:53:23 +0000
278@@ -32,7 +32,7 @@
279
280 // Combine one or more JavaScript files.
281 function combineJs(files, outputFile) {
282- var sourceMapName = syspath.basename(outputFile, '.js') + '-source-map';
283+ var sourceMapName = syspath.basename(outputFile) + '.map';
284 // We feed the minifier relative path names so the source map will map to
285 // relative URLs that can be easily served.
286 var relative_files = [];
287@@ -45,6 +45,9 @@
288 outSourceMap: sourceMapName,
289 sourceRoot: 'source'
290 });
291+ // The uglifyjs script does this instead of the library, so we have to do
292+ // it ourselves since we are using uglify as a library and not a script.
293+ result.code += '\n//@ sourceMappingURL=' + sourceMapName;
294 fs.writeFileSync(outputFile, result.code, 'utf8', throw_error);
295 fs.writeFileSync(sourceMapName, result.map, 'utf8', throw_error);
296 }
297
298=== modified file 'lib/views/stylesheet.less'
299--- lib/views/stylesheet.less 2013-02-07 19:04:00 +0000
300+++ lib/views/stylesheet.less 2013-02-11 17:53:23 +0000
301@@ -1414,7 +1414,7 @@
302 }
303 }
304
305-#login-mask {
306+#full-screen-mask {
307 display: block;
308 position: absolute;
309 top: 0;
310@@ -1423,18 +1423,18 @@
311 height: 100%;
312 z-index: 10000;
313 }
314-#login-column {
315+.centered-column {
316 display: block;
317 z-index: 10001;
318 position: absolute;
319 top: 80px;
320 left: 50%;
321 text-align: center;
322- width: 300px;
323- margin-left: -150px;
324+ width: 400px;
325+ margin-left: -200px;
326
327 div {
328- width: 220px;
329+ width: 260px;
330 text-align: left;
331 margin: 0 auto;
332 margin-bottom: 1ex;
333@@ -1445,17 +1445,20 @@
334 text-decoration: none
335 }
336 }
337- @login-panel-color: #f5f5f5;
338- @login-panel-gradient: (@login-panel-color - #111);
339- @login-panel-shadow: (@login-panel-color - #444);
340+
341+ @panel-color: #f5f5f5;
342+ @panel-gradient: (@panel-color - #111);
343+ @panel-shadow: (@panel-color - #444);
344 @curve-radius: ~"24px 28px";
345- div#login-form {
346+
347+ .panel {
348 input {
349+ width: 250px;
350 margin-top: 8px;
351 margin-bottom: 8px;
352 }
353 input[type=submit] {
354- width: 220px;
355+ width: 260px;
356 height: 26px;
357 text-transform: uppercase;
358 text-shadow: none;
359@@ -1474,12 +1477,10 @@
360 padding: 5px 25px 5px;
361 margin-top: 3ex;
362 margin-bottom: 4ex;
363- .create-button(@login-panel-color,
364- @login-panel-gradient,
365- @login-panel-shadow,
366- -6px);
367- .create-border-radius(~"24px / 28px");
368- div#login-header {
369+ .create-button(@panel-color, @panel-gradient, @panel-shadow, -6px);
370+ .create-border-radius(@curve-radius);
371+
372+ .header {
373 padding: 15px 25px 10px 25px;
374 margin-left: -25px;
375 margin-top: -5px;
376@@ -1489,8 +1490,8 @@
377 -moz-border-radius-topright: @curve-radius;
378 border-top-left-radius: @curve-radius;
379 border-top-right-radius: @curve-radius;
380- @gradient-start: @login-panel-gradient;
381- @gradient-end: @login-panel-shadow;
382+ @gradient-start: @panel-gradient;
383+ @gradient-end: @panel-shadow;
384 background-image: -ms-linear-gradient(
385 top, @gradient-start, @gradient-end);
386 background-image: -webkit-gradient(
387
388=== modified file 'test/index.html'
389--- test/index.html 2013-02-07 16:40:46 +0000
390+++ test/index.html 2013-02-11 17:53:23 +0000
391@@ -28,6 +28,7 @@
392
393
394 <!-- Tests (Alphabetical)-->
395+ <script src="test_startup.js"></script>
396 <script src="test_app.js"></script>
397 <script src="test_app_hotkeys.js"></script>
398 <script src="test_application_notifications.js"></script>
399
400=== modified file 'test/test_login.js'
401--- test/test_login.js 2013-01-18 13:40:28 +0000
402+++ test/test_login.js 2013-02-11 17:53:23 +0000
403@@ -85,7 +85,7 @@
404
405 describe('login view', function() {
406 var requires = ['node', 'juju-gui', 'juju-views', 'juju-tests-utils'];
407- var Y, conn, env, utils, juju, views, loginView, container, loginMask;
408+ var Y, conn, env, utils, juju, views, loginView, container, mask;
409 var test = it; // We aren't really doing BDD so let's be more direct.
410
411 before(function(done) {
412@@ -104,7 +104,7 @@
413 conn.open();
414 container = Y.one('body').appendChild('<div/>');
415 // Needed by the render method.
416- loginMask = Y.one('body').appendChild('<div/>').set('id', 'login-mask');
417+ mask = Y.one('body').appendChild('<div/>').set('id', 'full-screen-mask');
418 loginView = new views.login(
419 {container: container, env: env, help_text: 'Help text'});
420 });
421@@ -112,7 +112,7 @@
422 afterEach(function() {
423 env.destroy();
424 container.remove(true);
425- loginMask.remove(true);
426+ mask.remove(true);
427 });
428
429 test('the view login method logs in through the environment', function() {
430
431=== added file 'test/test_startup.js.bottom'
432--- test/test_startup.js.bottom 1970-01-01 00:00:00 +0000
433+++ test/test_startup.js.bottom 2013-02-11 17:53:23 +0000
434@@ -0,0 +1,50 @@
435+ startTheApp = function() {
436+ appStarted = true;
437+ };
438+ getDocument = function() {
439+ return {
440+ getElementById: function(id) {
441+ assert.equal(id, 'browser-warning');
442+ return {style: warningStyle};
443+ }
444+ };
445+ };
446+ });
447+
448+ it('knows that Chrome is supported', function() {
449+ assert.isTrue(isBrowserSupported('Chrome'));
450+ });
451+
452+ it('knows that Firefox is not supported', function() {
453+ assert.isFalse(isBrowserSupported('Firefox'));
454+ });
455+
456+ it('knows that IE is not supported', function() {
457+ assert.isFalse(isBrowserSupported('MSIE'));
458+ });
459+
460+ it('can display the browser warning', function() {
461+ displayBrowserWarning();
462+ assert.equal(warningStyle.display, 'block');
463+ });
464+
465+ it('will hide the browser warning when the user continues', function() {
466+ continueWithCurrentBrowser();
467+ assert.equal(warningStyle.display, 'none');
468+ });
469+
470+ it('will stop event propigation when the user continues', function() {
471+ var result = continueWithCurrentBrowser();
472+ // Since the function is an event handler of a submit button and we do
473+ // not want the form submittion to actually happen, the handler must
474+ // return false.
475+ assert.isFalse(result);
476+ });
477+
478+ it('will start the app when the user continues', function() {
479+ continueWithCurrentBrowser();
480+ assert.isTrue(appStarted);
481+ });
482+
483+ });
484+}) ();
485
486=== added file 'test/test_startup.js.top'
487--- test/test_startup.js.top 1970-01-01 00:00:00 +0000
488+++ test/test_startup.js.top 2013-02-11 17:53:23 +0000
489@@ -0,0 +1,10 @@
490+'use strict';
491+
492+(function() {
493+ describe('Application start-up', function() {
494+ var startTheApp, isBrowserSupported, displayBrowserWarning,
495+ continueWithCurrentBrowser, go, app, juju_config, getDocument,
496+ appStarted, warningStyle;
497+ before(function() {
498+ warningStyle = {display: null};
499+ appStarted = false;

Subscribers

People subscribed via source and target branches