1+ require 'rails_helper'
2+
3+ RSpec . describe "Dojos" , type : :request do
4+ describe "GET /dojos with year parameter" do
5+ before do
6+ # テストデータの準備
7+ # 2020年に作成されたアクティブな道場
8+ @dojo_2020_active = create ( :dojo ,
9+ name : "Test Dojo 2020" ,
10+ created_at : "2020-06-01" ,
11+ is_active : true
12+ )
13+
14+ # 2020年に作成、2021年に非アクティブ化
15+ @dojo_2020_inactive = create ( :dojo ,
16+ name : "Test Dojo 2020 Inactive" ,
17+ created_at : "2020-01-01" ,
18+ is_active : false ,
19+ inactivated_at : "2021-03-01"
20+ )
21+
22+ # 2021年に作成されたアクティブな道場
23+ @dojo_2021_active = create ( :dojo ,
24+ name : "Test Dojo 2021" ,
25+ created_at : "2021-01-01" ,
26+ is_active : true
27+ )
28+
29+ # 2019年に作成、2020年に非アクティブ化(2020年末時点では非アクティブ)
30+ @dojo_2019_inactive = create ( :dojo ,
31+ name : "Test Dojo 2019 Inactive" ,
32+ created_at : "2019-01-01" ,
33+ is_active : false ,
34+ inactivated_at : "2020-06-01"
35+ )
36+
37+ # counter > 1 の道場
38+ @dojo_multi_branch = create ( :dojo ,
39+ name : "Multi Branch Dojo" ,
40+ created_at : "2020-01-01" ,
41+ is_active : true ,
42+ counter : 3
43+ )
44+ end
45+
46+ describe "year parameter validation" do
47+ it "accepts valid years (2012 to current year)" do
48+ current_year = Date . current . year
49+ [ 2012 , 2020 , current_year ] . each do |year |
50+ get dojos_path ( year : year , format : :json )
51+ expect ( response ) . to have_http_status ( :success )
52+ end
53+ end
54+
55+ it "rejects years before 2012" do
56+ get dojos_path ( year : 2011 , format : :json )
57+ expect ( response ) . to redirect_to ( dojos_path )
58+ expect ( flash [ :alert ] ) . to include ( "2012年から" )
59+ end
60+
61+ it "rejects years after current year" do
62+ future_year = Date . current . year + 1
63+ get dojos_path ( year : future_year , format : :json )
64+ expect ( response ) . to redirect_to ( dojos_path )
65+ expect ( flash [ :alert ] ) . to include ( "無効です" )
66+ end
67+
68+ it "handles invalid year strings" do
69+ get dojos_path ( year : "invalid" , format : :json )
70+ expect ( response ) . to redirect_to ( dojos_path )
71+ expect ( flash [ :alert ] ) . to include ( "無効" )
72+ end
73+ end
74+
75+ describe "year filtering functionality" do
76+ context "when no year parameter is provided" do
77+ it "returns all dojos (active and inactive)" do
78+ get dojos_path ( format : :json )
79+ json_response = JSON . parse ( response . body )
80+
81+ dojo_ids = json_response . map { |d | d [ "id" ] }
82+ expect ( dojo_ids ) . to include ( @dojo_2020_active . id )
83+ expect ( dojo_ids ) . to include ( @dojo_2020_inactive . id )
84+ expect ( dojo_ids ) . to include ( @dojo_2021_active . id )
85+ expect ( dojo_ids ) . to include ( @dojo_2019_inactive . id )
86+ expect ( dojo_ids ) . to include ( @dojo_multi_branch . id )
87+ end
88+
89+ it "includes inactive dojos in HTML format" do
90+ get dojos_path ( format : :html )
91+ expect ( assigns ( :dojos ) . map { |d | d [ :id ] } ) . to include ( @dojo_2020_inactive . id )
92+ end
93+
94+ it "includes inactive dojos in CSV format" do
95+ get dojos_path ( format : :csv )
96+ csv = CSV . parse ( response . body , headers : true )
97+ csv_ids = csv . map { |row | row [ "ID" ] . to_i }
98+ expect ( csv_ids ) . to include ( @dojo_2020_inactive . id )
99+ end
100+ end
101+
102+ context "when year=2020 is specified" do
103+ it "returns only dojos active at the end of 2020" do
104+ get dojos_path ( year : 2020 , format : :json )
105+ json_response = JSON . parse ( response . body )
106+
107+ dojo_ids = json_response . map { |d | d [ "id" ] }
108+ # 2020年末時点でアクティブだった道場のみ含まれる
109+ expect ( dojo_ids ) . to include ( @dojo_2020_active . id )
110+ expect ( dojo_ids ) . to include ( @dojo_multi_branch . id )
111+
112+ # 2020年末時点で非アクティブだった道場は含まれない
113+ expect ( dojo_ids ) . not_to include ( @dojo_2019_inactive . id )
114+
115+ # 2021年に作成された道場は含まれない
116+ expect ( dojo_ids ) . not_to include ( @dojo_2021_active . id )
117+
118+ # 2021年に非アクティブ化された道場は2020年末時点ではアクティブなので含まれる
119+ expect ( dojo_ids ) . to include ( @dojo_2020_inactive . id )
120+ end
121+
122+ it "filters correctly in HTML format" do
123+ get dojos_path ( year : 2020 , format : :html )
124+
125+ dojo_ids = assigns ( :dojos ) . map { |d | d [ :id ] }
126+ expect ( dojo_ids ) . to include ( @dojo_2020_active . id )
127+ expect ( dojo_ids ) . not_to include ( @dojo_2019_inactive . id )
128+ expect ( dojo_ids ) . not_to include ( @dojo_2021_active . id )
129+ end
130+
131+ it "filters correctly in CSV format" do
132+ get dojos_path ( year : 2020 , format : :csv )
133+
134+ csv = CSV . parse ( response . body , headers : true )
135+ csv_ids = csv . map { |row | row [ "ID" ] . to_i }
136+ expect ( csv_ids ) . to include ( @dojo_2020_active . id )
137+ expect ( csv_ids ) . not_to include ( @dojo_2019_inactive . id )
138+ expect ( csv_ids ) . not_to include ( @dojo_2021_active . id )
139+ end
140+ end
141+
142+ context "when year=2021 is specified" do
143+ it "returns dojos active at the end of 2021" do
144+ get dojos_path ( year : 2021 , format : :json )
145+ json_response = JSON . parse ( response . body )
146+
147+ dojo_ids = json_response . map { |d | d [ "id" ] }
148+ # 2021年末時点でアクティブな道場
149+ expect ( dojo_ids ) . to include ( @dojo_2020_active . id )
150+ expect ( dojo_ids ) . to include ( @dojo_2021_active . id )
151+ expect ( dojo_ids ) . to include ( @dojo_multi_branch . id )
152+
153+ # 2021年3月に非アクティブ化された道場は含まれない
154+ expect ( dojo_ids ) . not_to include ( @dojo_2020_inactive . id )
155+ expect ( dojo_ids ) . not_to include ( @dojo_2019_inactive . id )
156+ end
157+ end
158+ end
159+
160+ describe "counter field in output" do
161+ it "includes counter field in JSON response" do
162+ get dojos_path ( format : :json )
163+ json_response = JSON . parse ( response . body )
164+
165+ multi_branch = json_response . find { |d | d [ "id" ] == @dojo_multi_branch . id }
166+ expect ( multi_branch [ "counter" ] ) . to eq ( 3 )
167+ end
168+
169+ it "includes counter column in CSV with sum total" do
170+ get dojos_path ( format : :csv )
171+ csv = CSV . parse ( response . body , headers : true )
172+
173+ # ヘッダーに支部数が含まれる
174+ expect ( csv . headers ) . to include ( "支部数" )
175+
176+ # 各道場のcounter値が含まれる
177+ multi_branch_row = csv . find { |row | row [ "ID" ] == @dojo_multi_branch . id . to_s }
178+ expect ( multi_branch_row [ "支部数" ] ) . to eq ( "3" )
179+ end
180+
181+ it "calculates counter_sum correctly" do
182+ get dojos_path ( format : :html )
183+
184+ expected_sum = [ @dojo_2020_active , @dojo_2020_inactive , @dojo_2021_active ,
185+ @dojo_2019_inactive , @dojo_multi_branch ] . sum ( &:counter )
186+ expect ( assigns ( :counter_sum ) ) . to eq ( expected_sum )
187+ end
188+
189+ it "calculates counter_sum for filtered year" do
190+ get dojos_path ( year : 2020 , format : :html )
191+
192+ # 2020年末時点でアクティブな道場のcounter合計
193+ active_in_2020 = [ @dojo_2020_active , @dojo_2020_inactive , @dojo_multi_branch ]
194+ expected_sum = active_in_2020 . sum ( &:counter )
195+ expect ( assigns ( :counter_sum ) ) . to eq ( expected_sum )
196+ end
197+ end
198+
199+ describe "CSV format specifics" do
200+ it "includes correct headers" do
201+ get dojos_path ( format : :csv )
202+ csv = CSV . parse ( response . body , headers : true )
203+
204+ expect ( csv . headers ) . to eq ( [ 'ID' , '道場名' , '支部数' , '都道府県' , 'URL' , '設立日' , '状態' ] )
205+ end
206+
207+ it "includes total row at the end" do
208+ get dojos_path ( format : :csv )
209+ lines = response . body . split ( "\n " )
210+
211+ # 最後の行が合計行
212+ last_line = lines . last
213+ expect ( last_line ) . to include ( "合計" )
214+ expect ( last_line ) . to include ( "道場" )
215+ end
216+
217+ it "formats dates correctly" do
218+ get dojos_path ( format : :csv )
219+ csv = CSV . parse ( response . body , headers : true )
220+
221+ first_dojo = csv . first
222+ expect ( first_dojo [ "設立日" ] ) . to match ( /\d {4}-\d {2}-\d {2}/ )
223+ end
224+
225+ it "shows active/inactive status correctly" do
226+ get dojos_path ( format : :csv )
227+ csv = CSV . parse ( response . body , headers : true )
228+
229+ active_row = csv . find { |row | row [ "ID" ] == @dojo_2020_active . id . to_s }
230+ expect ( active_row [ "状態" ] ) . to eq ( "アクティブ" )
231+
232+ inactive_row = csv . find { |row | row [ "ID" ] == @dojo_2020_inactive . id . to_s }
233+ expect ( inactive_row [ "状態" ] ) . to eq ( "非アクティブ" )
234+ end
235+ end
236+
237+ describe "HTML format year selection UI" do
238+ it "shows year selection form" do
239+ get dojos_path
240+ expect ( response . body ) . to include ( '年を選択' )
241+ expect ( response . body ) . to include ( '<select' )
242+ expect ( response . body ) . to include ( '2012' )
243+ expect ( response . body ) . to include ( Date . current . year . to_s )
244+ end
245+
246+ it "displays selected year message when filtered" do
247+ get dojos_path ( year : 2020 )
248+ expect ( response . body ) . to include ( '2020年末時点' )
249+ expect ( response . body ) . to include ( 'アクティブな道場を表示中' )
250+ end
251+
252+ it "includes CSV and JSON download links with year parameter" do
253+ get dojos_path ( year : 2020 )
254+ expect ( response . body ) . to include ( 'CSV' )
255+ expect ( response . body ) . to include ( 'JSON' )
256+ expect ( response . body ) . to include ( 'year=2020' )
257+ end
258+ end
259+ end
260+ end
0 commit comments