Skip to content

Commit 6f6409b

Browse files
committed
test: 道場年次フィルタリング機能のRSpecテストを追加
script/test_yearly_dojos_count.rb の内容をRSpecに移行。 CIでテストDBを使って自動実行可能に。 追加したテスト: - 年パラメータのバリデーション(2012-現在年) - 年次フィルタリング機能(全道場 vs 特定年のアクティブ道場) - counter(支部数)フィールドの表示と集計 - CSV形式の出力(ヘッダー、日付形式、合計行) - HTML形式の年選択UI また、Dojoファクトリーに必要な属性を追加。
1 parent 8a9a048 commit 6f6409b

File tree

2 files changed

+266
-0
lines changed

2 files changed

+266
-0
lines changed

spec/factories/dojos.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,11 @@
44
email { '' }
55
description { 'description' }
66
prefecture_id { 13 }
7+
tags { ['Scratch'] }
8+
url { 'https://example.com' }
9+
logo { '/img/dojos/default.webp' }
10+
counter { 1 }
11+
is_active { true }
12+
order { 131001 }
713
end
814
end

spec/requests/dojos_spec.rb

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
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

Comments
 (0)