quorum 0.3.1 → 0.3.2
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/.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
|