Skip to content

Commit 8b06f69

Browse files
committed
Extract traffic light signals as their own object
1 parent 1c35b07 commit 8b06f69

File tree

6 files changed

+243
-165
lines changed

6 files changed

+243
-165
lines changed

katas/4-gilded_traffic_light/fell/main.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@ def progress_lights
3434
@lights.each do |light|
3535
light.progress!
3636

37-
# No car crashes!
37+
# TODO: This is only necessary because the timings are such that we will
38+
# have a clash each cycle; an ideal solution would be to change the
39+
# timings, but the existing output remaining the same is a requirement
40+
#
41+
# Nothing to do unless there is goign to be a conflict
3842
next unless @lights.all?(&:allows_traffic?)
3943

4044
# Since we're turning green, then the other light must turn red
41-
@lights.find { it.direction != light.direction }.red!
45+
@lights.find { it != light }.red!
4246
end
4347
end
4448
end

katas/4-gilded_traffic_light/fell/pedestrian_signal.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
require_relative 'lib/colorize'
22

3-
# Tracks whether pedestrians can walk or not
4-
# and provides presentation logic
3+
# Tracks whether pedestrians can walk or not and provides presentation logic
54
class PedestrianSignal
65
include Colorize
76

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
require_relative '../traffic_light'
2+
require 'minitest/autorun'
3+
4+
class TrafficLightStateTest < Minitest::Test
5+
def red_test
6+
red = TrafficLightState.red
7+
8+
assert_equal false, red.allows_traffic?
9+
assert_equal true, red.allows_pedestrians?
10+
end
11+
12+
def green_test
13+
green = TrafficLightState.green
14+
15+
assert_equal true, green.allows_traffic?
16+
assert_equal false, green.allows_pedestrians?
17+
end
18+
19+
def amber_test
20+
amber = TrafficLightState.amber
21+
22+
assert_equal true, amber.allows_traffic?
23+
assert_equal false, amber.allows_pedestrians?
24+
end
25+
26+
def complete_test
27+
state = TrafficLightState.new(state: TrafficLightState::RED, timer: 0)
28+
29+
assert_equal true, state.complete?
30+
end
31+
32+
def incomplete_test
33+
state = TrafficLightState.new(state: TrafficLightState::RED, timer: 1)
34+
35+
assert_equal false, state.complete?
36+
end
37+
38+
def next_state_test
39+
assert_equal TrafficLightState.green, TrafficLightState.red.next_state
40+
assert_equal TrafficLightState.amber, TrafficLightState.green.next_state
41+
assert_equal TrafficLightState.red, TrafficLightState.amber.next_state
42+
end
43+
44+
def progress_timer_test
45+
state = TrafficLightState.new(state: TrafficLightState::RED, timer: 1)
46+
47+
assert_equal(false, timer.complete?)
48+
state.progress_timer
49+
assert_equal(true, timer.complete?)
50+
end
51+
52+
def to_s_contains_red_state
53+
state = TrafficLightState.new(state: TrafficLightState::RED, timer: 1)
54+
55+
assert_includes state.to_s, "State: \e[31mred\e[0m"
56+
end
57+
58+
def to_s_contains_green_state
59+
state = TrafficLightState.new(state: TrafficLightState::GREEN, timer: 1)
60+
61+
assert_includes state.to_s, "State: \e[32mgreen\e[0m"
62+
end
63+
64+
def to_s_contains_amber_state
65+
state = TrafficLightState.new(state: TrafficLightState::AMBER, timer: 1)
66+
67+
assert_includes state.to_s, "State: \e[33mamber\e[0m"
68+
end
69+
70+
def to_s_contains_timer
71+
state = TrafficLightState.new(state: TrafficLightState::AMBER, timer: 1)
72+
73+
assert_includes state.to_s, 'Time left: 1s'
74+
end
75+
end

katas/4-gilded_traffic_light/fell/test/traffic_light_test.rb

Lines changed: 37 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2,174 +2,125 @@
22
require 'minitest/autorun'
33

44
class TrafficLightTest < Minitest::Test
5-
def test_direction
6-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::GREEN_STATE)
7-
8-
assert_equal 'Widdershins', light.direction
9-
end
10-
11-
def test_state
12-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::GREEN_STATE)
13-
14-
# reader
15-
assert_equal TrafficLight::GREEN_STATE, light.state
16-
17-
# writer
18-
light.state = 'test_state'
19-
assert_equal 'test_state', light.state
20-
end
21-
22-
def test_timer
23-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::GREEN_STATE)
24-
25-
# reader
26-
assert_equal 55, light.timer
27-
28-
# writer
29-
light.timer = 101
30-
assert_equal 101, light.timer
31-
end
32-
335
def test_direction_to_s
34-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::GREEN_STATE)
6+
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLightState::GREEN)
357
light.to_s
368

379
assert_includes light.to_s, 'Direction: Widdershins'
3810
end
3911

4012
def test_time_left_to_s
41-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::GREEN_STATE)
13+
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLightState::GREEN)
4214
light.to_s
4315

4416
assert_includes light.to_s, 'Time left: 55s'
4517
end
4618

4719
def test_red_light_to_s
48-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::RED_STATE)
20+
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLightState::RED)
4921

5022
light.to_s
5123

5224
assert_includes light.to_s, "\e[31mred\e[0m"
5325
end
5426

5527
def test_green_light_to_s
56-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::GREEN_STATE)
28+
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLightState::GREEN)
5729

5830
light.to_s
5931

6032
assert_includes light.to_s, "\e[32mgreen\e[0m"
6133
end
6234

6335
def test_amber_light_to_s
64-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::AMBER_STATE)
36+
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLightState::AMBER)
6537

6638
light.to_s
6739

6840
assert_includes light.to_s, "\e[33mamber\e[0m"
6941
end
7042

7143
def test_progress_with_incomplete_timer
72-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::GREEN_STATE)
44+
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLightState::GREEN)
45+
7346
light.progress!
7447

75-
assert_equal 54, light.timer
76-
assert_equal TrafficLight::GREEN_STATE, light.state
48+
assert_includes light.to_s, 'green'
7749
end
7850

79-
def test_progress_progreses_state
80-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::GREEN_STATE)
51+
def test_progress_progreses_state_with_complete_timer
52+
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLightState::GREEN)
8153
light.progress!
8254

83-
assert_equal 3, light.timer
84-
assert_equal TrafficLight::AMBER_STATE, light.state
55+
assert_includes light.to_s, 'amber'
8556
end
8657

87-
def test_cannot_walk_pedestrian_signal_status
88-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::RED_STATE)
89-
90-
light.can_walk = true
58+
def test_inital_pedestrian_signal_status
59+
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLightState::RED)
9160

92-
assert_includes light.pedestrian_signal_status, "Widdershins: \e[32mWALK\e[0m"
61+
# Even on red, pedestrians cannot walk initially
62+
assert_includes light.pedestrian_signal_status, "Widdershins: \e[31mDON'T WALK\e[0m"
9363
end
9464

9565
def test_can_walk_pedestrian_signal_status
96-
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLight::RED_STATE)
66+
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLightState::AMBER)
9767

98-
assert_includes light.pedestrian_signal_status, "Widdershins: \e[31mDON'T WALK\e[0m"
99-
end
100-
101-
def test_current_state_complete
102-
light = TrafficLight.new(direction: 'Widdershins', timer: 0, state: TrafficLight::RED_STATE)
68+
# Progress to red light for traffic
69+
light.next_state!
10370

104-
assert_equal true, light.current_state_complete?
71+
assert_includes light.pedestrian_signal_status, "Widdershins: \e[32mWALK\e[0m"
10572
end
10673

107-
def test_current_state_incomplete
108-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::RED_STATE)
74+
def test_cannot_walk_pedestrian_signal_status
75+
light = TrafficLight.new(direction: 'Widdershins', timer: 55, state: TrafficLightState::GREEN)
76+
77+
# Run through the whole cycle once
78+
3.times do
79+
light.next_state!
80+
end
10981

110-
assert_equal false, light.current_state_complete?
82+
assert_includes light.pedestrian_signal_status, "Widdershins: \e[31mDON'T WALK\e[0m"
11183
end
11284

11385
def test_red
114-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::GREEN_STATE)
86+
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLightState::GREEN)
11587

11688
light.red!
11789

118-
assert_equal TrafficLight::RED_STATE, light.state
119-
assert_equal 10, light.timer
120-
assert_equal true, light.can_walk
121-
end
122-
123-
def test_green
124-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::RED_STATE)
125-
126-
light.green!
127-
128-
assert_equal TrafficLight::GREEN_STATE, light.state
129-
assert_equal 8, light.timer
130-
assert_equal false, light.can_walk
131-
end
132-
133-
def test_amber
134-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::RED_STATE)
135-
136-
light.amber!
137-
138-
assert_equal TrafficLight::AMBER_STATE, light.state
139-
assert_equal 3, light.timer
140-
assert_equal false, light.can_walk
90+
assert_equal false, light.allows_traffic?
91+
assert_equal true, light.allows_pedestrians?
14192
end
14293

14394
def test_next_state
144-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::RED_STATE)
95+
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLightState::RED)
14596

14697
light.next_state!
14798

148-
assert_equal TrafficLight::GREEN_STATE, light.state
99+
assert_includes light.to_s, 'green'
149100

150101
light.next_state!
151102

152-
assert_equal TrafficLight::AMBER_STATE, light.state
103+
assert_includes light.to_s, 'amber'
153104

154105
light.next_state!
155106

156-
assert_equal TrafficLight::RED_STATE, light.state
107+
assert_includes light.to_s, 'red'
157108
end
158109

159110
def test_allows_traffic_red
160-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::RED_STATE)
111+
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLightState::RED)
161112

162113
assert_equal false, light.allows_traffic?
163114
end
164115

165116
def test_allows_traffic_green
166-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::GREEN_STATE)
117+
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLightState::GREEN)
167118

168119
assert_equal true, light.allows_traffic?
169120
end
170121

171122
def test_allows_traffic_amber
172-
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLight::AMBER_STATE)
123+
light = TrafficLight.new(direction: 'Widdershins', timer: 1, state: TrafficLightState::AMBER)
173124

174125
assert_equal true, light.allows_traffic?
175126
end

0 commit comments

Comments
 (0)