6 use SGN::Test::Fixture;
8 use Test::WWW::Mechanize;
11 use CXGN::Pedigree::AddCrossingtrial;
12 use CXGN::Pedigree::AddCrosses;
13 use CXGN::Pedigree::AddCrossInfo;
14 use CXGN::Pedigree::AddProgeniesExistingAccessions;
15 use CXGN::Pedigree::AddPedigrees;
16 use Bio::GeneticRelationships::Individual;
17 use Bio::GeneticRelationships::Pedigree;
19 use CXGN::Pedigree::AddCrossTissueSamples;
21 use CXGN::Trial::Download;
22 use Spreadsheet::WriteExcel;
23 use Spreadsheet::Read;
25 #Needed to update IO::Socket::SSL
28 local $Data::Dumper::Indent = 0;
30 my $f = SGN::Test::Fixture->new();
31 my $schema = $f->bcs_schema;
32 my $phenome_schema = $f->phenome_schema;
34 my $mech = Test::WWW::Mechanize->new;
36 for my $extension ("xls", "xlsx") {
38 # test adding crossing trial
39 $mech->post_ok('http://localhost:3010/brapi/v1/token', [ "username" => "janedoe", "password" => "secretpw", "grant_type" => "password" ]);
40 my $response = decode_json $mech->content;
41 is($response->{'metadata'}->{'status'}->[2]->{'message'}, 'Login Successfull');
42 my $sgn_session_id = $response->{access_token};
43 print STDERR $sgn_session_id . "\n";
45 $mech->post_ok('http://localhost:3010/ajax/cross/add_crossingtrial', [ 'crossingtrial_name' => 'test_crossingtrial', 'crossingtrial_program_id' => 134,
46 'crossingtrial_location' => 'test_location', 'year' => '2017', 'project_description' => 'test description' ]);
48 $response = decode_json $mech->content;
49 is($response->{'success'}, '1');
51 $mech->post_ok('http://localhost:3010/ajax/cross/add_crossingtrial', [ 'crossingtrial_name' => 'test_crossingtrial2', 'crossingtrial_program_id' => 134,
52 'crossingtrial_location' => 'test_location', 'year' => '2018', 'project_description' => 'test description2' ]);
54 $response = decode_json $mech->content;
55 is($response->{'success'}, '1');
57 $mech->post_ok('http://localhost:3010/ajax/cross/add_crossingtrial', [ 'crossingtrial_name' => 'test_crossingtrial_deletion', 'crossingtrial_program_id' => 134,
58 'crossingtrial_location' => 'test_location', 'year' => '2019', 'project_description' => 'test deletion' ]);
60 $response = decode_json $mech->content;
61 is($response->{'success'}, '1');
63 #create populations for testing bulk and bulk_open cross types
64 $mech->post_ok('http://localhost:3010/ajax/population/new', [ "population_name"=> 'test_population_A', "accessions[]"=> ['UG120001', 'UG120002'] ]);
65 $response = decode_json $mech->content;
66 is($response->{'success'}, "Success! Population test_population_A created");
67 my $population_A_id = $response->{'population_id'};
69 $mech->post_ok('http://localhost:3010/ajax/population/new', [ "population_name"=> 'test_population_B', "accessions[]"=> ['UG120003', 'UG120004'] ]);
70 $response = decode_json $mech->content;
71 is($response->{'success'}, "Success! Population test_population_B created");
72 my $population_B_id = $response->{'population_id'};
74 # test adding cross and info
75 my $crossing_trial_rs = $schema->resultset('Project::Project')->find({ name => 'test_crossingtrial' });
76 my $crossing_trial_id = $crossing_trial_rs->project_id();
77 my $female_plot_id = $schema->resultset('Stock::Stock')->find({ name => 'KASESE_TP2013_842' })->stock_id();
78 my $male_plot_id = $schema->resultset('Stock::Stock')->find({ name => 'KASESE_TP2013_1591' })->stock_id();
79 my $cross_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "cross", "stock_type")->cvterm_id();
80 my $cross_combination_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "cross_combination", "stock_property")->cvterm_id();
82 my $before_adding_cross = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
83 my $before_adding_stocks = $schema->resultset("Stock::Stock")->search({})->count();
84 my $before_adding_stockprop = $schema->resultset("Stock::Stockprop")->search({ type_id => $cross_combination_type_id })->count();
85 my $before_adding_stockprop_all = $schema->resultset("Stock::Stockprop")->search({})->count();
86 my $before_adding_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
87 my $before_adding_cross_in_experiment = $schema->resultset("NaturalDiversity::NdExperiment")->search({})->count();
88 my $before_adding_cross_in_experiment_stock = $schema->resultset("NaturalDiversity::NdExperimentStock")->search({})->count();
90 $mech->post_ok('http://localhost:3010/ajax/cross/add_cross', [ 'crossing_trial_id' => $crossing_trial_id, 'cross_name' => 'test_add_cross', 'cross_combination' => 'UG120001xUG120002', 'cross_type' => 'biparental', 'maternal' => 'UG120001', 'paternal' => 'UG120002', 'female_plot' => $female_plot_id, 'male_plot' => $male_plot_id ]);
92 $response = decode_json $mech->content;
93 is($response->{'success'}, '1');
95 my $after_adding_cross = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
96 my $after_adding_stocks = $schema->resultset("Stock::Stock")->search({})->count();
97 my $after_adding_stockprop = $schema->resultset("Stock::Stockprop")->search({ type_id => $cross_combination_type_id })->count();
98 my $after_adding_stockprop_all = $schema->resultset("Stock::Stockprop")->search({})->count();
99 my $after_adding_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
100 my $after_adding_cross_in_experiment = $schema->resultset("NaturalDiversity::NdExperiment")->search({})->count();
101 my $after_adding_cross_in_experiment_stock = $schema->resultset("NaturalDiversity::NdExperimentStock")->search({})->count();
103 is($after_adding_cross, $before_adding_cross + 1);
104 is($after_adding_stocks, $before_adding_stocks + 1);
105 is($after_adding_stockprop, $before_adding_stockprop + 1);
106 is($after_adding_stockprop_all, $before_adding_stockprop_all + 2);
107 is($after_adding_relationship, $before_adding_relationship + 4);
108 is($after_adding_cross_in_experiment, $before_adding_cross_in_experiment + 1);
109 is($after_adding_cross_in_experiment_stock, $before_adding_cross_in_experiment_stock + 1);
111 #test adding a cross with backcross cross type
112 my $crossing_trial2_rs = $schema->resultset('Project::Project')->find({ name => 'test_crossingtrial2' });
113 my $crossing_trial2_id = $crossing_trial2_rs->project_id();
115 $mech->post_ok('http://localhost:3010/ajax/cross/add_cross', [ 'crossing_trial_id' => $crossing_trial2_id, 'cross_name' => 'test_backcross1', 'cross_combination' => 'test_add_crossxUG120001', 'cross_type' => 'backcross', 'maternal' => 'test_add_cross', 'paternal' => 'UG120001' ]);
117 $response = decode_json $mech->content;
118 is($response->{'success'}, '1');
120 #test uploading crosses with backcross cross type
121 my $file = $f->config->{basepath} . "/t/data/cross/backcross_upload.$extension";
122 my $ua = LWP::UserAgent->new;
123 $response = $ua->post(
124 'http://localhost:3010/ajax/cross/upload_crosses_file',
125 Content_Type => 'form-data',
127 "xls_crosses_simple_file" => [
129 "backcross_upload.$extension",
130 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
132 "upload_crosses_crossing_experiment_id" => $crossing_trial2_id,
133 "sgn_session_id" => $sgn_session_id
136 ok($response->is_success);
137 my $message = $response->decoded_content;
138 my $message_hash = decode_json $message;
139 is_deeply($message_hash, { 'success' => 1 });
141 # test uploading crosses with only accession info
143 my $before_uploading_cross_a = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
144 my $before_uploading_stocks_a = $schema->resultset("Stock::Stock")->search({})->count();
145 my $before_uploading_relationship_a = $schema->resultset("Stock::StockRelationship")->search({})->count();
147 my $file = $f->config->{basepath} . "/t/data/cross/crosses_simple_upload.$extension";
148 my $ua = LWP::UserAgent->new;
149 $response = $ua->post(
150 'http://localhost:3010/ajax/cross/upload_crosses_file',
151 Content_Type => 'form-data',
153 "xls_crosses_simple_file" => [
155 "crosses_simple_upload.$extension",
156 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
158 "upload_crosses_crossing_experiment_id" => $crossing_trial2_id,
159 "sgn_session_id" => $sgn_session_id
162 ok($response->is_success);
163 my $message = $response->decoded_content;
164 my $message_hash = decode_json $message;
165 is_deeply($message_hash, { 'success' => 1 });
167 my $after_uploading_cross_a = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
168 my $after_uploading_stocks_a = $schema->resultset("Stock::Stock")->search({})->count();
169 my $after_uploading_relationship_a = $schema->resultset("Stock::StockRelationship")->search({})->count();
171 is($after_uploading_cross_a, $before_uploading_cross_a + 4);
172 is($after_uploading_stocks_a, $before_uploading_stocks_a + 4);
173 is($after_uploading_relationship_a, $before_uploading_relationship_a + 8);
175 # test uploading crosses with plots
176 my $female_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "female_parent", "stock_relationship")->cvterm_id();
177 my $male_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "male_parent", "stock_relationship")->cvterm_id();
178 my $female_plot_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "female_plot_of", "stock_relationship")->cvterm_id();
179 my $male_plot_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "male_plot_of", "stock_relationship")->cvterm_id();
181 my $before_uploading_relationship_all = $schema->resultset("Stock::StockRelationship")->search({})->count();
182 my $before_uploading_relationship_female = $schema->resultset("Stock::StockRelationship")->search({ type_id => $female_type_id })->count();
183 my $before_uploading_relationship_male = $schema->resultset("Stock::StockRelationship")->search({ type_id => $male_type_id })->count();
184 my $before_uploading_relationship_femaleplot = $schema->resultset("Stock::StockRelationship")->search({ type_id => $female_plot_type_id })->count();
185 my $before_uploading_relationship_maleplot = $schema->resultset("Stock::StockRelationship")->search({ type_id => $male_plot_type_id })->count();
187 $file = $f->config->{basepath} . "/t/data/cross/crosses_plots_upload.$extension";
188 $ua = LWP::UserAgent->new;
189 $response = $ua->post(
190 'http://localhost:3010/ajax/cross/upload_crosses_file',
191 Content_Type => 'form-data',
193 "xls_crosses_plots_file" => [
195 "crosses_plots_upload.$extension",
196 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
198 "upload_crosses_crossing_experiment_id" => $crossing_trial2_id,
199 "sgn_session_id" => $sgn_session_id
202 ok($response->is_success);
203 $message = $response->decoded_content;
204 $message_hash = decode_json $message;
205 is_deeply($message_hash, { 'success' => 1 });
207 my $after_uploading_relationship_all = $schema->resultset("Stock::StockRelationship")->search({})->count();
208 my $after_uploading_relationship_female = $schema->resultset("Stock::StockRelationship")->search({ type_id => $female_type_id })->count();
209 my $after_uploading_relationship_male = $schema->resultset("Stock::StockRelationship")->search({ type_id => $male_type_id })->count();
210 my $after_uploading_relationship_femaleplot = $schema->resultset("Stock::StockRelationship")->search({ type_id => $female_plot_type_id })->count();
211 my $after_uploading_relationship_maleplot = $schema->resultset("Stock::StockRelationship")->search({ type_id => $male_plot_type_id })->count();
213 is($after_uploading_relationship_all, $before_uploading_relationship_all + 8);
214 is($after_uploading_relationship_female, $before_uploading_relationship_female + 2);
215 is($after_uploading_relationship_male, $before_uploading_relationship_male + 2);
216 is($after_uploading_relationship_femaleplot, $before_uploading_relationship_femaleplot + 2);
217 is($after_uploading_relationship_maleplot, $before_uploading_relationship_maleplot + 2);
219 #add plants for testing (a total of 38 entries)
220 my $trial = CXGN::Trial->new({ bcs_schema => $schema, trial_id => 165 });
221 $trial->create_plant_entities(2);
223 # test uploading crosses with plants
224 my $female_plant_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "female_parent", "stock_relationship")->cvterm_id();
225 my $male_plant_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "male_parent", "stock_relationship")->cvterm_id();
227 my $before_uploading_relationship_femaleplant = $schema->resultset("Stock::StockRelationship")->search({ type_id => $female_plant_type_id })->count();
228 my $before_uploading_relationship_maleplant = $schema->resultset("Stock::StockRelationship")->search({ type_id => $male_plant_type_id })->count();
230 $file = $f->config->{basepath} . "/t/data/cross/crosses_plants_upload.$extension";
231 $ua = LWP::UserAgent->new;
232 $response = $ua->post(
233 'http://localhost:3010/ajax/cross/upload_crosses_file',
234 Content_Type => 'form-data',
236 "xls_crosses_plants_file" => [
238 "crosses_plants_upload.$extension",
239 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
241 "upload_crosses_crossing_experiment_id" => $crossing_trial2_id,
242 "sgn_session_id" => $sgn_session_id
245 ok($response->is_success);
246 $message = $response->decoded_content;
247 $message_hash = decode_json $message;
248 is_deeply($message_hash, { 'success' => 1 });
250 my $after_uploading_relationship_femaleplant = $schema->resultset("Stock::StockRelationship")->search({ type_id => $female_plant_type_id })->count();
251 my $after_uploading_relationship_maleplant = $schema->resultset("Stock::StockRelationship")->search({ type_id => $male_plant_type_id })->count();
253 is($after_uploading_relationship_femaleplant, $before_uploading_relationship_femaleplant + 2);
254 is($after_uploading_relationship_maleplant, $before_uploading_relationship_maleplant + 2);
256 # test uploading crosses with simplified parent info format
257 my $before_uploading_cross_simplified_info = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
258 my $before_uploading_stocks_simplified_info = $schema->resultset("Stock::Stock")->search({})->count();
259 my $before_uploading_relationship_simplified_info = $schema->resultset("Stock::StockRelationship")->search({})->count();
261 my $file = $f->config->{basepath} . "/t/data/cross/crosses_simplified_parents_upload.$extension";
262 my $ua = LWP::UserAgent->new;
263 $response = $ua->post(
264 'http://localhost:3010/ajax/cross/upload_crosses_file',
265 Content_Type => 'form-data',
267 "xls_crosses_simplified_parents_file" => [
269 "crosses_simplified_parents_upload.$extension",
270 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
272 "upload_crosses_crossing_experiment_id" => $crossing_trial2_id,
273 "sgn_session_id" => $sgn_session_id
276 ok($response->is_success);
277 my $message = $response->decoded_content;
278 my $message_hash = decode_json $message;
279 is_deeply($message_hash, { 'success' => 1 });
281 my $after_uploading_cross_simplified_info = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
282 my $after_uploading_stocks_simplified_info = $schema->resultset("Stock::Stock")->search({})->count();
283 my $after_uploading_relationship_simplified_info = $schema->resultset("Stock::StockRelationship")->search({})->count();
285 is($after_uploading_cross_simplified_info, $before_uploading_cross_simplified_info + 4);
286 is($after_uploading_stocks_simplified_info, $before_uploading_stocks_simplified_info + 4);
287 is($after_uploading_relationship_simplified_info, $before_uploading_relationship_simplified_info + 13);
289 # test retrieving crosses in a trial
290 my $test_add_cross_rs = $schema->resultset('Stock::Stock')->find({ name => 'test_add_cross' });
291 my $test_add_cross_id = $test_add_cross_rs->stock_id();
292 my $UG120001_id = $schema->resultset('Stock::Stock')->find({ name => 'UG120001' })->stock_id();
293 my $UG120002_id = $schema->resultset('Stock::Stock')->find({ name => 'UG120002' })->stock_id();
295 $mech->post_ok("http://localhost:3010/ajax/breeders/trial/$crossing_trial_id/crosses_and_details_in_trial");
296 $response = decode_json $mech->content;
298 is_deeply($response, { 'data' => [ {
299 cross_id => $test_add_cross_id,
300 cross_name => 'test_add_cross',
301 cross_combination => 'UG120001xUG120002',
302 cross_type => 'biparental',
303 female_parent_id => $UG120001_id,
304 female_parent_name => 'UG120001',
305 female_ploidy_level => undef,
306 male_parent_id => $UG120002_id,
307 male_parent_name => 'UG120002',
308 male_ploidy_level => undef,
309 female_plot_id => $female_plot_id,
310 female_plot_name => 'KASESE_TP2013_842',
311 male_plot_id => $male_plot_id,
312 male_plot_name => 'KASESE_TP2013_1591',
313 female_plant_id => undef,
314 female_plant_name => undef,
315 male_plant_id => undef,
316 male_plant_name => undef
317 } ] }, 'crosses in a trial');
319 # test uploading 6 progenies with new accessions
320 my $offspring_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "offspring_of", "stock_relationship")->cvterm_id();
321 my $accession_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "accession", "stock_type")->cvterm_id();
323 my $before_add_progenies_stock = $schema->resultset("Stock::Stock")->search({})->count();
324 my $before_add_progenies_accession = $schema->resultset("Stock::Stock")->search({ type_id => $accession_type_id })->count();
325 my $before_add_progenies_relationship_all = $schema->resultset("Stock::StockRelationship")->search({})->count();
326 my $before_add_progenies_offspring = $schema->resultset("Stock::StockRelationship")->search({ type_id => $offspring_type_id })->count();
328 $file = $f->config->{basepath} . "/t/data/cross/update_progenies.$extension";
329 $ua = LWP::UserAgent->new;
330 $response = $ua->post(
331 'http://localhost:3010/ajax/cross/upload_progenies',
332 Content_Type => 'form-data',
334 progenies_new_upload_file => [
336 "update_progenies.$extension",
337 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
339 "sgn_session_id" => $sgn_session_id
342 ok($response->is_success);
343 $message = $response->decoded_content;
344 $message_hash = decode_json $message;
345 is_deeply($message_hash, { 'success' => 1 });
347 my $after_add_progenies_stock = $schema->resultset("Stock::Stock")->search({})->count();
348 my $after_add_progenies_accession = $schema->resultset("Stock::Stock")->search({ type_id => $accession_type_id })->count();
349 my $after_add_progenies_relationship_all = $schema->resultset("Stock::StockRelationship")->search({})->count();
350 my $after_add_progenies_offspring = $schema->resultset("Stock::StockRelationship")->search({ type_id => $offspring_type_id })->count();
352 is($after_add_progenies_stock, $before_add_progenies_stock + 6);
353 is($after_add_progenies_accession, $before_add_progenies_accession + 6);
354 is($after_add_progenies_relationship_all, $before_add_progenies_relationship_all + 18);
355 is($after_add_progenies_offspring, $before_add_progenies_offspring + 6);
358 #validate uploading 4 progenies using existing accessions (without previously stored pedigrees)
359 $file = $f->config->{basepath} . "/t/data/cross/update_progenies_existing_accessions.$extension";
360 $ua = LWP::UserAgent->new;
361 $response = $ua->post(
362 'http://localhost:3010/ajax/cross/validate_upload_existing_progenies',
363 Content_Type => 'form-data',
365 progenies_exist_upload_file => [
367 "update_progenies_existing_accessions.$extension",
368 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
370 "sgn_session_id" => $sgn_session_id
374 ok($response->is_success);
375 $message = $response->decoded_content;
376 $message_hash = decode_json $message;
377 my %response_hash = %$message_hash;
378 my $message1 = $response_hash{'error_string'};
379 my $message2 = $response_hash{'existing_pedigrees'};
384 #test storing 4 progenies using existing accessions (without previously stored pedigrees)
385 my $cross_name = 'test_add_cross';
386 my @existing_accessions = qw(XG120015 XG120021 XG120068 XG120073);
387 my $overwrite_pedigrees = 'true';
388 my $adding_progenies = CXGN::Pedigree::AddProgeniesExistingAccessions->new({
389 chado_schema => $schema,
390 cross_name => $cross_name,
391 progeny_names => \@existing_accessions,
394 ok(my $return = $adding_progenies->add_progenies_existing_accessions($overwrite_pedigrees));
395 ok(!exists($return->{error}));
397 my $after_add_progenies_exist_stock = $schema->resultset("Stock::Stock")->search({})->count();
398 my $after_add_progenies_exist_accession = $schema->resultset("Stock::Stock")->search({ type_id => $accession_type_id })->count();
399 my $after_add_progenies_exist_relationship_all = $schema->resultset("Stock::StockRelationship")->search({})->count();
400 my $after_add_progenies_exist_offspring = $schema->resultset("Stock::StockRelationship")->search({ type_id => $offspring_type_id })->count();
402 is($after_add_progenies_exist_stock, $after_add_progenies_stock);
403 is($after_add_progenies_exist_accession, $after_add_progenies_accession);
404 is($after_add_progenies_exist_relationship_all, $after_add_progenies_relationship_all + 12);
405 is($after_add_progenies_exist_offspring, $after_add_progenies_offspring + 4);
408 #validate uploading 2 progenies using existing accessions (accessions have previously stored pedigrees)
409 #adding pedigrees for testing
410 my $female_parent = Bio::GeneticRelationships::Individual->new(name => 'TestAccession1');
411 my $male_parent = Bio::GeneticRelationships::Individual->new(name => 'TestAccession2');
412 my $pedigree1 = Bio::GeneticRelationships::Pedigree->new(name => 'TestAccession3', cross_type => 'biparental');
413 $pedigree1->set_female_parent($female_parent);
414 $pedigree1->set_male_parent($male_parent);
416 my $pedigree2 = Bio::GeneticRelationships::Pedigree->new(name => 'TestAccession4', cross_type => 'biparental');
417 $pedigree2->set_female_parent($female_parent);
418 $pedigree2->set_male_parent($male_parent);
420 my @pedigrees = ($pedigree1, $pedigree2);
421 my $add_pedigrees = CXGN::Pedigree::AddPedigrees->new(schema => $schema, pedigrees => \@pedigrees);
422 my $pedigree_return = $add_pedigrees->add_pedigrees();
424 my $after_add_pedigrees_relationship_all = $schema->resultset("Stock::StockRelationship")->search({})->count();
426 $file = $f->config->{basepath} . "/t/data/cross/update_progenies_overwrite_pedigrees.$extension";
427 $ua = LWP::UserAgent->new;
428 $response = $ua->post(
429 'http://localhost:3010/ajax/cross/validate_upload_existing_progenies',
430 Content_Type => 'form-data',
432 progenies_exist_upload_file => [
434 "update_progenies_overwrite_pedigrees.$extension",
435 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
437 "sgn_session_id" => $sgn_session_id
441 ok($response->is_success);
442 $message = $response->decoded_content;
443 $message_hash = decode_json $message;
444 %response_hash = %$message_hash;
445 my $message3 = $response_hash{'error_string'};
446 my $message4 = $response_hash{'existing_pedigrees'};
451 #test storing 2 progenies using existing accessions (accessions have previously stored pedigrees)
452 $cross_name = 'test_add_cross';
453 @existing_accessions = qw(TestAccession3 TestAccession4);
454 $overwrite_pedigrees = 'true';
455 $adding_progenies = CXGN::Pedigree::AddProgeniesExistingAccessions->new({
456 chado_schema => $schema,
457 cross_name => $cross_name,
458 progeny_names => \@existing_accessions,
461 ok($return = $adding_progenies->add_progenies_existing_accessions($overwrite_pedigrees));
462 ok(!exists($return->{error}));
464 my $after_add_progenies_overwrite_stock = $schema->resultset("Stock::Stock")->search({})->count();
465 my $after_add_progenies_overwrite_accession = $schema->resultset("Stock::Stock")->search({ type_id => $accession_type_id })->count();
466 my $after_add_progenies_overwrite_relationship_all = $schema->resultset("Stock::StockRelationship")->search({})->count();
467 my $after_add_progenies_overwrite_offspring = $schema->resultset("Stock::StockRelationship")->search({ type_id => $offspring_type_id })->count();
469 is($after_add_progenies_overwrite_stock, $after_add_progenies_exist_stock);
470 is($after_add_progenies_overwrite_accession, $after_add_progenies_exist_accession);
471 is($after_add_progenies_overwrite_relationship_all, $after_add_pedigrees_relationship_all + 2);
472 is($after_add_progenies_overwrite_offspring, $after_add_progenies_exist_offspring + 2);
475 # test updating cross info by uploading
476 my $before_updating_info_stocks = $schema->resultset("Stock::Stock")->search({})->count();
477 my $before_updating_info_stockprop = $schema->resultset("Stock::Stockprop")->search({})->count();
478 my $before_updating_info_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
480 $file = $f->config->{basepath} . "/t/data/cross/update_crossinfo.$extension";
481 $ua = LWP::UserAgent->new;
482 $response = $ua->post(
483 'http://localhost:3010/ajax/cross/upload_info',
484 Content_Type => 'form-data',
486 crossinfo_upload_file => [
488 "update_crossinfo.$extension",
489 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
491 "sgn_session_id" => $sgn_session_id
494 ok($response->is_success);
495 $message = $response->decoded_content;
496 $message_hash = decode_json $message;
497 is_deeply($message_hash, { 'success' => 1 });
499 my $after_updating_info_stocks = $schema->resultset("Stock::Stock")->search({})->count();
500 my $after_updating_info_stockprop = $schema->resultset("Stock::Stockprop")->search({})->count();
501 my $after_updating_info_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
503 is($after_updating_info_stocks, $before_updating_info_stocks);
504 is($after_updating_info_stockprop, $before_updating_info_stockprop + 3);
505 is($after_updating_info_relationship, $before_updating_info_relationship);
507 # test uploading additional parent info
508 $file = $f->config->{basepath} . "/t/data/cross/upload_additional_info.$extension";
509 $ua = LWP::UserAgent->new;
510 $response = $ua->post(
511 'http://localhost:3010/ajax/cross/upload_info',
512 Content_Type => 'form-data',
514 additional_info_upload_file => [
516 "upload_additional_info.$extension",
517 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
519 "sgn_session_id" => $sgn_session_id
522 ok($response->is_success);
523 $message = $response->decoded_content;
524 $message_hash = decode_json $message;
525 is_deeply($message_hash, { 'success' => 1 });
527 my $after_upload_additional_info_stocks = $schema->resultset("Stock::Stock")->search({})->count();
528 my $after_upload_additional_info_stockprop = $schema->resultset("Stock::Stockprop")->search({})->count();
529 my $after_upload_additional_info_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
531 # note:added 3 more rows in stockprop table after uploading field crossing activities, then 3 more rows in stockprop table after uploading parent additional info
532 is($after_upload_additional_info_stocks, $before_updating_info_stocks);
533 is($after_upload_additional_info_stockprop, $before_updating_info_stockprop + 6);
534 is($after_upload_additional_info_relationship, $before_updating_info_relationship);
536 # test retrieving crossing experimental info after updating
537 $mech->post_ok("http://localhost:3010/ajax/breeders/trial/$crossing_trial_id/cross_properties_trial");
538 $response = decode_json $mech->content;
540 is_deeply($response, { 'data' => [
541 [ qq{<a href = "/cross/$test_add_cross_id">test_add_cross</a>}, 'UG120001xUG120002', "10", "2017/02/02", "10", "50", undef, undef ]
542 ] }, 'crossing experiment info');
545 # test uploading family names
546 my $family_name_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "family_name", "stock_type")->cvterm_id();
547 my $cross_member_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'cross_member_of', 'stock_relationship')->cvterm_id();
548 my $family_female_parent_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'family_female_parent_of', 'stock_relationship')->cvterm_id();
549 my $family_male_parent_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'family_male_parent_of', 'stock_relationship')->cvterm_id();
550 my $family_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, "family_type", "stock_property")->cvterm_id();
552 my $before_family_name_stocks = $schema->resultset("Stock::Stock")->search({})->count();
553 my $before_add_family_name = $schema->resultset("Stock::Stock")->search({ type_id => $family_name_type_id })->count();
554 my $before_upload_family_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
555 my $before_upload_family_member = $schema->resultset("Stock::StockRelationship")->search({ type_id => $cross_member_of_cvterm_id })->count();
556 my $before_upload_family_female = $schema->resultset("Stock::StockRelationship")->search({ type_id => $family_female_parent_cvterm_id })->count();
557 my $before_upload_family_male = $schema->resultset("Stock::StockRelationship")->search({ type_id => $family_male_parent_cvterm_id })->count();
558 my $before_upload_family_stockprop = $schema->resultset("Stock::Stockprop")->search({ type_id => $family_type_cvterm_id })->count();
560 $file = $f->config->{basepath} . "/t/data/cross/family_name_upload.$extension";
561 $ua = LWP::UserAgent->new;
562 $response = $ua->post(
563 'http://localhost:3010/ajax/cross/upload_family_names',
564 Content_Type => 'form-data',
566 same_parents_file => [
568 "family_name_upload.$extension",
569 Content_Type => ($extension eq "xls") ? 'application/vnd.ms-excel' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
571 "sgn_session_id" => $sgn_session_id
574 ok($response->is_success);
575 $message = $response->decoded_content;
576 $message_hash = decode_json $message;
577 is_deeply($message_hash, { 'success' => 1 });
579 my $after_family_name_stocks = $schema->resultset("Stock::Stock")->search({})->count();
580 my $after_add_family_name = $schema->resultset("Stock::Stock")->search({ type_id => $family_name_type_id })->count();
581 my $after_upload_family_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
582 my $after_upload_family_member = $schema->resultset("Stock::StockRelationship")->search({ type_id => $cross_member_of_cvterm_id })->count();
583 my $after_upload_family_female = $schema->resultset("Stock::StockRelationship")->search({ type_id => $family_female_parent_cvterm_id })->count();
584 my $after_upload_family_male = $schema->resultset("Stock::StockRelationship")->search({ type_id => $family_male_parent_cvterm_id })->count();
585 my $after_upload_family_stockprop = $schema->resultset("Stock::Stockprop")->search({ type_id => $family_type_cvterm_id })->count();
587 is($after_family_name_stocks, $before_family_name_stocks + 2);
588 is($after_add_family_name, $before_add_family_name + 2);
589 is($after_upload_family_relationship, $before_upload_family_relationship + 8);
590 is($after_upload_family_member, $before_upload_family_member + 4);
591 is($after_upload_family_female, $before_upload_family_female + 2);
592 is($after_upload_family_male, $before_upload_family_male + 2);
593 is($after_upload_family_stockprop, $before_upload_family_stockprop + 2);
595 #test retrieving family name info
596 my $family_stock_rs = $schema->resultset("Stock::Stock")->find({ name => 'family1x2', type_id => $family_name_type_id });
597 my $family_stock_id = $family_stock_rs->stock_id();
598 my $family_type = $schema->resultset("Stock::Stockprop")->find({ stock_id => $family_stock_id, type_id => $family_type_cvterm_id })->value();
599 is($family_type, 'same_parents');
600 #print STDERR "FAMILY ID =".Dumper($family_stock_id)."\n";
601 $mech->post_ok('http://localhost:3010/ajax/family/members/' . $family_stock_id);
602 $response = decode_json $mech->content;
603 my %data = %$response;
604 my $members = $data{data};
605 my $number_of_members = @$members;
606 is($number_of_members, 2);
608 $mech->post_ok('http://localhost:3010/ajax/family/all_progenies/' . $family_stock_id);
609 $response = decode_json $mech->content;
610 my %data = %$response;
611 my $progenies = $data{data};
612 my $number_of_progenies = @$progenies;
613 is($number_of_progenies, 2);
615 #test adding tissue culture samples
616 my $before_adding_samples_stockprop = $schema->resultset("Stock::Stockprop")->search({})->count();
618 my $cross_unique_id = 'test_add_cross';
619 my $sample_type = 'Embryo IDs';
620 my @ids = qw(test_embryo_1 test_embryo_2 test_embryo_3 test_embryo_4);
621 my $cross_add_samples = CXGN::Pedigree::AddCrossTissueSamples->new({
622 chado_schema => $schema,
623 cross_name => $cross_unique_id,
628 ok(my $return = $cross_add_samples->add_samples());
630 my $after_adding_samples_stockprop = $schema->resultset("Stock::Stockprop")->search({})->count();
631 is($after_adding_samples_stockprop, $before_adding_samples_stockprop + 1);
633 #test retrieving tissue culture samples
634 my $cross_id = $schema->resultset('Stock::Stock')->find({ name => 'test_add_cross' })->stock_id();
635 my $cross_samples_obj = CXGN::Cross->new({ schema => $schema, cross_stock_id => $cross_id });
636 my $cross_sample_data = $cross_samples_obj->get_cross_tissue_culture_samples();
637 my $embryo_ids_ref = $cross_sample_data->{'Embryo IDs'};
638 my $number_of_embryo_samples = @$embryo_ids_ref;
639 is($number_of_embryo_samples, 4);
642 #test search crosses using female parent
643 $mech->post_ok('http://localhost:3010/ajax/search/crosses', [ 'female_parent' => 'TMEB419' ]);
644 $response = decode_json $mech->content;
645 my %data1 = %$response;
646 my $result1 = $data1{data};
647 my $number_of_result1 = @$result1;
648 is($number_of_result1, 3);
650 #test search crosses using both female and male parents
651 $mech->post_ok('http://localhost:3010/ajax/search/crosses', [ 'female_parent' => 'TMEB419', 'male_parent' => 'TMEB693' ]);
652 $response = decode_json $mech->content;
653 my %data2 = %$response;
654 my $result2 = $data2{data};
655 my $number_of_result2 = @$result2;
656 is($number_of_result2, 2);
658 #test search crosses using male parent
659 $mech->post_ok('http://localhost:3010/ajax/search/crosses', [ 'male_parent' => 'TMEB693' ]);
660 $response = decode_json $mech->content;
661 my %data3 = %$response;
662 my $result3 = $data3{data};
663 my $number_of_result3 = @$result3;
664 is($number_of_result3, 2);
666 #test crossing experiment download
667 my @cross_properties = ("Tag Number", "Pollination Date", "Number of Bags", "Number of Flowers", "Number of Fruits", "Number of Seeds");
668 my $tempfile = "/tmp/test_download_crossing_experiment.$extension";
669 my $format = 'CrossingExperimentXLS';
670 my $create_spreadsheet = CXGN::Trial::Download->new({
671 bcs_schema => $f->bcs_schema,
672 trial_list => [ $crossing_trial2_id ],
673 filename => $tempfile,
675 field_crossing_data_order => \@cross_properties
678 $create_spreadsheet->download();
679 my $contents = ReadData $tempfile;
681 my $columns = $contents->[1]->{'cell'};
682 my @column_array = @$columns;
683 my $number_of_columns = scalar @column_array;
684 print STDERR "COLUMNS =".Dumper ($columns)."\n";
686 ok(scalar($number_of_columns) == 22, "check number of columns.");
687 is_deeply($contents->[1]->{'cell'}->[1], [
693 'test_cross_upload1',
694 'test_cross_upload2',
696 'test_bulk_open_cross',
697 'test_cross_upload3',
698 'test_cross_upload4',
699 'test_cross_upload5',
700 'test_cross_upload6',
701 'test_cross_simplified_parents_1',
702 'test_cross_simplified_parents_2',
703 'test_cross_simplified_parents_3',
704 'test_cross_simplified_parents_4'
705 ], "check column 1");
707 is_deeply($contents->[1]->{'cell'}->[3], [
725 ], "check column 3");
727 is_deeply($contents->[1]->{'cell'}->[4], [
745 ], "check column 4");
748 # test retrieving all cross entries
749 my $crosses = CXGN::Cross->new({ schema => $schema });
750 my $result = $crosses->get_all_cross_entries();
751 my @all_cross_entries = @$result;
752 my $first_cross = $all_cross_entries[0];
753 is(scalar @all_cross_entries, 16);
754 is($first_cross->[1], 'test_add_cross');
755 is($first_cross->[2], 'biparental');
756 is($first_cross->[4], 'UG120001');
757 is($first_cross->[8], 'UG120002');
758 is($first_cross->[11], '2017/02/02');
759 is($first_cross->[13], 8);
760 is($first_cross->[15], 'test_crossingtrial');
763 my $before_deleting_crosses = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
764 my $before_deleting_accessions = $schema->resultset("Stock::Stock")->search({ type_id => $accession_type_id })->count();
765 my $before_deleting_stocks = $schema->resultset("Stock::Stock")->search({})->count();
766 my $before_deleting_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
767 my $experiment_before_deleting_cross = $schema->resultset("NaturalDiversity::NdExperiment")->search({})->count();
768 my $experiment_stock_before_deleting_cross = $schema->resultset("NaturalDiversity::NdExperimentStock")->search({})->count();
770 # test_cross_upload1 has 2 progenies and has family name
771 my $deleting_cross_id = $schema->resultset("Stock::Stock")->find({ name => 'test_cross_upload1' })->stock_id;
772 $mech->post_ok('http://localhost:3010/ajax/cross/delete', [ 'cross_id' => $deleting_cross_id ]);
773 $response = decode_json $mech->content;
774 is($response->{'success'}, '1');
776 my $after_deleting_crosses = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
777 my $after_deleting_accessions = $schema->resultset("Stock::Stock")->search({ type_id => $accession_type_id })->count();
778 my $after_deleting_stocks = $schema->resultset("Stock::Stock")->search({})->count();
779 my $after_deleting_relationship = $schema->resultset("Stock::StockRelationship")->search({})->count();
780 my $experiment_after_deleting_cross = $schema->resultset("NaturalDiversity::NdExperiment")->search({})->count();
781 my $experiment_stock_after_deleting_cross = $schema->resultset("NaturalDiversity::NdExperimentStock")->search({})->count();
783 is($after_deleting_crosses, $before_deleting_crosses - 1);
784 is($after_deleting_accessions, $before_deleting_accessions - 2);
785 is($after_deleting_stocks, $before_deleting_stocks - 3);
786 is($after_deleting_relationship, $before_deleting_relationship - 9);
787 is($experiment_after_deleting_cross, $experiment_before_deleting_cross - 1);
788 is($experiment_stock_after_deleting_cross, $experiment_stock_before_deleting_cross - 1);
790 # test deleting empty crossing experiment
791 my $before_deleting_empty_experiment = $schema->resultset("Project::Project")->search({})->count();
793 my $crossing_experiment_id = $schema->resultset("Project::Project")->find({ name => 'test_crossingtrial_deletion' })->project_id;
794 $mech->get_ok('http://localhost:3010/ajax/breeders/trial/' . $crossing_experiment_id . '/delete/crossing_experiment');
795 $response = decode_json $mech->content;
796 is($response->{'success'}, '1');
798 my $after_deleting_empty_experiment = $schema->resultset("Project::Project")->search({})->count();
800 is($after_deleting_empty_experiment, $before_deleting_empty_experiment - 1);
802 # test deleting crossing experiment with crosses
803 my $before_deleting_experiment = $schema->resultset("Project::Project")->search({})->count();
805 my $crossing_experiment_id_2 = $schema->resultset("Project::Project")->find({ name => 'test_crossingtrial' })->project_id;
806 $mech->get_ok('http://localhost:3010/ajax/breeders/trial/' . $crossing_experiment_id_2 . '/delete/crossing_experiment');
807 $response = decode_json $mech->content;
808 ok($response->{'error'});
810 my $after_deleting_experiment = $schema->resultset("Project::Project")->search({})->count();
812 is($after_deleting_experiment, $before_deleting_experiment);
814 #test deleting all crosses in test_crossingtrial and test_crossingtrial2
815 $mech->get_ok('http://localhost:3010/ajax/breeders/trial/' . $crossing_trial2_id . '/delete_all_crosses_in_crossingtrial');
816 $mech->get_ok('http://localhost:3010/ajax/breeders/trial/' . $crossing_trial_id . '/delete_all_crosses_in_crossingtrial');
818 my $after_delete_all_crosses = $schema->resultset("Stock::Stock")->search({ type_id => $cross_type_id })->count();
819 my $after_delete_all_crosses_in_experiment = $schema->resultset("NaturalDiversity::NdExperiment")->search({})->count();
820 my $after_delete_all_crosses_in_experiment_stock = $schema->resultset("NaturalDiversity::NdExperimentStock")->search({})->count();
821 my $stocks_after_delete_all_crosses = $schema->resultset("Stock::Stock")->search({})->count();
823 is($after_delete_all_crosses, $before_adding_cross + 1); #one cross cannot be deleted because progenies have associated data
824 is($after_delete_all_crosses_in_experiment, $before_adding_cross_in_experiment + 1); #one cross cannot be deleted because progenies have associated data
826 # nd_experiment_stock has 38 more rows after adding plants for testing uploading crosses with plant info
827 is($after_delete_all_crosses_in_experiment_stock, $before_adding_cross_in_experiment_stock + 39);
829 # stock table has 43 more rows after adding family names and plants, one cross with two new accessions cannot be deleted
830 is($stocks_after_delete_all_crosses, $before_adding_stocks + 43);
832 # remove added crossing trials after test so that they don't affect downstream tests
833 my $project_owner_row_1 = $phenome_schema->resultset('ProjectOwner')->find({ project_id => $crossing_trial_rs->project_id() });
834 $project_owner_row_1->delete();
835 $crossing_trial_rs->delete();
837 my $project_owner_row_2 = $phenome_schema->resultset('ProjectOwner')->find({ project_id => $crossing_trial2_rs->project_id() });
838 $project_owner_row_2->delete();
839 $crossing_trial2_rs->delete();