OSDN Git Service

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