js-test-server 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/CHANGES +31 -0
  2. data/Gemfile +17 -0
  3. data/README.markdown +9 -0
  4. data/Rakefile +63 -0
  5. data/bin/jasmine-server +9 -0
  6. data/bin/js-test-client +8 -0
  7. data/bin/js-test-server +9 -0
  8. data/bin/screw-unit-server +9 -0
  9. data/lib/js_test_server.rb +29 -0
  10. data/lib/js_test_server/client.rb +23 -0
  11. data/lib/js_test_server/client/runner.rb +129 -0
  12. data/lib/js_test_server/configuration.rb +69 -0
  13. data/lib/js_test_server/server.rb +14 -0
  14. data/lib/js_test_server/server/app.rb +10 -0
  15. data/lib/js_test_server/server/representations.rb +12 -0
  16. data/lib/js_test_server/server/representations/dir.html.rb +22 -0
  17. data/lib/js_test_server/server/representations/frameworks.rb +3 -0
  18. data/lib/js_test_server/server/representations/not_found.html.rb +13 -0
  19. data/lib/js_test_server/server/representations/page.html.rb +32 -0
  20. data/lib/js_test_server/server/representations/remote_control_subscriber.rb +17 -0
  21. data/lib/js_test_server/server/representations/suite.html.rb +54 -0
  22. data/lib/js_test_server/server/representations/suites.rb +6 -0
  23. data/lib/js_test_server/server/representations/suites/jasmine.html.rb +32 -0
  24. data/lib/js_test_server/server/representations/suites/screw_unit.html.rb +45 -0
  25. data/lib/js_test_server/server/resources.rb +14 -0
  26. data/lib/js_test_server/server/resources/file.rb +58 -0
  27. data/lib/js_test_server/server/resources/framework_file.rb +15 -0
  28. data/lib/js_test_server/server/resources/implementations_deprecation.rb +8 -0
  29. data/lib/js_test_server/server/resources/not_found.rb +25 -0
  30. data/lib/js_test_server/server/resources/remote_control.rb +80 -0
  31. data/lib/js_test_server/server/resources/resource.rb +12 -0
  32. data/lib/js_test_server/server/resources/spec_file.rb +47 -0
  33. data/lib/js_test_server/server/resources/web_root.rb +17 -0
  34. data/lib/js_test_server/server/runner.rb +62 -0
  35. data/scratch.rb +8 -0
  36. data/spec/frameworks/jasmine/cruise_config.rb +21 -0
  37. data/spec/frameworks/jasmine/spec/jasmine_helper.rb +44 -0
  38. data/spec/frameworks/jasmine/spec/jasmine_spec.rb +31 -0
  39. data/spec/functional/functional_spec_helper.rb +55 -0
  40. data/spec/functional/functional_spec_server_starter.rb +69 -0
  41. data/spec/functional/jasmine/jasmine_functional_spec.rb +27 -0
  42. data/spec/functional/screw-unit/screw_unit_functional_spec.rb +27 -0
  43. data/spec/functional_suite.rb +16 -0
  44. data/spec/spec_helpers/be_http.rb +32 -0
  45. data/spec/spec_helpers/example_group.rb +41 -0
  46. data/spec/spec_helpers/fake_deferrable.rb +3 -0
  47. data/spec/spec_helpers/fake_selenium_driver.rb +16 -0
  48. data/spec/spec_helpers/mock_session.rb +30 -0
  49. data/spec/spec_helpers/show_test_exceptions.rb +22 -0
  50. data/spec/spec_helpers/wait_for.rb +11 -0
  51. data/spec/spec_suite.rb +3 -0
  52. data/spec/unit/js_test_core/client/runner_spec.rb +198 -0
  53. data/spec/unit/js_test_core/configuration_spec.rb +44 -0
  54. data/spec/unit/js_test_core/resources/file_spec.rb +79 -0
  55. data/spec/unit/js_test_core/resources/framework_file_spec.rb +58 -0
  56. data/spec/unit/js_test_core/resources/implementations_deprecation_spec.rb +16 -0
  57. data/spec/unit/js_test_core/resources/not_found_spec.rb +49 -0
  58. data/spec/unit/js_test_core/resources/remote_control_spec.rb +117 -0
  59. data/spec/unit/js_test_core/resources/spec_file_spec.rb +147 -0
  60. data/spec/unit/js_test_core/resources/web_root_spec.rb +26 -0
  61. data/spec/unit/js_test_core/server/server_spec.rb +67 -0
  62. data/spec/unit/unit_spec_helper.rb +34 -0
  63. data/spec/unit_suite.rb +10 -0
  64. metadata +220 -0
@@ -0,0 +1,58 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestServer::Server::Resources
4
+ describe FrameworkFile do
5
+ describe "Files" do
6
+ describe "GET /framework/JsTestServer.js" do
7
+ it "renders the JsTestServer.js file, which lives in the core framework directory" do
8
+ absolute_path = "#{framework_path}/example_framework.js"
9
+
10
+ response = get(FrameworkFile.path("example_framework.js"))
11
+ response.should be_http(
12
+ 200,
13
+ {
14
+ "Content-Type" => "text/javascript",
15
+ "Last-Modified" => ::File.mtime(absolute_path).rfc822
16
+ },
17
+ ::File.read(absolute_path)
18
+ )
19
+ end
20
+ end
21
+ end
22
+
23
+ describe "Directories" do
24
+ macro "returns a page with the files in the root core directory" do |relative_path|
25
+ it "returns a page with the files in the root core directory" do
26
+ response = get(FrameworkFile.path(relative_path))
27
+ response.should be_http(
28
+ 200,
29
+ {},
30
+ ""
31
+ )
32
+ doc = Nokogiri::HTML(response.body)
33
+ links = doc.search("a").map {|script| script["href"]}
34
+ links.should include("/framework/example_framework.js")
35
+ links.should include("/framework/example_framework.css")
36
+ links.should include("/framework/subdir")
37
+ end
38
+ end
39
+ describe "GET /framework" do
40
+ send("returns a page with the files in the root core directory", "")
41
+ end
42
+ describe "GET /framework/" do
43
+ send("returns a page with the files in the root core directory", "/")
44
+ end
45
+
46
+ describe "GET /framework/subdir" do
47
+ it "returns a page with the files in the directory" do
48
+ response = get(FrameworkFile.path("subdir"))
49
+ response.should be_http(
50
+ 200,
51
+ {},
52
+ %r(<a href="/framework/subdir/SubDirFile.js">SubDirFile.js</a>)
53
+ )
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestServer::Server::Resources
4
+ describe ImplementationsDeprecation do
5
+ describe "GET /implementations/*" do
6
+ it "responds with a 301 to /javascripts/*" do
7
+ response = get(ImplementationsDeprecation.path("/subdir/bar.js"))
8
+ response.should be_http(
9
+ 301,
10
+ {'Location' => File.path("/javascripts/subdir/bar.js")},
11
+ "This page has been moved to #{File.path("/javascripts/subdir/bar.js")}"
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestServer::Server::Resources
4
+ describe WebRoot do
5
+ describe "GET / - ResourceNotFound" do
6
+ it "returns a 404 error" do
7
+ response = get("/i_dont_exist")
8
+ response.should be_http(
9
+ 404,
10
+ {},
11
+ Regexp.new("File /i_dont_exist not found")
12
+ )
13
+ end
14
+ end
15
+
16
+ describe "PUT / - ResourceNotFound" do
17
+ it "returns a 404 error" do
18
+ response = put("/i_dont_exist")
19
+ response.should be_http(
20
+ 404,
21
+ {},
22
+ Regexp.new("File /i_dont_exist not found")
23
+ )
24
+ end
25
+ end
26
+
27
+ describe "POST / - ResourceNotFound" do
28
+ it "returns a 404 error" do
29
+ response = post("/i_dont_exist")
30
+ response.should be_http(
31
+ 404,
32
+ {},
33
+ Regexp.new("File /i_dont_exist not found")
34
+ )
35
+ end
36
+ end
37
+
38
+ describe "DELETE / - ResourceNotFound" do
39
+ it "returns a 404 error" do
40
+ response = delete("/i_dont_exist")
41
+ response.should be_http(
42
+ 404,
43
+ {},
44
+ Regexp.new("File /i_dont_exist not found")
45
+ )
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,117 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestServer::Server::Resources
4
+ describe RemoteControl do
5
+ attr_reader :browser_session, :command_line_session, :browser_async_callback
6
+ before do
7
+ @browser_session = rack_test_session("Browser Session")
8
+ @command_line_session = rack_test_session("Command Line Session")
9
+
10
+ @browser_async_callback = lambda do |commands_response|
11
+ browser_session.last_response = Rack::MockResponse.new(*commands_response)
12
+ end
13
+ end
14
+
15
+ describe "GET /remote_control/subscriber" do
16
+ it "renders a page that polls the commands" do
17
+ browser_session.get(RemoteControl.path("/subscriber"))
18
+ browser_session.last_response.should be_http( 200, {}, "" )
19
+
20
+ doc = Nokogiri::HTML(browser_session.last_response.body)
21
+ doc.at("a[href='#{RemoteControl.path("commands")}']").should_not be_nil
22
+ end
23
+ end
24
+
25
+ describe "POST /remote_control/commands" do
26
+ attr_reader :command_response
27
+
28
+ it "puts javascript to be executed to the queue and responds with the response from the browser" do
29
+ client_creates_a_command
30
+ browser_gets_commands_and_sends_response
31
+ wait_for {command_response}
32
+ command_response.should be_http(200, {}, "")
33
+ #command_response.should be_http(200, {}, "response from browser")
34
+ end
35
+
36
+ def client_creates_a_command
37
+ RemoteControl.queue.to_a.should be_empty
38
+ request_thread = Thread.start do
39
+ @command_response = command_line_session.post(RemoteControl.path("/commands"), :javascript => "alert('hello');")
40
+ end
41
+
42
+ wait_for { RemoteControl.queue.to_a.length == 1 }
43
+ end
44
+
45
+ def browser_gets_commands_and_sends_response
46
+ browser_session.get( RemoteControl.path("/commands"), {}, {
47
+ Thin::Request::ASYNC_CLOSE => FakeDeferrable.new,
48
+ Thin::Request::ASYNC_CALLBACK => browser_async_callback
49
+ })
50
+ commands = JSON.parse(browser_session.last_response.body)
51
+ commands.length.should == 1
52
+ #post("commands/#{commands.first["id"]}/response", "response" => "response from browser")
53
+ end
54
+ end
55
+
56
+ describe "GET /remote_control/commands" do
57
+ context "when the queue is empty" do
58
+ before do
59
+ RemoteControl.queue.to_a.should be_empty
60
+ end
61
+
62
+ context "when Object::Thin is defined" do
63
+ before do
64
+ Object.const_defined?(:Thin).should be_true
65
+ end
66
+
67
+ it "waits until there is a message in the queue to return a response" do
68
+ js = "alert('hello');"
69
+ browser_session.get(RemoteControl.path("/commands"), {}, {
70
+ Thin::Request::ASYNC_CLOSE => FakeDeferrable.new,
71
+ Thin::Request::ASYNC_CALLBACK => browser_async_callback
72
+ })
73
+ browser_session.last_response.should be_nil
74
+
75
+ command_line_session.post(RemoteControl.path("/commands"), {:javascript => js})
76
+
77
+ browser_session.last_response.should be_http(
78
+ 200,
79
+ {"Content-Type" => "application/json"},
80
+ [{"javascript" => js}].to_json
81
+ )
82
+ end
83
+ end
84
+
85
+ context "when Object::Thin is not defined" do
86
+ before do
87
+ stub(Object).const_defined?(:Thin) {false}
88
+ end
89
+
90
+ it "renders an empty array" do
91
+ browser_session.get(RemoteControl.path("/commands"))
92
+ browser_session.last_response.should be_http(200, {"Content-Type" => "application/json"}, [].to_json)
93
+ end
94
+ end
95
+ end
96
+
97
+ context "when the queue is not empty" do
98
+ attr_reader :js
99
+ before do
100
+ post(RemoteControl.path("/commands"), {:javascript => "alert('hello');"})
101
+ @js = "alert('hello');"
102
+ RemoteControl.queue.to_a.length.should == 1
103
+ RemoteControl.queue.to_a.first["javascript"].should == js
104
+ end
105
+
106
+ it "renders an array of the unsent javascript commands in the queue and clears the queue" do
107
+ browser_session.get(RemoteControl.path("/commands"), {}, {
108
+ Thin::Request::ASYNC_CLOSE => FakeDeferrable.new,
109
+ Thin::Request::ASYNC_CALLBACK => browser_async_callback
110
+ })
111
+ browser_session.last_response.should be_http(200, {"Content-Type" => "application/json"}, [{"javascript" => js}].to_json)
112
+ RemoteControl.queue.to_a.should be_empty
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,147 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestServer::Server::Resources
4
+ describe SpecFile do
5
+ describe "Configuration" do
6
+ attr_reader :doc
7
+ before do
8
+ JsTestServer.framework_name = "screw-unit"
9
+ JsTestServer::Server::Representations::Suite.project_js_files += ["/javascripts/test_file_1.js", "/javascripts/test_file_2.js"]
10
+ JsTestServer::Server::Representations::Suite.project_css_files += ["/stylesheets/test_file_1.css", "/stylesheets/test_file_2.css"]
11
+
12
+ response = get(SpecFile.path("/failing_spec"))
13
+ response.should be_http( 200, {}, "" )
14
+
15
+ @doc = Nokogiri::HTML(response.body)
16
+ end
17
+
18
+ after do
19
+ JsTestServer::Server::Representations::Suite.project_js_files.clear
20
+ JsTestServer::Server::Representations::Suite.project_css_files.clear
21
+ end
22
+
23
+ it "renders project js files" do
24
+ doc.at("script[@src='/javascripts/test_file_1.js']").should_not be_nil
25
+ doc.at("script[@src='/javascripts/test_file_2.js']").should_not be_nil
26
+ end
27
+
28
+ it "renders project css files" do
29
+ doc.at("link[@href='/stylesheets/test_file_1.css']").should_not be_nil
30
+ doc.at("link[@href='/stylesheets/test_file_2.css']").should_not be_nil
31
+ end
32
+ end
33
+
34
+ describe "Files" do
35
+ describe "GET /specs/failing_spec" do
36
+ it "renders a suite only for failing_spec.js as text/html" do
37
+ absolute_path = "#{spec_path}/failing_spec.js"
38
+
39
+ response = get(SpecFile.path("failing_spec"))
40
+ response.should be_http(
41
+ 200,
42
+ {
43
+ "Content-Type" => "text/html",
44
+ "Last-Modified" => ::File.mtime(absolute_path).rfc822
45
+ },
46
+ ""
47
+ )
48
+ doc = Nokogiri::HTML(response.body)
49
+ js_files = doc.search("script").map {|script| script["src"]}
50
+ js_files.should include("/specs/failing_spec.js")
51
+ end
52
+ end
53
+
54
+ describe "GET /specs/failing_spec.js" do
55
+ it "renders the contents of failing_spec.js as text/javascript" do
56
+ absolute_path = "#{spec_path}/failing_spec.js"
57
+
58
+ response = get(SpecFile.path("failing_spec.js"))
59
+ response.should be_http(
60
+ 200,
61
+ {
62
+ "Content-Type" => "text/javascript",
63
+ "Last-Modified" => ::File.mtime(absolute_path).rfc822
64
+ },
65
+ ::File.read(absolute_path)
66
+ )
67
+ end
68
+ end
69
+
70
+ describe "GET /specs/custom_suite" do
71
+ it "renders the custom_suite.html file" do
72
+ path = "#{spec_path}/custom_suite.html"
73
+
74
+ response = get(SpecFile.path("custom_suite.html"))
75
+ response.should be_http(
76
+ 200,
77
+ {
78
+ "Content-Type" => "text/html",
79
+ "Last-Modified" => ::File.mtime(path).rfc822
80
+ },
81
+ ::File.read(path)
82
+ )
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "Directories" do
88
+ describe "GET /specs" do
89
+ macro "renders a suite for all specs" do |relative_path|
90
+ it "renders a suite for all specs" do
91
+ path = "#{spec_path}"
92
+
93
+ response = get(relative_path)
94
+ response.should be_http(
95
+ 200,
96
+ {
97
+ "Content-Type" => "text/html",
98
+ "Last-Modified" => ::File.mtime(path).rfc822
99
+ },
100
+ ""
101
+ )
102
+ doc = Nokogiri::HTML(response.body)
103
+ js_files = doc.search("script").map {|script| script["src"]}
104
+ js_files.should include("/specs/failing_spec.js")
105
+ js_files.should include("/specs/custom_dir_and_suite/passing_spec.js")
106
+ js_files.should include("/specs/foo/passing_spec.js")
107
+ js_files.should include("/specs/foo/failing_spec.js")
108
+ end
109
+ end
110
+
111
+ send("renders a suite for all specs", SpecFile.path)
112
+ send("renders a suite for all specs", SpecFile.path("/"))
113
+ end
114
+
115
+ describe "GET /specs/foo" do
116
+ it "renders a spec suite that includes all of the javascript spec files in the directory" do
117
+ path = "#{spec_path}/foo"
118
+
119
+ response = get(SpecFile.path("foo"))
120
+ response.should be_http(
121
+ 200,
122
+ {
123
+ "Content-Type" => "text/html",
124
+ "Last-Modified" => ::File.mtime(path).rfc822
125
+ },
126
+ ""
127
+ )
128
+ doc = Nokogiri::HTML(response.body)
129
+ js_files = doc.search("script").map {|script| script["src"]}
130
+ js_files.should include("/specs/foo/passing_spec.js")
131
+ js_files.should include("/specs/foo/failing_spec.js")
132
+ end
133
+ end
134
+ end
135
+
136
+ describe "GET /specs/i_dont_exist" do
137
+ it "renders a 404" do
138
+ response = get(SpecFile.path("i_dont_exist"))
139
+ response.should be_http(
140
+ 404,
141
+ {},
142
+ "/specs/i_dont_exist not found"
143
+ )
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestServer::Server::Resources
4
+ describe WebRoot do
5
+ macro("includes a link to the spec suite") do |relative_path|
6
+ it "includes a link to the spec suite" do
7
+ response = get(relative_path)
8
+ response.should be_http(
9
+ 200,
10
+ {},
11
+ ""
12
+ )
13
+ doc = Nokogiri::HTML(response.body)
14
+ doc.css("a[href='/specs']").should_not be_nil
15
+ end
16
+ end
17
+
18
+ describe "GET " do
19
+ send("includes a link to the spec suite", "")
20
+ end
21
+
22
+ describe "GET /" do
23
+ send("includes a link to the spec suite", "/")
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestServer::Server
4
+ include JsTestServer
5
+ describe Runner do
6
+ describe ".cli" do
7
+ attr_reader :server, :builder, :stdout, :rackup_path
8
+ before do
9
+ @server = Runner.new
10
+ @builder = "builder"
11
+
12
+ @stdout = StringIO.new
13
+ Runner.const_set(:STDOUT, stdout)
14
+
15
+ @rackup_path = File.expand_path(Configuration.rackup_path)
16
+ end
17
+
18
+ after do
19
+ Runner.__send__(:remove_const, :STDOUT)
20
+ end
21
+
22
+
23
+ context "when the --framework-name and --framework-path are set" do
24
+ it "starts the server and sets SpecFile::suite_representation_class to be the ScrewUnit suite" do
25
+ project_spec_dir = File.expand_path("#{File.dirname(__FILE__)}/../../..")
26
+
27
+ mock.proxy(Thin::Runner).new(["--port", "8081", "--rackup", rackup_path, "start"]) do |runner|
28
+ mock(runner).run!
29
+ end
30
+
31
+ stub.proxy(Rack::Builder).new do |builder|
32
+ mock.proxy(builder).use(JsTestServer::Server::App)
33
+ stub.proxy(builder).use
34
+ mock(builder).run(is_a(JsTestServer::Server::App))
35
+ mock(builder).run(is_a(Sinatra::Application))
36
+ end
37
+
38
+ server.cli(
39
+ "--framework-name", "screw-unit",
40
+ "--framework-path", "#{project_spec_dir}/example_framework",
41
+ "--root-path", "#{project_spec_dir}/example_root",
42
+ "--spec-path", "#{project_spec_dir}/example_spec",
43
+ "--port", "8081"
44
+ )
45
+
46
+ JsTestServer::Configuration.instance.suite_representation_class.should == JsTestServer::Server::Representations::Suites::ScrewUnit
47
+ end
48
+ end
49
+
50
+ context "when the --framework-name or --framework-path are not set" do
51
+ it "raises an ArgumentError" do
52
+ lambda do
53
+ server.cli
54
+ end.should raise_error(ArgumentError)
55
+
56
+ lambda do
57
+ server.cli("--framework-name", "screw-unit")
58
+ end.should raise_error(ArgumentError)
59
+
60
+ lambda do
61
+ server.cli("--framework-path", "/path/to/framework")
62
+ end.should raise_error(ArgumentError)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end