js_test_core 0.1.1

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 (41) hide show
  1. data/CHANGES +9 -0
  2. data/README +12 -0
  3. data/Rakefile +72 -0
  4. data/lib/js_test_core.rb +30 -0
  5. data/lib/js_test_core/client.rb +50 -0
  6. data/lib/js_test_core/rack.rb +2 -0
  7. data/lib/js_test_core/rack/commonlogger.rb +5 -0
  8. data/lib/js_test_core/rails_server.rb +22 -0
  9. data/lib/js_test_core/resources.rb +10 -0
  10. data/lib/js_test_core/resources/dir.rb +52 -0
  11. data/lib/js_test_core/resources/file.rb +32 -0
  12. data/lib/js_test_core/resources/runners.rb +15 -0
  13. data/lib/js_test_core/resources/runners/firefox_runner.rb +73 -0
  14. data/lib/js_test_core/resources/specs/spec_dir.rb +50 -0
  15. data/lib/js_test_core/resources/specs/spec_file.rb +17 -0
  16. data/lib/js_test_core/resources/suite.rb +24 -0
  17. data/lib/js_test_core/resources/suite_finish.rb +19 -0
  18. data/lib/js_test_core/resources/web_root.rb +54 -0
  19. data/lib/js_test_core/selenium.rb +2 -0
  20. data/lib/js_test_core/selenium/selenium_driver.rb +5 -0
  21. data/lib/js_test_core/server.rb +111 -0
  22. data/lib/js_test_core/thin.rb +3 -0
  23. data/lib/js_test_core/thin/backends/js_test_core_server.rb +9 -0
  24. data/lib/js_test_core/thin/js_test_core_connection.rb +42 -0
  25. data/spec/spec_suite.rb +2 -0
  26. data/spec/unit/js_spec/client_spec.rb +137 -0
  27. data/spec/unit/js_spec/rails_server_spec.rb +45 -0
  28. data/spec/unit/js_spec/resources/dir_spec.rb +42 -0
  29. data/spec/unit/js_spec/resources/file_spec.rb +88 -0
  30. data/spec/unit/js_spec/resources/runner_spec.rb +24 -0
  31. data/spec/unit/js_spec/resources/runners/firefox_runner_spec.rb +161 -0
  32. data/spec/unit/js_spec/resources/specs/spec_dir_spec.rb +79 -0
  33. data/spec/unit/js_spec/resources/specs/spec_file_spec.rb +42 -0
  34. data/spec/unit/js_spec/resources/suite_finish_spec.rb +94 -0
  35. data/spec/unit/js_spec/resources/suite_spec.rb +44 -0
  36. data/spec/unit/js_spec/resources/web_root_spec.rb +67 -0
  37. data/spec/unit/js_spec/server_spec.rb +131 -0
  38. data/spec/unit/thin/js_test_core_connection_spec.rb +92 -0
  39. data/spec/unit/unit_spec_helper.rb +125 -0
  40. data/spec/unit_suite.rb +10 -0
  41. metadata +113 -0
@@ -0,0 +1,42 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe Dir do
6
+ attr_reader :dir, :absolute_path, :relative_path
7
+
8
+ describe "#locate" do
9
+ before do
10
+ @absolute_path = core_path
11
+ @relative_path = "/core"
12
+ @dir = Resources::Dir.new(absolute_path, relative_path)
13
+ end
14
+
15
+ describe "when passed a name of a real file" do
16
+ it "returns a Resources::File representing it" do
17
+ file = dir.locate("JsTestCore.css")
18
+ file.relative_path.should == "/core/JsTestCore.css"
19
+ file.absolute_path.should == "#{core_path}/JsTestCore.css"
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "#glob" do
25
+ before do
26
+ @absolute_path = spec_root_path
27
+ @relative_path = "/specs"
28
+ @dir = Resources::Dir.new(absolute_path, relative_path)
29
+ end
30
+
31
+ it "returns an array of matching Files under this directory with the correct relative paths" do
32
+ globbed_files = dir.glob("/**/*_spec.js")
33
+
34
+ globbed_files.size.should == 3
35
+ globbed_files.should contain_spec_file_with_correct_paths("/failing_spec.js")
36
+ globbed_files.should contain_spec_file_with_correct_paths("/foo/failing_spec.js")
37
+ globbed_files.should contain_spec_file_with_correct_paths("/foo/passing_spec.js")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,88 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe File do
6
+ attr_reader :request, :file
7
+
8
+ before do
9
+ WebRoot.dispatch_specs
10
+ stub(EventMachine).send_data
11
+ stub(EventMachine).close_connection
12
+ @file = Resources::File.new(absolute_path, relative_path)
13
+ @request = create_request('get', relative_path)
14
+ end
15
+
16
+ def absolute_path
17
+ "#{spec_root_path}/failing_spec.js"
18
+ end
19
+
20
+ def relative_path
21
+ "/specs/failing_spec.js"
22
+ end
23
+
24
+ describe "#absolute_path" do
25
+ it "returns the absolute path passed into the initializer" do
26
+ file.absolute_path.should == absolute_path
27
+ end
28
+ end
29
+
30
+ describe "#relative_path" do
31
+ it "returns the relative path passed into the initializer" do
32
+ file.relative_path.should == relative_path
33
+ end
34
+ end
35
+
36
+ describe "#get" do
37
+ attr_reader :response
38
+ before do
39
+ @response = Rack::Response.new
40
+ end
41
+
42
+ it "returns the contents of the file" do
43
+ file.get(request, response)
44
+ response.body.should == ::File.read(absolute_path)
45
+ end
46
+
47
+ describe "when File has an extension" do
48
+ describe '.js' do
49
+ it "sets Content-Type to text/javascript" do
50
+ file.get(request,response)
51
+ response.content_type.should == "text/javascript"
52
+ end
53
+ end
54
+
55
+ describe '.css' do
56
+ it "sets Content-Type to text/css" do
57
+ file.get(request, response)
58
+ response.content_type.should == "text/css"
59
+ end
60
+
61
+ def absolute_path
62
+ "#{core_path}/JsTestCore.css"
63
+ end
64
+
65
+ def relative_path
66
+ "/core/JsTestCore.css"
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "==" do
73
+ it "returns true when passed a file with the same absolute and relative paths" do
74
+ file.should == Resources::File.new(absolute_path, relative_path)
75
+ end
76
+
77
+ it "returns false when passed a file with a different absolute or relative path" do
78
+ file.should_not == Resources::File.new(absolute_path, "bogus")
79
+ file.should_not == Resources::File.new("bogus", relative_path)
80
+ end
81
+
82
+ it "when passed a Dir, returns false because File is not a Dir" do
83
+ file.should_not == Resources::Dir.new(absolute_path, relative_path)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe Runners do
6
+ attr_reader :runner
7
+ before do
8
+ @runner = Runners.new
9
+ end
10
+
11
+ describe "#locate" do
12
+ it "when passed 'firefox', returns a Firefox1Runner" do
13
+ runner.locate('firefox').is_a?(Runners::FirefoxRunner).should be_true
14
+ end
15
+
16
+ it "when not passed 'firefox', raises an error" do
17
+ lambda do
18
+ runner.locate('invalid')
19
+ end.should raise_error
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,161 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe Runners::FirefoxRunner do
6
+ attr_reader :runner, :request, :response, :driver, :suite_id
7
+
8
+ before do
9
+ Thread.current[:connection] = connection
10
+ @driver = "Selenium Driver"
11
+ @suite_id = 12345
12
+ stub(Selenium::SeleniumDriver).new('localhost', 4444, '*firefox', 'http://0.0.0.0:8080') do
13
+ driver
14
+ end
15
+ end
16
+
17
+ describe "#post" do
18
+ attr_reader :firefox_profile_path
19
+ before do
20
+ @request = Rack::Request.new( Rack::MockRequest.env_for('/runners/firefox') )
21
+ @response = Rack::Response.new
22
+ @runner = Runners::FirefoxRunner.new
23
+ stub(Thread).start.yields
24
+ end
25
+
26
+ it "keeps the connection open" do
27
+ stub(driver).start
28
+ stub(driver).open
29
+ stub(driver).session_id {suite_id}
30
+ dont_allow(EventMachine).send_data
31
+ dont_allow(EventMachine).close_connection
32
+ runner.post(request, response)
33
+
34
+ response.body.should be_empty
35
+ end
36
+
37
+ describe "when a selenium_host parameter is passed into the request" do
38
+ before do
39
+ request['selenium_host'] = "another-machine"
40
+ stub(driver).start
41
+ stub(driver).open
42
+ stub(driver).session_id {suite_id}
43
+ end
44
+
45
+ it "starts the Selenium Driver with the passed in selenium_host" do
46
+ mock(Selenium::SeleniumDriver).new('another-machine', 4444, '*firefox', 'http://0.0.0.0:8080') do
47
+ driver
48
+ end
49
+ runner.post(request, response)
50
+ end
51
+ end
52
+
53
+ describe "when a selenium_host parameter is not passed into the request" do
54
+ before do
55
+ request['selenium_host'].should be_nil
56
+ stub(driver).start
57
+ stub(driver).open
58
+ stub(driver).session_id {suite_id}
59
+ end
60
+
61
+ it "starts the Selenium Driver from localhost" do
62
+ mock(Selenium::SeleniumDriver).new('localhost', 4444, '*firefox', 'http://0.0.0.0:8080') do
63
+ driver
64
+ end
65
+ runner.post(request, response)
66
+ end
67
+ end
68
+
69
+ describe "when a selenium_port parameter is passed into the request" do
70
+ before do
71
+ request['selenium_port'] = "4000"
72
+ stub(driver).start
73
+ stub(driver).open
74
+ stub(driver).session_id {suite_id}
75
+ end
76
+
77
+ it "starts the Selenium Driver with the passed in selenium_port" do
78
+ mock(Selenium::SeleniumDriver).new('localhost', 4000, '*firefox', 'http://0.0.0.0:8080') do
79
+ driver
80
+ end
81
+ runner.post(request, response)
82
+ end
83
+ end
84
+
85
+ describe "when a selenium_port parameter is not passed into the request" do
86
+ before do
87
+ request['selenium_port'].should be_nil
88
+ stub(driver).start
89
+ stub(driver).open
90
+ stub(driver).session_id {suite_id}
91
+ end
92
+
93
+ it "starts the Selenium Driver from localhost" do
94
+ mock(Selenium::SeleniumDriver).new('localhost', 4444, '*firefox', 'http://0.0.0.0:8080') do
95
+ driver
96
+ end
97
+ runner.post(request, response)
98
+ end
99
+ end
100
+
101
+ describe "when a spec_url is passed into the request" do
102
+ before do
103
+ request['spec_url'] = "http://another-host:8080/specs/subdir"
104
+ end
105
+
106
+ it "runs Selenium with the passed in host and part to run the specified spec suite in Firefox" do
107
+ mock(Selenium::SeleniumDriver).new('localhost', 4444, '*firefox', 'http://another-host:8080') do
108
+ driver
109
+ end
110
+ mock(driver).start
111
+ mock(driver).open("http://another-host:8080/specs/subdir")
112
+ mock(driver).session_id {suite_id}
113
+
114
+ runner.post(request, response)
115
+ end
116
+ end
117
+
118
+ describe "when a spec_url is not passed into the request" do
119
+ before do
120
+ request['spec_url'].should be_nil
121
+ mock(Selenium::SeleniumDriver).new('localhost', 4444, '*firefox', 'http://0.0.0.0:8080') do
122
+ driver
123
+ end
124
+ end
125
+
126
+ it "uses Selenium to run the entire spec suite in Firefox" do
127
+ mock(driver).start
128
+ mock(driver).open("http://0.0.0.0:8080/specs")
129
+ mock(driver).session_id {suite_id}
130
+
131
+ runner.post(request, response)
132
+ end
133
+ end
134
+ end
135
+
136
+ describe "#finalize" do
137
+ before do
138
+ @request = Rack::Request.new( Rack::MockRequest.env_for('/runners/firefox') )
139
+ @response = Rack::Response.new
140
+ @runner = Runners::FirefoxRunner.new
141
+ stub(driver).start
142
+ stub(driver).open
143
+ stub(driver).session_id {suite_id}
144
+ runner.post(request, response)
145
+ end
146
+
147
+ it "kills the browser, sends the response body, and close the connection" do
148
+ mock(driver).stop
149
+ data = ""
150
+ stub(EventMachine).send_data do |signature, data, data_length|
151
+ data << data
152
+ end
153
+ mock(connection).close_connection_after_writing
154
+
155
+ runner.finalize("The text")
156
+ data.should include("The text")
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ module Specs
6
+ describe SpecDir do
7
+ attr_reader :dir, :absolute_path, :relative_path
8
+ before do
9
+ @absolute_path = spec_root_path
10
+ @relative_path = "/specs"
11
+ @dir = Resources::Specs::SpecDir.new(absolute_path, relative_path)
12
+ end
13
+
14
+ it "has an absolute path" do
15
+ dir.absolute_path.should == absolute_path
16
+ end
17
+
18
+ it "has a relative path" do
19
+ dir.relative_path.should == relative_path
20
+ end
21
+
22
+ describe "#locate when passed the name with an extension" do
23
+ it "when file exists, returns a Resources::File representing it" do
24
+ file = dir.locate("failing_spec.js")
25
+ file.relative_path.should == "/specs/failing_spec.js"
26
+ file.absolute_path.should == "#{spec_root_path}/failing_spec.js"
27
+ end
28
+
29
+ it "when file does not exist, raises error" do
30
+ lambda { dir.locate("nonexistent.js") }.should raise_error
31
+ end
32
+ end
33
+
34
+ describe "#locate when passed a name without an extension" do
35
+ it "when name corresponds to a subdirectory, returns a DirectoryRunner for the directory" do
36
+ subdir = dir.locate("foo")
37
+ subdir.should == spec_dir("/foo")
38
+ end
39
+
40
+ it "when name does not correspond to a .js file or directory, raises an error" do
41
+ lambda do
42
+ dir.locate("nonexistent")
43
+ end.should raise_error
44
+ end
45
+ end
46
+
47
+ describe "#get" do
48
+ attr_reader :request, :response
49
+ before do
50
+ @request = Rack::Request.new( Rack::MockRequest.env_for('/core') )
51
+ @response = Rack::Response.new
52
+ end
53
+
54
+ it "raises NotImplementedError" do
55
+ lambda do
56
+ dir.get(request, response)
57
+ end.should raise_error(NotImplementedError)
58
+ end
59
+
60
+ it "can be overridden from a Module without needing to redefine the #get method" do
61
+ spec_dir_class = Resources::Specs::SpecDir.clone
62
+ mod = Module.new do
63
+ def get(request, response)
64
+ end
65
+ end
66
+ spec_dir_class.class_eval do
67
+ include mod
68
+ end
69
+ @dir = spec_dir_class.new(absolute_path, relative_path)
70
+
71
+ lambda do
72
+ dir.get(request, response)
73
+ end.should_not raise_error
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ module Specs
6
+ describe SpecFile do
7
+ attr_reader :file, :absolute_path, :relative_path, :request, :response
8
+ before do
9
+ @absolute_path = "#{spec_root_path}/failing_spec.js"
10
+ @relative_path = "/specs/failing_spec.js"
11
+ @file = Resources::Specs::SpecFile.new(absolute_path, relative_path)
12
+ @request = Rack::Request.new( Rack::MockRequest.env_for(relative_path) )
13
+ @response = Rack::Response.new
14
+ end
15
+
16
+ describe "#get" do
17
+ it "raises NotImplementedError" do
18
+ lambda do
19
+ file.get(request, response)
20
+ end.should raise_error(NotImplementedError)
21
+ end
22
+
23
+ it "can be overridden from a Module without needing to redefine the #get method" do
24
+ spec_file_class = Resources::Specs::SpecFile.clone
25
+ mod = Module.new do
26
+ def get(request, response)
27
+ end
28
+ end
29
+ spec_file_class.class_eval do
30
+ include mod
31
+ end
32
+ @file = spec_file_class.new(absolute_path, relative_path)
33
+
34
+ lambda do
35
+ file.get(request, response)
36
+ end.should_not raise_error
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,94 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe SuiteFinish do
6
+ attr_reader :stdout, :suite_finish, :suite
7
+ before do
8
+ @stdout = StringIO.new
9
+ SuiteFinish.const_set(:STDOUT, stdout)
10
+ end
11
+
12
+ after do
13
+ SuiteFinish.__send__(:remove_const, :STDOUT)
14
+ end
15
+
16
+ describe ".post" do
17
+ describe "when Suite#id == 'user'" do
18
+ before do
19
+ @suite = Suite.new('user')
20
+ @suite_finish = SuiteFinish.new(suite)
21
+ end
22
+
23
+ it "writes the body of the request to stdout" do
24
+ body = "The text in the POST body"
25
+ request = Rack::Request.new({'rack.input' => StringIO.new("text=#{body}")})
26
+ request.body.string.should == "text=#{body}"
27
+ response = Rack::Response.new
28
+
29
+ suite_finish.post(request, response)
30
+ stdout.string.should == "#{body}\n"
31
+ end
32
+
33
+ it "sets the Content-Length to be 0" do
34
+ request = Rack::Request.new('rack.input' => StringIO.new(""))
35
+ response = Rack::Response.new
36
+
37
+ response.headers["Content-Length"].should be_nil
38
+ suite_finish.post(request, response)
39
+ response.headers["Content-Length"].should == "0"
40
+ end
41
+ end
42
+
43
+ describe "when Suite#id is not 'user'" do
44
+ attr_reader :request, :response, :runner, :suite_id, :driver
45
+ before do
46
+ runner_request = Rack::Request.new( Rack::MockRequest.env_for('/runners/firefox') )
47
+ runner_response = Rack::Response.new
48
+ @suite_id = '12345'
49
+ @driver = "Selenium Driver"
50
+ stub(Selenium::SeleniumDriver).new('localhost', 4444, '*firefox', 'http://0.0.0.0:8080') do
51
+ driver
52
+ end
53
+ stub(driver).start
54
+ stub(driver).open
55
+ stub(driver).session_id {suite_id}
56
+ stub(Thread).start.yields
57
+ Thread.current[:connection] = connection
58
+
59
+ @runner = Runners::FirefoxRunner.new
60
+ runner.post(runner_request, runner_response)
61
+
62
+ @suite = Suite.new(suite_id)
63
+ @suite_finish = SuiteFinish.new(suite)
64
+ end
65
+
66
+ it "resumes the FirefoxRunner" do
67
+ body = "The text in the POST body"
68
+ request = Rack::Request.new({'rack.input' => StringIO.new("text=#{body}")})
69
+ response = Rack::Response.new
70
+ mock.proxy(Runners::FirefoxRunner).resume(suite_id, body)
71
+ mock(driver).stop
72
+ stub(connection).send_data.once
73
+ stub(connection).close_connection.once
74
+
75
+ suite_finish.post(request, response)
76
+ end
77
+
78
+ it "sets the Content-Length to be 0" do
79
+ request = Rack::Request.new('rack.input' => StringIO.new(""))
80
+ response = Rack::Response.new
81
+ stub(Runners::FirefoxRunner).resume
82
+ stub(driver).stop
83
+ stub(connection).send_data
84
+ stub(connection).close_connection
85
+
86
+ response.headers["Content-Length"].should be_nil
87
+ suite_finish.post(request, response)
88
+ response.headers["Content-Length"].should == "0"
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end