screw_server 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. data/Gemfile.run +3 -0
  2. data/Gemfile.run.lock +41 -0
  3. data/assets/screw-jslint.js +69 -0
  4. data/assets/screw-server.js +120 -0
  5. data/assets/screw.css +70 -0
  6. data/assets/vendor/fulljslint.js +5699 -0
  7. data/assets/vendor/screw-unit/CHANGES +7 -0
  8. data/assets/vendor/screw-unit/EXAMPLE.html +68 -0
  9. data/assets/vendor/screw-unit/LICENSE +22 -0
  10. data/assets/vendor/screw-unit/README.markdown +307 -0
  11. data/assets/vendor/screw-unit/example/models/cat.js +5 -0
  12. data/assets/vendor/screw-unit/example/models/man.js +17 -0
  13. data/assets/vendor/screw-unit/example/spec/matchers/have.js +8 -0
  14. data/assets/vendor/screw-unit/example/spec/models/cat_spec.js +31 -0
  15. data/assets/vendor/screw-unit/example/spec/models/man_spec.js +34 -0
  16. data/assets/vendor/screw-unit/example/spec/spec_helper.js +5 -0
  17. data/assets/vendor/screw-unit/example/spec/suite.html +25 -0
  18. data/assets/vendor/screw-unit/lib/jquery-1.2.6.js +3549 -0
  19. data/assets/vendor/screw-unit/lib/jquery.fn.js +29 -0
  20. data/assets/vendor/screw-unit/lib/jquery.print.js +109 -0
  21. data/assets/vendor/screw-unit/lib/screw.behaviors.js +101 -0
  22. data/assets/vendor/screw-unit/lib/screw.builder.js +90 -0
  23. data/assets/vendor/screw-unit/lib/screw.css +90 -0
  24. data/assets/vendor/screw-unit/lib/screw.events.js +45 -0
  25. data/assets/vendor/screw-unit/lib/screw.matchers.js +203 -0
  26. data/assets/vendor/screw-unit/spec/behaviors_spec.js +188 -0
  27. data/assets/vendor/screw-unit/spec/matchers_spec.js +391 -0
  28. data/assets/vendor/screw-unit/spec/print_spec.js +158 -0
  29. data/assets/vendor/screw-unit/spec/spec_helper.js +0 -0
  30. data/assets/vendor/screw-unit/spec/suite.html +18 -0
  31. data/assets/vendor/smoke/LICENSE +22 -0
  32. data/assets/vendor/smoke/README.markdown +68 -0
  33. data/assets/vendor/smoke/lib/smoke.core.js +49 -0
  34. data/assets/vendor/smoke/lib/smoke.mock.js +219 -0
  35. data/assets/vendor/smoke/lib/smoke.stub.js +29 -0
  36. data/assets/vendor/smoke/plugins/screw.mocking.js +26 -0
  37. data/assets/vendor/smoke/spec/core_spec.js +115 -0
  38. data/assets/vendor/smoke/spec/mock_spec.js +431 -0
  39. data/assets/vendor/smoke/spec/screw_integration_spec.js +17 -0
  40. data/assets/vendor/smoke/spec/spec_helper.js +0 -0
  41. data/assets/vendor/smoke/spec/stub_spec.js +17 -0
  42. data/assets/vendor/smoke/spec/su/jquery-1.2.3.js +3408 -0
  43. data/assets/vendor/smoke/spec/su/jquery.fn.js +29 -0
  44. data/assets/vendor/smoke/spec/su/jquery.print.js +108 -0
  45. data/assets/vendor/smoke/spec/su/screw.behaviors.js +91 -0
  46. data/assets/vendor/smoke/spec/su/screw.builder.js +80 -0
  47. data/assets/vendor/smoke/spec/su/screw.css +74 -0
  48. data/assets/vendor/smoke/spec/su/screw.events.js +38 -0
  49. data/assets/vendor/smoke/spec/su/screw.matchers.js +65 -0
  50. data/assets/vendor/smoke/spec/suite.html +29 -0
  51. data/bin/screw_server +43 -0
  52. data/lib/screw_server/app.rb +197 -0
  53. data/lib/screw_server/base.rb +21 -0
  54. data/lib/screw_server/fixture_file.rb +17 -0
  55. data/lib/screw_server/jslint_suite.rb +51 -0
  56. data/lib/screw_server/spec_file.rb +76 -0
  57. data/lib/screw_server.rb +2 -0
  58. data/screw_server.gemspec +28 -0
  59. data/views/index.haml +13 -0
  60. data/views/missing_spec_helper.haml +12 -0
  61. data/views/no_specs.haml +11 -0
  62. data/views/run_spec.haml +30 -0
  63. data/views/sample_spec.js +7 -0
  64. data/views/sample_spec_helper.js +2 -0
  65. metadata +257 -0
@@ -0,0 +1,29 @@
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
+ return result;
25
+ };
26
+ function namespacedName(name) {
27
+ return 'fn.' + name;
28
+ }
29
+ })(jQuery);
@@ -0,0 +1,108 @@
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
+ };
23
+ $.each(properties.concat(extra[obj.tagName.toLowerCase()] || []), function() {
24
+ if (obj[this])
25
+ result.push(' ' + this.replace('className', 'class') + "=" + $.print(obj[this]))
26
+ });
27
+ return "<" + obj.tagName.toLowerCase()
28
+ + result.join('') + ">";
29
+ }
30
+ }
31
+
32
+ function print_object(obj, opts) {
33
+ var seen = opts.seen || [];
34
+
35
+ var result = [], key, value;
36
+ for (var k in obj) {
37
+ if (obj.hasOwnProperty(k) && $.inArray(obj[k], seen) < 0) {
38
+ seen.push(obj[k]);
39
+ value = $.print(obj[k], $.extend({}, opts, { max_array: 6, max_string: 40, seen: seen }));
40
+ } else
41
+ value = "...";
42
+ result.push(k + ": " + value);
43
+ }
44
+ if (result.length == 0) return "{}";
45
+ return "{ " + result.join(", ") + " }";
46
+ }
47
+
48
+ function print_jquery(obj) {
49
+ }
50
+
51
+ function print_string(value, opts) {
52
+ var character_substitutions = {
53
+ '\b': '\\b',
54
+ '\t': '\\t',
55
+ '\n': '\\n',
56
+ '\f': '\\f',
57
+ '\r': '\\r',
58
+ '"' : '\\"',
59
+ '\\': '\\\\'
60
+ };
61
+ var r = /["\\\x00-\x1f\x7f-\x9f]/g;
62
+
63
+ var str = r.test(value)
64
+ ? '"' + value.replace(r, function (a) {
65
+ var c = character_substitutions[a];
66
+ if (c) return c;
67
+ c = a.charCodeAt();
68
+ return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
69
+ }) + '"'
70
+ : '"' + value + '"';
71
+ if (str.length > opts.max_string)
72
+ return str.slice(0, opts.max_string + 1) + '..."';
73
+ else
74
+ return str;
75
+ }
76
+
77
+ $.print = function(obj, options) {
78
+ var opts = $.extend({}, { max_array: 10, max_string: 100 }, options);
79
+
80
+ if (typeof obj == 'undefined')
81
+ return "undefined";
82
+ else if (typeof obj == 'boolean')
83
+ return obj.toString();
84
+ else if (!obj && typeof obj == 'number')
85
+ return 'NaN';
86
+ else if (!obj)
87
+ return "null";
88
+ else if (typeof obj == 'string')
89
+ return print_string(obj, opts);
90
+ else if (obj instanceof RegExp)
91
+ return obj.toString();
92
+ else if (typeof obj == 'function' || obj instanceof Function)
93
+ return obj.toString().match(/^([^)]*\))/)[1];
94
+ else if (obj instanceof Array)
95
+ return print_array(obj, opts);
96
+ else if (obj.nodeType)
97
+ return print_element(obj);
98
+ else if (obj instanceof jQuery)
99
+ return "$(" + $.print(obj.get()) + ")";
100
+ else if (obj instanceof Error)
101
+ return print_object(obj, $.extend({}, options, { max_string: 200 }));
102
+ else if (obj instanceof Object)
103
+ return print_object(obj, opts);
104
+ else
105
+ return obj.toString().replace(/\n\s*/g, '');
106
+ }
107
+
108
+ })(jQuery);
@@ -0,0 +1,91 @@
1
+ (function($) {
2
+ $(Screw).bind('loaded', function() {
3
+ $('.status').fn({
4
+ display: function() {
5
+ $(this).text(
6
+ $('.passed').length + $('.failed').length + ' test(s), ' + $('.failed').length + ' failure(s)'
7
+ );
8
+ }
9
+ });
10
+
11
+ $('.describe').fn({
12
+ parent: function() {
13
+ return $(this).parent('.describes').parent('.describe');
14
+ },
15
+
16
+ run_befores: function() {
17
+ $(this).fn('parent').fn('run_befores');
18
+ $(this).children('.befores').children('.before').fn('run');
19
+ },
20
+
21
+ run_afters: function() {
22
+ $(this).fn('parent').fn('run_afters');
23
+ $(this).children('.afters').children('.after').fn('run');
24
+ },
25
+
26
+ enqueue: function() {
27
+ $(this).children('.its').children('.it').fn('enqueue');
28
+ $(this).children('.describes').children('.describe').fn('enqueue');
29
+ },
30
+
31
+ selector: function() {
32
+ return $(this).fn('parent').fn('selector')
33
+ + ' > .describes > .describe:eq(' + $(this).parent('.describes').children('.describe').index(this) + ')';
34
+ }
35
+ });
36
+
37
+ $('body > .describe').fn({
38
+ selector: function() { return 'body > .describe' }
39
+ });
40
+
41
+ $('.it').fn({
42
+ parent: function() {
43
+ return $(this).parent('.its').parent('.describe');
44
+ },
45
+
46
+ run: function() {
47
+ try {
48
+ try {
49
+ $(this).fn('parent').fn('run_befores');
50
+ $(this).data('screwunit.run')();
51
+ } finally {
52
+ $(this).fn('parent').fn('run_afters');
53
+ }
54
+ $(this).trigger('passed');
55
+ } catch(e) {
56
+ $(this).trigger('failed', [e]);
57
+ }
58
+ },
59
+
60
+ enqueue: function() {
61
+ var self = $(this).trigger('enqueued');
62
+ $(Screw)
63
+ .queue(function() {
64
+ self.fn('run');
65
+ setTimeout(function() { $(Screw).dequeue() }, 0);
66
+ });
67
+ },
68
+
69
+ selector: function() {
70
+ return $(this).fn('parent').fn('selector')
71
+ + ' > .its > .it:eq(' + $(this).parent('.its').children('.it').index(this) + ')';
72
+ }
73
+ });
74
+
75
+ $('.before').fn({
76
+ run: function() { $(this).data('screwunit.run')() }
77
+ });
78
+
79
+ $('.after').fn({
80
+ run: function() { $(this).data('screwunit.run')() }
81
+ });
82
+
83
+ $(Screw).trigger('before');
84
+ var to_run = unescape(location.search.slice(1)) || 'body > .describe > .describes > .describe';
85
+ $(to_run)
86
+ .focus()
87
+ .eq(0).trigger('scroll').end()
88
+ .fn('enqueue');
89
+ $(Screw).queue(function() { $(Screw).trigger('after') });
90
+ })
91
+ })(jQuery);
@@ -0,0 +1,80 @@
1
+ var Screw = (function($) {
2
+ var screw = {
3
+ Unit: function(fn) {
4
+ var contents = fn.toString().match(/^[^\{]*{((.*\n*)*)}/m)[1];
5
+ var fn = new Function("matchers", "specifications",
6
+ "with (specifications) { with (matchers) { " + contents + " } }"
7
+ );
8
+
9
+ $(Screw).queue(function() {
10
+ Screw.Specifications.context.push($('body > .describe'));
11
+ fn.call(this, Screw.Matchers, Screw.Specifications);
12
+ Screw.Specifications.context.pop();
13
+ $(this).dequeue();
14
+ });
15
+ },
16
+
17
+ Specifications: {
18
+ context: [],
19
+
20
+ describe: function(name, fn) {
21
+ var describe = $('<li class="describe">')
22
+ .append($('<h1>').text(name))
23
+ .append('<ol class="befores">')
24
+ .append('<ul class="its">')
25
+ .append('<ul class="describes">')
26
+ .append('<ol class="afters">');
27
+
28
+ this.context.push(describe);
29
+ fn.call();
30
+ this.context.pop();
31
+
32
+ this.context[this.context.length-1]
33
+ .children('.describes')
34
+ .append(describe);
35
+ },
36
+
37
+ it: function(name, fn) {
38
+ var it = $('<li class="it">')
39
+ .append($('<h2>').text(name))
40
+ .data('screwunit.run', fn);
41
+
42
+ this.context[this.context.length-1]
43
+ .children('.its')
44
+ .append(it);
45
+ },
46
+
47
+ before: function(fn) {
48
+ var before = $('<li class="before">')
49
+ .data('screwunit.run', fn);
50
+
51
+ this.context[this.context.length-1]
52
+ .children('.befores')
53
+ .append(before);
54
+ },
55
+
56
+ after: function(fn) {
57
+ var after = $('<li class="after">')
58
+ .data('screwunit.run', fn);
59
+
60
+ this.context[this.context.length-1]
61
+ .children('.afters')
62
+ .append(after);
63
+ }
64
+ }
65
+ };
66
+
67
+ $(screw).queue(function() { $(screw).trigger('loading') });
68
+ $(function() {
69
+ $('<div class="describe">')
70
+ .append('<h3 class="status">')
71
+ .append('<ol class="befores">')
72
+ .append('<ul class="describes">')
73
+ .append('<ol class="afters">')
74
+ .appendTo('body');
75
+
76
+ $(screw).dequeue();
77
+ $(screw).trigger('loaded');
78
+ });
79
+ return screw;
80
+ })(jQuery);
@@ -0,0 +1,74 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ font-weight: normal;
5
+ list-style: none;
6
+ font-size: 1em;
7
+ }
8
+
9
+ body {
10
+ background: #fff;
11
+ color: #333;
12
+ font-family: "Helvetica Neue", Helvetica, Arial, "Sans-Serif";
13
+ font-size: 78.5%;
14
+ padding-top: 3em;
15
+ }
16
+
17
+ h3.status {
18
+ position: fixed;
19
+ width: 100%;
20
+ top: 0;
21
+ left: 0;
22
+ margin: 0 0 1em 0;
23
+ padding: .75em;
24
+ font-size: 1.1em;
25
+ color: #fff;
26
+ background-color: #3875d7;
27
+ font-weight: normal;
28
+ -webkit-box-shadow: 0px 1px 5px #666;
29
+ -moz-box-shadow: 0px 2px 3px #999;
30
+ }
31
+
32
+ ul {
33
+ margin: .5em 0;
34
+ padding: 0 1em;
35
+ }
36
+
37
+ h1 {
38
+ margin: 0 1em;
39
+ padding: .25em 0;
40
+ border-bottom: 1px dotted #ccc;
41
+ font-weight: bold;
42
+ }
43
+
44
+ h2 {
45
+ padding: .2em .5em;
46
+ color: #ccc;
47
+ }
48
+
49
+ .enqueued h2 {
50
+ color: #999;
51
+ }
52
+
53
+ .passed h2 {
54
+ color: #333;
55
+ background: #abffa5;
56
+ border-top: 2px solid #ccffcc;
57
+ border-bottom: 2px solid #66ff66;
58
+ }
59
+
60
+ .failed h2 {
61
+ color: #333;
62
+ background: #ffaaaa;
63
+ border-top: 2px solid #ffcccc;
64
+ border-bottom: 2px solid #ff9977;
65
+ }
66
+
67
+ .error {
68
+ background-color: #f9f9f9;
69
+ margin-bottom: .5em;
70
+ padding: 1em;
71
+ border-left: 1px solid #ddd;
72
+ border-right: 1px solid #ddd;
73
+ border-bottom: 1px solid #ddd;
74
+ }
@@ -0,0 +1,38 @@
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
+ })
32
+ .bind('before', function() {
33
+ $('.status').text('Running...');
34
+ })
35
+ .bind('after', function() {
36
+ $('.status').fn('display')
37
+ })
38
+ })(jQuery);
@@ -0,0 +1,65 @@
1
+ Screw.Matchers = (function($) {
2
+ return matchers = {
3
+ expect: function(actual) {
4
+ return {
5
+ to: function(matcher, expected, not) {
6
+ var matched = matcher.match(expected, actual);
7
+ if (not ? matched : !matched) {
8
+ throw(matcher.failure_message(expected, actual, not));
9
+ }
10
+ },
11
+
12
+ to_not: function(matcher, expected) {
13
+ this.to(matcher, expected, true);
14
+ }
15
+ }
16
+ },
17
+
18
+ equal: {
19
+ match: function(expected, actual) {
20
+ if (expected instanceof Array) {
21
+ for (var i = 0; i < actual.length; i++)
22
+ if (!Screw.Matchers.equal.match(expected[i], actual[i])) return false;
23
+ return actual.length == expected.length;
24
+ } else if (expected instanceof Object) {
25
+ for (var key in expected)
26
+ if (expected[key] != actual[key]) return false;
27
+ for (var key in actual)
28
+ if (actual[key] != expected[key]) return false;
29
+ return true;
30
+ } else {
31
+ return expected == actual;
32
+ }
33
+ },
34
+
35
+ failure_message: function(expected, actual, not) {
36
+ return 'expected ' + $.print(actual) + (not ? ' to not equal ' : ' to equal ') + $.print(expected);
37
+ }
38
+ },
39
+
40
+ match: {
41
+ match: function(expected, actual) {
42
+ if (expected.constructor == RegExp)
43
+ return expected.exec(actual.toString());
44
+ else
45
+ return actual.indexOf(expected) > -1;
46
+ },
47
+
48
+ failure_message: function(expected, actual, not) {
49
+ return 'expected ' + $.print(actual) + (not ? ' to not match ' : ' to match ') + $.print(expected);
50
+ }
51
+ },
52
+
53
+ be_empty: {
54
+ match: function(expected, actual) {
55
+ if (actual.length == undefined) throw(actual.toString() + " does not respond to length");
56
+
57
+ return actual.length == 0;
58
+ },
59
+
60
+ failure_message: function(expected, actual, not) {
61
+ return 'expected ' + $.print(actual) + (not ? ' to not be empty' : ' to be empty');
62
+ }
63
+ }
64
+ }
65
+ })(jQuery);
@@ -0,0 +1,29 @@
1
+ <html>
2
+ <head>
3
+ <!-- require screw -->
4
+ <script src="su/jquery-1.2.3.js"></script>
5
+ <script src="su/jquery.fn.js"></script>
6
+ <script src="su/jquery.print.js"></script>
7
+ <script src="su/screw.builder.js"></script>
8
+ <script src="su/screw.matchers.js"></script>
9
+ <script src="su/screw.events.js"></script>
10
+ <script src="su/screw.behaviors.js"></script>
11
+
12
+ <!-- require smoke -->
13
+ <script src="../lib/smoke.core.js"></script>
14
+ <script src="../lib/smoke.mock.js"></script>
15
+ <script src="../lib/smoke.stub.js"></script>
16
+
17
+ <!-- require smoke screw plugin -->
18
+ <script src="../plugins/screw.mocking.js"></script>
19
+
20
+ <!-- load specs -->
21
+ <script src="stub_spec.js"></script>
22
+ <script src="mock_spec.js"></script>
23
+ <script src="core_spec.js"></script>
24
+ <script src="screw_integration_spec.js"></script>
25
+
26
+ <link rel="stylesheet" href="su/screw.css">
27
+ </head>
28
+ <body></body>
29
+ </html>
data/bin/screw_server ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if Object.const_defined?("Bundler")
4
+ puts "detected bundler environment from a different app!"
5
+ puts "trying to shell out of bundler's environment..."
6
+
7
+ ENV["RUBYOPT"] = ENV["RUBYOPT"].gsub("-rbundler/setup", "")
8
+ Kernel.exec(__FILE__)
9
+ end
10
+
11
+ require "rubygems"
12
+ gem "bundler", "= 1.0.7"
13
+ require "bundler"
14
+ ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile.run", __FILE__)
15
+ Bundler.require
16
+
17
+ options = {
18
+ :port => 3210,
19
+ :spec_base_dir => "spec/javascripts",
20
+ :code_base_dir => "public"
21
+ }
22
+
23
+ OptionParser.new do |opt|
24
+ opt.on('--port -p ', Integer, 'port to start screw_server on (default is 3210)') do |port|
25
+ options[:port] = port
26
+ end
27
+ opt.on(
28
+ "--spec spec_base_dir",
29
+ "directory that contains the javascript specs (default is ./#{options[:spec_base_dir]})"
30
+ ) do |spec_base_dir|
31
+ options[:spec_base_dir] = spec_base_dir
32
+ end
33
+ opt.on(
34
+ '--code code_base_dir',
35
+ "directory that contains the javascript code (default is ./#{options[:code_base_dir]})"
36
+ ) do |code_base_dir|
37
+ options[:code_base_dir] = code_base_dir
38
+ end
39
+ end.parse!
40
+
41
+ ScrewServer::Base.spec_base_dir = File.expand_path(options[:spec_base_dir])
42
+ ScrewServer::Base.code_base_dir = File.expand_path(options[:code_base_dir])
43
+ ScrewServer::App.run!(:host => 'localhost', :port => options[:port], :environment => "production")