js-test-server 0.2.0

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 (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