1
+ require "undirected_graph"
2
+
3
+ describe UndirectedGraph do
4
+
5
+ #First, accessor methods on an empty graph (to set a good base)
6
+ describe "empty graph" do
7
+ blank = UndirectedGraph . new ( )
8
+
9
+ describe ".vertices" do
10
+ context "given an empty graph" do
11
+ it "returns an empty hash" do
12
+ expect ( blank . vertices ( ) . length ( ) ) . to eql ( 0 )
13
+ end
14
+ end
15
+ end
16
+
17
+ describe ".size" do
18
+ context "given empty graph" do
19
+ it "size should be 0" do
20
+ expect ( blank . size ( ) ) . to eql ( 0 )
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ #mutator methods first:
27
+ describe ".add_vertex!" do
28
+ context "given an empty graph" do
29
+ it "adds exactly one vertex" do
30
+ g = UndirectedGraph . new ( )
31
+
32
+ expect ( g . add_vertex! ( "Water" ) ) . to eql ( true )
33
+ expect ( g . size ) . to eql ( 1 )
34
+ expect ( g . has_vertex? ( "Water" ) ) . to eql ( true )
35
+ end
36
+ end
37
+
38
+ context "graph with different element in it" do
39
+ it "adds the element" do
40
+ g = UndirectedGraph . new ( )
41
+ g . add_vertex! ( "Water" )
42
+
43
+ expect ( g . add_vertex! ( "Fire" ) ) . to eql ( true )
44
+ expect ( g . size ) . to eql ( 2 )
45
+ expect ( g . has_vertex? ( "Fire" ) ) . to eql ( true )
46
+ expect ( g . has_vertex? ( "Water" ) ) . to eql ( true )
47
+ end
48
+ end
49
+
50
+ context "given a graph with the same element in it" do
51
+ it "doesn't add the element" do
52
+ g = UndirectedGraph . new ( )
53
+ g . add_vertex! ( "Water" )
54
+
55
+ expect ( g . add_vertex! ( "Water" ) ) . to eql ( false )
56
+ expect ( g . size ) . to eql ( 1 )
57
+ end
58
+ end
59
+ end
60
+
61
+ describe ".add_edge!" do
62
+ context "given vertices not in the graph" do
63
+ it "throw an error" do
64
+ expect { UndirectedGraph . new ( ) . add_edge! ( "Grass" , "Electric" , 3 ) } . to raise_error ( ArgumentError )
65
+ end
66
+ end
67
+
68
+ context "given vertices without an edge between them" do
69
+ it "creates an edge pointing both ways" do
70
+ g = UndirectedGraph . new ( )
71
+ g . add_vertex! ( "Dragon" )
72
+ g . add_vertex! ( "Fairy" )
73
+
74
+ expect ( g . add_edge! ( "Dragon" , "Fairy" , 2 ) ) . to eql ( true )
75
+ expect ( g . has_edge? ( "Dragon" , "Fairy" ) ) . to eql ( true )
76
+ expect ( g . has_edge? ( "Fairy" , "Dragon" ) ) . to eql ( true )
77
+ expect ( g . weight ( "Dragon" , "Fairy" ) ) . to eql ( 2 )
78
+ expect ( g . weight ( "Fairy" , "Dragon" ) ) . to eql ( 2 )
79
+ end
80
+ end
81
+
82
+ context "given vertices with an edge already between them" do
83
+ it "updates the edge weight" do
84
+ g = UndirectedGraph . new ( )
85
+ g . add_vertex! ( "Dragon" )
86
+ g . add_vertex! ( "Fairy" )
87
+ g . add_edge! ( "Dragon" , "Fairy" , 0 )
88
+
89
+ expect ( g . add_edge! ( "Dragon" , "Fairy" , 2 ) ) . to eql ( false )
90
+ expect ( g . has_edge? ( "Dragon" , "Fairy" ) ) . to eql ( true )
91
+ expect ( g . has_edge? ( "Fairy" , "Dragon" ) ) . to eql ( true )
92
+
93
+ expect ( g . weight ( "Dragon" , "Fairy" ) ) . to eql ( 2 )
94
+ expect ( g . weight ( "Fairy" , "Dragon" ) ) . to eql ( 2 )
95
+ end
96
+ end
97
+
98
+ context "given vertices with an edge made one way" do
99
+ it "updates the edge, even when arguments reversed" do
100
+ g = UndirectedGraph . new ( )
101
+ g . add_vertex! ( "Dragon" )
102
+ g . add_vertex! ( "Fairy" )
103
+ g . add_edge! ( "Dragon" , "Fairy" , 0 )
104
+
105
+ expect ( g . add_edge! ( "Fairy" , "Dragon" , 2 ) ) . to eql ( false )
106
+ expect ( g . has_edge? ( "Dragon" , "Fairy" ) ) . to eql ( true )
107
+ expect ( g . has_edge? ( "Fairy" , "Dragon" ) ) . to eql ( true )
108
+
109
+ expect ( g . weight ( "Dragon" , "Fairy" ) ) . to eql ( 2 )
110
+ expect ( g . weight ( "Fairy" , "Dragon" ) ) . to eql ( 2 )
111
+ end
112
+ end
113
+
114
+ context "given a graph trying to make a self-loop" do
115
+ it "throws an error" do
116
+ g = UndirectedGraph . new ( )
117
+ g . add_vertex! ( "Dragon" )
118
+
119
+ expect { g . add_edge! ( "Dragon" , "Dragon" , 2 ) } . to raise_error ( ArgumentError )
120
+ end
121
+ end
122
+ end
123
+
124
+ describe ".remove_edge!" do
125
+ context "given vertices not in the graph" do
126
+ it "throw an error" do
127
+ expect { UndirectedGraph . new ( ) . remove_edge! ( "Grass" , "Electric" ) } . to raise_error ( ArgumentError )
128
+ end
129
+ end
130
+
131
+ context "given an edge not in graph" do
132
+ it "throw an error" do
133
+ g = UndirectedGraph . new ( )
134
+ g . add_vertex! ( "Grass" )
135
+ g . add_vertex! ( "Electric" )
136
+
137
+ expect { UndirectedGraph . new ( ) . remove_edge! ( "Grass" , "Electric" , 3 ) } . to raise_error ( ArgumentError )
138
+ end
139
+ end
140
+
141
+ context "given an edge in the graph" do
142
+ it "removes the edge between both vertices" do
143
+ g = UndirectedGraph . new ( )
144
+ g . add_vertex! ( "Fighting" )
145
+ g . add_vertex! ( "Steel" )
146
+ g . add_edge! ( "Fighting" , "Steel" , 2 )
147
+
148
+ expect ( g . remove_edge! ( "Fighting" , "Steel" ) ) . to eql ( 2 )
149
+ expect ( g . has_edge? ( "Fighting" , "Steel" ) ) . to eql ( false )
150
+ end
151
+ end
152
+
153
+ context "reverse arguments" do
154
+ it "still removes the edge" do
155
+ g = UndirectedGraph . new ( )
156
+ g = UndirectedGraph . new ( )
157
+ g . add_vertex! ( "Fighting" )
158
+ g . add_vertex! ( "Steel" )
159
+ g . add_edge! ( "Steel" , "Fighting" , 1 )
160
+
161
+ expect ( g . remove_edge! ( "Fighting" , "Steel" ) ) . to eql ( 1 )
162
+ expect ( g . has_edge? ( "Fighting" , "Steel" ) ) . to eql ( false )
163
+ expect ( g . has_edge? ( "Steel" , "Fighting" ) ) . to eql ( false )
164
+ end
165
+ end
166
+ end
167
+
168
+ describe ".remove_vertex!" do
169
+ context "given a graph with no vertices" do
170
+ it "throws an error" do
171
+ expect { UndirectedGraph . new ( ) . remove_vertex! ( "Dark" ) } . to raise_error ( ArgumentError )
172
+ end
173
+ end
174
+
175
+ context "given a graph with that isolated vertex" do
176
+ it "removes that vertex" do
177
+ g = UndirectedGraph . new ( )
178
+ g . add_vertex! ( "Fire" )
179
+
180
+ expect ( g . remove_vertex! ( "Fire" ) ) . to eql ( { } )
181
+ expect ( g . has_vertex? ( "Fire" ) ) . to eql ( false )
182
+ end
183
+ end
184
+
185
+ context "given a graph with an out vertex" do
186
+ it "removes that vertex and its connections" do
187
+ g = UndirectedGraph . new ( )
188
+ g . add_vertex! ( "Fire" )
189
+ g . add_vertex! ( "Grass" )
190
+ g . add_edge! ( "Fire" , "Grass" , 2 )
191
+
192
+ expect ( g . remove_vertex! ( "Fire" ) ) . to eql ( { "Grass" => 2 } )
193
+ expect ( g . has_vertex? ( "Fire" ) ) . to eql ( false )
194
+ expect ( g . degree ( "Grass" ) ) . to eql ( 0 )
195
+ end
196
+ end
197
+
198
+ context "given a graph with an in vertex" do
199
+ it "removes that vertex and its connections" do
200
+ g = UndirectedGraph . new ( )
201
+ g . add_vertex! ( "Fire" )
202
+ g . add_vertex! ( "Water" )
203
+ g . add_edge! ( "Water" , "Fire" , 2 )
204
+
205
+ expect ( g . remove_vertex! ( "Fire" ) ) . to eql ( { "Water" => 2 } )
206
+ expect ( g . has_vertex? ( "Fire" ) ) . to eql ( false )
207
+ expect ( g . degree ( "Water" ) ) . to eql ( 0 )
208
+ end
209
+ end
210
+ end
211
+
212
+ describe ".degree" do
213
+ context "vertex not in graph" do
214
+ it "throws an error" do
215
+ expect { UndirectedGraph . new ( ) . degree ( "Dark" ) } . to raise_error ( ArgumentError )
216
+ end
217
+ end
218
+
219
+ context "point to some vertexes" do
220
+ it "has proper degree" do
221
+ g = UndirectedGraph . new ( )
222
+ g . add_vertex! ( "Psychic" )
223
+ g . add_vertex! ( "Normal" )
224
+ g . add_vertex! ( "Ghost" )
225
+ g . add_edge! ( "Ghost" , "Psychic" , 2 )
226
+ g . add_edge! ( "Ghost" , "Normal" , 0 )
227
+
228
+ expect ( g . degree ( "Ghost" ) ) . to eql ( 2 )
229
+ end
230
+ end
231
+
232
+ context "add, remove, add, vertices" do
233
+ it "has degree of 1" do
234
+ g = UndirectedGraph . new ( )
235
+ g . add_vertex! ( "Bug" )
236
+ g . add_vertex! ( "Grass" )
237
+ g . add_edge! ( "Bug" , "Grass" , 2 )
238
+ g . remove_edge! ( "Bug" , "Grass" )
239
+ g . add_vertex! ( "Fire" )
240
+ g . add_edge! ( "Bug" , "Fire" , 0.5 )
241
+
242
+ expect ( g . degree ( "Bug" ) ) . to eql ( 1 )
243
+ end
244
+ end
245
+
246
+ context "reverse arguments" do
247
+ it "has proper degree" do
248
+ g = UndirectedGraph . new ( )
249
+ g . add_vertex! ( "Psychic" )
250
+ g . add_vertex! ( "Normal" )
251
+ g . add_vertex! ( "Ghost" )
252
+ g . add_edge! ( "Psychic" , "Ghost" , 1 )
253
+ g . add_edge! ( "Ghost" , "Normal" , 0 )
254
+
255
+ expect ( g . degree ( "Ghost" ) ) . to eql ( 2 )
256
+ end
257
+ end
258
+ end
259
+
260
+ describe ".neighbors" do
261
+ context "vertex not in graph" do
262
+ it "throws error" do
263
+ expect { UndirectedGraph . new ( ) . neighbors ( "Dark" ) } . to raise_error ( ArgumentError )
264
+ end
265
+ end
266
+
267
+ context "no neighbors" do
268
+ it "returns empty array" do
269
+ g = UndirectedGraph . new
270
+ g . add_vertex! ( "Steel" )
271
+ expect ( g . neighbors ( "Steel" ) ) . to eql ( [ ] )
272
+ end
273
+ end
274
+
275
+ context "two out neighbors" do
276
+ it "returns an array of both neighbors" do
277
+ g = UndirectedGraph . new
278
+ g . add_vertex! ( "Steel" )
279
+ g . add_vertex! ( "Rock" )
280
+ g . add_vertex! ( "Ice" )
281
+ g . add_edge! ( "Steel" , "Ice" , 2 )
282
+ g . add_edge! ( "Steel" , "Rock" , 2 )
283
+
284
+ n = g . neighbors ( "Steel" )
285
+ expect ( n . include? ( "Ice" ) ) . to eql ( true )
286
+ expect ( n . include? ( "Rock" ) ) . to eql ( true )
287
+ expect ( n . length ) . to eql ( 2 )
288
+ end
289
+ end
290
+
291
+ context "two in neighbors" do
292
+ it "returns array of both" do
293
+ g = UndirectedGraph . new ( )
294
+ g . add_vertex! ( "Psychic" )
295
+ g . add_vertex! ( "Normal" )
296
+ g . add_vertex! ( "Ghost" )
297
+ g . add_edge! ( "Psychic" , "Ghost" , 1 )
298
+ g . add_edge! ( "Normal" , "Ghost" , 0 )
299
+
300
+ n = g . neighbors ( "Ghost" )
301
+ expect ( n . include? ( "Normal" ) ) . to eql ( true )
302
+ expect ( n . include? ( "Psychic" ) ) . to eql ( true )
303
+ expect ( n . length ) . to eql ( 2 )
304
+ end
305
+ end
306
+ end
307
+ end
0 commit comments