Sanify MC test and correct the plan
[dbsrgits/DBIx-Class.git] / t / 96multi_create.t
1 use strict;
2 use warnings;
3
4 use Test::More;
5 use Test::Exception;
6 use lib qw(t/lib);
7 use DBICTest;
8
9 sub mc_diag { diag (@_) if $ENV{DBIC_MULTICREATE_DEBUG} };
10
11 plan tests => 84;
12
13 my $schema = DBICTest->init_schema();
14
15 mc_diag '* simple create + parent (the stuff $rs belongs_to)';
16 eval {
17   my $cd = $schema->resultset('CD')->create({
18     artist => { 
19       name => 'Fred Bloggs' 
20     },
21     title => 'Some CD',
22     year => 1996
23   });
24
25   isa_ok($cd, 'DBICTest::CD', 'Created CD object');
26   isa_ok($cd->artist, 'DBICTest::Artist', 'Created related Artist');
27   is($cd->artist->name, 'Fred Bloggs', 'Artist created correctly');
28 };
29 diag $@ if $@;
30
31 mc_diag '* same as above but the child and parent have no values, except for an explicit parent pk';
32 eval {
33   my $bm_rs = $schema->resultset('Bookmark');
34   my $bookmark = $bm_rs->create({
35     link => {
36       id => 66,
37     },
38   });
39
40   isa_ok($bookmark, 'DBICTest::Bookmark', 'Created Bookrmark object');
41   isa_ok($bookmark->link, 'DBICTest::Link', 'Created related Link');
42   is (
43     $bm_rs->search (
44       { 'link.title' => $bookmark->link->title },
45       { join => 'link' },
46     )->count,
47     1,
48     'Bookmark and link made it to the DB',
49   );
50 };
51 diag $@ if $@;
52
53 mc_diag '* create over > 1 levels of has_many create (A => { has_many => { B => has_many => C } } )';
54 eval {
55   my $artist = $schema->resultset('Artist')->first;
56   my $cd = $artist->create_related (cds => {
57     title => 'Music to code by',
58     year => 2007,
59     tags => [
60       { 'tag' => 'rock' },
61     ],
62   });
63
64   isa_ok($cd, 'DBICTest::CD', 'Created CD');
65   is($cd->title, 'Music to code by', 'CD created correctly');
66   is($cd->tags->count, 1, 'One tag created for CD');
67   is($cd->tags->first->tag, 'rock', 'Tag created correctly');
68
69 };
70 diag $@ if $@;
71
72 throws_ok (
73   sub {
74     # Create via update - add a new CD <--- THIS SHOULD HAVE NEVER WORKED!
75     $schema->resultset('Artist')->first->update({
76       cds => [
77         { title => 'Yet another CD',
78           year => 2006,
79         },
80       ],
81     });
82   },
83   qr/Recursive update is not supported over relationships of type multi/,
84   'create via update of multi relationships throws an exception'
85 );
86
87 mc_diag '* Create m2m while originating in the linker table';
88 eval {
89   my $artist = $schema->resultset('Artist')->first;
90   my $c2p = $schema->resultset('CD_to_Producer')->create ({
91     cd => {
92       artist => $artist,
93       title => 'Bad investment',
94       year => 2008,
95       tracks => [
96         { title => 'Just buy' },
97         { title => 'Why did we do it' },
98         { title => 'Burn baby burn' },
99       ],
100     },
101     producer => {
102       name => 'Lehman Bros.',
103     },
104   });
105
106   isa_ok ($c2p, 'DBICTest::CD_to_Producer', 'Linker object created');
107   my $prod = $schema->resultset ('Producer')->find ({ name => 'Lehman Bros.' });
108   isa_ok ($prod, 'DBICTest::Producer', 'Producer row found');
109   is ($prod->cds->count, 1, 'Producer has one production');
110   my $cd = $prod->cds->first;
111   is ($cd->title, 'Bad investment', 'CD created correctly');
112   is ($cd->tracks->count, 3, 'CD has 3 tracks');
113
114 };
115 diag $@ if $@;
116
117 mc_diag (<<'DG');
118 * Create over > 1 levels of might_have with multiple has_many and multiple m2m
119 but starting at a has_many level
120
121 CD -> has_many -> Tracks -> might have -> Single -> has_many -> Tracks
122                                                \
123                                                 \-> has_many \
124                                                               --> CD2Producer
125                                                 /-> has_many /
126                                                /
127                                           Producer
128 DG
129
130 eval {
131   my $artist = $schema->resultset('Artist')->first;
132   my $cd = $schema->resultset('CD')->create ({
133     artist => $artist,
134     title => 'Music to code by at night',
135     year => 2008,
136     tracks => [
137       {
138         title => 'Off by one again',
139       },
140       {
141         title => 'The dereferencer',
142         cd_single => {
143           artist => $artist,
144           year => 2008,
145           title => 'Was that a null (Single)',
146           tracks => [
147             { title => 'The dereferencer' },
148             { title => 'The dereferencer II' },
149           ],
150           cd_to_producer => [
151             {
152               producer => {
153                 name => 'K&R',
154               }
155             },
156             {
157               producer => {
158                 name => 'Don Knuth',
159               }
160             },
161           ]
162         },
163       },
164     ],
165   });
166
167   isa_ok ($cd, 'DBICTest::CD', 'Main CD object created');
168   is ($cd->title, 'Music to code by at night', 'Correct CD title');
169   is ($cd->tracks->count, 2, 'Two tracks on main CD');
170
171   my ($t1, $t2) = $cd->tracks->all;
172   is ($t1->title, 'Off by one again', 'Correct 1st track name');
173   is ($t1->cd_single, undef, 'No single for 1st track');
174   is ($t2->title, 'The dereferencer', 'Correct 2nd track name');
175   isa_ok ($t2->cd_single, 'DBICTest::CD', 'Created a single for 2nd track');
176
177   my $single = $t2->cd_single;
178   is ($single->tracks->count, 2, 'Two tracks on single CD');
179   is ($single->tracks->find ({ position => 1})->title, 'The dereferencer', 'Correct 1st track title');
180   is ($single->tracks->find ({ position => 2})->title, 'The dereferencer II', 'Correct 2nd track title');
181
182   is ($single->cd_to_producer->count, 2, 'Two producers created for the single cd');
183   is_deeply (
184     [ sort map { $_->producer->name } ($single->cd_to_producer->all) ],
185     ['Don Knuth', 'K&R'],
186     'Producers named correctly',
187   );
188 };
189 diag $@ if $@;
190
191 mc_diag (<<'DG');
192 * Same as above but starting at the might_have directly
193
194 Track -> might have -> Single -> has_many -> Tracks
195                            \
196                             \-> has_many \
197                                           --> CD2Producer
198                             /-> has_many /
199                            /
200                        Producer
201 DG
202
203 eval {
204   my $cd = $schema->resultset('CD')->first;
205   my $track = $schema->resultset('Track')->create ({
206     cd => $cd,
207     title => 'Multicreate rocks',
208     cd_single => {
209       artist => $cd->artist,
210       year => 2008,
211       title => 'Disemboweling MultiCreate',
212       tracks => [
213         { title => 'Why does mst write this way' },
214         { title => 'Chainsaw celebration' },
215         { title => 'Purl cleans up' },
216       ],
217       cd_to_producer => [
218         {
219           producer => {
220             name => 'mst',
221           }
222         },
223         {
224           producer => {
225             name => 'castaway',
226           }
227         },
228         {
229           producer => {
230             name => 'theorbtwo',
231           }
232         },
233       ]
234     },
235   });
236
237   isa_ok ($track, 'DBICTest::Track', 'Main Track object created');
238   is ($track->title, 'Multicreate rocks', 'Correct Track title');
239
240   my $single = $track->cd_single;
241   isa_ok ($single, 'DBICTest::CD', 'Created a single with the track');
242   is ($single->tracks->count, 3, '3 tracks on single CD');
243   is ($single->tracks->find ({ position => 1})->title, 'Why does mst write this way', 'Correct 1st track title');
244   is ($single->tracks->find ({ position => 2})->title, 'Chainsaw celebration', 'Correct 2nd track title');
245   is ($single->tracks->find ({ position => 3})->title, 'Purl cleans up', 'Correct 3rd track title');
246
247   is ($single->cd_to_producer->count, 3, '3 producers created for the single cd');
248   is_deeply (
249     [ sort map { $_->producer->name } ($single->cd_to_producer->all) ],
250     ['castaway', 'mst', 'theorbtwo'],
251     'Producers named correctly',
252   );
253 };
254 diag $@ if $@;
255
256 mc_diag '* Test might_have again but with a PK == FK in the middle (obviously not specified)';
257 eval {
258   my $artist = $schema->resultset('Artist')->first;
259   my $cd = $schema->resultset('CD')->create ({
260     artist => $artist,
261     title => 'Music to code by at twilight',
262     year => 2008,
263     artwork => {
264       images => [
265         { name => 'recursive descent' },
266         { name => 'tail packing' },
267       ],
268     },
269   });
270
271   isa_ok ($cd, 'DBICTest::CD', 'Main CD object created');
272   is ($cd->title, 'Music to code by at twilight', 'Correct CD title');
273   isa_ok ($cd->artwork, 'DBICTest::Artwork', 'Artwork created');
274
275   # this test might look weird, but it failed at one point, keep it there
276   my $art_obj = $cd->artwork;
277   ok ($art_obj->has_column_loaded ('cd_id'), 'PK/FK present on artwork object');
278   is ($art_obj->images->count, 2, 'Correct artwork image count via the new object');
279   is_deeply (
280     [ sort $art_obj->images->get_column ('name')->all ],
281     [ 'recursive descent', 'tail packing' ],
282     'Images named correctly in objects',
283   );
284
285   my $artwork = $schema->resultset('Artwork')->search (
286     { 'cd.title' => 'Music to code by at twilight' },
287     { join => 'cd' },
288   )->single;
289
290   is ($artwork->images->count, 2, 'Correct artwork image count via a new search');
291
292   is_deeply (
293     [ sort $artwork->images->get_column ('name')->all ],
294     [ 'recursive descent', 'tail packing' ],
295     'Images named correctly after search',
296   );
297 };
298 diag $@ if $@;
299
300 mc_diag '* Test might_have again but with just a PK and FK (neither specified) in the mid-table';
301 eval {
302   my $cd = $schema->resultset('CD')->first;
303   my $track = $schema->resultset ('Track')->create ({
304     cd => $cd,
305     title => 'Black',
306     lyrics => {
307       lyric_versions => [
308         { text => 'The color black' },
309         { text => 'The colour black' },
310       ],
311     },
312   });
313
314   isa_ok ($track, 'DBICTest::Track', 'Main track object created');
315   is ($track->title, 'Black', 'Correct track title');
316   isa_ok ($track->lyrics, 'DBICTest::Lyrics', 'Lyrics created');
317
318   # this test might look weird, but it was failing at one point, keep it there
319   my $lyric_obj = $track->lyrics;
320   ok ($lyric_obj->has_column_loaded ('lyric_id'), 'PK present on lyric object');
321   ok ($lyric_obj->has_column_loaded ('track_id'), 'FK present on lyric object');
322   is ($lyric_obj->lyric_versions->count, 2, 'Correct lyric versions count via the new object');
323   is_deeply (
324     [ sort $lyric_obj->lyric_versions->get_column ('text')->all ],
325     [ 'The color black', 'The colour black' ],
326     'Lyrics text in objects matches',
327   );
328
329
330   my $lyric = $schema->resultset('Lyrics')->search (
331     { 'track.title' => 'Black' },
332     { join => 'track' },
333   )->single;
334
335   is ($lyric->lyric_versions->count, 2, 'Correct lyric versions count via a new search');
336
337   is_deeply (
338     [ sort $lyric->lyric_versions->get_column ('text')->all ],
339     [ 'The color black', 'The colour black' ],
340     'Lyrics text via search matches',
341   );
342 };
343 diag $@ if $@;
344
345 mc_diag (<<'DG');
346 * Test a multilevel might-have with a PK == FK in the might_have/has_many table
347
348 CD -> might have -> Artwork
349                        \
350                         \-> has_many \
351                                       --> Artwork_to_Artist
352                         /-> has_many /
353                        /
354                      Artist
355 DG
356
357 eval {
358   my $someartist = $schema->resultset('Artist')->first;
359   my $cd = $schema->resultset('CD')->create ({
360     artist => $someartist,
361     title => 'Music to code by until the cows come home',
362     year => 2008,
363     artwork => {
364       artwork_to_artist => [
365         { artist => { name => 'cowboy joe' } },
366         { artist => { name => 'billy the kid' } },
367       ],
368     },
369   });
370
371   isa_ok ($cd, 'DBICTest::CD', 'Main CD object created');
372   is ($cd->title, 'Music to code by until the cows come home', 'Correct CD title');
373
374   my $art_obj = $cd->artwork;
375   ok ($art_obj->has_column_loaded ('cd_id'), 'PK/FK present on artwork object');
376   is ($art_obj->artists->count, 2, 'Correct artwork creator count via the new object');
377   is_deeply (
378     [ sort $art_obj->artists->get_column ('name')->all ],
379     [ 'billy the kid', 'cowboy joe' ],
380     'Artists named correctly when queried via object',
381   );
382
383   my $artwork = $schema->resultset('Artwork')->search (
384     { 'cd.title' => 'Music to code by until the cows come home' },
385     { join => 'cd' },
386   )->single;
387   is ($artwork->artists->count, 2, 'Correct artwork creator count via a new search');
388   is_deeply (
389     [ sort $artwork->artists->get_column ('name')->all ],
390     [ 'billy the kid', 'cowboy joe' ],
391     'Artists named correctly queried via a new search',
392   );
393 };
394 diag $@ if $@;
395
396 mc_diag '* Nested find_or_create';
397 eval {
398   my $newartist2 = $schema->resultset('Artist')->find_or_create({ 
399     name => 'Fred 3',
400     cds => [
401       { 
402         title => 'Noah Act',
403         year => 2007,
404       },
405     ],
406   });
407   is($newartist2->name, 'Fred 3', 'Created new artist with cds via find_or_create');
408 };
409 diag $@ if $@;
410
411 mc_diag '* Multiple same level has_many create';
412 eval {
413   my $artist2 = $schema->resultset('Artist')->create({
414     name => 'Fred 4',
415     cds => [
416       {
417         title => 'Music to code by',
418         year => 2007,
419       },
420     ],
421     cds_unordered => [
422       {
423         title => 'Music to code by',
424         year => 2007,
425       },
426     ]
427   });
428
429   is($artist2->in_storage, 1, 'artist with duplicate rels inserted okay');
430 };
431 diag $@ if $@;
432
433 mc_diag '* First create_related pass';
434 eval {
435         my $artist = $schema->resultset('Artist')->first;
436         
437         my $cd_result = $artist->create_related('cds', {
438         
439                 title => 'TestOneCD1',
440                 year => 2007,
441                 tracks => [
442                         { title => 'TrackOne' },
443                         { title => 'TrackTwo' },
444                 ],
445
446         });
447         
448         ok( $cd_result && ref $cd_result eq 'DBICTest::CD', "Got Good CD Class");
449         ok( $cd_result->title eq "TestOneCD1", "Got Expected Title");
450         
451         my $tracks = $cd_result->tracks;
452         
453         ok( ref $tracks eq "DBIx::Class::ResultSet", "Got Expected Tracks ResultSet");
454         
455         foreach my $track ($tracks->all)
456         {
457                 ok( $track && ref $track eq 'DBICTest::Track', 'Got Expected Track Class');
458         }
459 };
460 diag $@ if $@;
461
462 mc_diag '* second create_related with same arguments';
463 eval {
464         my $artist = $schema->resultset('Artist')->first;
465         
466         my $cd_result = $artist->create_related('cds', {
467         
468                 title => 'TestOneCD2',
469                 year => 2007,
470                 tracks => [
471                         { title => 'TrackOne' },
472                         { title => 'TrackTwo' },
473                 ],
474
475     liner_notes => { notes => 'I can haz liner notes?' },
476
477         });
478         
479         ok( $cd_result && ref $cd_result eq 'DBICTest::CD', "Got Good CD Class");
480         ok( $cd_result->title eq "TestOneCD2", "Got Expected Title");
481   ok( $cd_result->notes eq 'I can haz liner notes?', 'Liner notes');
482         
483         my $tracks = $cd_result->tracks;
484         
485         ok( ref $tracks eq "DBIx::Class::ResultSet", "Got Expected Tracks ResultSet");
486         
487         foreach my $track ($tracks->all)
488         {
489                 ok( $track && ref $track eq 'DBICTest::Track', 'Got Expected Track Class');
490         }
491 };
492 diag $@ if $@;
493
494 mc_diag '* create of parents of a record linker table';
495 eval {
496   my $cdp = $schema->resultset('CD_to_Producer')->create({
497     cd => { artist => 1, title => 'foo', year => 2000 },
498     producer => { name => 'jorge' }
499   });
500   ok($cdp, 'join table record created ok');
501 };
502 diag $@ if $@;
503
504 eval {
505   my $kurt_cobain = { name => 'Kurt Cobain' };
506
507   my $in_utero = $schema->resultset('CD')->new({
508       title => 'In Utero',
509       year  => 1993
510     });
511
512   $kurt_cobain->{cds} = [ $in_utero ];
513
514
515   $schema->resultset('Artist')->populate([ $kurt_cobain ]); # %)
516   $a = $schema->resultset('Artist')->find({name => 'Kurt Cobain'});
517
518   is($a->name, 'Kurt Cobain', 'Artist insertion ok');
519   is($a->cds && $a->cds->first && $a->cds->first->title, 
520                   'In Utero', 'CD insertion ok');
521 };
522 diag $@ if $@;
523
524 =pod
525 # This test case has been moved to t/96multi_create/cd_single.t
526 eval {
527   my $pink_floyd = { name => 'Pink Floyd' };
528
529   my $the_wall = { title => 'The Wall', year  => 1979 };
530
531   $pink_floyd->{cds} = [ $the_wall ];
532
533
534   $schema->resultset('Artist')->populate([ $pink_floyd ]); # %)
535   $a = $schema->resultset('Artist')->find({name => 'Pink Floyd'});
536
537   is($a->name, 'Pink Floyd', 'Artist insertion ok');
538   is($a->cds && $a->cds->first->title, 'The Wall', 'CD insertion ok');
539 };
540 diag $@ if $@;
541 =cut
542
543 mc_diag '* Create foreign key col obj including PK (See test 20 in 66relationships.t)';
544 ## Create foreign key col obj including PK
545 ## See test 20 in 66relationships.t
546 eval {
547   my $new_cd_hashref = { 
548     cdid => 27, 
549     title => 'Boogie Woogie', 
550     year => '2007', 
551     artist => { artistid => 17, name => 'king luke' }
552   };
553
554   my $cd = $schema->resultset("CD")->find(1);
555
556   is($cd->artist->id, 1, 'rel okay');
557
558   my $new_cd = $schema->resultset("CD")->create($new_cd_hashref);
559   is($new_cd->artist->id, 17, 'new id retained okay');
560 };
561 diag $@ if $@;
562
563 eval {
564         $schema->resultset("CD")->create({ 
565               cdid => 28, 
566               title => 'Boogie Wiggle', 
567               year => '2007', 
568               artist => { artistid => 18, name => 'larry' }
569              });
570 };
571 is($@, '', 'new cd created without clash on related artist');
572
573 mc_diag '* Make sure exceptions from errors in created rels propogate';
574 eval {
575     my $t = $schema->resultset("Track")->new({ cd => { artist => undef } });
576     #$t->cd($t->new_related('cd', { artist => undef } ) );
577     #$t->{_rel_in_storage} = 0;
578     $t->insert;
579 };
580 like($@, qr/cd.artist may not be NULL/, "Exception propogated properly");
581
582 mc_diag '* Test multi create over many_to_many';
583 eval {
584   $schema->resultset('CD')->create ({
585     artist => {
586       name => 'larry', # should already exist
587     },
588     title => 'Warble Marble',
589     year => '2009',
590     cd_to_producer => [
591       { producer => { name => 'Cowboy Neal' } },
592     ],
593   });
594
595   my $m2m_cd = $schema->resultset('CD')->search ({ title => 'Warble Marble'});
596   is ($m2m_cd->count, 1, 'One CD row created via M2M create');
597   is ($m2m_cd->first->producers->count, 1, 'CD row created with one producer');
598   is ($m2m_cd->first->producers->first->name, 'Cowboy Neal', 'Correct producer row created');
599 };
600
601 1;