pivotal-screw-unit 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. data/CHANGES +21 -0
  2. data/README.markdown +354 -0
  3. data/Rakefile +39 -0
  4. data/VERSION.yml +4 -0
  5. data/bin/screw_unit +6 -0
  6. data/bin/screw_unit_server +10 -0
  7. data/core/CHANGES +10 -0
  8. data/core/EXAMPLE.html +68 -0
  9. data/core/LICENSE +22 -0
  10. data/core/README.markdown +307 -0
  11. data/core/example/models/cat.js +5 -0
  12. data/core/example/models/man.js +17 -0
  13. data/core/example/spec/matchers/have.js +8 -0
  14. data/core/example/spec/models/cat_spec.js +31 -0
  15. data/core/example/spec/models/man_spec.js +34 -0
  16. data/core/example/spec/spec_helper.js +5 -0
  17. data/core/example/spec/suite.html +25 -0
  18. data/core/lib/jquery-1.3.2.js +4376 -0
  19. data/core/lib/jquery.fn.js +30 -0
  20. data/core/lib/jquery.print.js +109 -0
  21. data/core/lib/screw.behaviors.js +93 -0
  22. data/core/lib/screw.builder.js +94 -0
  23. data/core/lib/screw.css +90 -0
  24. data/core/lib/screw.events.js +45 -0
  25. data/core/lib/screw.matchers.js +244 -0
  26. data/core/spec/behaviors_spec.js +188 -0
  27. data/core/spec/matchers_spec.js +372 -0
  28. data/core/spec/print_spec.js +158 -0
  29. data/core/spec/spec_helper.js +0 -0
  30. data/core/spec/suite.html +19 -0
  31. data/core/spec/with_screw_context_spec.js +9 -0
  32. data/init.rb +0 -0
  33. data/lib/screw_unit/representations/spec.html.rb +117 -0
  34. data/lib/screw_unit/representations.rb +2 -0
  35. data/lib/screw_unit.rb +19 -0
  36. data/spec/functional/functional_spec.rb +25 -0
  37. data/spec/functional/functional_spec_helper.rb +34 -0
  38. data/spec/functional/functional_spec_server_starter.rb +63 -0
  39. data/spec/functional_suite.rb +10 -0
  40. data/spec/spec_suite.rb +3 -0
  41. data/spec/unit/js_test_core/specs/spec_dir_spec.rb +39 -0
  42. data/spec/unit/js_test_core/specs/spec_file_spec.rb +35 -0
  43. data/spec/unit/unit_spec_helper.rb +119 -0
  44. data/spec/unit_suite.rb +10 -0
  45. data/vendor/js-test-core/CHANGES +25 -0
  46. data/vendor/js-test-core/README +12 -0
  47. data/vendor/js-test-core/Rakefile +73 -0
  48. data/vendor/js-test-core/lib/js_test_core/client.rb +129 -0
  49. data/vendor/js-test-core/lib/js_test_core/extensions/time.rb +6 -0
  50. data/vendor/js-test-core/lib/js_test_core/extensions.rb +3 -0
  51. data/vendor/js-test-core/lib/js_test_core/rack/commonlogger.rb +5 -0
  52. data/vendor/js-test-core/lib/js_test_core/rack.rb +2 -0
  53. data/vendor/js-test-core/lib/js_test_core/rails_server.rb +22 -0
  54. data/vendor/js-test-core/lib/js_test_core/representations/spec.html.rb +23 -0
  55. data/vendor/js-test-core/lib/js_test_core/representations.rb +9 -0
  56. data/vendor/js-test-core/lib/js_test_core/resources/dir.rb +67 -0
  57. data/vendor/js-test-core/lib/js_test_core/resources/file.rb +42 -0
  58. data/vendor/js-test-core/lib/js_test_core/resources/runner.rb +107 -0
  59. data/vendor/js-test-core/lib/js_test_core/resources/session.rb +44 -0
  60. data/vendor/js-test-core/lib/js_test_core/resources/session_finish.rb +17 -0
  61. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec.rb +32 -0
  62. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_dir.rb +50 -0
  63. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_file.rb +21 -0
  64. data/vendor/js-test-core/lib/js_test_core/resources/web_root.rb +66 -0
  65. data/vendor/js-test-core/lib/js_test_core/resources.rb +17 -0
  66. data/vendor/js-test-core/lib/js_test_core/selenium/client/driver.rb +7 -0
  67. data/vendor/js-test-core/lib/js_test_core/selenium.rb +2 -0
  68. data/vendor/js-test-core/lib/js_test_core/selenium_server_configuration.rb +48 -0
  69. data/vendor/js-test-core/lib/js_test_core/server.rb +50 -0
  70. data/vendor/js-test-core/lib/js_test_core/thin/backends/js_test_core_server.rb +9 -0
  71. data/vendor/js-test-core/lib/js_test_core/thin/js_test_core_connection.rb +8 -0
  72. data/vendor/js-test-core/lib/js_test_core/thin.rb +3 -0
  73. data/vendor/js-test-core/lib/js_test_core.rb +41 -0
  74. data/vendor/js-test-core/spec/example_core/JsTestCore.css +0 -0
  75. data/vendor/js-test-core/spec/example_core/JsTestCore.js +0 -0
  76. data/vendor/js-test-core/spec/example_public/favicon.ico +0 -0
  77. data/vendor/js-test-core/spec/example_public/javascripts/foo.js +3 -0
  78. data/vendor/js-test-core/spec/example_public/javascripts/large_file.js +59 -0
  79. data/vendor/js-test-core/spec/example_public/javascripts/subdir/bar.js +1 -0
  80. data/vendor/js-test-core/spec/example_public/robots.txt +0 -0
  81. data/vendor/js-test-core/spec/example_public/stylesheets/example.css +3 -0
  82. data/vendor/js-test-core/spec/example_specs/custom_dir_and_suite/passing_spec.js +6 -0
  83. data/vendor/js-test-core/spec/example_specs/custom_dir_and_suite.html +9 -0
  84. data/vendor/js-test-core/spec/example_specs/custom_suite.html +8 -0
  85. data/vendor/js-test-core/spec/example_specs/failing_spec.js +5 -0
  86. data/vendor/js-test-core/spec/example_specs/foo/failing_spec.js +6 -0
  87. data/vendor/js-test-core/spec/example_specs/foo/passing_spec.js +6 -0
  88. data/vendor/js-test-core/spec/spec_suite.rb +2 -0
  89. data/vendor/js-test-core/spec/specs/failing_spec.js +0 -0
  90. data/vendor/js-test-core/spec/unit/js_test_core/client_spec.rb +192 -0
  91. data/vendor/js-test-core/spec/unit/js_test_core/rails_server_spec.rb +45 -0
  92. data/vendor/js-test-core/spec/unit/js_test_core/resources/dir_spec.rb +53 -0
  93. data/vendor/js-test-core/spec/unit/js_test_core/resources/file_not_found_spec.rb +16 -0
  94. data/vendor/js-test-core/spec/unit/js_test_core/resources/file_spec.rb +90 -0
  95. data/vendor/js-test-core/spec/unit/js_test_core/resources/runners/runner_spec.rb +303 -0
  96. data/vendor/js-test-core/spec/unit/js_test_core/resources/session_finish_spec.rb +79 -0
  97. data/vendor/js-test-core/spec/unit/js_test_core/resources/session_spec.rb +82 -0
  98. data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_dir_spec.rb +104 -0
  99. data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_file_spec.rb +41 -0
  100. data/vendor/js-test-core/spec/unit/js_test_core/resources/web_root_spec.rb +32 -0
  101. data/vendor/js-test-core/spec/unit/js_test_core/selenium_server_configuration_spec.rb +49 -0
  102. data/vendor/js-test-core/spec/unit/js_test_core/server_spec.rb +117 -0
  103. data/vendor/js-test-core/spec/unit/thin/js_test_core_connection_spec.rb +6 -0
  104. data/vendor/js-test-core/spec/unit/unit_spec_helper.rb +161 -0
  105. data/vendor/js-test-core/spec/unit_suite.rb +10 -0
  106. data/vendor/js-test-core/vendor/thin-rest/CHANGES +2 -0
  107. data/vendor/js-test-core/vendor/thin-rest/README +0 -0
  108. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/connection.rb +117 -0
  109. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/extensions/object.rb +21 -0
  110. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/extensions.rb +3 -0
  111. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/internal_error.html.rb +19 -0
  112. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/page.html.rb +41 -0
  113. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/resource_not_found.html.rb +18 -0
  114. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations.rb +4 -0
  115. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/internal_error.rb +11 -0
  116. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/resource.rb +105 -0
  117. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/resource_not_found.rb +19 -0
  118. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources.rb +4 -0
  119. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/routing_error.rb +5 -0
  120. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest.rb +10 -0
  121. data/vendor/js-test-core/vendor/thin-rest/spec/spec_suite.rb +5 -0
  122. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/connection_spec.rb +205 -0
  123. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/resource_not_found_spec.rb +16 -0
  124. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/resource_spec.rb +135 -0
  125. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/root_spec.rb +16 -0
  126. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest_spec_helper.rb +133 -0
  127. metadata +184 -0
@@ -0,0 +1,30 @@
1
+ (function($) {
2
+ $.fn.fn = function() {
3
+ var self = this;
4
+ var extension = arguments[0], name = arguments[0];
5
+ if (typeof name == "string") {
6
+ return apply(self, name, $.makeArray(arguments).slice(1, arguments.length));
7
+ } else {
8
+ $.each(extension, function(key, value) {
9
+ define(self, key, value);
10
+ });
11
+ return self;
12
+ }
13
+ };
14
+ function define(self, name, fn) {
15
+ self.data(namespacedName(name), fn);
16
+ };
17
+ function apply(self, name, args) {
18
+ var result;
19
+ self.each(function(i, item) {
20
+ var fn = $(item).data(namespacedName(name));
21
+ if (fn) result = fn.apply(item, args)
22
+ else throw(name + " is not defined");
23
+ });
24
+
25
+ return result;
26
+ };
27
+ function namespacedName(name) {
28
+ return 'fn.' + name;
29
+ }
30
+ })(jQuery);
@@ -0,0 +1,109 @@
1
+ (function($) {
2
+
3
+ function print_array(obj, opts) {
4
+ var result = [];
5
+ for (var i = 0; i < Math.min(opts.max_array, obj.length); i++)
6
+ result.push($.print(obj[i], $.extend({}, opts, { max_array: 3, max_string: 40 })));
7
+
8
+ if (obj.length > opts.max_array)
9
+ result.push((obj.length - opts.max_array) + ' more...');
10
+ if (result.length == 0) return "[]"
11
+ return "[ " + result.join(", ") + " ]";
12
+ }
13
+
14
+ function print_element(obj) {
15
+ if (obj.nodeType == 1) {
16
+ var result = [];
17
+ var properties = [ 'className', 'id' ];
18
+ var extra = {
19
+ 'input': ['type', 'name', 'value'],
20
+ 'a': ['href', 'target'],
21
+ 'form': ['method', 'action'],
22
+ 'script': ['src'],
23
+ 'link': ['href'],
24
+ 'img': ['src']
25
+ };
26
+
27
+ $.each(properties.concat(extra[obj.tagName.toLowerCase()] || []), function(){
28
+ if (obj[this])
29
+ result.push(' ' + this.replace('className', 'class') + "=" + $.print(obj[this]))
30
+ });
31
+ return "<" + obj.tagName.toLowerCase()
32
+ + result.join('') + ">";
33
+ }
34
+ }
35
+
36
+ function print_object(obj, opts) {
37
+ var seen = opts.seen || [ obj ];
38
+
39
+ var result = [], key, value;
40
+ for (var k in obj) {
41
+ if (obj.hasOwnProperty(k) && $.inArray(obj[k], seen) < 0) {
42
+ seen.push(obj[k]);
43
+ value = $.print(obj[k], $.extend({}, opts, { max_array: 6, max_string: 40, seen: seen }));
44
+ } else
45
+ value = "...";
46
+ result.push(k + ": " + value);
47
+ }
48
+ if (result.length == 0) return "{}";
49
+ return "{ " + result.join(", ") + " }";
50
+ }
51
+
52
+ function print_string(value, opts) {
53
+ var character_substitutions = {
54
+ '\b': '\\b',
55
+ '\t': '\\t',
56
+ '\n': '\\n',
57
+ '\f': '\\f',
58
+ '\r': '\\r',
59
+ '"' : '\\"',
60
+ '\\': '\\\\'
61
+ };
62
+ var r = /["\\\x00-\x1f\x7f-\x9f]/g;
63
+
64
+ var str = r.test(value)
65
+ ? '"' + value.replace(r, function (a) {
66
+ var c = character_substitutions[a];
67
+ if (c) return c;
68
+ c = a.charCodeAt();
69
+ return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
70
+ }) + '"'
71
+ : '"' + value + '"';
72
+ if (str.length > opts.max_string)
73
+ return str.slice(0, opts.max_string + 1) + '..."';
74
+ else
75
+ return str;
76
+ }
77
+
78
+ $.print = function(obj, options) {
79
+ var opts = $.extend({}, { max_array: 10, max_string: 100 }, options);
80
+
81
+ if (typeof obj == 'undefined')
82
+ return "undefined";
83
+ else if (typeof obj == 'boolean')
84
+ return obj.toString();
85
+ else if (typeof obj == 'number')
86
+ return obj.toString();
87
+ else if (!obj)
88
+ return "null";
89
+ else if (typeof obj == 'string')
90
+ return print_string(obj, opts);
91
+ else if (obj instanceof RegExp)
92
+ return obj.toString();
93
+ else if (obj instanceof Array || obj.callee || obj.item)
94
+ return print_array(obj, opts);
95
+ else if (typeof obj == 'function' || obj instanceof Function)
96
+ return obj.toString().match(/^([^)]*\))/)[1];
97
+ else if (obj.nodeType)
98
+ return print_element(obj);
99
+ else if (obj instanceof jQuery)
100
+ return "$(" + $.print(obj.get()) + ")";
101
+ else if (obj instanceof Error)
102
+ return print_object(obj, $.extend({}, options, { max_string: 200 }));
103
+ else if (obj instanceof Object)
104
+ return print_object(obj, opts);
105
+ else
106
+ return obj.toString().replace(/\n\s*/g, '');
107
+ }
108
+
109
+ })(jQuery);
@@ -0,0 +1,93 @@
1
+ (function($) {
2
+ $(Screw).bind('loaded', function() {
3
+ $('.status').fn({
4
+ display: function() {
5
+ $(this).html(
6
+ $('.passed').length + $('.failed').length + ' test(s), ' + $('.failed').length + ' failure(s)<br />' +
7
+ ((new Date() - Screw.suite_start_time)/1000.0).toString() + " seconds elapsed"
8
+ );
9
+ }
10
+ });
11
+
12
+ $('.describe').fn({
13
+ parent: function() {
14
+ return $(this).parent('.describes').parent('.describe');
15
+ },
16
+
17
+ run_befores: function() {
18
+ $(this).fn('parent').fn('run_befores');
19
+ $(this).children('.befores').children('.before').fn('run');
20
+ },
21
+
22
+ run_afters: function() {
23
+ $(this).fn('parent').fn('run_afters');
24
+ $(this).children('.afters').children('.after').fn('run');
25
+ },
26
+
27
+ enqueue: function() {
28
+ $(this).children('.its').children('.it').fn('enqueue');
29
+ $(this).children('.describes').children('.describe').fn('enqueue');
30
+ },
31
+
32
+ selector: function() {
33
+ return $(this).fn('parent').fn('selector')
34
+ + ' > .describes > .describe:eq(' + $(this).parent('.describes').children('.describe').index(this) + ')';
35
+ }
36
+ });
37
+
38
+ $('body > .describe').fn({
39
+ selector: function() { return 'body > .describe'; }
40
+ });
41
+
42
+ $('.it').fn({
43
+ parent: function() {
44
+ return $(this).parent('.its').parent('.describe');
45
+ },
46
+
47
+ run: function() {
48
+ try {
49
+ try {
50
+ $(this).fn('parent').fn('run_befores');
51
+ $(this).data('screwunit.run')();
52
+ } finally {
53
+ $(this).fn('parent').fn('run_afters');
54
+ }
55
+ $(this).trigger('passed');
56
+ } catch(e) {
57
+ $(this).trigger('failed', [e]);
58
+ }
59
+ },
60
+
61
+ enqueue: function() {
62
+ var self = $(this).trigger('enqueued');
63
+ $(Screw)
64
+ .queue(function() {
65
+ self.fn('run');
66
+ setTimeout(function() { $(Screw).dequeue(); }, 0);
67
+ });
68
+ },
69
+
70
+ selector: function() {
71
+ return $(this).fn('parent').fn('selector')
72
+ + ' > .its > .it:eq(' + $(this).parent('.its').children('.it').index(this) + ')';
73
+ }
74
+ });
75
+
76
+ $('body .before').fn({
77
+ run: function() { $(this).data('screwunit.run')(); }
78
+ });
79
+
80
+ $('body .after').fn({
81
+ run: function() {
82
+ $(this).data('screwunit.run')(); }
83
+ });
84
+
85
+ $(Screw).trigger('before');
86
+ var to_run = unescape(location.search.slice(1)) || 'body > .describe > .describes > .describe';
87
+ $(to_run)
88
+ .focus()
89
+ .eq(0).trigger('scroll').end()
90
+ .fn('enqueue');
91
+ $(Screw).queue(function() { $(Screw).trigger('after') });
92
+ });
93
+ })(jQuery);
@@ -0,0 +1,94 @@
1
+ var Screw = (function($) {
2
+ var screw = {
3
+ Unit: function(fn) {
4
+ var contents = fn.toString().match(/^[^\{]*{((.*\n*)*)}/m)[1];
5
+ var wrappedFn;
6
+ if(fn.length == 0) {
7
+ wrappedFn = new Function("matchers", "specifications",
8
+ "with (specifications) { with (matchers) { " + contents + " } }"
9
+ );
10
+ } else {
11
+ wrappedFn = function(matchers, specifications) {
12
+ var screwContext = {};
13
+ for(var method in matchers) {
14
+ screwContext[method] = matchers[method];
15
+ }
16
+ for(var method in specifications) {
17
+ screwContext[method] = specifications[method];
18
+ }
19
+ fn(screwContext);
20
+ }
21
+ }
22
+
23
+ $(Screw).queue(function() {
24
+ Screw.Specifications.context.push($('body > .describe'));
25
+ wrappedFn.call(this, Screw.Matchers, Screw.Specifications);
26
+ Screw.Specifications.context.pop();
27
+ $(this).dequeue();
28
+ });
29
+ },
30
+
31
+ Specifications: {
32
+ context: [],
33
+
34
+ describe: function(name, fn) {
35
+ var describe = $('<li class="describe">')
36
+ .append($('<h1 />').text(name))
37
+ .append('<ol class="befores">')
38
+ .append('<ul class="its">')
39
+ .append('<ul class="describes">')
40
+ .append('<ol class="afters">');
41
+
42
+ this.context.push(describe);
43
+ fn.call();
44
+ this.context.pop();
45
+
46
+ this.context[this.context.length-1]
47
+ .children('.describes')
48
+ .append(describe);
49
+ },
50
+
51
+ it: function(name, fn) {
52
+ var it = $('<li class="it">')
53
+ .append($('<h2 />').text(name))
54
+ .data('screwunit.run', fn);
55
+
56
+ this.context[this.context.length-1]
57
+ .children('.its')
58
+ .append(it);
59
+ },
60
+
61
+ before: function(fn) {
62
+ var before = $('<li class="before"></li>')
63
+ .data('screwunit.run', fn);
64
+
65
+ this.context[this.context.length-1]
66
+ .children('.befores')
67
+ .append(before);
68
+ },
69
+
70
+ after: function(fn) {
71
+ var after = $('<li class="after"></li>')
72
+ .data('screwunit.run', fn);
73
+
74
+ this.context[this.context.length-1]
75
+ .children('.afters')
76
+ .append(after);
77
+ }
78
+ }
79
+ };
80
+
81
+ $(screw).queue(function() { $(screw).trigger('loading') });
82
+ $(function() {
83
+ $('<div class="describe">')
84
+ .append('<h3 class="status" />')
85
+ .append('<ol class="befores">')
86
+ .append('<ul class="describes">')
87
+ .append('<ol class="afters">')
88
+ .appendTo('body');
89
+
90
+ $(screw).dequeue();
91
+ $(screw).trigger('loaded');
92
+ });
93
+ return screw;
94
+ })(jQuery);
@@ -0,0 +1,90 @@
1
+ html {
2
+ padding: 0.5em;
3
+ font-family: Georgia, serif;
4
+ background: #EDEBD5;
5
+ }
6
+
7
+ li {
8
+ list-style-type: none;
9
+ }
10
+
11
+ .focused {
12
+ background-color: #F4F2E4;
13
+ }
14
+
15
+ .focused * {
16
+ opacity: 1.0;
17
+ }
18
+
19
+ h1, h2, p {
20
+ opacity: 0.4;
21
+ }
22
+
23
+ .describes {
24
+ padding-left: 0;
25
+ }
26
+
27
+ .describes h1 {
28
+ font-size: 1.1em;
29
+ color: #877C21;
30
+ line-height: 1.8em;
31
+ margin: 0pt 0pt 0.6em;
32
+ border-bottom: 1px solid transparent;
33
+ }
34
+
35
+ .describes h1:hover {
36
+ cursor: pointer;
37
+ color: #000;
38
+ background-color: #F4F2E4;
39
+ border-bottom: 1px solid #9A8E51;
40
+ }
41
+
42
+ .describes .describe {
43
+ margin-left: 0.6em;
44
+ padding-left: 0.6em;
45
+ border: 1px dashed #6E6E6E;
46
+ }
47
+
48
+ .describes .describe .its {}
49
+
50
+ .describes .describe .its .it {
51
+ list-style-type: lower-roman;
52
+ list-style-position: outside;
53
+ }
54
+
55
+ .describes .describe .its .it h2 {
56
+ font-weight: normal;
57
+ font-style: italic;
58
+ padding-left: 0.5em;
59
+ font-size: 1.0em;
60
+ color: #877C21;
61
+ line-height: 1.8em;
62
+ margin: 0 0 0.5em;
63
+ border-bottom: 1px solid transparent;
64
+ }
65
+
66
+ .describes .describe .its .it.enqueued h2 {
67
+ background-color: #CC6600;
68
+ color: white !important;
69
+ }
70
+
71
+ .describes .describe .its .it.passed h2 {
72
+ background-color: #5A753D;
73
+ color: white !important;
74
+ }
75
+
76
+ .describes .describe .its .it.failed h2 {
77
+ background-color: #993300;
78
+ color: white !important;
79
+ }
80
+
81
+ .describes .describe .its .it.failed p {
82
+ margin-left: 1em;
83
+ color: #993300;
84
+ }
85
+
86
+ .describes .describe .its .it h2:hover {
87
+ cursor: pointer;
88
+ color: #000 !important;
89
+ border-bottom: 1px solid #9A8E51;
90
+ }
@@ -0,0 +1,45 @@
1
+ (function($) {
2
+ $(Screw)
3
+ .bind('loaded', function() {
4
+ $('.describe, .it')
5
+ .click(function() {
6
+ document.location = location.href.split('?')[0] + '?' + $(this).fn('selector');
7
+ return false;
8
+ })
9
+ .focus(function() {
10
+ return $(this).addClass('focused');
11
+ })
12
+ .bind('scroll', function() {
13
+ document.body.scrollTop = $(this).offset().top;
14
+ });
15
+
16
+ $('.it')
17
+ .bind('enqueued', function() {
18
+ $(this).addClass('enqueued');
19
+ })
20
+ .bind('running', function() {
21
+ $(this).addClass('running');
22
+ })
23
+ .bind('passed', function() {
24
+ $(this).addClass('passed');
25
+ })
26
+ .bind('failed', function(e, reason) {
27
+ $(this)
28
+ .addClass('failed')
29
+ .append($('<p class="error">').text(reason.toString()));
30
+
31
+ var file = reason.fileName || reason.sourceURL;
32
+ var line = reason.lineNumber || reason.line;
33
+ if (file || line) {
34
+ $(this).append($('<p class="error"></p>').text('line ' + line + ', ' + file));
35
+ }
36
+ });
37
+ })
38
+ .bind('before', function() {
39
+ Screw.suite_start_time = new Date();
40
+ $('.status').text('Running...');
41
+ })
42
+ .bind('after', function() {
43
+ $('body .status').fn('display');
44
+ });
45
+ })(jQuery);
@@ -0,0 +1,244 @@
1
+ Screw.Matchers = (function($) {
2
+ return matchers = {
3
+ expect: function(actual) {
4
+ var funcname = function(f) {
5
+ var s = f.toString().match(/function (\w*)/)[1];
6
+ if ((s == null) || (s.length == 0)) return "anonymous";
7
+ return s;
8
+ };
9
+
10
+ var stacktrace = function() {
11
+ var s = "";
12
+ for(var a = arguments.caller; a != null; a = a.caller) {
13
+ s += funcname(a.callee) + "\n";
14
+ if (a.caller == a) break;
15
+ }
16
+ return s;
17
+ };
18
+
19
+ return {
20
+ to: function(matcher, expected, not) {
21
+ var matched = matcher.match(expected, actual);
22
+ if (not ? matched : !matched) {
23
+ throw(matcher.failure_message(expected, actual, not));
24
+ }
25
+ },
26
+
27
+ to_not: function(matcher, expected) {
28
+ this.to(matcher, expected, true);
29
+ }
30
+ }
31
+ },
32
+
33
+ equal: {
34
+ match: function(expected, actual) {
35
+ if(expected == actual) return true;
36
+ if(actual == undefined) return false;
37
+
38
+ if (expected instanceof Array) {
39
+ for (var i = 0; i < actual.length; i++)
40
+ if (!Screw.Matchers.equal.match(expected[i], actual[i])) return false;
41
+ return actual.length == expected.length;
42
+ } else if (expected instanceof Object) {
43
+ for (var key in expected)
44
+ if (!this.match(expected[key], actual[key])) return false;
45
+ for (var key in actual)
46
+ if (!this.match(actual[key], expected[key])) return false;
47
+ return true;
48
+ }
49
+ return false;
50
+ },
51
+
52
+ failure_message: function(expected, actual, not) {
53
+ return 'expected ' + $.print(actual) + (not ? ' to not equal ' : ' to equal ') + $.print(expected);
54
+ }
55
+ },
56
+
57
+ be_gt: {
58
+ match: function(expected, actual) {
59
+ return actual > expected;
60
+ },
61
+
62
+ failure_message: function(expected, actual, not) {
63
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be greater than ' + $.print(expected);
64
+ }
65
+ },
66
+
67
+ be_gte: {
68
+ match: function(expected, actual) {
69
+ return actual >= expected;
70
+ },
71
+
72
+ failure_message: function(expected, actual, not) {
73
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be greater than or equal to ' + $.print(expected);
74
+ }
75
+ },
76
+
77
+ be_lt: {
78
+ match: function(expected, actual) {
79
+ return actual < expected;
80
+ },
81
+
82
+ failure_message: function(expected, actual, not) {
83
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be less than ' + $.print(expected);
84
+ }
85
+ },
86
+
87
+ be_lte: {
88
+ match: function(expected, actual) {
89
+ return actual <= expected;
90
+ },
91
+
92
+ failure_message: function(expected, actual, not) {
93
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be less than or equal to ' + $.print(expected);
94
+ }
95
+ },
96
+
97
+ match: {
98
+ match: function(expected, actual) {
99
+ if (expected.constructor == RegExp)
100
+ return expected.exec(actual.toString());
101
+ else
102
+ return actual.indexOf(expected) > -1;
103
+ },
104
+
105
+ failure_message: function(expected, actual, not) {
106
+ return 'expected ' + $.print(actual) + (not ? ' to not match ' : ' to match ') + $.print(expected);
107
+ }
108
+ },
109
+
110
+ be_empty: {
111
+ match: function(expected, actual) {
112
+ if (actual.length == undefined) throw(actual.toString() + " does not respond to length");
113
+
114
+ return actual.length == 0;
115
+ },
116
+
117
+ failure_message: function(expected, actual, not) {
118
+ return 'expected ' + $.print(actual) + (not ? ' to not be empty' : ' to be empty');
119
+ }
120
+ },
121
+
122
+ be_blank: {
123
+ match: function(expected, actual) {
124
+ if (actual == undefined) return true;
125
+ if (typeof(actual) == "string") actual = actual.replace(/^\s*(.*?)\s*$/, "$1");
126
+ return Screw.Matchers.be_empty.match(expected, actual);
127
+ },
128
+
129
+ failure_message: function(expected, actual, not) {
130
+ return 'expected ' + $.print(actual) + (not ? ' to not be blank' : ' to be blank');
131
+ }
132
+ },
133
+
134
+ have_length: {
135
+ match: function(expected, actual) {
136
+ if (actual.length == undefined) throw(actual.toString() + " does not respond to length");
137
+
138
+ return actual.length == expected;
139
+ },
140
+
141
+ failure_message: function(expected, actual, not) {
142
+ return 'expected ' + $.print(actual) + (not ? ' to not' : ' to') + ' have length ' + expected;
143
+ }
144
+ },
145
+
146
+ be_null: {
147
+ match: function(expected, actual) {
148
+ return actual == null;
149
+ },
150
+
151
+ failure_message: function(expected, actual, not) {
152
+ return 'expected ' + $.print(actual) + (not ? ' to not be null' : ' to be null');
153
+ }
154
+ },
155
+
156
+ be_undefined: {
157
+ match: function(expected, actual) {
158
+ return actual == undefined;
159
+ },
160
+
161
+ failure_message: function(expected, actual, not) {
162
+ return 'expected ' + $.print(actual) + (not ? ' to not be undefined' : ' to be undefined');
163
+ }
164
+ },
165
+
166
+ be_true: {
167
+ match: function(expected, actual) {
168
+ return actual;
169
+ },
170
+
171
+ failure_message: function(expected, actual, not) {
172
+ return 'expected ' + $.print(actual) + (not ? ' to not be true' : ' to be true');
173
+ }
174
+ },
175
+
176
+ be_false: {
177
+ match: function(expected, actual) {
178
+ return !actual;
179
+ },
180
+
181
+ failure_message: function(expected, actual, not) {
182
+ return 'expected ' + $.print(actual) + (not ? ' to not be false' : ' to be false');
183
+ }
184
+ },
185
+
186
+ match_html: {
187
+ munge: function(mungee) {
188
+ if (mungee instanceof jQuery) {
189
+ mungee = mungee.html();
190
+ } else if (typeof(mungee) == "string") {
191
+ var span = document.createElement("span");
192
+ span.innerHTML = mungee;
193
+ mungee = span.innerHTML;
194
+ }
195
+
196
+ var regEx = /\sjQuery\d+=['"]\d+['"]/g;
197
+ mungee = mungee.replace(regEx, "");
198
+
199
+ return mungee;
200
+ },
201
+
202
+ match: function(expected, actual) {
203
+ var trimmedExpected = this.munge(expected);
204
+ var trimmedActual = this.munge(actual);
205
+ return trimmedActual.indexOf(trimmedExpected) > -1;
206
+ },
207
+
208
+ failure_message: function(expected, actual, not) {
209
+ var trimmedExpected = this.munge(expected);
210
+ var trimmedActual = this.munge(actual);
211
+ return 'expected ' + $.print(trimmedActual, { max_string: 300 }) +
212
+ (not ? ' to not contain ' : ' to contain ') + $.print(trimmedExpected, { max_string: 300 });
213
+ }
214
+ },
215
+
216
+ match_selector: {
217
+ match: function(expected, actual) {
218
+ if (!(actual instanceof jQuery)) {
219
+ throw expected.toString() + " must be an instance of jQuery to match against a selector"
220
+ }
221
+
222
+ return actual.is(expected);
223
+ },
224
+
225
+ failure_message: function(expected, actual, not) {
226
+ return 'expected ' + $.print(actual) + (not ? ' to not match selector ' : ' to match selector ') + expected;
227
+ }
228
+ },
229
+
230
+ contain_selector: {
231
+ match: function(expected, actual) {
232
+ if (!(actual instanceof jQuery)) {
233
+ throw expected.toString() + " must be an instance of jQuery to match against a selector"
234
+ }
235
+
236
+ return actual.find(expected).length > 0;
237
+ },
238
+
239
+ failure_message: function(expected, actual, not) {
240
+ return 'expected ' + $.print(actual) + (not ? ' to not contain selector ' : ' to contain selector ') + expected;
241
+ }
242
+ }
243
+ }
244
+ })(jQuery);