OSDN Git Service

Merge branch 'v06' of git.sourceforge.jp:/gitroot/pettanr/pettanr into v06
[pettanr/pettanr.git] / spec / models / story_spec.rb
1 # -*- encoding: utf-8 -*-
2 require 'spec_helper'
3 #ストーリー
4
5 describe Story do
6   before do
7     @admin = FactoryGirl.create :admin
8     @demand_user = FactoryGirl.create :demand_user
9     @sp = FactoryGirl.create :system_picture
10     @lg = FactoryGirl.create :license_group
11     @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id
12     @user = FactoryGirl.create( :user_yas)
13     @author = FactoryGirl.create :author, :user_id => @user.id
14     @artist = FactoryGirl.create :artist_yas, :author_id => @author.id
15     @other_user = FactoryGirl.create( :user_yas)
16     @other_author = FactoryGirl.create :author, :user_id => @other_user.id
17     @other_artist = FactoryGirl.create :artist_yas, :author_id => @other_author.id
18   end
19   
20   describe '検証に於いて' do
21     before do
22       @comic = FactoryGirl.create :comic, :author_id => @author.id
23       @story = FactoryGirl.build :story, :comic_id => @comic.id
24     end
25     
26     context 'オーソドックスなデータのとき' do
27       it '下限データが通る' do
28         @story.title = 'a'
29         @story.visible = 0
30         @story.t = 0
31         @story.should be_valid
32       end
33       it '上限データが通る' do
34         @story.title = 'a'*100
35         @story.visible = 1
36         @story.t = 99999
37         @story.should be_valid
38       end
39     end
40     
41     context 'comic_idを検証するとき' do
42       it 'nullなら失敗する' do
43         @story.comic_id = nil
44         @story.should_not be_valid
45       end
46       it '数値でなければ失敗する' do
47         @story.comic_id = 'a'
48         @story.should_not be_valid
49       end
50       it '存在するコミックでなければ失敗する' do
51         @story.comic_id = 0
52         @story.should_not be_valid
53       end
54     end
55     
56     context 'titleを検証するとき' do
57       it 'nullなら失敗する' do
58         @story.title = nil
59         @story.should_not be_valid
60       end
61       it '100文字以上なら失敗する' do
62         @story.title = 'a'*101
63         @story.should_not be_valid
64       end
65     end
66     
67     context 'visibleを検証するとき' do
68       it 'nullなら失敗する' do
69         @story.visible = nil
70         @story.should_not be_valid
71       end
72       it '負なら失敗する' do
73         @story.visible = -1
74         @story.should_not be_valid
75       end
76       it '2以上なら失敗する' do
77         @story.visible = 2
78         @story.should_not be_valid
79       end
80     end
81     
82     context 'tを検証するとき' do
83       it 'nullなら失敗する' do
84         @story.t = nil
85         @story.should_not be_valid
86       end
87       it '数値でなければ失敗する' do
88         @story.t = 'a'
89         @story.should_not be_valid
90       end
91       it '負なら失敗する' do
92         @story.t = -1
93         @story.should_not be_valid
94       end
95     end
96   end
97   
98   describe '文字コード検証に於いて' do
99     before do
100       @comic = FactoryGirl.create :comic, :author_id => @author.id
101       @story = FactoryGirl.build :story, :comic_id => @comic.id
102     end
103     
104     context 'titleを検証するとき' do
105       it 'Shift JISなら失敗する' do
106         @story.title = "\x83G\x83r\x83]\x83D"
107         lambda{
108           @story.valid_encode
109         }.should raise_error(Pettanr::BadRequest)
110       end
111     end
112     
113     context 'descriptionを検証するとき' do
114       it 'Shift JISなら失敗する' do
115         @story.description = "\x83G\x83r\x83]\x83D"
116         lambda{
117           @story.valid_encode
118         }.should raise_error(Pettanr::BadRequest)
119       end
120     end
121   end
122   
123   describe 'デフォルト値補充に於いて' do
124     it 'visibleが0になっている' do
125       @story = FactoryGirl.build :story, :visible => nil
126       @story.supply_default
127       @story.visible.should eq 0
128     end
129   end
130   
131   describe '上書き補充に於いて' do
132   end
133   
134   describe '所持判定に於いて' do
135     before do
136       @comic = FactoryGirl.create :comic, :author_id => @author.id
137       @story = FactoryGirl.build :story, :comic_id => @comic.id
138     end
139     context '事前チェックする' do
140       it '自身にロールリストからの作家取得を依頼している' do
141         Story.should_receive(:get_author_from_roles).with(any_args).exactly(1)
142         r = @story.own?([@author])
143       end
144     end
145     context 'ロール内作家が取得できるとき' do
146       before do
147       end
148       it 'ロール内作家のidが自身のコミックの作家idと一致するなら許可する' do
149         Story.stub(:get_author_from_roles).with(any_args).and_return(@author)
150         r = @story.own?([@author])
151         r.should be_true
152       end
153       it 'ロール内作家のidが自身のコミックの作家idと一致しないならno' do
154         Story.stub(:get_author_from_roles).with(any_args).and_return(@other_author)
155         @story.own?(@other_author).should be_false
156       end
157     end
158     context 'ロール内作家が取得できないとき' do
159       before do
160         Story.stub(:get_author_from_roles).with(any_args).and_return(nil)
161       end
162       it 'Falseを返す' do
163         r = @story.own?([@author])
164         r.should be_false
165       end
166     end
167   end
168   
169   describe '閲覧許可に於いて' do
170     before do
171       @comic = FactoryGirl.create :comic, :author_id => @author.id
172       @story = FactoryGirl.build :story, :comic_id => @comic.id
173     end
174     context 'オープンモードのとき' do
175       before do
176         MagicNumber['run_mode'] = 0
177       end
178       it '自身にゲスト用ロールチェックを問い合わせしている' do
179         Story.any_instance.stub(:guest_role_check).and_return(true)
180         Story.any_instance.should_receive(:guest_role_check).with(any_args).exactly(1)
181         r = @story.visible?([@author])
182       end
183       it 'ゲスト用ロールチェックが失敗したとき、falseを返す' do
184         Story.any_instance.stub(:guest_role_check).and_return(false)
185         r = @story.visible?([@author])
186         r.should be_false
187       end
188     end
189     context 'クローズドモードのとき' do
190       before do
191         MagicNumber['run_mode'] = 1
192       end
193       it '自身に読者用ロールチェックを問い合わせしている' do
194         Story.any_instance.stub(:reader_role_check).and_return(true)
195         Story.any_instance.should_receive(:reader_role_check).with(any_args).exactly(1)
196         r = @story.visible?([@author])
197       end
198       it '読者用ロールチェックが失敗したとき、falseを返す' do
199         Story.any_instance.stub(:reader_role_check).and_return(false)
200         r = @story.visible?([@author])
201         r.should be_false
202       end
203     end
204     context '事前チェックする' do
205       before do
206         MagicNumber['run_mode'] = 1
207         Story.any_instance.stub(:reader_role_check).and_return(true)
208         Story.any_instance.stub(:own?).and_return(true)
209       end
210       it '自身に所持判定を問い合わせしている' do
211         Story.any_instance.should_receive(:own?).with(any_args).exactly(1)
212         r = @story.visible?([@author])
213       end
214     end
215     context 'つつがなく終わるとき' do
216       before do
217         MagicNumber['run_mode'] = 1
218         Story.any_instance.stub(:reader_role_check).and_return(true)
219       end
220       it '自分のストーリーなら許可する' do
221         Story.any_instance.stub(:own?).and_return(true)
222         Story.any_instance.stub(:visible).and_return(0)
223         r = @story.visible?([@author])
224         r.should be_true
225       end
226       it '他人の非公開ストーリーなら許可しない' do
227         Story.any_instance.stub(:own?).and_return(false)
228         Story.any_instance.stub(:visible).and_return(0)
229         r = @story.visible?([@author])
230         r.should be_false
231       end
232       it '他人のストーリーでも公開なら許可する' do
233         Story.any_instance.stub(:own?).and_return(false)
234         Story.any_instance.stub(:visible).and_return(1)
235         r = @story.visible?([@author])
236         r.should be_true
237       end
238     end
239   end
240   
241   describe '一覧取得に於いて' do
242     before do
243       @comic = FactoryGirl.create :comic, :author_id => @author.id
244       @story = FactoryGirl.create :story, :comic_id => @comic.id
245     end
246     context 'page補正について' do
247       it '文字列から数値に変換される' do
248         Story.page('8').should eq 8
249       end
250       it 'nilの場合は1になる' do
251         Story.page().should eq 1
252       end
253       it '0以下の場合は1になる' do
254         Story.page('0').should eq 1
255       end
256     end
257     context 'page_size補正について' do
258       it '文字列から数値に変換される' do
259         Story.page_size('7').should eq 7
260       end
261       it 'nilの場合はStory.default_page_sizeになる' do
262         Story.page_size().should eq Story.default_page_size
263       end
264       it '0以下の場合はStory.default_page_sizeになる' do
265         Story.page_size('0').should eq Story.default_page_size
266       end
267       it 'Story.max_page_sizeを超えた場合はStory.max_page_sizeになる' do
268         Story.page_size('1000').should eq Story.max_page_size
269       end
270     end
271     context 'つつがなく終わるとき' do
272       it '一覧取得オプションを利用している' do
273         Story.stub(:list_opt).with(any_args).and_return({})
274         Story.should_receive(:list_opt).with(any_args).exactly(1)
275         r = Story.list
276       end
277     end
278     it 'リストを返す' do
279       c = Story.list
280       c.should eq [@story]
281     end
282     it '非公開ストーリーは(自分のストーリーであっても)含んでいない' do
283       FactoryGirl.create :story, :comic_id => @comic.id, :visible => 0
284       c = Story.list
285       c.should eq [@story]
286     end
287     it '時系列で並んでいる' do
288       #公開ストーリーは(他人のストーリーであっても)含んでいる
289       other_comic = FactoryGirl.create :comic, :author_id => @other_author.id
290       v = FactoryGirl.create :story, :comic_id => other_comic.id, :updated_at => Time.now + 100
291       c = Story.list
292       c.should eq [v, @story]
293     end
294     context 'DBに5件あって1ページの件数を2件に変えたとして' do
295       before do
296         @story2 = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 100
297         @story3 = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 200
298         @story4 = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 300
299         @story5 = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 400
300         Story.stub(:default_page_size).and_return(2)
301       end
302       it '通常は2件を返す' do
303         c = Story.list
304         c.should have(2).items 
305       end
306       it 'page=1なら末尾2件を返す' do
307         #時系列で並んでいる
308         c = Story.list(1)
309         c.should eq [@story5, @story4]
310       end
311       it 'page=2なら中間2件を返す' do
312         c = Story.list(2)
313         c.should eq [@story3, @story2]
314       end
315       it 'page=3なら先頭1件を返す' do
316         c = Story.list(3)
317         c.should eq [@story]
318       end
319     end
320   end
321   
322   describe '自分のストーリー一覧取得に於いて' do
323     before do
324       @comic = FactoryGirl.create :comic, :author_id => @author.id
325       @story = FactoryGirl.create :story, :comic_id => @comic.id
326     end
327     context 'つつがなく終わるとき' do
328       it '一覧取得オプションを利用している' do
329         Story.stub(:list_opt).with(any_args).and_return({})
330         Story.should_receive(:list_opt).with(any_args).exactly(1)
331         r = Story.mylist @author
332       end
333     end
334     it 'リストを返す' do
335       c = Story.mylist @author
336       c.should eq [@story]
337     end
338     it '時系列で並んでいる' do
339       nc = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 100
340       cl = Story.mylist @author
341       cl.should eq [nc, @story]
342     end
343     it '他人のストーリーは公開でも含まない' do
344       other_comic = FactoryGirl.create :comic, :author_id => @other_author.id
345       nc = FactoryGirl.create :story, :comic_id => other_comic.id, :visible => 1
346       cl = Story.mylist @author
347       cl.should eq [@story]
348     end
349     it '自分のストーリーは非公開でも含んでいる' do
350       nc = FactoryGirl.create :story, :comic_id => @comic.id, :visible => 0, :updated_at => Time.now + 100
351       cl = Story.mylist @author
352       cl.should eq [nc, @story]
353     end
354     context 'DBに5件あって1ページの件数を2件に変えたとして' do
355       before do
356         @story2 = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 100
357         @story3 = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 200
358         @story4 = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 300
359         @story5 = FactoryGirl.create :story, :comic_id => @comic.id, :updated_at => Time.now + 400
360       end
361       it '通常は2件を返す' do
362         c = Story.mylist @author, 1, 2
363         c.should have(2).items 
364       end
365       it 'page=1なら末尾2件を返す' do
366         #時系列で並んでいる
367         c = Story.mylist(@author, 1, 2)
368         c.should eq [@story5, @story4]
369       end
370       it 'page=2なら中間2件を返す' do
371         c = Story.mylist(@author, 2, 2)
372         c.should eq [@story3, @story2]
373       end
374       it 'page=3なら先頭1件を返す' do
375         c = Story.mylist(@author, 3, 2)
376         c.should eq [@story]
377       end
378     end
379   end
380   
381   describe '他作家のストーリー一覧取得に於いて' do
382     before do
383       @comic = FactoryGirl.create :comic, :author_id => @author.id
384       @story = FactoryGirl.create :story, :comic_id => @comic.id
385       @other_comic = FactoryGirl.create :comic, :visible => 1, :author_id => @other_author.id
386       @other_story = FactoryGirl.create :story, :visible => 1, :comic_id => @other_comic.id
387     end
388     context 'つつがなく終わるとき' do
389       it '一覧取得オプションを利用している' do
390         Story.stub(:list_opt).with(any_args).and_return({})
391         Story.should_receive(:list_opt).with(any_args).exactly(1)
392         r = Story.himlist @other_author
393       end
394     end
395     it '指定した作家のリストを返す' do
396       r = Story.himlist @other_author
397       r.should eq [@other_story]
398     end
399     it '時系列で並んでいる' do
400       nc = FactoryGirl.create :story, :comic_id => @other_comic.id, :updated_at => Time.now + 100
401       r = Story.himlist @other_author
402       r.should eq [nc, @other_story]
403     end
404     it '公開ストーリーに限る ' do
405       hidden = FactoryGirl.create :story, :comic_id => @other_comic.id, :visible => 0
406       r = Story.himlist @other_author
407       r.should eq [@other_story]
408     end
409     context 'DBに5件あって1ページの件数を2件に変えたとして' do
410       before do
411         @other_story2 = FactoryGirl.create :story, :comic_id => @other_comic.id, :updated_at => Time.now + 100
412         @other_story3 = FactoryGirl.create :story, :comic_id => @other_comic.id, :updated_at => Time.now + 200
413         @other_story4 = FactoryGirl.create :story, :comic_id => @other_comic.id, :updated_at => Time.now + 300
414         @other_story5 = FactoryGirl.create :story, :comic_id => @other_comic.id, :updated_at => Time.now + 400
415       end
416       it '通常は2件を返す' do
417         c = Story.himlist @other_author, 1, 2
418         c.should have(2).items 
419       end
420       it 'page=1なら末尾2件を返す' do
421         #時系列で並んでいる
422         c = Story.himlist(@other_author, 1, 2)
423         c.should eq [@other_story5, @other_story4]
424       end
425       it 'page=2なら中間2件を返す' do
426         c = Story.himlist(@other_author, 2, 2)
427         c.should eq [@other_story3, @other_story2]
428       end
429       it 'page=3なら先頭1件を返す' do
430         c = Story.himlist(@other_author, 3, 2)
431         c.should eq [@other_story]
432       end
433     end
434   end
435   
436   describe 'ストーリー一覧ページ制御に於いて' do
437     before do
438       Story.stub(:count).with(any_args).and_return(100)
439     end
440     it 'ページ制御を返す' do
441       r = Story.list_paginate 
442       r.is_a?(Kaminari::PaginatableArray).should be_true
443     end
444     it 'ストーリー一覧の取得条件を利用している' do
445       Story.stub(:list_where).with(any_args).and_return('')
446       Story.should_receive(:list_where).with(any_args).exactly(1)
447       r = Story.list_paginate 
448     end
449     it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do
450       r = Story.list_paginate 3, 10
451       r.limit_value.should eq 10
452       r.offset_value.should eq 20
453     end
454   end
455   
456   describe '自分のストーリー一覧ページ制御に於いて' do
457     before do
458       Story.stub(:count).with(any_args).and_return(100)
459     end
460     it 'ページ制御を返す' do
461       r = Story.mylist_paginate @author
462       r.is_a?(Kaminari::PaginatableArray).should be_true
463     end
464     it '自分のストーリー一覧の取得条件を利用している' do
465       Story.stub(:mylist_where).with(any_args).and_return('')
466       Story.should_receive(:mylist_where).with(any_args).exactly(1)
467       r = Story.mylist_paginate @author
468     end
469     it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do
470       r = Story.mylist_paginate @author, 3, 10
471       r.limit_value.should eq 10
472       r.offset_value.should eq 20
473     end
474   end
475   
476   describe '他作家のストーリー一覧ページ制御に於いて' do
477     before do
478       Story.stub(:count).with(any_args).and_return(100)
479     end
480     it 'ページ制御を返す' do
481       r = Story.himlist_paginate @other_author
482       r.is_a?(Kaminari::PaginatableArray).should be_true
483     end
484     it '他作家のストーリー一覧の取得条件を利用している' do
485       Story.stub(:himlist_where).with(any_args).and_return('')
486       Story.should_receive(:himlist_where).with(any_args).exactly(1)
487       r = Story.himlist_paginate @other_author
488     end
489     it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do
490       r = Story.himlist_paginate @other_author, 3, 10
491       r.limit_value.should eq 10
492       r.offset_value.should eq 20
493     end
494   end
495   
496   describe '一覧取得オプションに於いて' do
497     it '1つの項目を含んでいる' do
498       r = Story.list_opt
499       r.should have(1).items
500     end
501     it 'コミックを含んでいる' do
502       r = Story.list_opt
503       r.has_key?(:comic).should be_true
504     end
505       it 'コミックは作家を含んでいる' do
506         r = Story.list_opt
507         r[:comic].has_key?(:author).should be_true
508       end
509   end
510   describe 'json一覧出力オプションに於いて' do
511     before do
512       @comic = FactoryGirl.create :comic, :author_id => @author.id
513       @story = FactoryGirl.create :story, :comic_id => @comic.id, :visible => 1
514     end
515     it 'コミックを含んでいる' do
516       r = Story.list.to_json Story.list_json_opt
517       j = JSON.parse r
518       i = j.first
519       i.has_key?('comic').should be_true
520     end
521       it 'コミックは作家を含んでいる' do
522         r = Story.list.to_json Story.list_json_opt
523         j = JSON.parse r
524         i = j.first
525         s = i['comic']
526         s.has_key?('author').should be_true
527       end
528   end
529   
530   describe '単体取得に於いて' do
531     before do
532       @comic = FactoryGirl.create :comic, :author_id => @author.id
533       @story = FactoryGirl.create :story, :comic_id => @comic.id
534     end
535     context 'つつがなく終わるとき' do
536       it '単体取得オプションを利用している' do
537         Story.stub(:show_opt).with(any_args).and_return({})
538         Story.should_receive(:show_opt).with(any_args).exactly(1)
539         r = Story.show @story.id, @author
540       end
541       it '閲覧許可を問い合わせている' do
542         Story.any_instance.stub(:visible?).with(any_args).and_return(true)
543         Story.any_instance.should_receive(:visible?).with(any_args).exactly(1)
544         r = Story.show @story.id, @author
545       end
546     end
547     it '指定のストーリーを返す' do
548       c = Story.show @story.id, @author
549       c.should eq @story
550     end
551     context '閲覧許可が出なかったとき' do
552       it '403Forbidden例外を返す' do
553         Story.any_instance.stub(:visible?).and_return(false)
554         lambda{
555           Story.show @story.id, @author
556         }.should raise_error(ActiveRecord::Forbidden)
557       end
558     end
559     context '存在しないストーリーを開こうとしたとき' do
560       it '404RecordNotFound例外を返す' do
561         lambda{
562           Story.show 110, @author
563         }.should raise_error(ActiveRecord::RecordNotFound)
564       end
565     end
566   end
567   
568   describe '編集取得に於いて' do
569     before do
570       @comic = FactoryGirl.create :comic, :author_id => @author.id
571       @story = FactoryGirl.create :story, :comic_id => @comic.id
572     end
573     context 'つつがなく終わるとき' do
574       it '単体取得オプションを利用している' do
575         Story.stub(:show_opt).with(any_args).and_return({})
576         Story.should_receive(:show_opt).with(any_args).exactly(1)
577         r = Story.edit @story.id, @author
578       end
579       it '所持判定を問い合わせている' do
580         Story.any_instance.stub(:own?).with(any_args).and_return(true)
581         Story.any_instance.should_receive(:own?).with(any_args).exactly(1)
582         r = Story.edit @story.id, @author
583       end
584     end
585     it '指定のストーリーを返す' do
586       Story.any_instance.stub(:own?).and_return(true)
587       c = Story.edit @story.id, @author.id
588       c.should eq @story
589     end
590     context '他人のストーリーを開こうとしたとき' do
591       it '403Forbidden例外を返す' do
592         Story.any_instance.stub(:own?).and_return(false)
593         lambda{
594           Story.edit @story.id, @author
595         }.should raise_error(ActiveRecord::Forbidden)
596       end
597     end
598     context '存在しないストーリーを開こうとしたとき' do
599       it '404RecordNotFound例外を返す' do
600         lambda{
601           Story.edit 110, @author
602         }.should raise_error(ActiveRecord::RecordNotFound)
603       end
604     end
605   end
606   describe '単体取得オプションに於いて' do
607     it 'includeキーを含んでいる' do
608       r = Story.show_opt
609       r.has_key?(:include).should be_true
610     end
611     it '1つの項目を含んでいる' do
612       r = Story.show_opt[:include]
613       r.should have(1).items
614     end
615     it 'コミックを含んでいる' do
616       r = Story.show_opt[:include]
617       r.has_key?(:comic).should be_true
618     end
619       it 'コミックは作家を含んでいる' do
620         r = Story.show_opt[:include]
621         r[:comic].has_key?(:author).should be_true
622       end
623   end
624   describe 'json単体出力オプションに於いて' do
625     before do
626       @comic = FactoryGirl.create :comic, :author_id => @author.id
627       @story = FactoryGirl.create :story, :comic_id => @comic.id, :visible => 1
628     end
629     it 'コミックを含んでいる' do
630       r = Story.show(@story.id, @author).to_json Story.show_json_opt
631       j = JSON.parse r
632       i = j
633       i.has_key?('comic').should be_true
634     end
635       it 'コミックは作家を含んでいる' do
636         r = Story.show(@story.id, @author).to_json Story.show_json_opt
637         j = JSON.parse r
638         i = j
639         s = i['comic']
640         s.has_key?('author').should be_true
641       end
642   end
643   
644   describe 't補充値に於いて' do
645     before do
646       @comic = FactoryGirl.create :comic, :author_id => @author.id
647     end
648     
649     context 'コミック初のコマなら' do
650       it '0を補充値とする' do
651         @story = FactoryGirl.build :story, :comic_id => @comic.id
652         @story.t = nil
653         r = Story.new_t @story.comic_id
654         r.should eq 0
655       end
656     end
657     context 'コミックに一個コマがあるとき' do
658       it '1を補充値とする' do
659         FactoryGirl.create :story, :comic_id => @comic.id, :t => 0
660         @story = FactoryGirl.build :story, :comic_id => @comic.id
661         @story.t = nil
662         r = Story.new_t @story.comic_id
663         r.should eq 1
664       end
665     end
666     context 'コミックに2個コマがあるとき' do
667       it '2を補充値とする' do
668         FactoryGirl.create :story, :comic_id => @comic.id, :t => 0
669         FactoryGirl.create :story, :comic_id => @comic.id, :t => 1
670         @story = FactoryGirl.build :story, :comic_id => @comic.id
671         @story.t = nil
672         r = Story.new_t @story.comic_id
673         r.should eq 2
674       end
675     end
676   end
677   describe 'シリアライズチェックに於いて' do
678     context 'つつがなく終わるとき' do
679       it '0からシリアライズされているならTrueを返す' do
680         r = Story.serial? [0, 1, 2]
681         r.should be_true
682       end
683       it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do
684         r = Story.serial? [0, 2, 1]
685         r.should be_true
686       end
687       it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do
688         r = Story.serial? [ 2, 1, 4, 3, 0]
689         r.should be_true
690       end
691     end
692     context '異常なとき' do
693       it '0から始まらないならFalseを返す' do
694         r = Story.serial? [1, 2, 3]
695         r.should be_false
696       end
697       it '連続していないならFalseを返す' do
698         r = Story.serial? [0, 1, 2, 4]
699         r.should be_false
700       end
701       it '連続していないならFalseを返す' do
702         r = Story.serial? [0, 1, 2, 4, 5]
703         r.should be_false
704       end
705     end
706   end
707   describe 't収集に於いて' do
708     before do
709       @comic = FactoryGirl.create :comic, :author_id => @author.id
710       @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
711       @comic2 = FactoryGirl.create :comic, :author_id => @author.id
712       @c2story = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
713     end
714     context 'つつがなく終わるとき' do
715       it 'ストーリーから同一コミックのtだけを収集している' do
716         r = Story.collect_t @story
717         r.should eq [0]
718       end
719     end
720     context '複数コマのとき' do
721       it 'ストーリーから同一コミックのtだけを収集している' do
722         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
723         r = Story.collect_t @story
724         r.sort.should eq [0, 1]
725       end
726     end
727     context '複数ストーリーでヨソのコミックも混じっているとき' do
728       it 'ストーリーから同一コミックのtだけを収集している' do
729         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
730         r = Story.collect_t @story
731         r.sort.should eq [0, 1]
732       end
733     end
734   end
735   describe 'tチェックに於いて' do
736     before do
737       @comic = FactoryGirl.create :comic, :author_id => @author.id
738       @story = FactoryGirl.build :story, :t => 1, :comic_id => @comic.id
739     end
740     context 'つつがなく終わるとき' do
741       it 't収集を依頼している' do
742         Story.should_receive(:collect_t).with(any_args).exactly(1)
743         Story.stub(:collect_t).with(any_args).and_return([])
744         Story.stub(:serial?).with(any_args).and_return(true)
745         r = Story.validate_t @story
746       end
747       it '収集したtをシリアライズチェック依頼している' do
748         Story.stub(:collect_t).with(any_args).and_return([])
749         Story.should_receive(:serial?).with(any_args).exactly(1)
750         Story.stub(:serial?).with(any_args).and_return(true)
751         r = Story.validate_t @story
752       end
753     end
754     #実データでチェック
755     #依頼チェックだけでは不安なので最低限のチェックを
756     context '新規のとき' do
757       it '一件だけで正常通過している' do
758         @story = FactoryGirl.build :story, :comic_id => @comic.id, :t => 0
759         r = Story.validate_t @story
760         r.should be_true 
761       end
762     end
763     context '既存のとき' do
764       it '2件目を作っても正常通過している' do
765         @story = FactoryGirl.create :story, :comic_id => @comic.id, :t => 0
766         @story2 = FactoryGirl.build :story, :comic_id => @comic.id, :t => 1
767         r = Story.validate_t @story2
768         r.should be_true 
769       end
770     end
771   end
772   describe '挿入シフトに於いて' do
773     before do
774       @comic = FactoryGirl.create :comic, :author_id => @author.id
775     end
776     context '依頼チェック' do
777       #テーブルが空で0に挿入
778       it 'Updateを依頼している' do
779         Story.stub(:update_all).with(any_args)
780         Story.should_receive(:update_all).with(any_args).exactly(1)
781         @story = FactoryGirl.build :story, :t => 0, :comic_id => @comic.id
782         @story.insert_shift
783       end
784     end
785     context 'テーブルに1件(t:0)で0に挿入したとき' do
786       before do
787         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
788         @story2 = FactoryGirl.build :story, :t => 0, :comic_id => @comic.id
789       end
790       it '既存の行を1にシフトしている' do
791         @story2.insert_shift
792         l = Story.find :all
793         l.first.t.should eq 1
794       end
795       it 'これから挿入するt(0)が欠番になっている' do
796         @story2.insert_shift
797         l = Story.find(:all).map {|s| s.t }
798         l.include?(0).should_not be_true
799       end
800     end
801     context 'テーブルに2件(t:0,1)で1に挿入したとき' do
802       before do
803         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
804         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
805         @story3 = FactoryGirl.build :story, :t => 1, :comic_id => @comic.id
806       end
807       it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do
808         @story3.insert_shift
809         l = Story.find(:all).map {|s| s.t }
810         l.sort.should eq [0, 2]
811       end
812     end
813     context 'テーブルに5件(t:0,1,2,3,4)で2に挿入したとき' do
814       before do
815         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
816         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
817         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
818         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
819         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
820         @story6 = FactoryGirl.build :story, :t => 2, :comic_id => @comic.id
821       end
822       it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do
823         @story6.insert_shift
824         l = Story.find(:all).map {|s| s.t }
825         l.sort.should eq [0, 1, 3, 4, 5]
826       end
827     end
828     context '先ほどのケース+他のコミック1件で挿入したとき' do
829       before do
830         @comic2 = FactoryGirl.create :comic, :author_id => @author.id
831         @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
832         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
833         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
834         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
835         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
836         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
837         @story6 = FactoryGirl.build :story, :t => 2, :comic_id => @comic.id
838       end
839       it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do
840         @story6.insert_shift
841         l = Story.find(:all, :conditions => ['comic_id = ?', @comic.id]).map {|s| s.t }
842         l.sort.should eq [0, 1, 3, 4, 5]
843       end
844       it '他のコミックに影響がない' do
845         ot = @storyc2.t
846         @story6.insert_shift
847         @storyc2.reload
848         @storyc2.t.should eq ot
849       end
850     end
851   end
852   describe '少ない方に移動に於いて' do
853     before do
854       @comic = FactoryGirl.create :comic
855     end
856     context '依頼チェック' do
857       it 'Updateを依頼している' do
858         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
859         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
860         Story.stub(:update_all).with(any_args)
861         Story.should_receive(:update_all).with(any_args).exactly(1)
862         ot = @story2.t
863         @story2.t = 0
864         @story2.lesser_shift ot
865       end
866     end
867     context 'テーブルに2件(t:0,1)で1を0に移動したとき' do
868       before do
869         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
870         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
871         @ot = @story2.t
872         @story2.t = 0
873       end
874       it '既存のt0を1にシフトしてこれから挿入するt(0)が欠番になっている' do
875         #移動させたい行はそのまま残る
876         @story2.lesser_shift @ot
877         l = Story.find(:all).map {|s| s.t }
878         l.sort.should eq [1, 1]
879       end
880       it '既存のt0を1にシフトしている' do
881         @story2.lesser_shift @ot
882         @story.reload
883         @story.t.should eq 1
884       end
885     end
886     context 'テーブルに3件(t:0,1,2)で2を1に移動したとき' do
887       before do
888         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
889         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
890         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
891         @ot = @story3.t
892         @story3.t = 1
893       end
894       it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do
895         #移動させたい行はそのまま残る
896         @story3.lesser_shift @ot
897         l = Story.find(:all).map {|s| s.t }
898         l.sort.should eq [0, 2, 2]
899       end
900       it '既存のt1を2にシフトしている' do
901         @story3.lesser_shift @ot
902         @story2.reload
903         @story2.t.should eq 2
904       end
905     end
906     context 'テーブルに5件(t:0,1,2,3,4)で3を1に移動したとき' do
907       before do
908         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
909         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
910         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
911         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
912         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
913         @ot = @story4.t
914         @story4.t = 1
915       end
916       it 'これから挿入するt(1)が欠番になっている' do
917         #移動させたい行はそのまま残る
918         @story4.lesser_shift @ot
919         l = Story.find(:all).map {|s| s.t }
920         l.sort.should eq [0, 2, 3, 3, 4]
921       end
922       it '既存のt0には変化がない' do
923         @story4.lesser_shift @ot
924         @story.reload
925         @story.t.should eq 0
926       end
927       it '既存のt4には変化がない' do
928         @story4.lesser_shift @ot
929         @story5.reload
930         @story5.t.should eq 4
931       end
932       it '既存のt1を2にシフトしている' do
933         @story4.lesser_shift @ot
934         @story2.reload
935         @story2.t.should eq 2
936       end
937       it '既存のt2を3にシフトしている' do
938         @story4.lesser_shift @ot
939         @story3.reload
940         @story3.t.should eq 3
941       end
942     end
943     context '先ほどのケース+他のコミック1件で挿入したとき' do
944       before do
945         @comic2 = FactoryGirl.create :comic
946         @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
947         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
948         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
949         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
950         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
951         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
952         @ot = @story4.t
953         @story4.t = 1
954       end
955       it 'これから挿入するt(1)が欠番になっている' do
956         @story4.lesser_shift @ot
957         l = Story.find(:all).map {|s| s.t }
958         l.sort.should eq [0, 0, 2, 3, 3, 4]
959       end
960       it '既存のt0には変化がない' do
961         @story4.lesser_shift @ot
962         @story.reload
963         @story.t.should eq 0
964       end
965       it '既存のt4には変化がない' do
966         @story4.lesser_shift @ot
967         @story5.reload
968         @story5.t.should eq 4
969       end
970       it '既存のt1を2にシフトしている' do
971         @story4.lesser_shift @ot
972         @story2.reload
973         @story2.t.should eq 2
974       end
975       it '既存のt2を3にシフトしている' do
976         @story4.lesser_shift @ot
977         @story3.reload
978         @story3.t.should eq 3
979       end
980       it '他のコミックに影響がない' do
981         @story4.lesser_shift @ot
982         @storyc2.reload
983         @storyc2.t.should eq 0
984       end
985     end
986     #例外ケース。
987     #負のときは0として正常扱い
988     context 'テーブルに2件(t:0,1)で1を-1に移動したとき' do
989       before do
990         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
991         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
992         @ot = @story2.t
993         @story2.t = -1
994       end
995       it '既存のt0を1にシフトしてこれから挿入するt(0)が欠番になっている' do
996         #移動させたい行はそのまま残る
997         @story2.lesser_shift @ot
998         l = Story.find(:all).map {|s| s.t }
999         l.sort.should eq [1, 1]
1000       end
1001       it '既存のt0を1にシフトしている' do
1002         @story2.lesser_shift @ot
1003         @story.reload
1004         @story.t.should eq 1
1005       end
1006       it '既存のt1は0に補正されている' do
1007         @story2.lesser_shift @ot
1008         @story2.t.should eq 0
1009       end
1010     end
1011   end
1012   describe '大きい方に移動に於いて' do
1013     before do
1014       @comic = FactoryGirl.create :comic, :author_id => @author.id
1015     end
1016     context '依頼チェック' do
1017       it 'Updateを依頼している' do
1018         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1019         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1020         Story.stub(:update_all).with(any_args)
1021         Story.should_receive(:update_all).with(any_args).exactly(1)
1022         ot = @story.t
1023         @story.t = 1
1024         @story.higher_shift ot
1025       end
1026     end
1027     context 'テーブルに2件(t:0,1)で0を1に移動したとき' do
1028       before do
1029         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1030         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1031         @ot = @story.t
1032         @story.t = 1
1033       end
1034       it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do
1035         #移動させたい行はそのまま残る
1036         @story.higher_shift @ot
1037         l = Story.find(:all).map {|s| s.t }
1038         l.sort.should eq [0, 0]
1039       end
1040       it '既存のt1を0にシフトしている' do
1041         @story.higher_shift @ot
1042         @story2.reload
1043         @story2.t.should eq 0
1044       end
1045     end
1046     context 'テーブルに3件(t:0,1,2)で0を1に移動したとき' do
1047       before do
1048         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1049         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1050         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1051         @ot = @story.t
1052         @story.t = 1
1053       end
1054       it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do
1055         #移動させたい行はそのまま残る
1056         @story.higher_shift @ot
1057         l = Story.find(:all).map {|s| s.t }
1058         l.sort.should eq [0, 0, 2]
1059       end
1060       it '既存のt1を0にシフトしている' do
1061         @story.higher_shift @ot
1062         @story2.reload
1063         @story2.t.should eq 0
1064       end
1065     end
1066     context 'テーブルに5件(t:0,1,2,3,4)で1を3に移動したとき' do
1067       before do
1068         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1069         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1070         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1071         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
1072         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
1073         @ot = @story2.t
1074         @story2.t = 3
1075       end
1076       it 'これから挿入するt(3)が欠番になっている' do
1077         #移動させたい行はそのまま残る
1078         @story2.higher_shift @ot
1079         l = Story.find(:all).map {|s| s.t }
1080         l.sort.should eq [0, 1, 1, 2, 4]
1081       end
1082       it '既存のt0には変化がない' do
1083         @story2.higher_shift @ot
1084         @story.reload
1085         @story.t.should eq 0
1086       end
1087       it '既存のt4には変化がない' do
1088         @story2.higher_shift @ot
1089         @story5.reload
1090         @story5.t.should eq 4
1091       end
1092       it '既存のt2を1にシフトしている' do
1093         @story2.higher_shift @ot
1094         @story3.reload
1095         @story3.t.should eq 1
1096       end
1097       it '既存のt3を2にシフトしている' do
1098         @story2.higher_shift @ot
1099         @story4.reload
1100         @story4.t.should eq 2
1101       end
1102     end
1103     context '先ほどのケース+他のコミック1件で挿入したとき' do
1104       before do
1105         @comic2 = FactoryGirl.create :comic, :author_id => @author.id
1106         @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
1107         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1108         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1109         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1110         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
1111         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
1112         @ot = @story2.t
1113         @story2.t = 3
1114       end
1115       it 'これから挿入するt(3)が欠番になっている' do
1116         #移動させたい行はそのまま残る
1117         @story2.higher_shift @ot
1118         l = Story.find(:all).map {|s| s.t }
1119         l.sort.should eq [0, 0, 1, 1, 2, 4]
1120       end
1121       it '既存のt0には変化がない' do
1122         @story2.higher_shift @ot
1123         @story.reload
1124         @story.t.should eq 0
1125       end
1126       it '既存のt4には変化がない' do
1127         @story2.higher_shift @ot
1128         @story5.reload
1129         @story5.t.should eq 4
1130       end
1131       it '既存のt2を1にシフトしている' do
1132         @story2.higher_shift @ot
1133         @story3.reload
1134         @story3.t.should eq 1
1135       end
1136       it '既存のt3を2にシフトしている' do
1137         @story2.higher_shift @ot
1138         @story4.reload
1139         @story4.t.should eq 2
1140       end
1141       it '他のコミックに影響がない' do
1142         @story2.higher_shift @ot
1143         @storyc2.reload
1144         @storyc2.t.should eq 0
1145       end
1146     end
1147     #例外ケース。
1148     #max超えたときはmaxとして正常扱い
1149     context 'テーブルに2件(t:0,1)で0を2に移動したとき' do
1150       before do
1151         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1152         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1153         @ot = @story.t
1154         @story.t = 2
1155       end
1156       it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do
1157         #移動させたい行はそのまま残る
1158         @story.higher_shift @ot
1159         l = Story.find(:all).map {|s| s.t }
1160         l.sort.should eq [0, 0]
1161       end
1162       it '既存のt1を0にシフトしている' do
1163         @story.higher_shift @ot
1164         @story2.reload
1165         @story2.t.should eq 0
1166       end
1167       it '既存のt0は1に補正されている' do
1168         @story.higher_shift @ot
1169         @story.t.should eq 1
1170       end
1171     end
1172   end
1173   describe '入れ替えに於いて' do
1174     before do
1175       @comic = FactoryGirl.create :comic, :author_id => @author.id
1176       @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1177       @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1178     end
1179     context '新tが旧tより小さいとき' do
1180       it '少ない方に移動を依頼している' do
1181         Story.any_instance.stub(:lesser_shift).with(any_args)
1182         Story.any_instance.should_receive(:lesser_shift).with(any_args).exactly(1)
1183         ot = @story2.t
1184         @story2.t = 0
1185         @story2.update_shift ot
1186       end
1187     end
1188     context '新tが旧tより大きいとき' do
1189       it '大きい方に移動を依頼している' do
1190         Story.any_instance.stub(:higher_shift).with(any_args)
1191         Story.any_instance.should_receive(:higher_shift).with(any_args).exactly(1)
1192         ot = @story.t
1193         @story.t = 1
1194         @story.update_shift ot
1195       end
1196     end
1197   end
1198   describe '順序入れ替えに於いて' do
1199     before do
1200       @comic = FactoryGirl.create :comic, :author_id => @author.id
1201     end
1202     context 'オブジェクトが新規でtが空のとき' do
1203       it '末尾追加としてtを補充依頼している' do
1204         @story = FactoryGirl.build :story, :comic_id => @comic.id
1205         Story.stub(:new_t).with(any_args).and_return(0)
1206         Story.should_receive(:new_t).with(any_args).exactly(1)
1207         @story.t = nil
1208         r = @story.rotate
1209       end
1210     end
1211     context 'オブジェクトが新規でtが設定されているとき' do
1212       it '挿入追加として挿入シフトを依頼している' do
1213         @story = FactoryGirl.build :story, :comic_id => @comic.id
1214         Story.any_instance.stub(:insert_shift).with(any_args)
1215         Story.any_instance.should_receive(:insert_shift).with(any_args).exactly(1)
1216         @story.t = 0
1217         r = @story.rotate
1218       end
1219     end
1220     context 'オブジェクトが新規でなくtが設定されているとき' do
1221       it '移動として入れ替えを依頼している' do
1222         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1223         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1224         Story.any_instance.stub(:update_shift).with(any_args)
1225         Story.any_instance.should_receive(:update_shift).with(1).exactly(1)
1226         @story2.t = 0
1227         r = @story.rotate 1
1228       end
1229     end
1230     context 'オブジェクトが新規でなくtが空のとき' do
1231       it '入れ替えもシフトもせず、tを空のままにしている' do
1232         #結果、tに欠番が生じてシリアライズチェックでひっかかる
1233       end
1234     end
1235   end
1236   describe '編集許可に於いて' do
1237     before do
1238       @comic = FactoryGirl.create :comic, :author_id => @author.id
1239       @story = FactoryGirl.build :story, :t => nil, :comic_id => @comic.id
1240     end
1241     context 'つつがなく終わるとき' do
1242       it 'trueを返す' do
1243         r = @story.allow? @author
1244         r.should be_true
1245       end
1246     end
1247     context 'コミックで引っかかるとき' do
1248       it 'falseを返す' do
1249         Comic.any_instance.stub(:own?).with(any_args).and_return(false)
1250         r = @story.allow? @other_author
1251         r.should be_false
1252       end
1253     end
1254     context 'コミックが指定されていなかったとき' do
1255       it 'nilを返す' do
1256         Comic.any_instance.stub(:own?).with(any_args).and_return(true)
1257         @story.comic_id = nil
1258         r = @story.allow? @author
1259         r.should eq nil
1260       end
1261     end
1262   end
1263   describe '保存に於いて' do
1264     before do
1265       @comic = FactoryGirl.create :comic, :author_id => @author.id
1266       @story = FactoryGirl.build :story, :t => nil, :comic_id => @comic.id
1267     end
1268     context 'つつがなく終わるとき' do
1269       it '編集許可チェックを依頼している' do
1270         Story.any_instance.stub(:allow?).with(any_args).and_return(true)
1271         Story.any_instance.should_receive(:allow?).with(any_args).exactly(1)
1272         r = @story.store @author
1273       end
1274       it '順序入れ替えを依頼している' do
1275         Story.any_instance.stub(:rotate).with(any_args).and_return(0)
1276         Story.any_instance.should_receive(:rotate).with(any_args).exactly(1)
1277         Story.any_instance.stub(:save).with(any_args).and_return(true)
1278         Story.stub(:validate_t).with(any_args).and_return(true)
1279         r = @story.store @author
1280       end
1281       it '保存を依頼している' do
1282         Story.stub(:new_t).with(any_args).and_return(0)
1283         Story.any_instance.stub(:save).with(any_args).and_return(true)
1284         Story.any_instance.should_receive(:save).with(any_args).exactly(1)
1285         Story.stub(:validate_t).with(any_args).and_return(true)
1286         r = @story.store @author
1287       end
1288       it 'tのシリアライズチェックを依頼している' do
1289         Story.stub(:new_t).with(any_args).and_return(0)
1290         Story.any_instance.stub(:save).with(any_args).and_return(true)
1291         Story.stub(:validate_t).with(any_args).and_return(true)
1292         Story.should_receive(:validate_t).with(any_args).exactly(1)
1293         r = @story.store @author
1294       end
1295     end
1296     #入れ替えテストと同じテストを実施。こちらはシフトだけでなく本尊も更新されている
1297     context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で2に挿入したとき' do
1298       before do
1299         @comic2 = FactoryGirl.create :comic, :author_id => @author.id
1300         @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
1301         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1302         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1303         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1304         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
1305         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
1306         @story6 = FactoryGirl.build :story, :t => 2, :comic_id => @comic.id
1307       end
1308       it '既存のt0には変化がない' do
1309         @story6.store @author
1310         @story.reload
1311         @story.t.should eq 0
1312       end
1313       it '既存のt1には変化がない' do
1314         @story6.store @author
1315         @story2.reload
1316         @story2.t.should eq 1
1317       end
1318       it '既存のt2を3にシフトしている' do
1319         @story6.store @author
1320         @story3.reload
1321         @story3.t.should eq 3
1322       end
1323       it '既存のt3を4にシフトしている' do
1324         @story6.store @author
1325         @story4.reload
1326         @story4.t.should eq 4
1327       end
1328       it '既存のt5を5にシフトしている' do
1329         @story6.store @author
1330         @story5.reload
1331         @story5.t.should eq 5
1332       end
1333       it '新規のt2が作成されている' do
1334         @story6.store @author
1335         @story6.reload
1336         @story6.t.should eq 2
1337       end
1338       it '他のコミックに影響がない' do
1339         @ot = @storyc2.t
1340         @story6.store @author
1341         @storyc2.reload
1342         @storyc2.t.should eq @ot
1343       end
1344     end
1345     context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で3を1に移動したとき' do
1346       before do
1347         @comic2 = FactoryGirl.create :comic, :author_id => @author.id
1348         @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
1349         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1350         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1351         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1352         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
1353         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
1354         @ot = @story4.t
1355         @story4.t = 1
1356       end
1357       it '既存のt0には変化がない' do
1358         @story4.store  @author, @ot
1359         @story.reload
1360         @story.t.should eq 0
1361       end
1362       it '既存のt4には変化がない' do
1363         @story4.store @author, @ot
1364         @story5.reload
1365         @story5.t.should eq 4
1366       end
1367       it '既存のt1を2にシフトしている' do
1368         @story4.store @author, @ot
1369         @story2.reload
1370         @story2.t.should eq 2
1371       end
1372       it '既存のt2を3にシフトしている' do
1373         @story4.store @author, @ot
1374         @story3.reload
1375         @story3.t.should eq 3
1376       end
1377       it '既存のt3を1にシフトしている' do
1378         @story4.store @author, @ot
1379         @story4.reload
1380         @story4.t.should eq 1
1381       end
1382       it '他のコミックに影響がない' do
1383         @story4.store @author, @ot
1384         @storyc2.reload
1385         @storyc2.t.should eq 0
1386       end
1387     end
1388     context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で1を3に移動したとき' do
1389       before do
1390         @comic2 = FactoryGirl.create :comic, :author_id => @author.id
1391         @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
1392         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1393         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1394         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1395         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
1396         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
1397         @ot = @story2.t
1398         @story2.t = 3
1399       end
1400       it '既存のt0には変化がない' do
1401         @story2.store @author, @ot
1402         @story.reload
1403         @story.t.should eq 0
1404       end
1405       it '既存のt4には変化がない' do
1406         @story2.store @author, @ot
1407         @story5.reload
1408         @story5.t.should eq 4
1409       end
1410       it '既存のt1を3にシフトしている' do
1411         @story2.store @author, @ot
1412         @story2.reload
1413         @story2.t.should eq 3
1414       end
1415       it '既存のt2を1にシフトしている' do
1416         @story2.store @author, @ot
1417         @story3.reload
1418         @story3.t.should eq 1
1419       end
1420       it '既存のt3を2にシフトしている' do
1421         @story2.store @author, @ot
1422         @story4.reload
1423         @story4.t.should eq 2
1424       end
1425       it '他のコミックに影響がない' do
1426         @story2.store @author, @ot
1427         @storyc2.reload
1428         @storyc2.t.should eq 0
1429       end
1430     end
1431     #ロールバックテスト。入れ替えが直接DBをいじるので、すべてのケースで確実にロールバックを確認する
1432     context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で2に挿入したが保存に失敗したとき' do
1433       before do
1434         Story.any_instance.stub(:save).with(any_args).and_return(false)
1435         @comic2 = FactoryGirl.create :comic, :author_id => @author.id
1436         @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
1437         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1438         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1439         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1440         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
1441         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
1442         @story6 = FactoryGirl.build :story, :t => 2, :comic_id => @comic.id
1443       end
1444       it '既存のtに変化がない' do
1445         @story6.store @author
1446         @story.reload
1447         @story.t.should eq 0
1448         @story2.reload
1449         @story2.t.should eq 1
1450         @story3.reload
1451         @story3.t.should eq 2
1452         @story4.reload
1453         @story4.t.should eq 3
1454         @story5.reload
1455         @story5.t.should eq 4
1456         @storyc2.reload
1457         @storyc2.t.should eq 0
1458       end
1459       it 'falseを返す' do
1460         r = @story6.store @author
1461         r.should be_false
1462       end
1463     end
1464     context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で3を1に移動したがシリアルチェックに失敗したとき' do
1465       before do
1466         Story.stub(:validate_t).with(any_args).and_return(false)
1467         @comic2 = FactoryGirl.create :comic, :author_id => @author.id
1468         @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id
1469         @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1470         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1471         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1472         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
1473         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
1474         @ot = @story4.t
1475         @story4.t = 1
1476       end
1477       it '既存のtに変化がない' do
1478         @story4.store @author, @ot
1479         @story.reload
1480         @story.t.should eq 0
1481         @story2.reload
1482         @story2.t.should eq 1
1483         @story3.reload
1484         @story3.t.should eq 2
1485         @story4.reload
1486         @story4.t.should eq 3
1487         @story5.reload
1488         @story5.t.should eq 4
1489         @storyc2.reload
1490         @storyc2.t.should eq 0
1491       end
1492       it 'falseを返す' do
1493         r = @story4.store @author, @ot
1494         r.should be_false
1495       end
1496       it 'tにエラーメッセージが入っている' do
1497         @story4.store @author, @ot
1498         @story4.errors[:t].should_not be_empty
1499         @story4.valid?.should be_true
1500       end
1501     end
1502     context '編集不可だったとき' do
1503       before do
1504         @story = FactoryGirl.build :story, :t => 0, :comic_id => @comic.id
1505         Story.any_instance.stub(:allow?).and_return(false)
1506       end
1507       it '403Forbidden例外を返す' do
1508         lambda{
1509           @story.store @author
1510         }.should raise_error(ActiveRecord::Forbidden)
1511       end
1512     end
1513   end
1514   describe '切り詰め処理つき削除に於いて' do
1515     before do
1516       @comic = FactoryGirl.create :comic, :author_id => @author.id
1517       @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id
1518     end
1519     context 'つつがなく終わるとき' do
1520       it '削除を依頼している' do
1521         Story.any_instance.stub(:destroy_with_story_sheet).with(any_args).and_return(true)
1522         Story.any_instance.should_receive(:destroy_with_story_sheet).with(any_args).exactly(1)
1523         r = @story.destroy_and_shorten
1524       end
1525       it '削除される' do
1526         lambda{
1527           @story.destroy_and_shorten
1528         }.should change(Story, :count ).by(-1)
1529       end
1530       it 'Trueを返す' do
1531         r = @story.destroy_and_shorten
1532         r.should be_true 
1533       end
1534     end
1535     context '削除に失敗したとき' do
1536       before do
1537         Story.any_instance.stub(:destroy_with_story_sheet).and_return(false)
1538       end
1539       it 'ロールバックされる' do
1540         lambda{
1541           @story.destroy_and_shorten
1542         }.should_not change(Story, :count )
1543       end
1544       it 'Falseを返す' do
1545         r = @story.destroy_and_shorten
1546         r.should be_false
1547       end
1548     end
1549     #連携テスト。切り詰めが直接DBをいじる
1550     context '2件で先頭を削除したとき' do
1551       before do
1552         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1553       end
1554       it '行が削除される' do
1555         lambda{
1556           @story.destroy_and_shorten
1557         }.should change(Story, :count ).by(-1)
1558       end
1559       it '先頭は削除される' do
1560         @story.destroy_and_shorten
1561         lambda{
1562           Story.find @story.id
1563         }.should raise_error(ActiveRecord::RecordNotFound)
1564       end
1565       it '2件目は前に詰められる' do
1566         @story.destroy_and_shorten
1567         @story2.reload
1568         @story2.t.should eq 0
1569       end
1570     end
1571     context '3件で先頭を削除したとき' do
1572       before do
1573         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1574         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1575       end
1576       it '行が削除される' do
1577         lambda{
1578           @story.destroy_and_shorten
1579         }.should change(Story, :count ).by(-1)
1580       end
1581       it '先頭は削除される' do
1582         @story.destroy_and_shorten
1583         lambda{
1584           Story.find @story.id
1585         }.should raise_error(ActiveRecord::RecordNotFound)
1586       end
1587       it '2件目は前に詰められる' do
1588         @story.destroy_and_shorten
1589         @story2.reload
1590         @story2.t.should eq 0
1591       end
1592       it '3件目は前に詰められる' do
1593         @story.destroy_and_shorten
1594         @story3.reload
1595         @story3.t.should eq 1
1596       end
1597     end
1598     context '5件で3件目を削除したとき' do
1599       before do
1600         @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id
1601         @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id
1602         @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id
1603         @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id
1604       end
1605       it '行が削除される' do
1606         lambda{
1607           @story3.destroy_and_shorten
1608         }.should change(Story, :count ).by(-1)
1609       end
1610       it '1件目は変化がない' do
1611         @story3.destroy_and_shorten
1612         @story.reload
1613         @story.t.should eq 0
1614       end
1615       it '2件目は変化がない' do
1616         @story3.destroy_and_shorten
1617         @story2.reload
1618         @story2.t.should eq 1
1619       end
1620       it '3件目は削除される' do
1621         @story3.destroy_and_shorten
1622         lambda{
1623           Story.find @story3.id
1624         }.should raise_error(ActiveRecord::RecordNotFound)
1625       end
1626       it '4件目は前に詰められる' do
1627         @story3.destroy_and_shorten
1628         @story4.reload
1629         @story4.t.should eq 2
1630       end
1631       it '5件目は前に詰められる' do
1632         @story3.destroy_and_shorten
1633         @story5.reload
1634         @story5.t.should eq 3
1635       end
1636     end
1637     #ロールバックテスト。切り詰めが直接DBをいじるので、すべてのケースで確実にロールバックを確認する
1638   end
1639   describe '削除に於いて' do
1640     before do
1641       @comic = FactoryGirl.create :comic, :author_id => @author.id
1642       @story = FactoryGirl.create :story, :comic_id => @comic.id
1643       @sheet = FactoryGirl.create :sheet, :author_id => @author.id
1644       @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id
1645       @other_comic = FactoryGirl.create :comic, :author_id => @author.id
1646       @other_story = FactoryGirl.create :story, :comic_id => @other_comic.id
1647       @other_sheet = FactoryGirl.create :sheet, :author_id => @author.id
1648       @other_story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id
1649     end
1650     context 'つつがなく終わるとき' do
1651       it '自身を削除する' do
1652         lambda {
1653           r = @story.destroy_with_story_sheet
1654         }.should change(Story, :count).by(-1)
1655         lambda {
1656           r = Story.find @story.id
1657         }.should raise_error
1658       end
1659       it '自身にリンクしているスト紙をすべて削除する' do
1660         lambda {
1661           r = @story.destroy_with_story_sheet
1662         }.should change(StorySheet, :count).by(-1)
1663         lambda {
1664           r = StorySheet.find @story_sheet.id
1665         }.should raise_error
1666       end
1667       it 'Trueを返す' do
1668         r = @story.destroy_with_story_sheet
1669         r.should be_true
1670       end
1671     end
1672     context '削除に失敗したとき' do
1673       before do
1674         StorySheet.any_instance.stub(:destroy).with(any_args).and_return(false)
1675       end
1676       it 'Falseを返す' do
1677         r = @story.destroy_with_story_sheet
1678         r.should be_false
1679       end
1680       it 'ロールバックしている' do
1681         lambda {
1682           r = @story.destroy_with_story_sheet
1683         }.should_not change(Story, :count)
1684         lambda {
1685           r = @story.destroy_with_story_sheet
1686         }.should_not change(StorySheet, :count)
1687       end
1688     end
1689   end
1690 end