quorum 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +21 -0
- data/Gemfile +3 -11
- data/Gemfile.lock +62 -58
- data/HISTORY.md +9 -0
- data/README.rdoc +29 -19
- data/Rakefile +51 -0
- data/app/assets/javascripts/quorum/jobs.js +4 -0
- data/app/assets/javascripts/quorum/quorum.js +315 -239
- data/app/controllers/quorum/jobs_controller.rb +4 -4
- data/app/models/quorum/job.rb +1 -1
- data/app/views/quorum/jobs/new.html.erb +7 -7
- data/app/views/quorum/jobs/show.html.erb +22 -8
- data/app/views/quorum/jobs/templates/_blast_detailed_report_template.html.erb +2 -2
- data/app/views/quorum/jobs/templates/_blast_template.html.erb +2 -2
- data/lib/generators/templates/blast.rb +1 -13
- data/lib/generators/templates/logger.rb +4 -4
- data/lib/quorum/version.rb +1 -1
- data/lib/workers/quorum.rb +3 -3
- data/spec/dummy/quorum/blastdb/test.nin +0 -0
- data/spec/dummy/quorum/blastdb/test.pin +0 -0
- data/spec/dummy/quorum/lib/search_tools/blast.rb +7 -19
- data/spec/javascripts/fixtures/quorum_tabs.html +5 -0
- data/spec/javascripts/quorum_spec.js +187 -12
- data/spec/requests/jobs_spec.rb +22 -3
- data/spec/templates/logger_spec.rb +3 -3
- data/vendor/assets/javascripts/underscore-min.js +27 -25
- metadata +6 -5
@@ -1,9 +1,9 @@
|
|
1
1
|
<div id="show">
|
2
2
|
<h1>Search Results</h1>
|
3
3
|
<p class="small right"><%= link_to raw("Search Again »"), :jobs %></p>
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
<%# Tabs %>
|
5
|
+
<%# To remove an algorithm from the view, simply comment out the %>
|
6
|
+
<%# div#tabs ul li and corresponding div#tabs-(tab number) %>
|
7
7
|
<div id="tabs">
|
8
8
|
<ul>
|
9
9
|
<li><a href="#tabs-1">Blastn</a></li>
|
@@ -12,7 +12,7 @@
|
|
12
12
|
<li><a href="#tabs-4">Blastp</a></li>
|
13
13
|
</ul>
|
14
14
|
|
15
|
-
|
15
|
+
<%# Search results per algorithm %>
|
16
16
|
<div id="tabs-1">
|
17
17
|
<h2>Blastn</h2>
|
18
18
|
<div id="blastn-results">
|
@@ -41,10 +41,10 @@
|
|
41
41
|
</div>
|
42
42
|
</div>
|
43
43
|
</div>
|
44
|
-
|
44
|
+
<%# End Tabs %>
|
45
45
|
<p class="small right"><%= link_to raw("Search Again »"), :jobs %></p>
|
46
46
|
|
47
|
-
|
47
|
+
<%# Detailed report element %>
|
48
48
|
<div id="detailed_report_dialog" title="Quorum Report Details"></div>
|
49
49
|
</div>
|
50
50
|
<div id="quorum">
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</p>
|
55
55
|
</div>
|
56
56
|
|
57
|
-
|
57
|
+
<%# Templates %>
|
58
58
|
<%= render :partial => "quorum/jobs/templates/blast_template" %>
|
59
59
|
<%= render :partial => "quorum/jobs/templates/blast_detailed_report_template" %>
|
60
60
|
|
@@ -63,10 +63,24 @@
|
|
63
63
|
//
|
64
64
|
// Asynchronously poll Quorum for search results.
|
65
65
|
//
|
66
|
-
// pollResults(id, interval)
|
66
|
+
// QUORUM.pollResults(id, callback, callback_obj, interval)
|
67
67
|
// id: Job.id
|
68
|
+
// callback: Define your own callback function to override the default.
|
69
|
+
// callback should expect the following params.
|
70
|
+
// id: Job.id (Int),
|
71
|
+
// data: JSON data (JSON),
|
72
|
+
// algorithm: Supported algorithm (String).
|
73
|
+
// callback_obj: Callback object.
|
68
74
|
// interval: poll interval in milliseconds. 5000 default.
|
69
75
|
//
|
76
|
+
// Example:
|
77
|
+
// QUORUM.pollResults(<%= @jobs.id %>, MYAPP.myCoolCallback, MYAPP, 5000);
|
78
|
+
//
|
79
|
+
// Example callback:
|
80
|
+
// MYAPP.myCoolCallback = function(id, data, algo) {
|
81
|
+
// // awesome logic
|
82
|
+
// };
|
83
|
+
//
|
70
84
|
QUORUM.pollResults(<%= @jobs.id %>);
|
71
85
|
});
|
72
86
|
</script>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
<%# Detailed Report Template %>
|
2
2
|
<script type="text/template" id="detailed_report_template">
|
3
3
|
<h3>Query Accession {{= query }}</h3>
|
4
4
|
{{ _.each(data, function(v) { }}
|
@@ -19,7 +19,7 @@
|
|
19
19
|
<p class="small">Hit Description: {{= v.hit_def }}</p>
|
20
20
|
<table class="report_details">
|
21
21
|
<tr>
|
22
|
-
<td>E-value: {{= v.evalue }}</td>
|
22
|
+
<td>E-value: {{= QUORUM.formatEvalue(v.evalue) }}</td>
|
23
23
|
<td>Bit Score: {{= v.bit_score }}</td>
|
24
24
|
<td></td>
|
25
25
|
</tr>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
<%# Blast Results Template %>
|
2
2
|
<script type="text/template" id="blast_template">
|
3
3
|
{{ if (data[0].results === false) { }}
|
4
4
|
<p><strong>Your search returned 0 hits.</strong></p>
|
@@ -56,7 +56,7 @@
|
|
56
56
|
{{= v.id }},
|
57
57
|
'{{= v.query }}',
|
58
58
|
'{{= algo }}')">
|
59
|
-
{{= v.evalue }}
|
59
|
+
{{= QUORUM.formatEvalue(v.evalue) }}
|
60
60
|
</a>
|
61
61
|
</td>
|
62
62
|
</tr>
|
@@ -232,18 +232,6 @@ module Quorum
|
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
|
-
#
|
236
|
-
# Make the E-value look pretty.
|
237
|
-
#
|
238
|
-
def format_evalue(evalue)
|
239
|
-
evalue = evalue.to_s
|
240
|
-
e = evalue.slice!(/e.*/)
|
241
|
-
unless e.nil?
|
242
|
-
e = " x 10<sup>" << e.sub(/e/, '') << "</sup>"
|
243
|
-
end
|
244
|
-
evalue.to_f.round(1).to_s << e.to_s
|
245
|
-
end
|
246
|
-
|
247
235
|
#
|
248
236
|
# Format Blast report hit_display_id and hit_def.
|
249
237
|
#
|
@@ -295,7 +283,7 @@ module Quorum
|
|
295
283
|
@data[:hsp_num] = hsp.hsp_num
|
296
284
|
@data[:bit_score] = hsp.bit_score
|
297
285
|
@data[:score] = hsp.score
|
298
|
-
@data[:evalue] =
|
286
|
+
@data[:evalue] = hsp.evalue
|
299
287
|
@data[:query_from] = hsp.query_from
|
300
288
|
@data[:query_to] = hsp.query_to
|
301
289
|
@data[:hit_from] = hsp.hit_from
|
@@ -29,13 +29,13 @@ module Quorum
|
|
29
29
|
# Removes instance files.
|
30
30
|
#
|
31
31
|
def remove_files(files)
|
32
|
-
|
33
|
-
|
34
|
-
else
|
35
|
-
log(
|
32
|
+
if Dir.glob(files).empty?
|
33
|
+
log(
|
36
34
|
"remove_files",
|
37
35
|
"Unable to remove #{files}"
|
38
36
|
)
|
37
|
+
else
|
38
|
+
`rm #{files}`
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
data/lib/quorum/version.rb
CHANGED
data/lib/workers/quorum.rb
CHANGED
@@ -24,9 +24,7 @@ module Workers
|
|
24
24
|
Net::SSH.start(ssh_host, ssh_user, ssh_options) do |ssh|
|
25
25
|
ssh.open_channel do |ch|
|
26
26
|
ch.exec(cmd) do |ch, success|
|
27
|
-
|
28
|
-
Rails.logger.warn "Channel Net::SSH exec() failed. :'("
|
29
|
-
else
|
27
|
+
if success
|
30
28
|
# Capture STDOUT from ch.exec()
|
31
29
|
if stdout
|
32
30
|
ch.on_data do |ch, data|
|
@@ -37,6 +35,8 @@ module Workers
|
|
37
35
|
ch.on_request("exit-status") do |ch, data|
|
38
36
|
exit_status = data.read_long
|
39
37
|
end
|
38
|
+
else
|
39
|
+
Rails.logger.warn "Channel Net::SSH exec() failed. :'("
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
Binary file
|
Binary file
|
@@ -13,9 +13,9 @@ module Quorum
|
|
13
13
|
class QuorumJob < ActiveRecord::Base
|
14
14
|
self.table_name = "quorum_jobs"
|
15
15
|
|
16
|
-
has_one :quorum_blastn_job,
|
16
|
+
has_one :quorum_blastn_job,
|
17
17
|
:foreign_key => "job_id"
|
18
|
-
has_many :quorum_blastn_job_reports,
|
18
|
+
has_many :quorum_blastn_job_reports,
|
19
19
|
:foreign_key => "blastn_job_id"
|
20
20
|
|
21
21
|
has_one :quorum_blastx_job,
|
@@ -217,7 +217,7 @@ module Quorum
|
|
217
217
|
File.open(@na_fasta, "w") { |f| f << @na_sequence }
|
218
218
|
File.open(@aa_fasta, "w") { |f| f << @aa_sequence }
|
219
219
|
|
220
|
-
@out = File.join(@tmp, @hash + ".out.xml")
|
220
|
+
@out = File.join(@tmp, @hash + ".out.xml")
|
221
221
|
File.new(@out, "w")
|
222
222
|
|
223
223
|
case @algorithm
|
@@ -232,18 +232,6 @@ module Quorum
|
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
|
-
#
|
236
|
-
# Make the E-value look pretty.
|
237
|
-
#
|
238
|
-
def format_evalue(evalue)
|
239
|
-
evalue = evalue.to_s
|
240
|
-
e = evalue.slice!(/e.*/)
|
241
|
-
unless e.nil?
|
242
|
-
e = " x 10<sup>" << e.sub(/e/, '') << "</sup>"
|
243
|
-
end
|
244
|
-
evalue.to_f.round(1).to_s << e.to_s
|
245
|
-
end
|
246
|
-
|
247
235
|
#
|
248
236
|
# Format Blast report hit_display_id and hit_def.
|
249
237
|
#
|
@@ -269,7 +257,7 @@ module Quorum
|
|
269
257
|
|
270
258
|
#
|
271
259
|
# Parse and save Blast results using bio-blastxmlparser.
|
272
|
-
# Only save Blast results if results.bit_score > @min_score.
|
260
|
+
# Only save Blast results if results.bit_score > @min_score.
|
273
261
|
#
|
274
262
|
def parse_and_save_results
|
275
263
|
# Helper to avoid having to perform a query.
|
@@ -295,7 +283,7 @@ module Quorum
|
|
295
283
|
@data[:hsp_num] = hsp.hsp_num
|
296
284
|
@data[:bit_score] = hsp.bit_score
|
297
285
|
@data[:score] = hsp.score
|
298
|
-
@data[:evalue] =
|
286
|
+
@data[:evalue] = hsp.evalue
|
299
287
|
@data[:query_from] = hsp.query_from
|
300
288
|
@data[:query_to] = hsp.query_to
|
301
289
|
@data[:hit_from] = hsp.hit_from
|
@@ -311,7 +299,7 @@ module Quorum
|
|
311
299
|
|
312
300
|
# Hsps are only reported if a query hit against the Blast db.
|
313
301
|
# Only save the @data if bit_score exists.
|
314
|
-
if @data[:bit_score] &&
|
302
|
+
if @data[:bit_score] &&
|
315
303
|
(@data[:bit_score].to_i > @min_score.to_i)
|
316
304
|
@data[:results] = true
|
317
305
|
@data["#{@algorithm}_job_id".to_sym] = @job.method(@job_association).call.job_id
|
@@ -410,7 +398,7 @@ module Quorum
|
|
410
398
|
# Execute Blast on a given dataset.
|
411
399
|
#
|
412
400
|
def execute_blast
|
413
|
-
generate_blast_cmd
|
401
|
+
generate_blast_cmd
|
414
402
|
@logger.log("NCBI Blast", @cmd)
|
415
403
|
system(@cmd)
|
416
404
|
parse_and_save_results
|
@@ -8,3 +8,8 @@
|
|
8
8
|
<div id="tabs-2">Tab 2</div>
|
9
9
|
<div id="tabs-3">Tab 3</div>
|
10
10
|
</div>
|
11
|
+
|
12
|
+
<div id="detailed_report_dialog" title="Quorum Report Details"></div>
|
13
|
+
<script type="text/template" id="blast_template"></script>
|
14
|
+
<script type="text/template" id="detailed_report_template"></script>
|
15
|
+
<a id="download_sequence">Download Sequence</a>
|
@@ -1,9 +1,73 @@
|
|
1
1
|
//
|
2
|
-
//
|
2
|
+
// QUORUM Specs
|
3
3
|
//
|
4
4
|
|
5
5
|
describe("QUORUM", function() {
|
6
6
|
|
7
|
+
//
|
8
|
+
// Spec covers QUORUM.algorithms.
|
9
|
+
//
|
10
|
+
// QUORUM.algorithms should be an array of strings.
|
11
|
+
//
|
12
|
+
it("contains an array of strings", function() {
|
13
|
+
expect(QUORUM.algorithms.join('')).toMatch(/[a-zA-Z]/g);
|
14
|
+
});
|
15
|
+
|
16
|
+
//
|
17
|
+
// Spec covers QUORUM.pollResults.
|
18
|
+
//
|
19
|
+
// QUORUM.pollResults calls itself via setTimeout() if the returned JSON
|
20
|
+
// dataset is empty.
|
21
|
+
//
|
22
|
+
// If callback is defined, call callback function. Otherwise call default
|
23
|
+
// anonymous function buildTemplate().
|
24
|
+
//
|
25
|
+
it("fetches JSON and calls user defined callback function", function() {
|
26
|
+
spyOn($, 'getJSON');
|
27
|
+
spyOn(window, 'setTimeout');
|
28
|
+
var id = 1,
|
29
|
+
callback = jasmine.createSpy(),
|
30
|
+
data = 'foo';
|
31
|
+
|
32
|
+
QUORUM.pollResults(id, callback, null, 5000, ['a']);
|
33
|
+
|
34
|
+
// setTimeout()
|
35
|
+
$.getJSON.mostRecentCall.args[1]('');
|
36
|
+
expect(window.setTimeout).toHaveBeenCalled();
|
37
|
+
|
38
|
+
// callback()
|
39
|
+
$.getJSON.mostRecentCall.args[1](data);
|
40
|
+
expect(callback).toHaveBeenCalledWith(id, data, 'a');
|
41
|
+
});
|
42
|
+
|
43
|
+
//
|
44
|
+
// Spec covers QUORUM.viewDetailedReport.
|
45
|
+
//
|
46
|
+
// Open detailed report dialog modal box and load template.
|
47
|
+
//
|
48
|
+
it("renders modal box containing detailed report", function() {
|
49
|
+
loadFixtures('quorum_tabs.html');
|
50
|
+
|
51
|
+
spyOn($, 'getJSON');
|
52
|
+
spyOn(QUORUM, 'autoScroll');
|
53
|
+
var id = 1,
|
54
|
+
focus_id = 1,
|
55
|
+
query = 'foo',
|
56
|
+
algo = 'a',
|
57
|
+
data = 'bar';
|
58
|
+
|
59
|
+
QUORUM.viewDetailedReport(id, focus_id, query, algo);
|
60
|
+
|
61
|
+
expect($("#detailed_report_dialog")).toBeVisible();
|
62
|
+
|
63
|
+
// Fetch JSON to build the template and scroll to focus_id.
|
64
|
+
$.getJSON.mostRecentCall.args[1](data);
|
65
|
+
expect(QUORUM.autoScroll).toHaveBeenCalledWith(focus_id, false);
|
66
|
+
|
67
|
+
// Close the dialog box.
|
68
|
+
$("#detailed_report_dialog").dialog('close');
|
69
|
+
});
|
70
|
+
|
7
71
|
//
|
8
72
|
// Spec covers QUORUM.formatSequenceReport & QUORUM.addBaseTitleIndex.
|
9
73
|
//
|
@@ -52,6 +116,10 @@ describe("QUORUM", function() {
|
|
52
116
|
expect(report).toEqual("<p class='small'>Alignment (Mouse over for positions):</p><span class='small'><pre>\nqseq <a rel='quorum-tipsy' title=10>E</a><a rel='quorum-tipsy' title=11>L</a><a rel='quorum-tipsy' title=12>V</a><a rel='quorum-tipsy' title=13>I</a><a rel='quorum-tipsy' title=14>S</a>\n ELVIS\nhseq <a rel='quorum-tipsy' title=121>E</a><a rel='quorum-tipsy' title=122>L</a><a rel='quorum-tipsy' title=123>V</a><a rel='quorum-tipsy' title=124>I</a><a rel='quorum-tipsy' title=125>S</a>\n\n</pre></span>");
|
53
117
|
});
|
54
118
|
|
119
|
+
//
|
120
|
+
// jQuery tipsy plugin should display anchor's title attribute on mouseover
|
121
|
+
// and hide on mouseout.
|
122
|
+
//
|
55
123
|
it("should display title via jquery.tipsy on mouse over hide on mouse out", function() {
|
56
124
|
loadFixtures('formatted_sequence.html');
|
57
125
|
$('a[rel=quorum-tipsy]').tipsy({ gravity: 's' });
|
@@ -63,6 +131,12 @@ describe("QUORUM", function() {
|
|
63
131
|
expect($('.tipsy')).not.toBeVisible();
|
64
132
|
});
|
65
133
|
|
134
|
+
//
|
135
|
+
// Spec covers QUORUM.formatStrand.
|
136
|
+
//
|
137
|
+
// If number is > 0 print forward.
|
138
|
+
// If number is < 0 print reverse.
|
139
|
+
//
|
66
140
|
it("prints hit strand as forward / forward for + / + intergers", function() {
|
67
141
|
expect(QUORUM.formatStrand(1, 1)).toEqual("forward / forward");
|
68
142
|
});
|
@@ -79,26 +153,127 @@ describe("QUORUM", function() {
|
|
79
153
|
expect(QUORUM.formatStrand(-1, -1)).toEqual("reverse / reverse");
|
80
154
|
});
|
81
155
|
|
156
|
+
//
|
157
|
+
// Spec covers QUORUM.formatEvalue
|
158
|
+
//
|
159
|
+
// Format Blast Evalues for HTML.
|
160
|
+
//
|
161
|
+
it("returns empty string if evalue is not set", function() {
|
162
|
+
expect(QUORUM.formatEvalue("")).toEqual("");
|
163
|
+
expect(QUORUM.formatEvalue(null)).toEqual("");
|
164
|
+
expect(QUORUM.formatEvalue(undefined)).toEqual("");
|
165
|
+
});
|
166
|
+
|
167
|
+
it("formats blast evalue", function() {
|
168
|
+
expect(QUORUM.formatEvalue("0")).toEqual("0.0");
|
169
|
+
expect(QUORUM.formatEvalue("0.0")).toEqual("0.0");
|
170
|
+
expect(QUORUM.formatEvalue("1.23966346466766e-65")).toEqual("1.2 x 10<sup>-65</sup>");
|
171
|
+
expect(QUORUM.formatEvalue("1.2966346466766e-165")).toEqual("1.3 x 10<sup>-165</sup>");
|
172
|
+
expect(QUORUM.formatEvalue("1.23456789")).toEqual("1.2");
|
173
|
+
});
|
174
|
+
|
175
|
+
//
|
176
|
+
// Spec covers QUORUM.displayHspLinks.
|
82
177
|
//
|
83
178
|
// Only print links to HSPs whers data id != focus.
|
84
179
|
//
|
85
180
|
it("prints HSP links", function() {
|
86
|
-
var focus = 1
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
181
|
+
var focus = 1,
|
182
|
+
group = "1,2",
|
183
|
+
data = [
|
184
|
+
{"id":1,"hsp_group":"1,2","hsp_num":1},
|
185
|
+
{"id":2,"hsp_group":"1,2","hsp_num":2}
|
186
|
+
];
|
187
|
+
|
188
|
+
var hsps = QUORUM.displayHspLinks(focus, group, data);
|
93
189
|
expect(hsps).toEqual("Related <a onclick=\"(QUORUM.openWindow('http://www.ncbi.nlm.nih.gov/books/NBK62051/def-item/blast_glossary.HSP','HSP', 800, 300))\">HSPs</a>: 1 <a onclick='(QUORUM.autoScroll(2, true))'>2</a> ");
|
94
190
|
});
|
95
191
|
|
192
|
+
//
|
193
|
+
// QUORUM.displayHspLinks should return an empty string if group is not set.
|
194
|
+
//
|
195
|
+
it("prints HSP links", function() {
|
196
|
+
var focus = 1,
|
197
|
+
group = null,
|
198
|
+
data = [
|
199
|
+
{"id":1,"hsp_group":"1,2","hsp_num":1},
|
200
|
+
{"id":2,"hsp_group":"1,2","hsp_num":2}
|
201
|
+
];
|
202
|
+
|
203
|
+
var hsps = QUORUM.displayHspLinks(focus, group, data);
|
204
|
+
expect(hsps).toEqual("");
|
205
|
+
});
|
206
|
+
|
207
|
+
//
|
208
|
+
// Spec covers QUORUM.downloadSequence.
|
209
|
+
//
|
210
|
+
// Download a Blast hit sequence file.
|
211
|
+
//
|
212
|
+
it("sends request to server to extract Blast hit sequence", function() {
|
213
|
+
loadFixtures("quorum_tabs.html");
|
214
|
+
|
215
|
+
spyOn($, 'getJSON');
|
216
|
+
spyOn(QUORUM, 'getSequenceFile');
|
217
|
+
var id = 1,
|
218
|
+
algo_id = 1,
|
219
|
+
algo = 'a',
|
220
|
+
el = $("#download_sequence"),
|
221
|
+
data = [{meta_id:"foo"}];
|
222
|
+
|
223
|
+
QUORUM.downloadSequence(id, algo_id, algo, el);
|
224
|
+
|
225
|
+
expect(el.html()).toEqual('Fetching sequence...');
|
226
|
+
|
227
|
+
$.getJSON.mostRecentCall.args[1](data);
|
228
|
+
expect(QUORUM.getSequenceFile).toHaveBeenCalledWith(id, data[0].meta_id, el);
|
229
|
+
});
|
230
|
+
|
231
|
+
//
|
232
|
+
// Spec covers QUORUM.getSequenceFile.
|
233
|
+
//
|
234
|
+
// Poll application for Blast hit sequence file and force browser to
|
235
|
+
// download via iframe.
|
236
|
+
//
|
237
|
+
it("polls server to extract Blast hit sequence, once found, force browser to download via iframe", function() {
|
238
|
+
loadFixtures("quorum_tabs.html");
|
239
|
+
|
240
|
+
spyOn($, 'get');
|
241
|
+
spyOn(window, 'setTimeout');
|
242
|
+
var id = 1,
|
243
|
+
meta_id = 'foo',
|
244
|
+
el = $("#download_sequence"),
|
245
|
+
data = 'bar',
|
246
|
+
error = 'error';
|
247
|
+
|
248
|
+
QUORUM.getSequenceFile(id, meta_id, el);
|
249
|
+
|
250
|
+
// setTimeout()
|
251
|
+
$.get.mostRecentCall.args[1]('');
|
252
|
+
expect(window.setTimeout).toHaveBeenCalled();
|
253
|
+
|
254
|
+
// Print error message
|
255
|
+
$.get.mostRecentCall.args[1](error);
|
256
|
+
expect(el.html()).toEqual(error);
|
257
|
+
|
258
|
+
// Force browser to download file.
|
259
|
+
$.get.mostRecentCall.args[1](data);
|
260
|
+
expect(el.html()).toEqual('Sequence Downloaded Successfully');
|
261
|
+
expect($('iframe.quorum_sequence_download')).toBeDefined();
|
262
|
+
$('.quorum_sequence_download').remove();
|
263
|
+
});
|
264
|
+
|
265
|
+
//
|
266
|
+
// Spec covers QUORUM.openWindow.
|
267
|
+
//
|
268
|
+
// Open a URL in a new window.
|
269
|
+
//
|
96
270
|
it("opens url in a new window", function() {
|
97
271
|
spyOn(window, 'open');
|
98
|
-
var url
|
99
|
-
|
100
|
-
|
101
|
-
|
272
|
+
var url = "http://google.com",
|
273
|
+
name = "Google",
|
274
|
+
width = 300,
|
275
|
+
height = 300;
|
276
|
+
|
102
277
|
QUORUM.openWindow(url, name, width, height);
|
103
278
|
expect(window.open).toHaveBeenCalledWith(url, name, "width=" + width + ",height=" + height + ",scrollbars=yes");
|
104
279
|
});
|
data/spec/requests/jobs_spec.rb
CHANGED
@@ -49,8 +49,9 @@ describe "Jobs" do
|
|
49
49
|
|
50
50
|
context "javascript", @javascript do
|
51
51
|
before(:all) do
|
52
|
-
Capybara.current_driver = :selenium
|
53
52
|
Capybara.default_wait_time = 5
|
53
|
+
Capybara.server_port = 53331
|
54
|
+
Capybara.current_driver = :selenium
|
54
55
|
end
|
55
56
|
before(:each) do
|
56
57
|
ResqueSpec.reset!
|
@@ -142,12 +143,30 @@ describe "Jobs" do
|
|
142
143
|
end
|
143
144
|
end
|
144
145
|
|
145
|
-
describe "GET /quorum/jobs/
|
146
|
-
it "displays notice and renders form" do
|
146
|
+
describe "GET /quorum/jobs/id" do
|
147
|
+
it "displays notice and renders form with invalid id" do
|
147
148
|
visit job_path('12893479812347912')
|
148
149
|
page.should have_content("The data you requested is unavailable. Please check your URL and try again.")
|
149
150
|
current_path.should eq(new_job_path)
|
150
151
|
end
|
151
152
|
end
|
152
153
|
|
154
|
+
describe "GET /quorum/jobs/id/get_quorum_search_results" do
|
155
|
+
it "renders JSON results => false with invalid id" do
|
156
|
+
visit "/quorum/jobs/23542352345/get_quorum_search_results.json"
|
157
|
+
page.should have_content("[{\"results\":false}]")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "GET /quorum/jobs/id/get_quorum_blast_hit_sequence" do
|
162
|
+
it "renders empty JSON with invalid id" do
|
163
|
+
visit "/quorum/jobs/23542352345/get_quorum_blast_hit_sequence.json"
|
164
|
+
page.should have_content("[]")
|
165
|
+
end
|
166
|
+
|
167
|
+
it "renders empty JSON with invalid id and valid params" do
|
168
|
+
visit "/quorum/jobs/23542352345/get_quorum_blast_hit_sequence.json?algo=blastn"
|
169
|
+
page.should have_content("[]")
|
170
|
+
end
|
171
|
+
end
|
153
172
|
end
|
@@ -4,7 +4,7 @@ require 'generators/templates/logger'
|
|
4
4
|
describe "Quorum::Logger" do
|
5
5
|
describe "#log" do
|
6
6
|
before(:all) do
|
7
|
-
@args = File.join(::Rails.root.to_s, "log")
|
7
|
+
@args = File.join(::Rails.root.to_s, "log")
|
8
8
|
@logger = Quorum::Logger.new(@args)
|
9
9
|
end
|
10
10
|
|
@@ -21,7 +21,7 @@ describe "Quorum::Logger" do
|
|
21
21
|
it "records program, message, exits and removes files" do
|
22
22
|
lambda {
|
23
23
|
@logger.log(
|
24
|
-
"RSpec", "This is a test.", 1,
|
24
|
+
"RSpec", "This is a test.", 1,
|
25
25
|
File.join(@args, "quorum.log")
|
26
26
|
)
|
27
27
|
}.should raise_error(SystemExit)
|
@@ -31,5 +31,5 @@ describe "Quorum::Logger" do
|
|
31
31
|
).should be_false
|
32
32
|
|
33
33
|
end
|
34
|
-
end
|
34
|
+
end
|
35
35
|
end
|