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,197 @@
1
+ require 'sinatra/base'
2
+
3
+ require 'screw_server/jslint_suite'
4
+ require "screw_server/spec_file"
5
+
6
+ module ScrewServer
7
+ class App < Sinatra::Base
8
+
9
+ SPEC_BASE_URL = "___screw_specs___"
10
+ ASSET_BASE_URL = "___screw_assets___"
11
+ VIEW_PATH = File.join(File.dirname(__FILE__), "..", "..", "views")
12
+
13
+ set :views, VIEW_PATH
14
+
15
+ get "/run/:name" do
16
+ run_specs([SpecFile.new(params[:name])])
17
+ end
18
+
19
+ get "/run" do
20
+ run_specs(SpecFile.all)
21
+ end
22
+
23
+ get "/bisect/:victim/:begin/:end" do
24
+ victim = params[:victim]
25
+ suspects = SpecFile.all.map { |spec| spec.name } - [victim]
26
+
27
+ subset = suspects[params[:begin].to_i..(params[:end].to_i - 1)]
28
+
29
+ puts "suspects: #{subset.length}"
30
+
31
+ specs_to_run = (subset + [victim]).map {|name| SpecFile.new(name) }
32
+ run_specs(specs_to_run)
33
+ end
34
+
35
+ get "/" do
36
+ @specs = SpecFile.all
37
+ if @specs.empty?
38
+ render_setup_tutorial(:no_specs)
39
+ else
40
+ haml :index
41
+ end
42
+ end
43
+
44
+ get "/monitor" do
45
+ spec = SpecFile.latest
46
+ @include_monitor_code = true
47
+ run_specs([spec]);
48
+ end
49
+
50
+ get "/has_changes_since/:spec/:timestamp" do
51
+ if SpecFile.latest.name != params[:spec]
52
+ "true"
53
+ else
54
+ spec = SpecFile.new(params[:spec])
55
+ if spec.last_dependency_change > params[:timestamp].to_i
56
+ "true"
57
+ else
58
+ "false"
59
+ end
60
+ end
61
+ end
62
+
63
+ get "/#{SPEC_BASE_URL}/*" do
64
+ send_file(file_from_base_dir(Base.spec_base_dir, params[:splat]))
65
+ end
66
+
67
+ get "/#{ASSET_BASE_URL}/*" do
68
+ send_file(file_from_base_dir(asset_base_dir, params[:splat]))
69
+ end
70
+
71
+ helpers do
72
+ def cache_busting_url(url)
73
+ "#{url}?#{rand}"
74
+ end
75
+
76
+ def jslint_suites
77
+ jslint_file = File.join(Base.spec_base_dir, "jslint.rb")
78
+ if !File.exists?(jslint_file)
79
+ []
80
+ else
81
+ JslintSuite.suites_from(jslint_file).map do |suite|
82
+ {
83
+ :file_list => suite.file_list.map { |file| url_for_source_file(file) },
84
+ :options => suite.options_with_defaults
85
+ }
86
+ end
87
+ end
88
+ end
89
+
90
+ def url_for_screw_asset(file)
91
+ "/#{ASSET_BASE_URL}/#{file}"
92
+ end
93
+
94
+ def url_for_spec(file)
95
+ "/#{SPEC_BASE_URL}/#{file}"
96
+ end
97
+
98
+ def fixture_html
99
+ @specs.inject({}) { |result, spec| result.merge(spec.fixture_hash) }
100
+ end
101
+
102
+ def required_files
103
+ @specs.map(&:required_scripts).flatten.uniq
104
+ end
105
+
106
+ def monitor_code
107
+ spec = SpecFile.latest
108
+ <<-EOS
109
+ Screw.check_for_change = function() {
110
+ Screw.ajax({
111
+ url: "/has_changes_since/#{spec.name}/#{spec.last_dependency_change}",
112
+ cache: false,
113
+ success: function(answer) {
114
+ if (answer === "true") {
115
+ location.reload();
116
+ }
117
+ else {
118
+ setTimeout(Screw.check_for_change, 1000);
119
+ }
120
+ }
121
+ });
122
+ };
123
+ Screw.check_for_change();
124
+ EOS
125
+ end
126
+
127
+ def screw_assets
128
+ %w{
129
+ vendor/fulljslint.js
130
+ vendor/screw-unit/lib/jquery.fn.js
131
+ vendor/screw-unit/lib/jquery.print.js
132
+ vendor/screw-unit/lib/screw.builder.js
133
+ vendor/screw-unit/lib/screw.matchers.js
134
+ vendor/screw-unit/lib/screw.events.js
135
+ vendor/screw-unit/lib/screw.behaviors.js
136
+ vendor/smoke/lib/smoke.core.js
137
+ vendor/smoke/lib/smoke.mock.js
138
+ vendor/smoke/lib/smoke.stub.js
139
+ vendor/smoke/plugins/screw.mocking.js
140
+ screw-server.js
141
+ }
142
+ end
143
+
144
+ def sample_spec_file
145
+ "\n"+File.read(File.join(VIEW_PATH, "sample_spec.js"))
146
+ end
147
+
148
+ def sample_spec_helper
149
+ "\n"+File.read(File.join(VIEW_PATH, "sample_spec_helper.js"))
150
+ end
151
+ end
152
+
153
+ def self.run!(*args)
154
+ set(:public, Base.code_base_dir)
155
+ super(*args)
156
+ end
157
+
158
+ private
159
+
160
+ def file_from_base_dir(base_dir, file)
161
+ File.expand_path(File.join(base_dir, file)).tap do |result|
162
+ unless result.start_with?(base_dir)
163
+ raise Sinatra::NotFound, "Forbidden Access out of base directory"
164
+ end
165
+ end
166
+ end
167
+
168
+ def url_for_source_file(filename)
169
+ file = File.expand_path(filename)
170
+ if file.start_with?(Base.code_base_dir)
171
+ file[Base.code_base_dir.length..-1]
172
+ elsif file.start_with?(Base.spec_base_dir)
173
+ url_for_spec(file[(Base.spec_base_dir.length + 1)..-1])
174
+ else
175
+ raise "file #{file} cannot be checked by jslint since it it not inside the spec or code path"
176
+ end
177
+ end
178
+
179
+ def run_specs(specs)
180
+ if File.exists?(SpecFile.spec_helper_file)
181
+ @specs = specs
182
+ haml :run_spec
183
+ else
184
+ render_setup_tutorial(:missing_spec_helper)
185
+ end
186
+ end
187
+
188
+ def asset_base_dir
189
+ @assert_base_dir ||= File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "assets"))
190
+ end
191
+
192
+ def render_setup_tutorial(template)
193
+ @spec_base_dir = Base.spec_base_dir
194
+ haml template
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,21 @@
1
+ module ScrewServer
2
+ module Base
3
+ def self.spec_base_dir=(d)
4
+ raise "expected a directory with javascript specs under #{d}" unless File.exists?(d)
5
+ @spec_base_dir = d
6
+ end
7
+
8
+ def self.spec_base_dir
9
+ @spec_base_dir
10
+ end
11
+
12
+ def self.code_base_dir=(d)
13
+ raise "expected a directory with javascript code under #{d}" unless File.exists?(d)
14
+ @code_base_dir = d
15
+ end
16
+
17
+ def self.code_base_dir
18
+ @code_base_dir
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module ScrewServer
2
+ class FixtureFile
3
+ attr_reader :name
4
+
5
+ def self.base_dir
6
+ File.join(Base.spec_base_dir, "fixtures")
7
+ end
8
+
9
+ def initialize(name)
10
+ @name = name
11
+ end
12
+
13
+ def filename
14
+ "#{Base.spec_base_dir}/fixtures/#{name}.html"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,51 @@
1
+ module ScrewServer
2
+ class JslintSuite
3
+
4
+ DEFAULT_OPTIONS = {
5
+ # true
6
+ "bitwise" => true,
7
+ "browser" => true,
8
+ "eqeqeq" => true,
9
+ "immed" => true,
10
+ "newcap" => true,
11
+ "nomen" => true,
12
+ "regexp" => true,
13
+ "undef" => true,
14
+ # false
15
+ "plusplus" => false,
16
+ "indent" => false,
17
+ "onevar" => false,
18
+ "white" => false,
19
+ "regexp" => false,
20
+ "nomen" => false
21
+ }
22
+
23
+ attr_accessor :name, :file_list, :options
24
+
25
+ def initialize(n)
26
+ @name = n
27
+ end
28
+
29
+ def file_list=(v)
30
+ @file_list = v.map { |file| File.expand_path(file) }
31
+ end
32
+
33
+ def self.suites_from(file)
34
+ @suites = []
35
+ eval(IO.read(file), binding, file)
36
+ @suites
37
+ end
38
+
39
+ def options_with_defaults
40
+ DEFAULT_OPTIONS.merge(self.options || {})
41
+ end
42
+
43
+ private
44
+
45
+ def self.jslint(name)
46
+ suite = JslintSuite.new(name)
47
+ yield suite
48
+ @suites << suite
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,76 @@
1
+ require "screw_server/base"
2
+ require "screw_server/fixture_file"
3
+
4
+ module ScrewServer
5
+ class SpecFile
6
+ def self.all
7
+ Dir.glob(File.join(Base.spec_base_dir, "*_spec.js")).sort.map do |file|
8
+ SpecFile.new(file.gsub("#{Base.spec_base_dir}/", "").gsub("_spec.js", ""))
9
+ end
10
+ end
11
+
12
+ def self.latest
13
+ SpecFile.all.sort{ |a, b| a.last_changed <=> b.last_changed }.last
14
+ end
15
+
16
+ attr_reader :name
17
+
18
+ def initialize(name)
19
+ @name = name
20
+ end
21
+
22
+ def filename
23
+ File.join(Base.spec_base_dir, full_name)
24
+ end
25
+
26
+ def full_name
27
+ name + "_spec.js"
28
+ end
29
+
30
+ def used_fixtures
31
+ scan_for_statement("use_fixture", filename).map {|name| FixtureFile.new(name) }
32
+ end
33
+
34
+ def fixture_hash
35
+ used_fixtures.inject({}) do |result, fixture|
36
+ result.merge(fixture.name => File.read(fixture.filename))
37
+ end
38
+ end
39
+
40
+ def required_scripts
41
+ required_files_in(SpecFile.spec_helper_file) + required_files_in(filename)
42
+ end
43
+
44
+ def last_dependency_change
45
+ used_files.map do |file|
46
+ File.mtime(file).to_i rescue 0
47
+ end.max
48
+ end
49
+
50
+ def last_changed
51
+ @last_changed ||= File.mtime(filename).to_i
52
+ end
53
+
54
+ def used_files
55
+ [filename, SpecFile.spec_helper_file] +
56
+ used_fixtures.map(&:filename) +
57
+ required_scripts.map {|script| File.join(Base.code_base_dir, script)}
58
+ end
59
+
60
+ def self.spec_helper_file
61
+ File.join(Base.spec_base_dir, "spec_helper.js")
62
+ end
63
+
64
+ protected
65
+
66
+ def scan_for_statement(statement, filename)
67
+ File.read(filename).scan(/#{statement}\(["']\/?(.+)['"]\)/).map { |groups| groups[0] }
68
+ end
69
+
70
+ def required_files_in(filename)
71
+ files = scan_for_statement("require", filename)
72
+ files = files.reject { |file| file == "spec_helper.js" }
73
+ files = files.map { |file| file.gsub("../../public", "") }
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,2 @@
1
+ require "screw_server/base"
2
+ require "screw_server/app"
@@ -0,0 +1,28 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{screw_server}
3
+ s.version = "0.1.4"
4
+ s.authors = ["Kristian Hanekamp", "Infopark AG"]
5
+ s.description = %q{Screw Server - easy javascript unit tests}
6
+ s.email = %q{kristian.hanekamp@infopark.de}
7
+ s.files =
8
+ Dir.glob("{lib,assets,views}/**/*") +
9
+ ["bin/screw_server", "Gemfile.run", "Gemfile.run.lock", "screw_server.gemspec"]
10
+ s.summary = %q{Screw Server}
11
+
12
+ s.add_dependency("json", "=1.4.3")
13
+ s.add_dependency("haml", "= 3.0.13")
14
+ s.add_dependency("bundler", "= 1.0.7")
15
+
16
+ # sinatra and dependencies
17
+ s.add_dependency("rack", "= 1.1.0")
18
+ s.add_dependency("sinatra", "= 1.0")
19
+
20
+ # thin and dependencies
21
+ s.add_dependency("daemons", "= 1.0.10")
22
+ # eventmachine 0.12.[7-10] has a bug when running without native extensions
23
+ # http://groups.google.com/group/eventmachine/browse_thread/thread/29fef72ee865ed6d
24
+ s.add_dependency("eventmachine", "= 0.12.6")
25
+ s.add_dependency("thin", "= 1.2.7")
26
+
27
+ s.executables = ['screw_server']
28
+ end
data/views/index.haml ADDED
@@ -0,0 +1,13 @@
1
+ %html
2
+ %head
3
+ %link{:rel => "stylesheet", :href => url_for_screw_asset("screw.css"), :type => "text/css"}
4
+
5
+ %body
6
+ %h1 Screw Server
7
+ %div{:style => "margin: 20px;"}
8
+ %div{:style => "margin: 20px;"}
9
+ %a{:href => "/run"} RUN ALL
10
+ %a{:href => "/monitor"} MONITOR
11
+ -@specs.each do |spec|
12
+ %li
13
+ %a{:href => "/run/#{spec.name}"}= spec.name
@@ -0,0 +1,12 @@
1
+ %html
2
+ %head
3
+ %link{:rel => "stylesheet", :href => url_for_screw_asset("screw.css"), :type => "text/css"}
4
+
5
+ %body
6
+ %p Cannot find #{@spec_base_dir}/spec_helper.js.
7
+ %br
8
+ %p Please create that file and use it for global test helpers.
9
+ %p Initially the file should at least require jQuery like this:
10
+ %br
11
+ %pre
12
+ = sample_spec_helper
@@ -0,0 +1,11 @@
1
+ %html
2
+ %head
3
+ %link{:rel => "stylesheet", :href => url_for_screw_asset("screw.css"), :type => "text/css"}
4
+
5
+ %body
6
+ %p The directory #{@spec_base_dir} does not contain any specs.
7
+ %br
8
+ %p Create a file #{@spec_base_dir}/foo_spec.js with the following content
9
+ %br
10
+ %pre
11
+ = sample_spec_file
@@ -0,0 +1,30 @@
1
+ %html
2
+ %head
3
+ %link{:rel => "stylesheet", :href => url_for_screw_asset("screw.css"), :type => "text/css"}
4
+
5
+ - required_files.each do |required_file|
6
+ %script{:type => "text/javascript", :src => cache_busting_url("/#{required_file}")}
7
+
8
+ - screw_assets.each do |asset|
9
+ %script{:type => "text/javascript", :src => url_for_screw_asset(asset)}
10
+
11
+ %script{:type => "text/javascript", :src => url_for_spec("spec_helper.js")}
12
+
13
+ %script{:type => "text/javascript"}
14
+ = "fixture_container = #{fixture_html.to_json}"
15
+ = "Screw.jslint_suites = #{jslint_suites.to_json};"
16
+ %body
17
+ %h3#screw_server_loading{:class => "status"}
18
+ Loading...
19
+ #fixture_container
20
+ - @specs.each do |spec|
21
+ %script{:type => "text/javascript", :src => cache_busting_url(url_for_spec(spec.full_name))}
22
+
23
+ %script{:type => "text/javascript", :src => url_for_screw_asset("screw-jslint.js")}
24
+
25
+ :javascript
26
+ $("#screw_server_loading").remove();
27
+
28
+ - if @include_monitor_code
29
+ %script{:type => "text/javascript"}
30
+ = monitor_code
@@ -0,0 +1,7 @@
1
+ Screw.Unit(function(){
2
+ describe("Simple Test", function() {
3
+ it("should be simple to write", function() {
4
+ expect(2 * 2).to(equal, 4);
5
+ });
6
+ });
7
+ });
@@ -0,0 +1,2 @@
1
+ // adjust the url below to match your application's jquery url
2
+ require("/javascripts/jquery.js");