screw_server 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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")