bpm 1.0.0.beta.4 → 1.0.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/TODO.md +4 -10
  3. data/backbone/LICENSE +22 -0
  4. data/backbone/README +25 -0
  5. data/backbone/Rakefile +42 -0
  6. data/backbone/backbone-0.5.1.bpkg +0 -0
  7. data/backbone/examples/backbone-localstorage.js +84 -0
  8. data/backbone/examples/todos/destroy.png +0 -0
  9. data/backbone/examples/todos/index.html +87 -0
  10. data/backbone/examples/todos/todos.css +311 -0
  11. data/backbone/examples/todos/todos.js +258 -0
  12. data/backbone/index.html +2606 -0
  13. data/backbone/index.js +1 -0
  14. data/backbone/lib/backbone.js +1149 -0
  15. data/backbone/lib/index.js +1 -0
  16. data/backbone/package.json +14 -0
  17. data/backbone/test/collection.js +345 -0
  18. data/backbone/test/events.js +70 -0
  19. data/backbone/test/model.coffee +43 -0
  20. data/backbone/test/model.js +424 -0
  21. data/backbone/test/noconflict.js +12 -0
  22. data/backbone/test/router.js +116 -0
  23. data/backbone/test/speed.js +45 -0
  24. data/backbone/test/sync.js +133 -0
  25. data/backbone/test/test-zepto.html +30 -0
  26. data/backbone/test/test.html +31 -0
  27. data/backbone/test/vendor/jquery-1.5.js +8176 -0
  28. data/backbone/test/vendor/jslitmus.js +649 -0
  29. data/backbone/test/vendor/json2.js +481 -0
  30. data/backbone/test/vendor/qunit.css +196 -0
  31. data/backbone/test/vendor/qunit.js +1364 -0
  32. data/backbone/test/vendor/underscore-1.1.6.js +807 -0
  33. data/backbone/test/vendor/zepto-0.6.js +692 -0
  34. data/backbone/test/view.js +137 -0
  35. data/lib/bpm/cli/base.rb +22 -7
  36. data/lib/bpm/package.rb +17 -5
  37. data/lib/bpm/project.rb +49 -32
  38. data/lib/bpm/version.rb +1 -1
  39. data/spec/cli/add_spec.rb +22 -4
  40. data/spec/cli/fetch_spec.rb +0 -1
  41. data/spec/cli/init_spec.rb +25 -10
  42. data/spec/cli/list_spec.rb +103 -62
  43. data/spec/cli/pack_spec.rb +36 -4
  44. data/spec/fixtures/packages/backbone/LICENSE +22 -0
  45. data/spec/fixtures/packages/backbone/README +25 -0
  46. data/spec/fixtures/packages/backbone/Rakefile +42 -0
  47. data/spec/fixtures/packages/backbone/examples/backbone-localstorage.js +84 -0
  48. data/spec/fixtures/packages/backbone/examples/todos/destroy.png +0 -0
  49. data/spec/fixtures/packages/backbone/examples/todos/index.html +87 -0
  50. data/spec/fixtures/packages/backbone/examples/todos/todos.css +311 -0
  51. data/spec/fixtures/packages/backbone/examples/todos/todos.js +258 -0
  52. data/spec/fixtures/packages/backbone/index.html +2606 -0
  53. data/spec/fixtures/packages/backbone/lib/backbone.js +1149 -0
  54. data/spec/fixtures/packages/backbone/lib/index.js +1 -0
  55. data/spec/fixtures/packages/backbone/package.json +14 -0
  56. data/spec/fixtures/packages/backbone/test/collection.js +345 -0
  57. data/spec/fixtures/packages/backbone/test/events.js +70 -0
  58. data/spec/fixtures/packages/backbone/test/model.coffee +43 -0
  59. data/spec/fixtures/packages/backbone/test/model.js +424 -0
  60. data/spec/fixtures/packages/backbone/test/noconflict.js +12 -0
  61. data/spec/fixtures/packages/backbone/test/router.js +116 -0
  62. data/spec/fixtures/packages/backbone/test/speed.js +45 -0
  63. data/spec/fixtures/packages/backbone/test/sync.js +133 -0
  64. data/spec/fixtures/packages/backbone/test/test-zepto.html +30 -0
  65. data/spec/fixtures/packages/backbone/test/test.html +31 -0
  66. data/spec/fixtures/packages/backbone/test/vendor/jquery-1.5.js +8176 -0
  67. data/spec/fixtures/packages/backbone/test/vendor/jslitmus.js +649 -0
  68. data/spec/fixtures/packages/backbone/test/vendor/json2.js +481 -0
  69. data/spec/fixtures/packages/backbone/test/vendor/qunit.css +196 -0
  70. data/spec/fixtures/packages/backbone/test/vendor/qunit.js +1364 -0
  71. data/spec/fixtures/packages/backbone/test/vendor/underscore-1.1.6.js +807 -0
  72. data/spec/fixtures/packages/backbone/test/vendor/zepto-0.6.js +692 -0
  73. data/spec/fixtures/packages/backbone/test/view.js +137 -0
  74. data/spec/fixtures/projects/init_app/assets/bpm_libs.js +1 -1
  75. data/spec/fixtures/projects/init_app/assets/bpm_styles.css +1 -1
  76. data/spec/fixtures/projects/init_app/new_project.json +1 -10
  77. data/spec/pipeline_spec.rb +5 -5
  78. data/spec/plugins/minifier_spec.rb +1 -1
  79. data/spec/plugins/transport_spec.rb +1 -1
  80. metadata +116 -28
  81. data/spec/fixtures/projects/init_app/assets/new_project/bpm_libs.js +0 -6
  82. data/spec/fixtures/projects/init_app/assets/new_project/bpm_styles.css +0 -5
@@ -0,0 +1,649 @@
1
+ // JSLitmus.js
2
+ //
3
+ // Copyright (c) 2010, Robert Kieffer, http://broofa.com
4
+ // Available under MIT license (http://en.wikipedia.org/wiki/MIT_License)
5
+
6
+ (function() {
7
+ // Private methods and state
8
+
9
+ // Get platform info but don't go crazy trying to recognize everything
10
+ // that's out there. This is just for the major platforms and OSes.
11
+ var platform = 'unknown platform', ua = navigator.userAgent;
12
+
13
+ // Detect OS
14
+ var oses = ['Windows','iPhone OS','(Intel |PPC )?Mac OS X','Linux'].join('|');
15
+ var pOS = new RegExp('((' + oses + ') [^ \);]*)').test(ua) ? RegExp.$1 : null;
16
+ if (!pOS) pOS = new RegExp('((' + oses + ')[^ \);]*)').test(ua) ? RegExp.$1 : null;
17
+
18
+ // Detect browser
19
+ var pName = /(Chrome|MSIE|Safari|Opera|Firefox)/.test(ua) ? RegExp.$1 : null;
20
+
21
+ // Detect version
22
+ var vre = new RegExp('(Version|' + pName + ')[ \/]([^ ;]*)');
23
+ var pVersion = (pName && vre.test(ua)) ? RegExp.$2 : null;
24
+ var platform = (pOS && pName && pVersion) ? pName + ' ' + pVersion + ' on ' + pOS : 'unknown platform';
25
+
26
+ /**
27
+ * A smattering of methods that are needed to implement the JSLitmus testbed.
28
+ */
29
+ var jsl = {
30
+ /**
31
+ * Enhanced version of escape()
32
+ */
33
+ escape: function(s) {
34
+ s = s.replace(/,/g, '\\,');
35
+ s = escape(s);
36
+ s = s.replace(/\+/g, '%2b');
37
+ s = s.replace(/ /g, '+');
38
+ return s;
39
+ },
40
+
41
+ /**
42
+ * Get an element by ID.
43
+ */
44
+ $: function(id) {
45
+ return document.getElementById(id);
46
+ },
47
+
48
+ /**
49
+ * Null function
50
+ */
51
+ F: function() {},
52
+
53
+ /**
54
+ * Set the status shown in the UI
55
+ */
56
+ status: function(msg) {
57
+ var el = jsl.$('jsl_status');
58
+ if (el) el.innerHTML = msg || '';
59
+ },
60
+
61
+ /**
62
+ * Convert a number to an abbreviated string like, "15K" or "10M"
63
+ */
64
+ toLabel: function(n) {
65
+ if (n == Infinity) {
66
+ return 'Infinity';
67
+ } else if (n > 1e9) {
68
+ n = Math.round(n/1e8);
69
+ return n/10 + 'B';
70
+ } else if (n > 1e6) {
71
+ n = Math.round(n/1e5);
72
+ return n/10 + 'M';
73
+ } else if (n > 1e3) {
74
+ n = Math.round(n/1e2);
75
+ return n/10 + 'K';
76
+ }
77
+ return n;
78
+ },
79
+
80
+ /**
81
+ * Copy properties from src to dst
82
+ */
83
+ extend: function(dst, src) {
84
+ for (var k in src) dst[k] = src[k]; return dst;
85
+ },
86
+
87
+ /**
88
+ * Like Array.join(), but for the key-value pairs in an object
89
+ */
90
+ join: function(o, delimit1, delimit2) {
91
+ if (o.join) return o.join(delimit1); // If it's an array
92
+ var pairs = [];
93
+ for (var k in o) pairs.push(k + delimit1 + o[k]);
94
+ return pairs.join(delimit2);
95
+ },
96
+
97
+ /**
98
+ * Array#indexOf isn't supported in IE, so we use this as a cross-browser solution
99
+ */
100
+ indexOf: function(arr, o) {
101
+ if (arr.indexOf) return arr.indexOf(o);
102
+ for (var i = 0; i < this.length; i++) if (arr[i] === o) return i;
103
+ return -1;
104
+ }
105
+ };
106
+
107
+ /**
108
+ * Test manages a single test (created with
109
+ * JSLitmus.test())
110
+ *
111
+ * @private
112
+ */
113
+ var Test = function (name, f) {
114
+ if (!f) throw new Error('Undefined test function');
115
+ if (!/function[^\(]*\(([^,\)]*)/.test(f.toString())) {
116
+ throw new Error('"' + name + '" test: Test is not a valid Function object');
117
+ }
118
+ this.loopArg = RegExp.$1;
119
+ this.name = name;
120
+ this.f = f;
121
+ };
122
+
123
+ jsl.extend(Test, /** @lends Test */ {
124
+ /** Calibration tests for establishing iteration loop overhead */
125
+ CALIBRATIONS: [
126
+ new Test('calibrating loop', function(count) {while (count--);}),
127
+ new Test('calibrating function', jsl.F)
128
+ ],
129
+
130
+ /**
131
+ * Run calibration tests. Returns true if calibrations are not yet
132
+ * complete (in which case calling code should run the tests yet again).
133
+ * onCalibrated - Callback to invoke when calibrations have finished
134
+ */
135
+ calibrate: function(onCalibrated) {
136
+ for (var i = 0; i < Test.CALIBRATIONS.length; i++) {
137
+ var cal = Test.CALIBRATIONS[i];
138
+ if (cal.running) return true;
139
+ if (!cal.count) {
140
+ cal.isCalibration = true;
141
+ cal.onStop = onCalibrated;
142
+ //cal.MIN_TIME = .1; // Do calibrations quickly
143
+ cal.run(2e4);
144
+ return true;
145
+ }
146
+ }
147
+ return false;
148
+ }
149
+ });
150
+
151
+ jsl.extend(Test.prototype, {/** @lends Test.prototype */
152
+ /** Initial number of iterations */
153
+ INIT_COUNT: 10,
154
+ /** Max iterations allowed (i.e. used to detect bad looping functions) */
155
+ MAX_COUNT: 1e9,
156
+ /** Minimum time a test should take to get valid results (secs) */
157
+ MIN_TIME: .5,
158
+
159
+ /** Callback invoked when test state changes */
160
+ onChange: jsl.F,
161
+
162
+ /** Callback invoked when test is finished */
163
+ onStop: jsl.F,
164
+
165
+ /**
166
+ * Reset test state
167
+ */
168
+ reset: function() {
169
+ delete this.count;
170
+ delete this.time;
171
+ delete this.running;
172
+ delete this.error;
173
+ },
174
+
175
+ /**
176
+ * Run the test (in a timeout). We use a timeout to make sure the browser
177
+ * has a chance to finish rendering any UI changes we've made, like
178
+ * updating the status message.
179
+ */
180
+ run: function(count) {
181
+ count = count || this.INIT_COUNT;
182
+ jsl.status(this.name + ' x ' + count);
183
+ this.running = true;
184
+ var me = this;
185
+ setTimeout(function() {me._run(count);}, 200);
186
+ },
187
+
188
+ /**
189
+ * The nuts and bolts code that actually runs a test
190
+ */
191
+ _run: function(count) {
192
+ var me = this;
193
+
194
+ // Make sure calibration tests have run
195
+ if (!me.isCalibration && Test.calibrate(function() {me.run(count);})) return;
196
+ this.error = null;
197
+
198
+ try {
199
+ var start, f = this.f, now, i = count;
200
+
201
+ // Start the timer
202
+ start = new Date();
203
+
204
+ // Now for the money shot. If this is a looping function ...
205
+ if (this.loopArg) {
206
+ // ... let it do the iteration itself
207
+ f(count);
208
+ } else {
209
+ // ... otherwise do the iteration for it
210
+ while (i--) f();
211
+ }
212
+
213
+ // Get time test took (in secs)
214
+ this.time = Math.max(1,new Date() - start)/1000;
215
+
216
+ // Store iteration count and per-operation time taken
217
+ this.count = count;
218
+ this.period = this.time/count;
219
+
220
+ // Do we need to do another run?
221
+ this.running = this.time <= this.MIN_TIME;
222
+
223
+ // ... if so, compute how many times we should iterate
224
+ if (this.running) {
225
+ // Bump the count to the nearest power of 2
226
+ var x = this.MIN_TIME/this.time;
227
+ var pow = Math.pow(2, Math.max(1, Math.ceil(Math.log(x)/Math.log(2))));
228
+ count *= pow;
229
+ if (count > this.MAX_COUNT) {
230
+ throw new Error('Max count exceeded. If this test uses a looping function, make sure the iteration loop is working properly.');
231
+ }
232
+ }
233
+ } catch (e) {
234
+ // Exceptions are caught and displayed in the test UI
235
+ this.reset();
236
+ this.error = e;
237
+ }
238
+
239
+ // Figure out what to do next
240
+ if (this.running) {
241
+ me.run(count);
242
+ } else {
243
+ jsl.status('');
244
+ me.onStop(me);
245
+ }
246
+
247
+ // Finish up
248
+ this.onChange(this);
249
+ },
250
+
251
+ /**
252
+ * Get the number of operations per second for this test.
253
+ *
254
+ * @param normalize if true, iteration loop overhead taken into account
255
+ */
256
+ getHz: function(/**Boolean*/ normalize) {
257
+ var p = this.period;
258
+
259
+ // Adjust period based on the calibration test time
260
+ if (normalize && !this.isCalibration) {
261
+ var cal = Test.CALIBRATIONS[this.loopArg ? 0 : 1];
262
+
263
+ // If the period is within 20% of the calibration time, then zero the
264
+ // it out
265
+ p = p < cal.period*1.2 ? 0 : p - cal.period;
266
+ }
267
+
268
+ return Math.round(1/p);
269
+ },
270
+
271
+ /**
272
+ * Get a friendly string describing the test
273
+ */
274
+ toString: function() {
275
+ return this.name + ' - ' + this.time/this.count + ' secs';
276
+ }
277
+ });
278
+
279
+ // CSS we need for the UI
280
+ var STYLESHEET = '<style> \
281
+ #jslitmus {font-family:sans-serif; font-size: 12px;} \
282
+ #jslitmus a {text-decoration: none;} \
283
+ #jslitmus a:hover {text-decoration: underline;} \
284
+ #jsl_status { \
285
+ margin-top: 10px; \
286
+ font-size: 10px; \
287
+ color: #888; \
288
+ } \
289
+ A IMG {border:none} \
290
+ #test_results { \
291
+ margin-top: 10px; \
292
+ font-size: 12px; \
293
+ font-family: sans-serif; \
294
+ border-collapse: collapse; \
295
+ border-spacing: 0px; \
296
+ } \
297
+ #test_results th, #test_results td { \
298
+ border: solid 1px #ccc; \
299
+ vertical-align: top; \
300
+ padding: 3px; \
301
+ } \
302
+ #test_results th { \
303
+ vertical-align: bottom; \
304
+ background-color: #ccc; \
305
+ padding: 1px; \
306
+ font-size: 10px; \
307
+ } \
308
+ #test_results #test_platform { \
309
+ color: #444; \
310
+ text-align:center; \
311
+ } \
312
+ #test_results .test_row { \
313
+ color: #006; \
314
+ cursor: pointer; \
315
+ } \
316
+ #test_results .test_nonlooping { \
317
+ border-left-style: dotted; \
318
+ border-left-width: 2px; \
319
+ } \
320
+ #test_results .test_looping { \
321
+ border-left-style: solid; \
322
+ border-left-width: 2px; \
323
+ } \
324
+ #test_results .test_name {white-space: nowrap;} \
325
+ #test_results .test_pending { \
326
+ } \
327
+ #test_results .test_running { \
328
+ font-style: italic; \
329
+ } \
330
+ #test_results .test_done {} \
331
+ #test_results .test_done { \
332
+ text-align: right; \
333
+ font-family: monospace; \
334
+ } \
335
+ #test_results .test_error {color: #600;} \
336
+ #test_results .test_error .error_head {font-weight:bold;} \
337
+ #test_results .test_error .error_body {font-size:85%;} \
338
+ #test_results .test_row:hover td { \
339
+ background-color: #ffc; \
340
+ text-decoration: underline; \
341
+ } \
342
+ #chart { \
343
+ margin: 10px 0px; \
344
+ width: 250px; \
345
+ } \
346
+ #chart img { \
347
+ border: solid 1px #ccc; \
348
+ margin-bottom: 5px; \
349
+ } \
350
+ #chart #tiny_url { \
351
+ height: 40px; \
352
+ width: 250px; \
353
+ } \
354
+ #jslitmus_credit { \
355
+ font-size: 10px; \
356
+ color: #888; \
357
+ margin-top: 8px; \
358
+ } \
359
+ </style>';
360
+
361
+ // HTML markup for the UI
362
+ var MARKUP = '<div id="jslitmus"> \
363
+ <button onclick="JSLitmus.runAll(event)">Run Tests</button> \
364
+ <button id="stop_button" disabled="disabled" onclick="JSLitmus.stop()">Stop Tests</button> \
365
+ <br \> \
366
+ <br \> \
367
+ <input type="checkbox" style="vertical-align: middle" id="test_normalize" checked="checked" onchange="JSLitmus.renderAll()""> Normalize results \
368
+ <table id="test_results"> \
369
+ <colgroup> \
370
+ <col /> \
371
+ <col width="100" /> \
372
+ </colgroup> \
373
+ <tr><th id="test_platform" colspan="2">' + platform + '</th></tr> \
374
+ <tr><th>Test</th><th>Ops/sec</th></tr> \
375
+ <tr id="test_row_template" class="test_row" style="display:none"> \
376
+ <td class="test_name"></td> \
377
+ <td class="test_result">Ready</td> \
378
+ </tr> \
379
+ </table> \
380
+ <div id="jsl_status"></div> \
381
+ <div id="chart" style="display:none"> \
382
+ <a id="chart_link" target="_blank"><img id="chart_image"></a> \
383
+ TinyURL (for chart): \
384
+ <iframe id="tiny_url" frameBorder="0" scrolling="no" src=""></iframe> \
385
+ </div> \
386
+ <a id="jslitmus_credit" title="JSLitmus home page" href="http://code.google.com/p/jslitmus" target="_blank">Powered by JSLitmus</a> \
387
+ </div>';
388
+
389
+ /**
390
+ * The public API for creating and running tests
391
+ */
392
+ window.JSLitmus = {
393
+ /** The list of all tests that have been registered with JSLitmus.test */
394
+ _tests: [],
395
+ /** The queue of tests that need to be run */
396
+ _queue: [],
397
+
398
+ /**
399
+ * The parsed query parameters the current page URL. This is provided as a
400
+ * convenience for test functions - it's not used by JSLitmus proper
401
+ */
402
+ params: {},
403
+
404
+ /**
405
+ * Initialize
406
+ */
407
+ _init: function() {
408
+ // Parse query params into JSLitmus.params[] hash
409
+ var match = (location + '').match(/([^?#]*)(#.*)?$/);
410
+ if (match) {
411
+ var pairs = match[1].split('&');
412
+ for (var i = 0; i < pairs.length; i++) {
413
+ var pair = pairs[i].split('=');
414
+ if (pair.length > 1) {
415
+ var key = pair.shift();
416
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
417
+ this.params[key] = value;
418
+ }
419
+ }
420
+ }
421
+
422
+ // Write out the stylesheet. We have to do this here because IE
423
+ // doesn't honor sheets written after the document has loaded.
424
+ document.write(STYLESHEET);
425
+
426
+ // Setup the rest of the UI once the document is loaded
427
+ if (window.addEventListener) {
428
+ window.addEventListener('load', this._setup, false);
429
+ } else if (document.addEventListener) {
430
+ document.addEventListener('load', this._setup, false);
431
+ } else if (window.attachEvent) {
432
+ window.attachEvent('onload', this._setup);
433
+ }
434
+
435
+ return this;
436
+ },
437
+
438
+ /**
439
+ * Set up the UI
440
+ */
441
+ _setup: function() {
442
+ var el = jsl.$('jslitmus_container');
443
+ if (!el) document.body.appendChild(el = document.createElement('div'));
444
+
445
+ el.innerHTML = MARKUP;
446
+
447
+ // Render the UI for all our tests
448
+ for (var i=0; i < JSLitmus._tests.length; i++)
449
+ JSLitmus.renderTest(JSLitmus._tests[i]);
450
+ },
451
+
452
+ /**
453
+ * (Re)render all the test results
454
+ */
455
+ renderAll: function() {
456
+ for (var i = 0; i < JSLitmus._tests.length; i++)
457
+ JSLitmus.renderTest(JSLitmus._tests[i]);
458
+ JSLitmus.renderChart();
459
+ },
460
+
461
+ /**
462
+ * (Re)render the chart graphics
463
+ */
464
+ renderChart: function() {
465
+ var url = JSLitmus.chartUrl();
466
+ jsl.$('chart_link').href = url;
467
+ jsl.$('chart_image').src = url;
468
+ jsl.$('chart').style.display = '';
469
+
470
+ // Update the tiny URL
471
+ jsl.$('tiny_url').src = 'http://tinyurl.com/api-create.php?url='+escape(url);
472
+ },
473
+
474
+ /**
475
+ * (Re)render the results for a specific test
476
+ */
477
+ renderTest: function(test) {
478
+ // Make a new row if needed
479
+ if (!test._row) {
480
+ var trow = jsl.$('test_row_template');
481
+ if (!trow) return;
482
+
483
+ test._row = trow.cloneNode(true);
484
+ test._row.style.display = '';
485
+ test._row.id = '';
486
+ test._row.onclick = function() {JSLitmus._queueTest(test);};
487
+ test._row.title = 'Run ' + test.name + ' test';
488
+ trow.parentNode.appendChild(test._row);
489
+ test._row.cells[0].innerHTML = test.name;
490
+ }
491
+
492
+ var cell = test._row.cells[1];
493
+ var cns = [test.loopArg ? 'test_looping' : 'test_nonlooping'];
494
+
495
+ if (test.error) {
496
+ cns.push('test_error');
497
+ cell.innerHTML =
498
+ '<div class="error_head">' + test.error + '</div>' +
499
+ '<ul class="error_body"><li>' +
500
+ jsl.join(test.error, ': ', '</li><li>') +
501
+ '</li></ul>';
502
+ } else {
503
+ if (test.running) {
504
+ cns.push('test_running');
505
+ cell.innerHTML = 'running';
506
+ } else if (jsl.indexOf(JSLitmus._queue, test) >= 0) {
507
+ cns.push('test_pending');
508
+ cell.innerHTML = 'pending';
509
+ } else if (test.count) {
510
+ cns.push('test_done');
511
+ var hz = test.getHz(jsl.$('test_normalize').checked);
512
+ cell.innerHTML = hz != Infinity ? hz : '&infin;';
513
+ cell.title = 'Looped ' + test.count + ' times in ' + test.time + ' seconds';
514
+ } else {
515
+ cell.innerHTML = 'ready';
516
+ }
517
+ }
518
+ cell.className = cns.join(' ');
519
+ },
520
+
521
+ /**
522
+ * Create a new test
523
+ */
524
+ test: function(name, f) {
525
+ // Create the Test object
526
+ var test = new Test(name, f);
527
+ JSLitmus._tests.push(test);
528
+
529
+ // Re-render if the test state changes
530
+ test.onChange = JSLitmus.renderTest;
531
+
532
+ // Run the next test if this one finished
533
+ test.onStop = function(test) {
534
+ if (JSLitmus.onTestFinish) JSLitmus.onTestFinish(test);
535
+ JSLitmus.currentTest = null;
536
+ JSLitmus._nextTest();
537
+ };
538
+
539
+ // Render the new test
540
+ this.renderTest(test);
541
+ },
542
+
543
+ /**
544
+ * Add all tests to the run queue
545
+ */
546
+ runAll: function(e) {
547
+ e = e || window.event;
548
+ var reverse = e && e.shiftKey, len = JSLitmus._tests.length;
549
+ for (var i = 0; i < len; i++) {
550
+ JSLitmus._queueTest(JSLitmus._tests[!reverse ? i : (len - i - 1)]);
551
+ }
552
+ },
553
+
554
+ /**
555
+ * Remove all tests from the run queue. The current test has to finish on
556
+ * it's own though
557
+ */
558
+ stop: function() {
559
+ while (JSLitmus._queue.length) {
560
+ var test = JSLitmus._queue.shift();
561
+ JSLitmus.renderTest(test);
562
+ }
563
+ },
564
+
565
+ /**
566
+ * Run the next test in the run queue
567
+ */
568
+ _nextTest: function() {
569
+ if (!JSLitmus.currentTest) {
570
+ var test = JSLitmus._queue.shift();
571
+ if (test) {
572
+ jsl.$('stop_button').disabled = false;
573
+ JSLitmus.currentTest = test;
574
+ test.run();
575
+ JSLitmus.renderTest(test);
576
+ if (JSLitmus.onTestStart) JSLitmus.onTestStart(test);
577
+ } else {
578
+ jsl.$('stop_button').disabled = true;
579
+ JSLitmus.renderChart();
580
+ }
581
+ }
582
+ },
583
+
584
+ /**
585
+ * Add a test to the run queue
586
+ */
587
+ _queueTest: function(test) {
588
+ if (jsl.indexOf(JSLitmus._queue, test) >= 0) return;
589
+ JSLitmus._queue.push(test);
590
+ JSLitmus.renderTest(test);
591
+ JSLitmus._nextTest();
592
+ },
593
+
594
+ /**
595
+ * Generate a Google Chart URL that shows the data for all tests
596
+ */
597
+ chartUrl: function() {
598
+ var n = JSLitmus._tests.length, markers = [], data = [];
599
+ var d, min = 0, max = -1e10;
600
+ var normalize = jsl.$('test_normalize').checked;
601
+
602
+ // Gather test data
603
+ for (var i=0; i < JSLitmus._tests.length; i++) {
604
+ var test = JSLitmus._tests[i];
605
+ if (test.count) {
606
+ var hz = test.getHz(normalize);
607
+ var v = hz != Infinity ? hz : 0;
608
+ data.push(v);
609
+ markers.push('t' + jsl.escape(test.name + '(' + jsl.toLabel(hz)+ ')') + ',000000,0,' +
610
+ markers.length + ',10');
611
+ max = Math.max(v, max);
612
+ }
613
+ }
614
+ if (markers.length <= 0) return null;
615
+
616
+ // Build chart title
617
+ var title = document.getElementsByTagName('title');
618
+ title = (title && title.length) ? title[0].innerHTML : null;
619
+ var chart_title = [];
620
+ if (title) chart_title.push(title);
621
+ chart_title.push('Ops/sec (' + platform + ')');
622
+
623
+ // Build labels
624
+ var labels = [jsl.toLabel(min), jsl.toLabel(max)];
625
+
626
+ var w = 250, bw = 15;
627
+ var bs = 5;
628
+ var h = markers.length*(bw + bs) + 30 + chart_title.length*20;
629
+
630
+ var params = {
631
+ chtt: escape(chart_title.join('|')),
632
+ chts: '000000,10',
633
+ cht: 'bhg', // chart type
634
+ chd: 't:' + data.join(','), // data set
635
+ chds: min + ',' + max, // max/min of data
636
+ chxt: 'x', // label axes
637
+ chxl: '0:|' + labels.join('|'), // labels
638
+ chsp: '0,1',
639
+ chm: markers.join('|'), // test names
640
+ chbh: [bw, 0, bs].join(','), // bar widths
641
+ // chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient
642
+ chs: w + 'x' + h
643
+ };
644
+ return 'http://chart.apis.google.com/chart?' + jsl.join(params, '=', '&');
645
+ }
646
+ };
647
+
648
+ JSLitmus._init();
649
+ })();