spassky 0.1.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.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +84 -0
- data/LICENSE +13 -0
- data/README.md +47 -0
- data/Rakefile +5 -0
- data/bin/spassky +8 -0
- data/bin/spassky-server +9 -0
- data/config.ru +6 -0
- data/features/connection.feature +9 -0
- data/features/device_timeout.feature +31 -0
- data/features/run_html_tests.feature +65 -0
- data/features/run_qunit_tests.feature +45 -0
- data/features/server.feature +11 -0
- data/features/step_definitions/steps.rb +66 -0
- data/features/support/env.rb +31 -0
- data/features/support/fixtures/qunit.js +1512 -0
- data/lib/spassky/client/cli.rb +12 -0
- data/lib/spassky/client/directory_reader.rb +14 -0
- data/lib/spassky/client/pusher.rb +36 -0
- data/lib/spassky/client/test_runner.rb +44 -0
- data/lib/spassky/client/writer.rb +31 -0
- data/lib/spassky/client.rb +1 -0
- data/lib/spassky/server/app.rb +76 -0
- data/lib/spassky/server/assert.js +5 -0
- data/lib/spassky/server/device_list.rb +18 -0
- data/lib/spassky/server/html_test.rb +27 -0
- data/lib/spassky/server/random_string_generator.rb +7 -0
- data/lib/spassky/server/test_run.rb +64 -0
- data/lib/spassky/server.rb +1 -0
- data/lib/spassky/test_result.rb +110 -0
- data/lib/spassky/version.rb +3 -0
- data/lib/spassky.rb +9 -0
- data/spassky.gemspec +31 -0
- data/spec/spassky/client/cli_spec.rb +48 -0
- data/spec/spassky/client/directory_reader_spec.rb +35 -0
- data/spec/spassky/client/pusher_spec.rb +72 -0
- data/spec/spassky/client/test_runner_spec.rb +130 -0
- data/spec/spassky/client/writer_spec.rb +31 -0
- data/spec/spassky/server/app_spec.rb +177 -0
- data/spec/spassky/server/device_list_spec.rb +32 -0
- data/spec/spassky/server/random_string_generator_spec.rb +13 -0
- data/spec/spassky/server/test_run_spec.rb +98 -0
- data/spec/spassky/test_result_spec.rb +116 -0
- data/spec/spec_helper.rb +3 -0
- metadata +215 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'spassky/client/test_runner'
|
3
|
+
|
4
|
+
module Spassky::Client
|
5
|
+
describe TestRunner do
|
6
|
+
before do
|
7
|
+
@test_pusher = mock(:test_pusher)
|
8
|
+
@writer = mock(:writer)
|
9
|
+
@writer.stub!(:write_passing)
|
10
|
+
@writer.stub!(:write_failing)
|
11
|
+
Kernel.stub!(:exit)
|
12
|
+
@directory_reader = mock(:directory_reader)
|
13
|
+
@directory_reader.stub!(:read_files).and_return({ "test.html" => "contents" })
|
14
|
+
@test_runner = TestRunner.new(@test_pusher, @writer, @directory_reader)
|
15
|
+
end
|
16
|
+
|
17
|
+
def new_in_progress_test_result
|
18
|
+
test_result = mock :in_progress_test_result
|
19
|
+
test_result.stub!(:status).and_return "in progress"
|
20
|
+
test_result.stub!(:summary).and_return "in progress summary"
|
21
|
+
test_result.stub!(:completed_since).and_return([])
|
22
|
+
test_result
|
23
|
+
end
|
24
|
+
|
25
|
+
def new_passed_test_result
|
26
|
+
test_result = mock :passed_test_result
|
27
|
+
test_result.stub!(:status).and_return "pass"
|
28
|
+
test_result.stub!(:summary).and_return "pass summary"
|
29
|
+
test_result.stub!(:completed_since).and_return([])
|
30
|
+
test_result
|
31
|
+
end
|
32
|
+
|
33
|
+
def new_failed_test_result
|
34
|
+
test_result = mock :failed_test_result
|
35
|
+
test_result.stub!(:status).and_return "fail"
|
36
|
+
test_result.stub!(:summary).and_return "fail summary"
|
37
|
+
test_result.stub!(:completed_since).and_return([])
|
38
|
+
test_result
|
39
|
+
end
|
40
|
+
|
41
|
+
def new_timeout_test_result
|
42
|
+
test_result = mock :timeout_test_result
|
43
|
+
test_result.stub!(:status).and_return "timed out"
|
44
|
+
test_result.stub!(:summary).and_return "timed out summary"
|
45
|
+
test_result.stub!(:completed_since).and_return([])
|
46
|
+
test_result
|
47
|
+
end
|
48
|
+
|
49
|
+
it "reads a test" do
|
50
|
+
@test_pusher.stub!(:push)
|
51
|
+
@directory_reader.should_receive(:read_files).and_return(:file_body)
|
52
|
+
@test_runner.run_tests("foo_test")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "gets the test name from the base name of the pattern and pushes the test" do
|
56
|
+
@test_pusher.should_receive(:push).with({:name => 'foo_test', :contents => { "test.html" => "contents" }.to_json })
|
57
|
+
@test_runner.run_tests("path/to/foo_test")
|
58
|
+
end
|
59
|
+
|
60
|
+
context "timeout" do
|
61
|
+
it 'returns a exit status of 2' do
|
62
|
+
@test_pusher.stub!(:push).and_yield(new_timeout_test_result)
|
63
|
+
Kernel.should_receive(:exit).with(2)
|
64
|
+
@test_runner.run_tests("foo_test")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "failing test" do
|
69
|
+
before do
|
70
|
+
@test_pusher.stub!(:push).and_yield(new_failed_test_result)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "only writes once" do
|
74
|
+
@writer.should_receive(:write_failing).once
|
75
|
+
@test_runner.run_tests("foo_test")
|
76
|
+
end
|
77
|
+
|
78
|
+
it "writes out an error code" do
|
79
|
+
Kernel.should_receive(:exit).with(1)
|
80
|
+
@test_runner.run_tests("foo_test")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "passing test" do
|
85
|
+
it "writes passing output" do
|
86
|
+
@test_pusher.stub!(:push).and_yield(new_passed_test_result)
|
87
|
+
@writer.should_receive(:write_passing).with("pass summary")
|
88
|
+
@test_runner.run_tests("foo_test")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "in progress" do
|
93
|
+
it "writes nothing" do
|
94
|
+
@test_pusher.stub!(:push).and_yield(new_in_progress_test_result)
|
95
|
+
@writer = mock(:writer)
|
96
|
+
@writer.should_not_receive(:write_passing)
|
97
|
+
@writer.should_not_receive(:write_failing)
|
98
|
+
TestRunner.new(@test_pusher, @writer, @directory_reader).run_tests("foo_test")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "in progress, then passed result yielded" do
|
103
|
+
it "only writes out the summary when the status is not 'in progress'" do
|
104
|
+
in_progress_test_result = new_in_progress_test_result
|
105
|
+
pass_test_result = new_passed_test_result
|
106
|
+
@test_pusher.stub!(:push).and_yield(in_progress_test_result).and_yield(pass_test_result)
|
107
|
+
@writer.should_receive(:write_passing).with("pass summary").once
|
108
|
+
@test_runner.run_tests("foo_test")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "in progress twice then passed result yielded" do
|
113
|
+
it "writes the difference between test results on each iteration" do
|
114
|
+
in_progress_one = new_in_progress_test_result
|
115
|
+
in_progress_two = new_in_progress_test_result
|
116
|
+
@test_pusher.stub!(:push).and_yield(in_progress_one).and_yield(in_progress_two)
|
117
|
+
|
118
|
+
in_progress_two.stub!(:completed_since).with(in_progress_one).and_return([
|
119
|
+
mock(:status_one, :status => "pass", :user_agent => "ipad", :test_name => "foo"),
|
120
|
+
mock(:status_one, :status => "fail", :user_agent => "iphone", :test_name => "bar")
|
121
|
+
])
|
122
|
+
|
123
|
+
@writer.should_receive(:write_passing).with("PASS foo on ipad").once
|
124
|
+
@writer.should_receive(:write_failing).with("FAIL bar on iphone").once
|
125
|
+
|
126
|
+
@test_runner.run_tests("foo bar")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spassky/client/writer'
|
2
|
+
|
3
|
+
module Spassky::Client
|
4
|
+
describe DefaultWriter do
|
5
|
+
it "writes failures in no colour" do
|
6
|
+
output = mock(:output)
|
7
|
+
output.should_receive(:puts).with("hello")
|
8
|
+
DefaultWriter.new(output).write_failing("hello")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "writes passes in no colour" do
|
12
|
+
output = mock(:output)
|
13
|
+
output.should_receive(:puts).with("hello")
|
14
|
+
DefaultWriter.new(output).write_passing("hello")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ColouredWriter do
|
19
|
+
it "writes failures in red" do
|
20
|
+
output = mock(:output)
|
21
|
+
output.should_receive(:puts).with("\e[31mhello\e[0m")
|
22
|
+
ColouredWriter.new(output).write_failing("hello")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "writes passes in green" do
|
26
|
+
output = mock(:output)
|
27
|
+
output.should_receive(:puts).with("\e[32mhello\e[0m")
|
28
|
+
ColouredWriter.new(output).write_passing("hello")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'capybara'
|
4
|
+
require 'capybara/dsl'
|
5
|
+
require 'rack/test'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
ENV["RACK_ENV"] = "test"
|
9
|
+
require 'spassky/server/app'
|
10
|
+
|
11
|
+
module Spassky::Server
|
12
|
+
describe App do
|
13
|
+
include Rack::Test::Methods
|
14
|
+
|
15
|
+
before do
|
16
|
+
RandomStringGenerator.stub!(:random_string).and_return("random-string")
|
17
|
+
end
|
18
|
+
|
19
|
+
def app
|
20
|
+
App.new(device_list)
|
21
|
+
end
|
22
|
+
|
23
|
+
let :device_list do
|
24
|
+
mock(:device_list, :update_last_connected => true, :recently_connected_devices => [])
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "GET /device/connect" do
|
28
|
+
it "redirects to a unique URL" do
|
29
|
+
RandomStringGenerator.should_receive(:random_string).and_return("random-string")
|
30
|
+
get "/device/connect"
|
31
|
+
last_response.should be_redirect
|
32
|
+
last_response.location.should == "http://example.org/device/idle/random-string"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "GET /device/idle/123" do
|
37
|
+
|
38
|
+
it "tells the device list that the device connected" do
|
39
|
+
device_list.should_receive(:update_last_connected).with("some user agent")
|
40
|
+
header "User-Agent", "some user agent"
|
41
|
+
get "/device/idle/123"
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when there are no tests to run on the connected device" do
|
45
|
+
it "serves HTML page with a meta-refresh tag" do
|
46
|
+
TestRun.stub!(:find_next_to_run_for_user_agent).and_return(nil)
|
47
|
+
RandomStringGenerator.should_receive(:random_string).and_return("next-iteration")
|
48
|
+
get "/device/idle/123"
|
49
|
+
last_response.body.should include("<meta http-equiv=\"refresh\" content=\"1; url='/device/idle/next-iteration'\">")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when there is a test to run on the connected device" do
|
54
|
+
it "redirects to /test_runs/:id/run/:random/test_name" do
|
55
|
+
RandomStringGenerator.stub!(:random_string).and_return("a-random-string")
|
56
|
+
test = mock(:test, :contents => "test contents")
|
57
|
+
test.stub!(:id).and_return("the-test-id")
|
58
|
+
test.stub!(:name).and_return("the-test-name")
|
59
|
+
TestRun.stub!(:find_next_to_run_for_user_agent).with("some user agent").and_return(test)
|
60
|
+
header "User-Agent", "some user agent"
|
61
|
+
get '/device/idle/123'
|
62
|
+
last_response.should be_redirect
|
63
|
+
last_response.location.should == 'http://example.org/test_runs/the-test-id/run/a-random-string/the-test-name'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "GET /test_runs/:id/run/:random/assert" do
|
69
|
+
it "saves the test result" do
|
70
|
+
test = mock(:test)
|
71
|
+
TestRun.stub!(:find).with('123').and_return(test)
|
72
|
+
header "User-Agent", "the user agent"
|
73
|
+
test.should_receive(:save_results_for_user_agent).with(:user_agent => "the user agent", :status => "pass")
|
74
|
+
get "/test_runs/123/run/random/assert?status=pass"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "GET /test_runs/:id/run/:random/filename" do
|
79
|
+
before do
|
80
|
+
@test_contents = {
|
81
|
+
"test_file.js" => "some javascript",
|
82
|
+
"fake_test.html.file" => "don't choose this one",
|
83
|
+
"test_name.html" => "actual test!"
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
context "file name is a file" do
|
88
|
+
it "returns the specified file" do
|
89
|
+
test = mock(:test, :name => "fake_test.html.file", :contents => @test_contents)
|
90
|
+
TestRun.stub!(:find).with('123').and_return(test)
|
91
|
+
header "User-Agent", "some user agent"
|
92
|
+
get "/test_runs/123/run/random/fake_test.html.file"
|
93
|
+
last_response.body.should include("don't choose this one")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "file name is not a file" do
|
98
|
+
it "returns the first file that ends with .html" do
|
99
|
+
test = mock(:test, :name => "directory/test_name.html", :contents => @test_contents)
|
100
|
+
TestRun.stub!(:find).with('123').and_return(test)
|
101
|
+
header "User-Agent", "some user agent"
|
102
|
+
get "/test_runs/123/run/random/not_a_file"
|
103
|
+
last_response.body.should include("actual test!")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "when the test contents includes a </head> tag" do
|
108
|
+
before do
|
109
|
+
@test_contents["test_name.html"] = "</head>"
|
110
|
+
@test = mock(:test, :name => "test_name", :contents => @test_contents)
|
111
|
+
TestRun.stub!(:find).with('123').and_return(@test)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "adds a meta-refresh tag to the test contents" do
|
115
|
+
RandomStringGenerator.stub!(:random_string).and_return("next-iteration")
|
116
|
+
get "/test_runs/123/run/random/test_name.html"
|
117
|
+
url = "/device/idle/next-iteration"
|
118
|
+
last_response.body.should include("<meta http-equiv=\"refresh\" content=\"1; url='#{url}'\"></head>")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "adds the assert.js script to the head" do
|
122
|
+
File.stub!(:read).and_return("assert.js!")
|
123
|
+
get "/test_runs/123/run/random/test_name.html"
|
124
|
+
last_response.body.should include("<script type=\"text/javascript\">assert.js!</script>")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "POST /test_runs" do
|
130
|
+
before do
|
131
|
+
device_list.stub!(:recently_connected_devices).and_return(["foo", "bar"])
|
132
|
+
@test_run = mock(:test_run)
|
133
|
+
@test_run.stub!(:id).and_return(42)
|
134
|
+
TestRun.stub!(:create).and_return(@test_run)
|
135
|
+
RandomStringGenerator.stub!(:random_string).and_return("number")
|
136
|
+
@test_contents = {"file1" => "file1 contents", "file2" => "file2 contents"}
|
137
|
+
end
|
138
|
+
|
139
|
+
it "creates a test run" do
|
140
|
+
TestRun.should_receive(:create).with(:name => "first-test", :contents => @test_contents, :devices => ["foo", "bar"])
|
141
|
+
post "/test_runs", { :name => "first-test", :contents => @test_contents.to_json }
|
142
|
+
end
|
143
|
+
|
144
|
+
it "redirects to the status page" do
|
145
|
+
post "/test_runs", { :name => "first-test", :contents => @test_contents.to_json}
|
146
|
+
last_response.should be_redirect
|
147
|
+
last_response.location.should =~ /test_runs\/42$/
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "GET /test_runs/123" do
|
152
|
+
it "returns the status of the test with the id '123'" do
|
153
|
+
test_run = mock(:test_run)
|
154
|
+
test_result = mock(:test_result)
|
155
|
+
test_result.stub!(:to_json).and_return("the test run as json")
|
156
|
+
test_run.stub!(:result).and_return(test_result)
|
157
|
+
test_run.stub!(:update_connected_devices)
|
158
|
+
TestRun.should_receive(:find).with('123').and_return test_run
|
159
|
+
get '/test_runs/123'
|
160
|
+
last_response.body.should == "the test run as json"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "tells the test run which devices are still connected" do
|
164
|
+
test_run = mock(:test_run)
|
165
|
+
test_result = mock(:test_result)
|
166
|
+
test_result.stub!(:to_json).and_return("the test run as json")
|
167
|
+
test_run.stub!(:result).and_return(test_result)
|
168
|
+
TestRun.stub!(:find).with('123').and_return test_run
|
169
|
+
still_connected_devices = ["device1", "device2"]
|
170
|
+
device_list.stub!(:recently_connected_devices).and_return(still_connected_devices)
|
171
|
+
test_run.should_receive(:update_connected_devices).with(still_connected_devices)
|
172
|
+
get '/test_runs/123'
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'spassky/server/device_list'
|
3
|
+
|
4
|
+
module Spassky::Server
|
5
|
+
describe DeviceList do
|
6
|
+
it "keeps track of when devices last connected" do
|
7
|
+
list = DeviceList.new
|
8
|
+
list.update_last_connected("foo")
|
9
|
+
list.update_last_connected("bar")
|
10
|
+
list.recently_connected_devices.should == ["foo", "bar"]
|
11
|
+
end
|
12
|
+
|
13
|
+
it "clears all devices" do
|
14
|
+
list = DeviceList.new
|
15
|
+
list.update_last_connected("foo")
|
16
|
+
list.update_last_connected("bar")
|
17
|
+
list.clear
|
18
|
+
list.recently_connected_devices.size.should == 0
|
19
|
+
end
|
20
|
+
|
21
|
+
it "ignores devices connected more than 3 seconds ago" do
|
22
|
+
list = DeviceList.new
|
23
|
+
now = Time.now
|
24
|
+
Time.stub!(:now).and_return(now - 3)
|
25
|
+
list.update_last_connected("a")
|
26
|
+
Time.stub!(:now).and_return(now - 2)
|
27
|
+
list.update_last_connected("b")
|
28
|
+
Time.stub!(:now).and_return(now)
|
29
|
+
list.recently_connected_devices.should == ["b"]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'spassky/server/random_string_generator'
|
3
|
+
|
4
|
+
module Spassky::Server
|
5
|
+
describe RandomStringGenerator do
|
6
|
+
it "returns the current ticks" do
|
7
|
+
now = mock
|
8
|
+
now.stub!(:to_i).and_return(123)
|
9
|
+
Time.stub!(:now).and_return(now)
|
10
|
+
RandomStringGenerator.random_string.should == "123"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'spassky/server/test_run'
|
3
|
+
|
4
|
+
module Spassky::Server
|
5
|
+
describe TestRun do
|
6
|
+
before do
|
7
|
+
TestRun.delete_all
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can be created and retrieved" do
|
11
|
+
created = TestRun.create(:name => "a test", :contents => "the contents")
|
12
|
+
retrieved = TestRun.find(created.id)
|
13
|
+
created.should == retrieved
|
14
|
+
end
|
15
|
+
|
16
|
+
it "assigns each test run a unique id" do
|
17
|
+
test_run1 = TestRun.create(:name => "test run 1", :contents => "the contents")
|
18
|
+
test_run2 =TestRun.create(:name => "test run 2", :contents => "the contents")
|
19
|
+
test_run1.id.should_not == test_run2.id
|
20
|
+
end
|
21
|
+
|
22
|
+
it "finds a test run by it's id" do
|
23
|
+
first = TestRun.create(:name => "test run 1", :contents => "the contents")
|
24
|
+
second = TestRun.create(:name => "test run 2", :contents => "the contents")
|
25
|
+
TestRun.find(first.id.to_s).should == first
|
26
|
+
TestRun.find(second.id).should == second
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns the next test to run for each device" do
|
30
|
+
created = TestRun.create(:name => "test", :contents => "contents", :devices => ["x", "y"])
|
31
|
+
TestRun.find_next_to_run_for_user_agent("x").should == created
|
32
|
+
TestRun.find_next_to_run_for_user_agent("y").should == created
|
33
|
+
end
|
34
|
+
|
35
|
+
it "only returns a test run per user agent until results are saved" do
|
36
|
+
created = TestRun.create(:name => "another test", :contents => "the contents of the test", :devices => ["user agent 1"])
|
37
|
+
TestRun.find_next_to_run_for_user_agent("user agent 1").should == created
|
38
|
+
TestRun.find_next_to_run_for_user_agent("user agent 1").should == created
|
39
|
+
created.save_results_for_user_agent(:user_agent => "user agent 1", :status => "pass")
|
40
|
+
TestRun.find_next_to_run_for_user_agent("user agent 1").should be_nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns 'in progress' status per user agent until the results are saved" do
|
44
|
+
created = TestRun.create(:name => "another test", :contents => "the contents of the test")
|
45
|
+
created.result.status.should == 'in progress'
|
46
|
+
created.save_results_for_user_agent(:user_agent => "some user agent", :status => "pass")
|
47
|
+
created.result.status.should == 'pass'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns failed if the saved tests results failed" do
|
51
|
+
created = TestRun.create(:name => "another test", :contents => "the contents of the test")
|
52
|
+
created.save_results_for_user_agent(:user_agent => "another user agent", :status => "fail")
|
53
|
+
created.result.status.should == 'fail'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "rejects nonsense status" do
|
57
|
+
run = TestRun.create(:name => "another test", :contents => "the contents of the test")
|
58
|
+
lambda {
|
59
|
+
run.save_results_for_user_agent(:user_agent => "another user agent", :status => "wtf?")
|
60
|
+
}.should raise_error("wtf? is not a valid status")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "creates an in progress test result from the device list" do
|
64
|
+
run = TestRun.create(
|
65
|
+
:name => "another test",
|
66
|
+
:contents => "the contents of the test",
|
67
|
+
:devices => ["device1", "device2"]
|
68
|
+
)
|
69
|
+
run.result.device_statuses.size.should == 2
|
70
|
+
run.result.device_statuses.first.status.should == "in progress"
|
71
|
+
run.result.device_statuses.last.status.should == "in progress"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "updates the status of disconnected devices to 'timed out'" do
|
75
|
+
run = TestRun.create(
|
76
|
+
:name => "another test",
|
77
|
+
:contents => "the contents of the test",
|
78
|
+
:devices => ["device1", "device2"]
|
79
|
+
)
|
80
|
+
run.update_connected_devices(["device1"])
|
81
|
+
run.result.device_statuses.first.status.should == "in progress"
|
82
|
+
run.result.device_statuses.last.status.should == "timed out"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "does not update the status of disconnected devices that have already passed or failed" do
|
86
|
+
run = TestRun.create(
|
87
|
+
:name => "another test",
|
88
|
+
:contents => "the contents of the test",
|
89
|
+
:devices => ["device1", "device2"]
|
90
|
+
)
|
91
|
+
run.save_results_for_user_agent(:user_agent => "device1", :status => "pass")
|
92
|
+
run.save_results_for_user_agent(:user_agent => "device2", :status => "fail")
|
93
|
+
run.update_connected_devices([])
|
94
|
+
run.result.device_statuses.first.status.should == "pass"
|
95
|
+
run.result.device_statuses.last.status.should == "fail"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'spassky/test_result'
|
3
|
+
|
4
|
+
module Spassky
|
5
|
+
describe TestResult do
|
6
|
+
context "when no devices are connected" do
|
7
|
+
it "is in progress" do
|
8
|
+
TestResult.new([]).status.should == "in progress"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when one device passes" do
|
13
|
+
it "outputs a summary" do
|
14
|
+
test_result = TestResult.new([
|
15
|
+
Spassky::DeviceTestStatus.new('agent1', 'pass', 'test')
|
16
|
+
])
|
17
|
+
test_result.summary.should == "1 test passed on 1 device"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when all devices pass" do
|
22
|
+
it "is a pass" do
|
23
|
+
TestResult.new([
|
24
|
+
Spassky::DeviceTestStatus.new('agent1', 'pass', 'test'),
|
25
|
+
Spassky::DeviceTestStatus.new('agent2', 'pass', 'test')
|
26
|
+
]).status.should == "pass"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "outputs a pluralised summary" do
|
30
|
+
test_result = TestResult.new([
|
31
|
+
Spassky::DeviceTestStatus.new('agent1', 'pass', 'test'),
|
32
|
+
Spassky::DeviceTestStatus.new('agent2', 'pass', 'test')
|
33
|
+
])
|
34
|
+
test_result.summary.should == "1 test passed on 2 devices"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when any device fails" do
|
39
|
+
it "is a fail" do
|
40
|
+
TestResult.new([
|
41
|
+
Spassky::DeviceTestStatus.new('agent1', 'pass', 'test'),
|
42
|
+
Spassky::DeviceTestStatus.new('agent2', 'fail', 'test')
|
43
|
+
]).status.should == "fail"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "outputs a summary" do
|
47
|
+
test_result = TestResult.new([
|
48
|
+
Spassky::DeviceTestStatus.new('agent1', 'fail', 'test')
|
49
|
+
])
|
50
|
+
test_result.summary.should == "1 test failed on 1 device"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when any test is still in progress" do
|
55
|
+
it "is a fail" do
|
56
|
+
TestResult.new([
|
57
|
+
Spassky::DeviceTestStatus.new('agent1', 'pass', 'test'),
|
58
|
+
Spassky::DeviceTestStatus.new('agent2', 'fail', 'test'),
|
59
|
+
Spassky::DeviceTestStatus.new('agent3', 'in progress', 'test')
|
60
|
+
]).status.should == "in progress"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when 1 test times out" do
|
65
|
+
it "outputs the correct summary" do
|
66
|
+
test_result = TestResult.new([
|
67
|
+
Spassky::DeviceTestStatus.new('agent1', 'timed out', 'test')
|
68
|
+
])
|
69
|
+
test_result.summary.should == "1 test timed out on 1 device"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "has the status 'timed out'" do
|
73
|
+
test_result = TestResult.new([
|
74
|
+
Spassky::DeviceTestStatus.new('agent1', 'timed out', 'test'),
|
75
|
+
Spassky::DeviceTestStatus.new('agent2', 'pass', 'test')
|
76
|
+
])
|
77
|
+
test_result.status.should == "timed out"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "can be serialized and deserialized" do
|
82
|
+
test_result = TestResult.new([Spassky::DeviceTestStatus.new('agent', 'pass', 'test')])
|
83
|
+
json = test_result.to_json
|
84
|
+
deserialized = TestResult.from_json(json)
|
85
|
+
deserialized.device_statuses.size.should == 1
|
86
|
+
deserialized.device_statuses.first.user_agent.should == 'agent'
|
87
|
+
deserialized.device_statuses.first.status.should == 'pass'
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#completed_since(nil)" do
|
91
|
+
it "returns all device test results that are not in progress" do
|
92
|
+
status_1 = Spassky::DeviceTestStatus.new('agent', 'pass', 'test1')
|
93
|
+
status_2 = Spassky::DeviceTestStatus.new('agent', 'in progress', 'test2')
|
94
|
+
status_3 = Spassky::DeviceTestStatus.new('agent', 'fail', 'test3')
|
95
|
+
test_result = TestResult.new([status_1, status_2, status_3])
|
96
|
+
test_result.completed_since(nil).should == [status_1, status_3]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#completed_since(other_test_result)" do
|
101
|
+
it "returns all device test results that are no longer in progress" do
|
102
|
+
status_a1 = Spassky::DeviceTestStatus.new('agent', 'pass', 'test1')
|
103
|
+
status_a2 = Spassky::DeviceTestStatus.new('agent', 'in progress', 'test2')
|
104
|
+
status_a3 = Spassky::DeviceTestStatus.new('agent', 'in progress', 'test3')
|
105
|
+
status_b1 = Spassky::DeviceTestStatus.new('agent', 'pass', 'test1')
|
106
|
+
status_b2 = Spassky::DeviceTestStatus.new('agent', 'fail', 'test2')
|
107
|
+
status_b3 = Spassky::DeviceTestStatus.new('agent', 'timed out', 'test3')
|
108
|
+
|
109
|
+
test_result_before = TestResult.new([status_a1, status_a2, status_a3])
|
110
|
+
test_result_after = TestResult.new([status_b1, status_b2, status_b3])
|
111
|
+
|
112
|
+
test_result_after.completed_since(test_result_before).should == [status_b2, status_b3]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/spec/spec_helper.rb
ADDED