chemistrykit 3.8.1 → 3.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG.md +15 -5
  3. data/Gemfile +4 -0
  4. data/README.md +13 -1
  5. data/Rakefile +3 -3
  6. data/chemistrykit.gemspec +7 -3
  7. data/features/brew.feature +1 -1
  8. data/features/chemists.feature +56 -1
  9. data/features/concurrency.feature +2 -2
  10. data/features/exit_status.feature +1 -0
  11. data/features/logging.feature +88 -85
  12. data/features/reporting.feature +105 -0
  13. data/features/step_definitions/steps.rb +4 -4
  14. data/features/support/env.rb +1 -1
  15. data/features/tags.feature +1 -0
  16. data/lib/chemistrykit/chemist.rb +6 -1
  17. data/lib/chemistrykit/chemist/repository/csv_chemist_repository.rb +1 -1
  18. data/lib/chemistrykit/cli/cli.rb +33 -12
  19. data/lib/chemistrykit/configuration.rb +2 -2
  20. data/lib/chemistrykit/formula/formula_lab.rb +13 -0
  21. data/lib/chemistrykit/{parallel_tests_mods.rb → parallel_tests/rspec/runner.rb} +5 -5
  22. data/lib/chemistrykit/reporting/html_report_assembler.rb +170 -0
  23. data/lib/chemistrykit/rspec/html_formatter.rb +241 -0
  24. data/lib/chemistrykit/rspec/j_unit_formatter.rb +124 -0
  25. data/report/config.rb +28 -0
  26. data/report/index.html +213 -0
  27. data/report/javascripts/foundation/foundation.abide.js +194 -0
  28. data/report/javascripts/foundation/foundation.alerts.js +52 -0
  29. data/report/javascripts/foundation/foundation.clearing.js +516 -0
  30. data/report/javascripts/foundation/foundation.cookie.js +74 -0
  31. data/report/javascripts/foundation/foundation.dropdown.js +177 -0
  32. data/report/javascripts/foundation/foundation.forms.js +533 -0
  33. data/report/javascripts/foundation/foundation.interchange.js +280 -0
  34. data/report/javascripts/foundation/foundation.joyride.js +850 -0
  35. data/report/javascripts/foundation/foundation.js +440 -0
  36. data/report/javascripts/foundation/foundation.magellan.js +135 -0
  37. data/report/javascripts/foundation/foundation.orbit.js +412 -0
  38. data/report/javascripts/foundation/foundation.placeholder.js +179 -0
  39. data/report/javascripts/foundation/foundation.reveal.js +330 -0
  40. data/report/javascripts/foundation/foundation.section.js +400 -0
  41. data/report/javascripts/foundation/foundation.tooltips.js +208 -0
  42. data/report/javascripts/foundation/foundation.topbar.js +300 -0
  43. data/report/javascripts/vendor/custom.modernizr.js +4 -0
  44. data/report/javascripts/vendor/jquery.js +9789 -0
  45. data/report/sass/_normalize.scss +402 -0
  46. data/report/sass/_settings.scss +1301 -0
  47. data/report/sass/app.scss +571 -0
  48. data/report/stylesheets/app.css +3636 -0
  49. data/spec/integration/lib/chemistrykit/formula/formula_lab_spec.rb +26 -2
  50. data/spec/integration/lib/chemistrykit/reporting/html_reporting_assembler_spec.rb +18 -0
  51. data/spec/support/evidence/results_0.html +30 -0
  52. data/spec/support/evidence/results_1.html +27 -0
  53. data/spec/unit/lib/chemistrykit/chemist/repository/csv_chemist_repository_spec.rb +15 -2
  54. data/spec/unit/lib/chemistrykit/chemist_spec.rb +17 -1
  55. data/spec/unit/lib/chemistrykit/configuration_spec.rb +2 -2
  56. data/spec/unit/lib/chemistrykit/formula/formula_lab_spec.rb +7 -0
  57. data/spec/unit/lib/chemistrykit/reporting/html_reporting_assembler_spec.rb +22 -0
  58. metadata +94 -13
  59. data/lib/chemistrykit/j_unit.rb +0 -121
@@ -0,0 +1,440 @@
1
+ /*
2
+ * Foundation Responsive Library
3
+ * http://foundation.zurb.com
4
+ * Copyright 2013, ZURB
5
+ * Free to use under the MIT license.
6
+ * http://www.opensource.org/licenses/mit-license.php
7
+ */
8
+
9
+ /*jslint unparam: true, browser: true, indent: 2 */
10
+
11
+ // Accommodate running jQuery or Zepto in noConflict() mode by
12
+ // using an anonymous function to redefine the $ shorthand name.
13
+ // See http://docs.jquery.com/Using_jQuery_with_Other_Libraries
14
+ // and http://zeptojs.com/
15
+ var libFuncName = null;
16
+
17
+ if (typeof jQuery === "undefined" &&
18
+ typeof Zepto === "undefined" &&
19
+ typeof $ === "function") {
20
+ libFuncName = $;
21
+ } else if (typeof jQuery === "function") {
22
+ libFuncName = jQuery;
23
+ } else if (typeof Zepto === "function") {
24
+ libFuncName = Zepto;
25
+ } else {
26
+ throw new TypeError();
27
+ }
28
+
29
+ (function ($, window, document, undefined) {
30
+ 'use strict';
31
+
32
+ /*
33
+ matchMedia() polyfill - Test a CSS media
34
+ type/query in JS. Authors & copyright (c) 2012:
35
+ Scott Jehl, Paul Irish, Nicholas Zakas.
36
+ Dual MIT/BSD license
37
+
38
+ https://github.com/paulirish/matchMedia.js
39
+ */
40
+
41
+ window.matchMedia = window.matchMedia || (function( doc, undefined ) {
42
+
43
+ "use strict";
44
+
45
+ var bool,
46
+ docElem = doc.documentElement,
47
+ refNode = docElem.firstElementChild || docElem.firstChild,
48
+ // fakeBody required for <FF4 when executed in <head>
49
+ fakeBody = doc.createElement( "body" ),
50
+ div = doc.createElement( "div" );
51
+
52
+ div.id = "mq-test-1";
53
+ div.style.cssText = "position:absolute;top:-100em";
54
+ fakeBody.style.background = "none";
55
+ fakeBody.appendChild(div);
56
+
57
+ return function(q){
58
+
59
+ div.innerHTML = "&shy;<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>";
60
+
61
+ docElem.insertBefore( fakeBody, refNode );
62
+ bool = div.offsetWidth === 42;
63
+ docElem.removeChild( fakeBody );
64
+
65
+ return {
66
+ matches: bool,
67
+ media: q
68
+ };
69
+
70
+ };
71
+
72
+ }( document ));
73
+
74
+ // add dusty browser stuff
75
+ if (!Array.prototype.filter) {
76
+ Array.prototype.filter = function(fun /*, thisp */) {
77
+ "use strict";
78
+
79
+ if (this == null) {
80
+ throw new TypeError();
81
+ }
82
+
83
+ var t = Object(this),
84
+ len = t.length >>> 0;
85
+ if (typeof fun !== "function") {
86
+ return;
87
+ }
88
+
89
+ var res = [],
90
+ thisp = arguments[1];
91
+ for (var i = 0; i < len; i++) {
92
+ if (i in t) {
93
+ var val = t[i]; // in case fun mutates this
94
+ if (fun && fun.call(thisp, val, i, t)) {
95
+ res.push(val);
96
+ }
97
+ }
98
+ }
99
+
100
+ return res;
101
+ }
102
+ }
103
+
104
+ if (!Function.prototype.bind) {
105
+ Function.prototype.bind = function (oThis) {
106
+ if (typeof this !== "function") {
107
+ // closest thing possible to the ECMAScript 5 internal IsCallable function
108
+ throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
109
+ }
110
+
111
+ var aArgs = Array.prototype.slice.call(arguments, 1),
112
+ fToBind = this,
113
+ fNOP = function () {},
114
+ fBound = function () {
115
+ return fToBind.apply(this instanceof fNOP && oThis
116
+ ? this
117
+ : oThis,
118
+ aArgs.concat(Array.prototype.slice.call(arguments)));
119
+ };
120
+
121
+ fNOP.prototype = this.prototype;
122
+ fBound.prototype = new fNOP();
123
+
124
+ return fBound;
125
+ };
126
+ }
127
+
128
+ if (!Array.prototype.indexOf) {
129
+ Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
130
+ "use strict";
131
+ if (this == null) {
132
+ throw new TypeError();
133
+ }
134
+ var t = Object(this);
135
+ var len = t.length >>> 0;
136
+ if (len === 0) {
137
+ return -1;
138
+ }
139
+ var n = 0;
140
+ if (arguments.length > 1) {
141
+ n = Number(arguments[1]);
142
+ if (n != n) { // shortcut for verifying if it's NaN
143
+ n = 0;
144
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
145
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
146
+ }
147
+ }
148
+ if (n >= len) {
149
+ return -1;
150
+ }
151
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
152
+ for (; k < len; k++) {
153
+ if (k in t && t[k] === searchElement) {
154
+ return k;
155
+ }
156
+ }
157
+ return -1;
158
+ }
159
+ }
160
+
161
+ // fake stop() for zepto.
162
+ $.fn.stop = $.fn.stop || function() {
163
+ return this;
164
+ };
165
+
166
+ window.Foundation = {
167
+ name : 'Foundation',
168
+
169
+ version : '4.3.1',
170
+
171
+ cache : {},
172
+
173
+ init : function (scope, libraries, method, options, response, /* internal */ nc) {
174
+ var library_arr,
175
+ args = [scope, method, options, response],
176
+ responses = [],
177
+ nc = nc || false;
178
+
179
+ // disable library error catching,
180
+ // used for development only
181
+ if (nc) this.nc = nc;
182
+
183
+ // check RTL
184
+ this.rtl = /rtl/i.test($('html').attr('dir'));
185
+
186
+ // set foundation global scope
187
+ this.scope = scope || this.scope;
188
+
189
+ if (libraries && typeof libraries === 'string' && !/reflow/i.test(libraries)) {
190
+ if (/off/i.test(libraries)) return this.off();
191
+
192
+ library_arr = libraries.split(' ');
193
+
194
+ if (library_arr.length > 0) {
195
+ for (var i = library_arr.length - 1; i >= 0; i--) {
196
+ responses.push(this.init_lib(library_arr[i], args));
197
+ }
198
+ }
199
+ } else {
200
+ if (/reflow/i.test(libraries)) args[1] = 'reflow';
201
+
202
+ for (var lib in this.libs) {
203
+ responses.push(this.init_lib(lib, args));
204
+ }
205
+ }
206
+
207
+ // if first argument is callback, add to args
208
+ if (typeof libraries === 'function') {
209
+ args.unshift(libraries);
210
+ }
211
+
212
+ return this.response_obj(responses, args);
213
+ },
214
+
215
+ response_obj : function (response_arr, args) {
216
+ for (var i = 0, len = args.length; i < len; i++) {
217
+ if (typeof args[i] === 'function') {
218
+ return args[i]({
219
+ errors: response_arr.filter(function (s) {
220
+ if (typeof s === 'string') return s;
221
+ })
222
+ });
223
+ }
224
+ }
225
+
226
+ return response_arr;
227
+ },
228
+
229
+ init_lib : function (lib, args) {
230
+ return this.trap(function () {
231
+ if (this.libs.hasOwnProperty(lib)) {
232
+ this.patch(this.libs[lib]);
233
+ return this.libs[lib].init.apply(this.libs[lib], args);
234
+ } else {
235
+ return function () {};
236
+ }
237
+ }.bind(this), lib);
238
+ },
239
+
240
+ trap : function (fun, lib) {
241
+ if (!this.nc) {
242
+ try {
243
+ return fun();
244
+ } catch (e) {
245
+ return this.error({name: lib, message: 'could not be initialized', more: e.name + ' ' + e.message});
246
+ }
247
+ }
248
+
249
+ return fun();
250
+ },
251
+
252
+ patch : function (lib) {
253
+ this.fix_outer(lib);
254
+ lib.scope = this.scope;
255
+ lib.rtl = this.rtl;
256
+ },
257
+
258
+ inherit : function (scope, methods) {
259
+ var methods_arr = methods.split(' ');
260
+
261
+ for (var i = methods_arr.length - 1; i >= 0; i--) {
262
+ if (this.lib_methods.hasOwnProperty(methods_arr[i])) {
263
+ this.libs[scope.name][methods_arr[i]] = this.lib_methods[methods_arr[i]];
264
+ }
265
+ }
266
+ },
267
+
268
+ random_str : function (length) {
269
+ var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
270
+
271
+ if (!length) {
272
+ length = Math.floor(Math.random() * chars.length);
273
+ }
274
+
275
+ var str = '';
276
+ for (var i = 0; i < length; i++) {
277
+ str += chars[Math.floor(Math.random() * chars.length)];
278
+ }
279
+ return str;
280
+ },
281
+
282
+ libs : {},
283
+
284
+ // methods that can be inherited in libraries
285
+ lib_methods : {
286
+ set_data : function (node, data) {
287
+ // this.name references the name of the library calling this method
288
+ var id = [this.name,+new Date(),Foundation.random_str(5)].join('-');
289
+
290
+ Foundation.cache[id] = data;
291
+ node.attr('data-' + this.name + '-id', id);
292
+ return data;
293
+ },
294
+
295
+ get_data : function (node) {
296
+ return Foundation.cache[node.attr('data-' + this.name + '-id')];
297
+ },
298
+
299
+ remove_data : function (node) {
300
+ if (node) {
301
+ delete Foundation.cache[node.attr('data-' + this.name + '-id')];
302
+ node.attr('data-' + this.name + '-id', '');
303
+ } else {
304
+ $('[data-' + this.name + '-id]').each(function () {
305
+ delete Foundation.cache[$(this).attr('data-' + this.name + '-id')];
306
+ $(this).attr('data-' + this.name + '-id', '');
307
+ });
308
+ }
309
+ },
310
+
311
+ throttle : function(fun, delay) {
312
+ var timer = null;
313
+ return function () {
314
+ var context = this, args = arguments;
315
+ clearTimeout(timer);
316
+ timer = setTimeout(function () {
317
+ fun.apply(context, args);
318
+ }, delay);
319
+ };
320
+ },
321
+
322
+ // parses data-options attribute on nodes and turns
323
+ // them into an object
324
+ data_options : function (el) {
325
+ var opts = {}, ii, p,
326
+ opts_arr = (el.attr('data-options') || ':').split(';'),
327
+ opts_len = opts_arr.length;
328
+
329
+ function isNumber (o) {
330
+ return ! isNaN (o-0) && o !== null && o !== "" && o !== false && o !== true;
331
+ }
332
+
333
+ function trim(str) {
334
+ if (typeof str === 'string') return $.trim(str);
335
+ return str;
336
+ }
337
+
338
+ // parse options
339
+ for (ii = opts_len - 1; ii >= 0; ii--) {
340
+ p = opts_arr[ii].split(':');
341
+
342
+ if (/true/i.test(p[1])) p[1] = true;
343
+ if (/false/i.test(p[1])) p[1] = false;
344
+ if (isNumber(p[1])) p[1] = parseInt(p[1], 10);
345
+
346
+ if (p.length === 2 && p[0].length > 0) {
347
+ opts[trim(p[0])] = trim(p[1]);
348
+ }
349
+ }
350
+
351
+ return opts;
352
+ },
353
+
354
+ delay : function (fun, delay) {
355
+ return setTimeout(fun, delay);
356
+ },
357
+
358
+ // animated scrolling
359
+ scrollTo : function (el, to, duration) {
360
+ if (duration < 0) return;
361
+ var difference = to - $(window).scrollTop();
362
+ var perTick = difference / duration * 10;
363
+
364
+ this.scrollToTimerCache = setTimeout(function() {
365
+ if (!isNaN(parseInt(perTick, 10))) {
366
+ window.scrollTo(0, $(window).scrollTop() + perTick);
367
+ this.scrollTo(el, to, duration - 10);
368
+ }
369
+ }.bind(this), 10);
370
+ },
371
+
372
+ // not supported in core Zepto
373
+ scrollLeft : function (el) {
374
+ if (!el.length) return;
375
+ return ('scrollLeft' in el[0]) ? el[0].scrollLeft : el[0].pageXOffset;
376
+ },
377
+
378
+ // test for empty object or array
379
+ empty : function (obj) {
380
+ if (obj.length && obj.length > 0) return false;
381
+ if (obj.length && obj.length === 0) return true;
382
+
383
+ for (var key in obj) {
384
+ if (hasOwnProperty.call(obj, key)) return false;
385
+ }
386
+
387
+ return true;
388
+ }
389
+ },
390
+
391
+ fix_outer : function (lib) {
392
+ lib.outerHeight = function (el, bool) {
393
+ if (typeof Zepto === 'function') {
394
+ return el.height();
395
+ }
396
+
397
+ if (typeof bool !== 'undefined') {
398
+ return el.outerHeight(bool);
399
+ }
400
+
401
+ return el.outerHeight();
402
+ };
403
+
404
+ lib.outerWidth = function (el, bool) {
405
+ if (typeof Zepto === 'function') {
406
+ return el.width();
407
+ }
408
+
409
+ if (typeof bool !== 'undefined') {
410
+ return el.outerWidth(bool);
411
+ }
412
+
413
+ return el.outerWidth();
414
+ };
415
+ },
416
+
417
+ error : function (error) {
418
+ return error.name + ' ' + error.message + '; ' + error.more;
419
+ },
420
+
421
+ // remove all foundation events.
422
+ off: function () {
423
+ $(this.scope).off('.fndtn');
424
+ $(window).off('.fndtn');
425
+ return true;
426
+ },
427
+
428
+ zj : $
429
+ };
430
+
431
+ $.fn.foundation = function () {
432
+ var args = Array.prototype.slice.call(arguments, 0);
433
+
434
+ return this.each(function () {
435
+ Foundation.init.apply(Foundation, [this].concat(args));
436
+ return this;
437
+ });
438
+ };
439
+
440
+ }(libFuncName, this, this.document));
@@ -0,0 +1,135 @@
1
+ /*jslint unparam: true, browser: true, indent: 2 */
2
+
3
+ ;(function ($, window, document, undefined) {
4
+ 'use strict';
5
+
6
+ Foundation.libs.magellan = {
7
+ name : 'magellan',
8
+
9
+ version : '4.2.2',
10
+
11
+ settings : {
12
+ activeClass: 'active',
13
+ threshold: 0
14
+ },
15
+
16
+ init : function (scope, method, options) {
17
+ this.scope = scope || this.scope;
18
+ Foundation.inherit(this, 'data_options');
19
+
20
+ if (typeof method === 'object') {
21
+ $.extend(true, this.settings, method);
22
+ }
23
+
24
+ if (typeof method !== 'string') {
25
+ if (!this.settings.init) {
26
+ this.fixed_magellan = $("[data-magellan-expedition]");
27
+ this.set_threshold();
28
+ this.last_destination = $('[data-magellan-destination]').last();
29
+ this.events();
30
+ }
31
+
32
+ return this.settings.init;
33
+ } else {
34
+ return this[method].call(this, options);
35
+ }
36
+ },
37
+
38
+ events : function () {
39
+ var self = this;
40
+ $(this.scope).on('arrival.fndtn.magellan', '[data-magellan-arrival]', function (e) {
41
+ var $destination = $(this),
42
+ $expedition = $destination.closest('[data-magellan-expedition]'),
43
+ activeClass = $expedition.attr('data-magellan-active-class')
44
+ || self.settings.activeClass;
45
+
46
+ $destination
47
+ .closest('[data-magellan-expedition]')
48
+ .find('[data-magellan-arrival]')
49
+ .not($destination)
50
+ .removeClass(activeClass);
51
+ $destination.addClass(activeClass);
52
+ });
53
+
54
+ this.fixed_magellan
55
+ .on('update-position.fndtn.magellan', function(){
56
+ var $el = $(this);
57
+ // $el.data("magellan-fixed-position","");
58
+ // $el.data("magellan-top-offset", "");
59
+ })
60
+ .trigger('update-position');
61
+
62
+ $(window)
63
+ .on('resize.fndtn.magellan', function() {
64
+ this.fixed_magellan.trigger('update-position');
65
+ }.bind(this))
66
+
67
+ .on('scroll.fndtn.magellan', function() {
68
+ var windowScrollTop = $(window).scrollTop();
69
+ self.fixed_magellan.each(function() {
70
+ var $expedition = $(this);
71
+ if (typeof $expedition.data('magellan-top-offset') === 'undefined') {
72
+ $expedition.data('magellan-top-offset', $expedition.offset().top);
73
+ }
74
+ if (typeof $expedition.data('magellan-fixed-position') === 'undefined') {
75
+ $expedition.data('magellan-fixed-position', false)
76
+ }
77
+ var fixed_position = (windowScrollTop + self.settings.threshold) > $expedition.data("magellan-top-offset");
78
+ var attr = $expedition.attr('data-magellan-top-offset');
79
+
80
+ if ($expedition.data("magellan-fixed-position") != fixed_position) {
81
+ $expedition.data("magellan-fixed-position", fixed_position);
82
+ if (fixed_position) {
83
+ $expedition.addClass('fixed');
84
+ $expedition.css({position:"fixed", top:0});
85
+ } else {
86
+ $expedition.removeClass('fixed');
87
+ $expedition.css({position:"", top:""});
88
+ }
89
+ if (fixed_position && typeof attr != 'undefined' && attr != false) {
90
+ $expedition.css({position:"fixed", top:attr + "px"});
91
+ }
92
+ }
93
+ });
94
+ });
95
+
96
+
97
+ if (this.last_destination.length > 0) {
98
+ $(window).on('scroll.fndtn.magellan', function (e) {
99
+ var windowScrollTop = $(window).scrollTop(),
100
+ scrolltopPlusHeight = windowScrollTop + $(window).height(),
101
+ lastDestinationTop = Math.ceil(self.last_destination.offset().top);
102
+
103
+ $('[data-magellan-destination]').each(function () {
104
+ var $destination = $(this),
105
+ destination_name = $destination.attr('data-magellan-destination'),
106
+ topOffset = $destination.offset().top - windowScrollTop;
107
+
108
+ if (topOffset <= self.settings.threshold) {
109
+ $("[data-magellan-arrival='" + destination_name + "']").trigger('arrival');
110
+ }
111
+ // In large screens we may hit the bottom of the page and dont reach the top of the last magellan-destination, so lets force it
112
+ if (scrolltopPlusHeight >= $(self.scope).height() && lastDestinationTop > windowScrollTop && lastDestinationTop < scrolltopPlusHeight) {
113
+ $('[data-magellan-arrival]').last().trigger('arrival');
114
+ }
115
+ });
116
+ });
117
+ }
118
+
119
+ this.settings.init = true;
120
+ },
121
+
122
+ set_threshold : function () {
123
+ if (!this.settings.threshold) {
124
+ this.settings.threshold = (this.fixed_magellan.length > 0) ?
125
+ this.outerHeight(this.fixed_magellan, true) : 0;
126
+ }
127
+ },
128
+
129
+ off : function () {
130
+ $(this.scope).off('.fndtn.magellan');
131
+ },
132
+
133
+ reflow : function () {}
134
+ };
135
+ }(Foundation.zj, this, this.document));