Adds checking for request body options that are both valid JSON and readable files
[arvados.git] / apps / workbench / test / integration / websockets_test.rb
1 require 'integration_helper'
2
3 class WebsocketTest < ActionDispatch::IntegrationTest
4   setup do
5     need_selenium "to make websockets work"
6   end
7
8   test "test page" do
9     visit(page_with_token("admin", "/websockets"))
10     fill_in("websocket-message-content", :with => "Stuff")
11     click_button("Send")
12     assert_text '"status":400'
13   end
14
15   test "test live logging" do
16     visit(page_with_token("admin", "/pipeline_instances/zzzzz-d1hrv-9fm8l10i9z2kqc6"))
17     click_link("Log")
18     assert_no_text '123 hello'
19
20     api = ArvadosApiClient.new
21
22     Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
23     api.api("logs", "", {log: {
24                 object_uuid: "zzzzz-d1hrv-9fm8l10i9z2kqc6",
25                 event_type: "stderr",
26                 properties: {"text" => "123 hello"}}})
27     assert_text '123 hello'
28   end
29
30
31   [["pipeline_instances", api_fixture("pipeline_instances")['pipeline_with_newer_template']['uuid']],
32    ["jobs", api_fixture("jobs")['running']['uuid']]].each do |c|
33     test "test live logging scrolling #{c[0]}" do
34
35       controller = c[0]
36       uuid = c[1]
37
38       visit(page_with_token("admin", "/#{controller}/#{uuid}"))
39       click_link("Log")
40       assert_no_text '123 hello'
41
42       api = ArvadosApiClient.new
43
44       text = ""
45       (1..1000).each do |i|
46         text << "#{i} hello\n"
47       end
48
49       Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
50       api.api("logs", "", {log: {
51                   object_uuid: uuid,
52                   event_type: "stderr",
53                   properties: {"text" => text}}})
54       assert_text '1000 hello'
55
56       # First test that when we're already at the bottom of the page, it scrolls down
57       # when a new line is added.
58       old_top = page.evaluate_script("$('#event_log_div').scrollTop()")
59
60       api.api("logs", "", {log: {
61                   object_uuid: uuid,
62                   event_type: "stderr",
63                   properties: {"text" => "1001 hello\n"}}})
64       assert_text '1001 hello'
65
66       # Check that new value of scrollTop is greater than the old one
67       new_top = page.evaluate_script("$('#event_log_div').scrollTop()")
68       assert_operator new_top, :>, old_top
69
70       # Now scroll to 30 pixels from the top
71       page.execute_script "$('#event_log_div').scrollTop(30)"
72       assert_equal 30, page.evaluate_script("$('#event_log_div').scrollTop()")
73
74       api.api("logs", "", {log: {
75                   object_uuid: uuid,
76                   event_type: "stderr",
77                   properties: {"text" => "1002 hello\n"}}})
78       assert_text '1002 hello'
79
80       # Check that we haven't changed scroll position
81       assert_equal 30, page.evaluate_script("$('#event_log_div').scrollTop()")
82     end
83   end
84
85   test "pipeline instance arv-refresh-on-log-event" do
86     Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
87     # Do something and check that the pane reloads.
88     p = PipelineInstance.create({state: "RunningOnServer",
89                                   components: {
90                                     c1: {
91                                       script: "test_hash.py",
92                                       script_version: "1de84a854e2b440dc53bf42f8548afa4c17da332"
93                                     }
94                                   }
95                                 })
96
97     visit(page_with_token("admin", "/pipeline_instances/#{p.uuid}"))
98
99     assert_text 'Active'
100     assert page.has_link? 'Pause'
101     assert_no_text 'Complete'
102     assert page.has_no_link? 'Re-run with latest'
103
104     p.state = "Complete"
105     p.save!
106
107     assert_no_text 'Active'
108     assert page.has_no_link? 'Pause'
109     assert_text 'Complete'
110     assert page.has_link? 'Re-run with latest'
111   end
112
113   test "job arv-refresh-on-log-event" do
114     Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
115     # Do something and check that the pane reloads.
116     p = Job.where(uuid: api_fixture('jobs')['running_will_be_completed']['uuid']).results.first
117
118     visit(page_with_token("admin", "/jobs/#{p.uuid}"))
119
120     assert_no_text 'complete'
121     assert_no_text 'Re-run job'
122
123     p.state = "Complete"
124     p.save!
125
126     assert_text 'complete'
127     assert_text 'Re-run job'
128   end
129
130   test "dashboard arv-refresh-on-log-event" do
131     Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
132
133     visit(page_with_token("admin", "/"))
134
135     assert_no_text 'test dashboard arv-refresh-on-log-event'
136
137     # Do something and check that the pane reloads.
138     p = PipelineInstance.create({state: "RunningOnServer",
139                                   name: "test dashboard arv-refresh-on-log-event",
140                                   components: {
141                                   }
142                                 })
143
144     assert_text 'test dashboard arv-refresh-on-log-event'
145   end
146
147   test 'job graph appears when first data point is already in logs table' do
148     job_graph_first_datapoint_test
149   end
150
151   test 'job graph appears when first data point arrives by websocket' do
152     use_token :admin do
153       Log.find(api_fixture('logs')['crunchstat_for_running_job']['uuid']).destroy
154     end
155     job_graph_first_datapoint_test expect_existing_datapoints: false
156   end
157
158   def job_graph_first_datapoint_test expect_existing_datapoints: true
159     uuid = api_fixture('jobs')['running']['uuid']
160
161     visit page_with_token "active", "/jobs/#{uuid}"
162     click_link "Log"
163
164     assert_selector '#event_log_div', visible: true
165
166     if expect_existing_datapoints
167       assert_selector '#log_graph_div', visible: true
168       # Magic numbers 12.99 etc come from the job log fixture:
169       assert_last_datapoint 'T1-cpu', (((12.99+0.99)/10.0002)/8)
170     else
171       # Until graphable data arrives, we should see the text log but not the graph.
172       assert_no_selector '#log_graph_div', visible: true
173     end
174
175     text = "2014-11-07_23:33:51 #{uuid} 31708 1 stderr crunchstat: cpu 1970.8200 user 60.2700 sys 8 cpus -- interval 10.0002 seconds 35.3900 user 0.8600 sys"
176
177     assert_triggers_dom_event 'arv-log-event' do
178       use_token :active do
179         api = ArvadosApiClient.new
180         api.api("logs", "", {log: {
181                     object_uuid: uuid,
182                     event_type: "stderr",
183                     properties: {"text" => text}}})
184       end
185     end
186
187     # Graph should have appeared (even if it hadn't above). It's
188     # important not to wait like matchers usually do: we are
189     # confirming the graph is visible _immediately_ after the first
190     # data point arrives.
191     using_wait_time 0 do
192       assert_selector '#log_graph_div', visible: true
193     end
194     assert_last_datapoint 'T1-cpu', (((35.39+0.86)/10.0002)/8)
195   end
196
197   test "live log charting from replayed log" do
198     uuid = api_fixture("jobs")['running']['uuid']
199
200     visit page_with_token "active", "/jobs/#{uuid}"
201     click_link "Log"
202
203     assert_triggers_dom_event 'arv-log-event' do
204       ApiServerForTests.new.run_rake_task("replay_job_log", "test/job_logs/crunchstatshort.log,1.0,#{uuid}")
205     end
206
207     assert_last_datapoint 'T1-cpu', (((35.39+0.86)/10.0002)/8)
208   end
209
210   def assert_last_datapoint series, value
211     datum = page.evaluate_script("jobGraphData[jobGraphData.length-1]['#{series}']")
212     assert_in_epsilon value, datum.to_f
213   end
214 end