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