Back ported a lot of changes made to the Koans directory.
[ruby_koans.git] / src / about_proxy_object_project.rb
1 require File.expand_path(File.dirname(__FILE__) + '/edgecase')
2
3 # Project: Create a Proxy Class
4 #
5 # In this assignment, create a proxy class (one is started for you
6 # below).  You should be able to initialize the proxy object with any
7 # object.  Any messages sent to the proxy object should be forwarded
8 # to the target object.  As each message is sent, the proxy should
9 # record the name of the method sent.
10 #
11 # The proxy class is started for you.  You will need to add a method
12 # missing handler and any other supporting methods.  The specification
13 # of the Proxy class is given in the AboutProxyObjectProject koan.
14
15 class Proxy
16   def initialize(target_object)
17     @object = target_object
18     # ADD MORE CODE HERE
19     #--
20     @messages = []
21     #++
22   end
23
24   # WRITE CODE HERE
25   #--
26   attr_reader :messages
27
28   def method_missing(sym, *args, &block)
29     @messages << sym
30     @object.send(sym, *args, &block)
31   end
32
33   def called?(method)
34     @messages.include?(method)
35   end
36
37   def number_of_times_called(method)
38     @messages.select { |m| m == method }.size
39   end
40   #++
41 end
42
43 # The proxy object should pass the following Koan:
44 #
45 class AboutProxyObjectProject < EdgeCase::Koan
46   def test_proxy_method_returns_wrapped_object
47     # NOTE: The Television class is defined below
48     tv = Proxy.new(Television.new)
49
50     # HINT: Proxy class is defined above, may need tweaking...
51
52     assert tv.instance_of?(Proxy)
53   end
54
55   def test_tv_methods_still_perform_their_function
56     tv = Proxy.new(Television.new)
57
58     tv.channel = 10
59     tv.power
60
61     assert_equal 10, tv.channel
62     assert tv.on?
63   end
64
65   def test_proxy_records_messages_sent_to_tv
66     tv = Proxy.new(Television.new)
67
68     tv.power
69     tv.channel = 10
70
71     assert_equal [:power, :channel=], tv.messages
72   end
73
74   def test_proxy_handles_invalid_messages
75     tv = Proxy.new(Television.new)
76
77     assert_raise(NoMethodError) do
78       tv.no_such_method
79     end
80   end
81
82   def test_proxy_reports_methods_have_been_called
83     tv = Proxy.new(Television.new)
84
85     tv.power
86     tv.power
87
88     assert tv.called?(:power)
89     assert ! tv.called?(:channel)
90   end
91
92   def test_proxy_counts_method_calls
93     tv = Proxy.new(Television.new)
94
95     tv.power
96     tv.channel = 48
97     tv.power
98
99     assert_equal 2, tv.number_of_times_called(:power)
100     assert_equal 1, tv.number_of_times_called(:channel=)
101     assert_equal 0, tv.number_of_times_called(:on?)
102   end
103
104   def test_proxy_can_record_more_than_just_tv_objects
105     proxy = Proxy.new("Code Mash 2009")
106
107     proxy.upcase!
108     result = proxy.split
109
110     assert_equal ["CODE", "MASH", "2009"], result
111     assert_equal [:upcase!, :split], proxy.messages
112   end
113 end
114
115
116 # ====================================================================
117 # The following code is to support the testing of the Proxy class.  No
118 # changes should be necessary to anything below this comment.
119
120 # Example class using in the proxy testing above.
121 class Television
122   attr_accessor :channel
123
124   def power
125     if @power == :on
126       @power = :off
127     else
128       @power = :on
129     end
130   end
131
132   def on?
133     @power == :on
134   end
135 end
136
137 # Tests for the Television class.  All of theses tests should pass.
138 class TelevisionTest < EdgeCase::Koan
139   def test_it_turns_on
140     tv = Television.new
141
142     tv.power
143     assert tv.on?
144   end
145
146   def test_it_also_turns_off
147     tv = Television.new
148
149     tv.power
150     tv.power
151
152     assert ! tv.on?
153   end
154
155   def test_edge_case_on_off
156     tv = Television.new
157
158     tv.power
159     tv.power
160     tv.power
161
162     assert tv.on?
163
164     tv.power
165
166     assert ! tv.on?
167   end
168
169   def test_can_set_the_channel
170     tv = Television.new
171
172     tv.channel = 11
173     assert_equal 11, tv.channel
174   end
175 end