jw-rails-erd 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +86 -0
- data/Rakefile +20 -0
- data/bin/erd +4 -0
- data/lib/generators/erd/USAGE +4 -0
- data/lib/generators/erd/install_generator.rb +14 -0
- data/lib/generators/erd/templates/auto_generate_diagram.rake +6 -0
- data/lib/rails-erd.rb +1 -0
- data/lib/rails_erd/cli.rb +164 -0
- data/lib/rails_erd/config.rb +97 -0
- data/lib/rails_erd/custom.rb +99 -0
- data/lib/rails_erd/diagram/graphviz.rb +295 -0
- data/lib/rails_erd/diagram/templates/node.html.erb +14 -0
- data/lib/rails_erd/diagram/templates/node.record.erb +4 -0
- data/lib/rails_erd/diagram.rb +188 -0
- data/lib/rails_erd/domain/attribute.rb +160 -0
- data/lib/rails_erd/domain/entity.rb +104 -0
- data/lib/rails_erd/domain/relationship/cardinality.rb +118 -0
- data/lib/rails_erd/domain/relationship.rb +203 -0
- data/lib/rails_erd/domain/specialization.rb +90 -0
- data/lib/rails_erd/domain.rb +153 -0
- data/lib/rails_erd/railtie.rb +10 -0
- data/lib/rails_erd/tasks.rake +58 -0
- data/lib/rails_erd/version.rb +4 -0
- data/lib/rails_erd.rb +73 -0
- data/lib/tasks/auto_generate_diagram.rake +21 -0
- data/test/support_files/erdconfig.another_example +3 -0
- data/test/support_files/erdconfig.example +19 -0
- data/test/support_files/erdconfig.exclude.example +19 -0
- data/test/test_helper.rb +160 -0
- data/test/unit/attribute_test.rb +316 -0
- data/test/unit/cardinality_test.rb +123 -0
- data/test/unit/config_test.rb +110 -0
- data/test/unit/diagram_test.rb +352 -0
- data/test/unit/domain_test.rb +258 -0
- data/test/unit/entity_test.rb +252 -0
- data/test/unit/graphviz_test.rb +461 -0
- data/test/unit/rake_task_test.rb +174 -0
- data/test/unit/relationship_test.rb +476 -0
- data/test/unit/specialization_test.rb +67 -0
- metadata +155 -0
@@ -0,0 +1,461 @@
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
2
|
+
require "rails_erd/diagram/graphviz"
|
3
|
+
|
4
|
+
class GraphvizTest < ActiveSupport::TestCase
|
5
|
+
def setup
|
6
|
+
RailsERD.options.filetype = :png
|
7
|
+
RailsERD.options.warn = false
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
FileUtils.rm Dir["erd*.*"] rescue nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def diagram(options = {})
|
15
|
+
@diagram ||= Diagram::Graphviz.new(Domain.generate(options), options).tap do |diagram|
|
16
|
+
diagram.generate
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_dot_nodes(diagram)
|
21
|
+
[].tap do |nodes|
|
22
|
+
diagram.graph.each_node do |name, node|
|
23
|
+
nodes << node
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_dot_node(diagram, name)
|
29
|
+
diagram.graph.get_node(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_dot_node_pairs(diagram)
|
33
|
+
[].tap do |edges|
|
34
|
+
diagram.graph.each_edge do |edge|
|
35
|
+
edges << [edge.node_one, edge.node_two]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_dot_edges(diagram)
|
41
|
+
[].tap do |edges|
|
42
|
+
diagram.graph.each_edge do |edge|
|
43
|
+
edges << edge
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_dot_edge_styles(diagram)
|
49
|
+
find_dot_edges(diagram).map { |e| [e[:arrowtail].to_s.tr('"', ''), e[:arrowhead].to_s.tr('"', '')] }
|
50
|
+
end
|
51
|
+
|
52
|
+
# Diagram properties =======================================================
|
53
|
+
test "file name should depend on file type" do
|
54
|
+
create_simple_domain
|
55
|
+
begin
|
56
|
+
assert_equal "erd.svg", Diagram::Graphviz.create(:filetype => :svg)
|
57
|
+
ensure
|
58
|
+
FileUtils.rm "erd.svg" rescue nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
test "rank direction should be lr for horizontal orientation" do
|
63
|
+
create_simple_domain
|
64
|
+
assert_equal '"LR"', diagram(:orientation => :horizontal).graph[:rankdir].to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
test "rank direction should be tb for vertical orientation" do
|
68
|
+
create_simple_domain
|
69
|
+
assert_equal '"TB"', diagram(:orientation => :vertical).graph[:rankdir].to_s
|
70
|
+
end
|
71
|
+
|
72
|
+
# Diagram generation =======================================================
|
73
|
+
test "create should create output for domain with attributes" do
|
74
|
+
create_model "Foo", :bar => :references, :column => :string do
|
75
|
+
belongs_to :bar
|
76
|
+
end
|
77
|
+
create_model "Bar", :column => :string
|
78
|
+
|
79
|
+
Diagram.any_instance.expects(:save)
|
80
|
+
Diagram::Graphviz.create
|
81
|
+
end
|
82
|
+
|
83
|
+
test "create should create output for domain without attributes" do
|
84
|
+
create_simple_domain
|
85
|
+
|
86
|
+
Diagram.any_instance.expects(:save)
|
87
|
+
Diagram::Graphviz.create
|
88
|
+
end
|
89
|
+
|
90
|
+
test "create should write to file with dot extension if type is dot" do
|
91
|
+
create_simple_domain
|
92
|
+
|
93
|
+
Diagram.any_instance.expects(:save)
|
94
|
+
Diagram::Graphviz.create(:filetype => :dot)
|
95
|
+
end
|
96
|
+
|
97
|
+
test "create should create output for filenames that have spaces" do
|
98
|
+
create_simple_domain
|
99
|
+
|
100
|
+
Diagram.any_instance.expects(:save)
|
101
|
+
Diagram::Graphviz.create(:filename => "erd with spaces")
|
102
|
+
end
|
103
|
+
|
104
|
+
test "create should write to file with dot extension without requiring graphviz" do
|
105
|
+
create_simple_domain
|
106
|
+
begin
|
107
|
+
GraphViz.class_eval do
|
108
|
+
alias_method :old_output_and_errors_from_command, :output_and_errors_from_command
|
109
|
+
def output_and_errors_from_command(*args); raise end
|
110
|
+
end
|
111
|
+
assert_nothing_raised do
|
112
|
+
Diagram::Graphviz.create(:filetype => :dot)
|
113
|
+
end
|
114
|
+
ensure
|
115
|
+
GraphViz.class_eval do
|
116
|
+
alias_method :output_and_errors_from_command, :old_output_and_errors_from_command
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
test "create should create output for domain with attributes if orientation is vertical" do
|
122
|
+
create_model "Foo", :bar => :references, :column => :string do
|
123
|
+
belongs_to :bar
|
124
|
+
end
|
125
|
+
create_model "Bar", :column => :string
|
126
|
+
|
127
|
+
Diagram.any_instance.expects(:save)
|
128
|
+
Diagram::Graphviz.create(:orientation => :vertical)
|
129
|
+
end
|
130
|
+
|
131
|
+
test "create should create output for domain if orientation is vertical" do
|
132
|
+
create_simple_domain
|
133
|
+
|
134
|
+
Diagram.any_instance.expects(:save)
|
135
|
+
Diagram::Graphviz.create(:orientation => :vertical)
|
136
|
+
end
|
137
|
+
|
138
|
+
test "create should not create output if there are no connected models" do
|
139
|
+
Diagram::Graphviz.create rescue nil
|
140
|
+
assert !File.exists?("erd.png")
|
141
|
+
end
|
142
|
+
|
143
|
+
test "create should abort and complain if there are no connected models" do
|
144
|
+
message = nil
|
145
|
+
begin
|
146
|
+
Diagram::Graphviz.create
|
147
|
+
rescue => e
|
148
|
+
message = e.message
|
149
|
+
end
|
150
|
+
assert_match /No entities found/, message
|
151
|
+
end
|
152
|
+
|
153
|
+
test "create should abort and complain if output directory does not exist" do
|
154
|
+
message = nil
|
155
|
+
|
156
|
+
begin
|
157
|
+
create_simple_domain
|
158
|
+
Diagram::Graphviz.create(:filename => "does_not_exist/foo")
|
159
|
+
rescue => e
|
160
|
+
message = e.message
|
161
|
+
end
|
162
|
+
|
163
|
+
assert_match /Output directory 'does_not_exist' does not exist/, message
|
164
|
+
end
|
165
|
+
|
166
|
+
test "create should not fail when reserved words are used as node names" do
|
167
|
+
create_model "Node", :name => :string
|
168
|
+
create_model "Edge", :node => :references do
|
169
|
+
belongs_to :node
|
170
|
+
end
|
171
|
+
assert_nothing_raised do
|
172
|
+
Diagram::Graphviz.create
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Graphviz output ==========================================================
|
177
|
+
test "generate should create directed graph" do
|
178
|
+
create_simple_domain
|
179
|
+
assert_equal "digraph", diagram.graph.type
|
180
|
+
end
|
181
|
+
|
182
|
+
test "generate should add title to graph" do
|
183
|
+
create_simple_domain
|
184
|
+
assert_equal '"Domain model\n\n"', diagram.graph.graph[:label].to_s
|
185
|
+
end
|
186
|
+
|
187
|
+
test "generate should add title with application name to graph" do
|
188
|
+
begin
|
189
|
+
Object::Quux = Module.new
|
190
|
+
Object::Quux::Application = Class.new
|
191
|
+
Object::Rails = Struct.new(:application).new(Object::Quux::Application.new)
|
192
|
+
create_simple_domain
|
193
|
+
assert_equal '"Quux domain model\n\n"', diagram.graph.graph[:label].to_s
|
194
|
+
ensure
|
195
|
+
Object::Quux.send :remove_const, :Application
|
196
|
+
Object.send :remove_const, :Quux
|
197
|
+
Object.send :remove_const, :Rails
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
test "generate should omit title if set to false" do
|
202
|
+
create_simple_domain
|
203
|
+
assert_equal "", diagram(:title => false).graph.graph[:label].to_s
|
204
|
+
end
|
205
|
+
|
206
|
+
test "generate should create node for each entity" do
|
207
|
+
create_model "Foo", :bar => :references do
|
208
|
+
belongs_to :bar
|
209
|
+
end
|
210
|
+
create_model "Bar"
|
211
|
+
assert_equal ["m_Bar", "m_Foo"], find_dot_nodes(diagram).map(&:id).sort
|
212
|
+
end
|
213
|
+
|
214
|
+
test "generate should add html label for entities" do
|
215
|
+
RailsERD.options.markup = true
|
216
|
+
create_model "Foo", :bar => :references do
|
217
|
+
belongs_to :bar
|
218
|
+
end
|
219
|
+
create_model "Bar"
|
220
|
+
assert_match %r{<\w+.*?>Bar</\w+>}, find_dot_node(diagram, "m_Bar")[:label].to_gv
|
221
|
+
end
|
222
|
+
|
223
|
+
test "generate should add record label for entities" do
|
224
|
+
RailsERD.options.markup = false
|
225
|
+
create_model "Foo", :bar => :references do
|
226
|
+
belongs_to :bar
|
227
|
+
end
|
228
|
+
create_model "Bar"
|
229
|
+
assert_equal %Q("Bar"), find_dot_node(diagram, "m_Bar")[:label].to_gv
|
230
|
+
end
|
231
|
+
|
232
|
+
test "generate should add attributes to entity html labels" do
|
233
|
+
RailsERD.options.markup = true
|
234
|
+
create_model "Foo", :bar => :references do
|
235
|
+
belongs_to :bar
|
236
|
+
end
|
237
|
+
create_model "Bar", :column => :string
|
238
|
+
assert_match %r{<\w+.*?>column <\w+.*?>string</\w+.*?>}, find_dot_node(diagram, "m_Bar")[:label].to_gv
|
239
|
+
end
|
240
|
+
|
241
|
+
test "generate should add attributes to entity record labels" do
|
242
|
+
RailsERD.options.markup = false
|
243
|
+
create_model "Foo", :bar => :references do
|
244
|
+
belongs_to :bar
|
245
|
+
end
|
246
|
+
create_model "Bar", :column => :string, :column_two => :boolean
|
247
|
+
assert_equal %Q("Bar|column (string)\\ncolumn_two (boolean)\\n"), find_dot_node(diagram, "m_Bar")[:label].to_gv
|
248
|
+
end
|
249
|
+
|
250
|
+
test "generate should not add any attributes to entity labels if attributes is set to false" do
|
251
|
+
create_model "Jar", :contents => :string
|
252
|
+
create_model "Lid", :jar => :references do
|
253
|
+
belongs_to :jar
|
254
|
+
end
|
255
|
+
assert_no_match %r{contents}, find_dot_node(diagram(:attributes => false), "m_Jar")[:label].to_gv
|
256
|
+
end
|
257
|
+
|
258
|
+
test "node html labels should have direction reversing braces for vertical orientation" do
|
259
|
+
RailsERD.options.markup = true
|
260
|
+
create_model "Book", :author => :references do
|
261
|
+
belongs_to :author
|
262
|
+
end
|
263
|
+
create_model "Author", :name => :string
|
264
|
+
assert_match %r(\A<\{\s*<.*\|.*>\s*\}>\Z)m, find_dot_node(diagram(:orientation => :vertical), "m_Author")[:label].to_gv
|
265
|
+
end
|
266
|
+
|
267
|
+
test "node html labels should not have direction reversing braces for horizontal orientation" do
|
268
|
+
RailsERD.options.markup = true
|
269
|
+
create_model "Book", :author => :references do
|
270
|
+
belongs_to :author
|
271
|
+
end
|
272
|
+
create_model "Author", :name => :string
|
273
|
+
assert_match %r(\A<\s*<.*\|.*>\s*>\Z)m, find_dot_node(diagram(:orientation => :horizontal), "m_Author")[:label].to_gv
|
274
|
+
end
|
275
|
+
|
276
|
+
test "node record labels should have direction reversing braces for vertical orientation" do
|
277
|
+
RailsERD.options.markup = false
|
278
|
+
create_model "Book", :author => :references do
|
279
|
+
belongs_to :author
|
280
|
+
end
|
281
|
+
create_model "Author", :name => :string
|
282
|
+
assert_match %r(\A"\{\w+|.*\}"\Z)m, find_dot_node(diagram(:orientation => :vertical), "m_Author")[:label].to_gv
|
283
|
+
end
|
284
|
+
|
285
|
+
test "node record labels should not have direction reversing braces for horizontal orientation" do
|
286
|
+
RailsERD.options.markup = false
|
287
|
+
create_model "Book", :author => :references do
|
288
|
+
belongs_to :author
|
289
|
+
end
|
290
|
+
create_model "Author", :name => :string
|
291
|
+
assert_match %r(\A"\w+|.*"\Z)m, find_dot_node(diagram(:orientation => :horizontal), "m_Author")[:label].to_gv
|
292
|
+
end
|
293
|
+
|
294
|
+
test "generate should create edge for each relationship" do
|
295
|
+
create_model "Foo", :bar => :references do
|
296
|
+
belongs_to :bar
|
297
|
+
end
|
298
|
+
create_model "Bar", :foo => :references do
|
299
|
+
belongs_to :foo
|
300
|
+
end
|
301
|
+
assert_equal [["m_Bar", "m_Foo"], ["m_Foo", "m_Bar"]], find_dot_node_pairs(diagram).sort
|
302
|
+
end
|
303
|
+
|
304
|
+
test "generate should create edge to polymorphic entity if polymorphism is true" do
|
305
|
+
create_model "Cannon", :defensible => :references do
|
306
|
+
belongs_to :defensible, :polymorphic => true
|
307
|
+
end
|
308
|
+
create_model "Stronghold" do
|
309
|
+
has_many :cannons, :as => :defensible
|
310
|
+
end
|
311
|
+
create_model "Galleon" do
|
312
|
+
has_many :cannons, :as => :defensible
|
313
|
+
end
|
314
|
+
assert_equal [["m_Defensible", "m_Cannon"], ["m_Defensible", "m_Galleon"], ["m_Defensible", "m_Stronghold"]],
|
315
|
+
find_dot_node_pairs(diagram(:polymorphism => true)).sort
|
316
|
+
end
|
317
|
+
|
318
|
+
test "generate should create edge to each child of polymorphic entity if polymorphism is false" do
|
319
|
+
create_model "Cannon", :defensible => :references do
|
320
|
+
belongs_to :defensible, :polymorphic => true
|
321
|
+
end
|
322
|
+
create_model "Stronghold" do
|
323
|
+
has_many :cannons, :as => :defensible
|
324
|
+
end
|
325
|
+
create_model "Galleon" do
|
326
|
+
has_many :cannons, :as => :defensible
|
327
|
+
end
|
328
|
+
assert_equal [["m_Galleon", "m_Cannon"], ["m_Stronghold", "m_Cannon"]], find_dot_node_pairs(diagram).sort
|
329
|
+
end
|
330
|
+
|
331
|
+
test "generate should create edge to abstract entity if polymorphism is true" do
|
332
|
+
create_model "Person", :settlement => :references
|
333
|
+
create_model "Country" do
|
334
|
+
has_many :settlements
|
335
|
+
end
|
336
|
+
create_model "Settlement" do
|
337
|
+
self.abstract_class = true
|
338
|
+
belongs_to :country
|
339
|
+
has_many :people
|
340
|
+
end
|
341
|
+
create_model "City", Settlement, :country => :references
|
342
|
+
assert_equal [["m_Country", "m_Settlement"], ["m_Settlement", "m_City"], ["m_Settlement", "m_Person"]],
|
343
|
+
find_dot_node_pairs(diagram(:polymorphism => true)).sort
|
344
|
+
end
|
345
|
+
|
346
|
+
test "generate should create edge to each child of abstract entity if polymorphism is false" do
|
347
|
+
create_model "Person", :settlement => :references
|
348
|
+
create_model "Country" do
|
349
|
+
has_many :settlements
|
350
|
+
end
|
351
|
+
create_model "Settlement" do
|
352
|
+
self.abstract_class = true
|
353
|
+
belongs_to :country
|
354
|
+
has_many :people
|
355
|
+
end
|
356
|
+
create_model "City", Settlement, :country => :references
|
357
|
+
assert_equal [["m_City", "m_Person"], ["m_Country", "m_City"]], find_dot_node_pairs(diagram).sort
|
358
|
+
end
|
359
|
+
|
360
|
+
# Simple notation style ====================================================
|
361
|
+
test "generate should use no style for one to one cardinalities with simple notation" do
|
362
|
+
create_one_to_one_assoc_domain
|
363
|
+
assert_equal [["none", "none"]], find_dot_edge_styles(diagram(:notation => :simple))
|
364
|
+
end
|
365
|
+
|
366
|
+
test "generate should use normal arrow head for one to many cardinalities with simple notation" do
|
367
|
+
create_one_to_many_assoc_domain
|
368
|
+
assert_equal [["none", "normal"]], find_dot_edge_styles(diagram(:notation => :simple))
|
369
|
+
end
|
370
|
+
|
371
|
+
test "generate should use normal arrow head and tail for many to many cardinalities with simple notation" do
|
372
|
+
create_many_to_many_assoc_domain
|
373
|
+
assert_equal [["normal", "normal"]], find_dot_edge_styles(diagram(:notation => :simple))
|
374
|
+
end
|
375
|
+
|
376
|
+
# Advanced notation style ==================================================
|
377
|
+
test "generate should use open dots for one to one cardinalities with bachman notation" do
|
378
|
+
create_one_to_one_assoc_domain
|
379
|
+
assert_equal [["odot", "odot"]], find_dot_edge_styles(diagram(:notation => :bachman))
|
380
|
+
end
|
381
|
+
|
382
|
+
test "generate should use dots for mandatory one to one cardinalities with bachman notation" do
|
383
|
+
create_one_to_one_assoc_domain
|
384
|
+
One.class_eval do
|
385
|
+
validates_presence_of :other
|
386
|
+
end
|
387
|
+
assert_equal [["dot", "odot"]], find_dot_edge_styles(diagram(:notation => :bachman))
|
388
|
+
end
|
389
|
+
|
390
|
+
test "generate should use normal arrow and open dot head with dot tail for one to many cardinalities with bachman notation" do
|
391
|
+
create_one_to_many_assoc_domain
|
392
|
+
assert_equal [["odot", "odotnormal"]], find_dot_edge_styles(diagram(:notation => :bachman))
|
393
|
+
end
|
394
|
+
|
395
|
+
test "generate should use normal arrow and dot head for mandatory one to many cardinalities with bachman notation" do
|
396
|
+
create_one_to_many_assoc_domain
|
397
|
+
One.class_eval do
|
398
|
+
validates_presence_of :many
|
399
|
+
end
|
400
|
+
assert_equal [["dot", "odotnormal"]], find_dot_edge_styles(diagram(:notation => :bachman))
|
401
|
+
end
|
402
|
+
|
403
|
+
test "generate should use normal arrow and open dot head and tail for many to many cardinalities with bachman notation" do
|
404
|
+
create_many_to_many_assoc_domain
|
405
|
+
assert_equal [["odotnormal", "odotnormal"]], find_dot_edge_styles(diagram(:notation => :bachman))
|
406
|
+
end
|
407
|
+
|
408
|
+
test "generate should use normal arrow and dot tail and head for mandatory many to many cardinalities with bachman notation" do
|
409
|
+
create_many_to_many_assoc_domain
|
410
|
+
Many.class_eval do
|
411
|
+
validates_presence_of :more
|
412
|
+
end
|
413
|
+
More.class_eval do
|
414
|
+
validates_presence_of :many
|
415
|
+
end
|
416
|
+
assert_equal [["dotnormal", "dotnormal"]], find_dot_edge_styles(diagram(:notation => :bachman))
|
417
|
+
end
|
418
|
+
|
419
|
+
# Crows-foot notation style ================================================
|
420
|
+
test "generate should use 0/1 crowsfeet for one to one cardinalities with crowsfoot notation" do
|
421
|
+
create_one_to_one_assoc_domain
|
422
|
+
assert_equal [["teeodot", "teeodot"]], find_dot_edge_styles(diagram(:notation => :crowsfoot))
|
423
|
+
end
|
424
|
+
|
425
|
+
test "generate should use 1/1 crowsfeet for mandatory one to one cardinalities with crowsfoot notation" do
|
426
|
+
create_one_to_one_assoc_domain
|
427
|
+
One.class_eval do
|
428
|
+
validates_presence_of :other
|
429
|
+
end
|
430
|
+
assert_equal [["teeodot","teetee"]], find_dot_edge_styles(diagram(:notation => :crowsfoot))
|
431
|
+
end
|
432
|
+
|
433
|
+
test "generate should use 0/* crowsfeet with 0/1 crowsfeet for one to many cardinalities with crowsfoot notation" do
|
434
|
+
create_one_to_many_assoc_domain
|
435
|
+
assert_equal [["teeodot", "crowodot"]], find_dot_edge_styles(diagram(:notation => :crowsfoot))
|
436
|
+
end
|
437
|
+
|
438
|
+
test "generate should use 0/* crowsfeet with 1/1 crowsfett for mandatory one to many cardinalities with crowsfoot notation" do
|
439
|
+
create_one_to_many_assoc_domain
|
440
|
+
One.class_eval do
|
441
|
+
validates_presence_of :many
|
442
|
+
end
|
443
|
+
assert_equal [["teeodot", "crowtee"]], find_dot_edge_styles(diagram(:notation => :crowsfoot))
|
444
|
+
end
|
445
|
+
|
446
|
+
test "generate should use 0/* and 0/* crowsfeet for many to many cardinalities with crowsfoot notation" do
|
447
|
+
create_many_to_many_assoc_domain
|
448
|
+
assert_equal [["crowodot", "crowodot"]], find_dot_edge_styles(diagram(:notation => :crowsfoot))
|
449
|
+
end
|
450
|
+
|
451
|
+
test "generate should use 1/* and 1/* tail and head for mandatory many to many cardinalities with crowsfoot notation" do
|
452
|
+
create_many_to_many_assoc_domain
|
453
|
+
Many.class_eval do
|
454
|
+
validates_presence_of :more
|
455
|
+
end
|
456
|
+
More.class_eval do
|
457
|
+
validates_presence_of :many
|
458
|
+
end
|
459
|
+
assert_equal [["crowtee", "crowtee"]], find_dot_edge_styles(diagram(:notation => :crowsfoot))
|
460
|
+
end
|
461
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class RakeTaskTest < ActiveSupport::TestCase
|
4
|
+
include ActiveSupport::Testing::Isolation
|
5
|
+
|
6
|
+
def setup
|
7
|
+
require "rake"
|
8
|
+
load "rails_erd/tasks.rake"
|
9
|
+
|
10
|
+
RailsERD.options.filetype = :dot
|
11
|
+
RailsERD.options.warn = false
|
12
|
+
Rake.application.options.silent = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
FileUtils.rm "erd.dot" rescue nil
|
17
|
+
end
|
18
|
+
|
19
|
+
define_method :create_app do
|
20
|
+
Object::Quux = Module.new
|
21
|
+
Object::Quux::Application = Class.new
|
22
|
+
Object::Rails = Struct.new(:application).new(Object::Quux::Application.new)
|
23
|
+
Rails.class_eval do
|
24
|
+
define_method :backtrace_cleaner do
|
25
|
+
ActiveSupport::BacktraceCleaner.new.tap do |cleaner|
|
26
|
+
cleaner.add_filter { |line| line.sub(File.dirname(__FILE__), "test/unit") }
|
27
|
+
cleaner.add_silencer { |line| line !~ /^test\/unit/ }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Diagram generation =======================================================
|
34
|
+
test "generate task should create output based on domain model" do
|
35
|
+
create_simple_domain
|
36
|
+
|
37
|
+
Diagram.any_instance.expects(:save)
|
38
|
+
Rake::Task["erd:generate"].execute
|
39
|
+
end
|
40
|
+
|
41
|
+
test "generate task should not create output if there are no connected models" do
|
42
|
+
Rake::Task["erd:generate"].execute rescue nil
|
43
|
+
assert !File.exists?("erd.dot")
|
44
|
+
end
|
45
|
+
|
46
|
+
test "generate task should eager load application environment" do
|
47
|
+
eager_loaded, environment_loaded = nil
|
48
|
+
create_app
|
49
|
+
|
50
|
+
Rails.application.class_eval do
|
51
|
+
define_method :eager_load! do
|
52
|
+
eager_loaded = true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Rake::Task.define_task :environment do
|
57
|
+
environment_loaded = true
|
58
|
+
end
|
59
|
+
|
60
|
+
create_simple_domain
|
61
|
+
|
62
|
+
Rake::Task["erd:generate"].invoke
|
63
|
+
|
64
|
+
assert_equal [true, true], [eager_loaded, environment_loaded]
|
65
|
+
end
|
66
|
+
|
67
|
+
test "generate task should complain if active record is not loaded" do
|
68
|
+
create_app
|
69
|
+
|
70
|
+
Rails.application.class_eval do
|
71
|
+
define_method :eager_load! do end
|
72
|
+
end
|
73
|
+
|
74
|
+
Rake::Task.define_task :environment
|
75
|
+
Object.send :remove_const, :ActiveRecord
|
76
|
+
message = nil
|
77
|
+
|
78
|
+
begin
|
79
|
+
Rake::Task["erd:generate"].invoke
|
80
|
+
rescue => e
|
81
|
+
message = e.message
|
82
|
+
end
|
83
|
+
assert_equal "Active Record was not loaded.", message
|
84
|
+
end
|
85
|
+
|
86
|
+
test "generate task should complain with simplified stack trace if application could not be loaded" do
|
87
|
+
create_app
|
88
|
+
l1, l2 = nil, nil
|
89
|
+
Rails.application.class_eval do
|
90
|
+
define_method :eager_load! do
|
91
|
+
l1 = __LINE__ + 1
|
92
|
+
raise "FooBar"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
Rake::Task.define_task :environment
|
96
|
+
message = nil
|
97
|
+
begin
|
98
|
+
l2 = __LINE__ + 1
|
99
|
+
Rake::Task["erd:generate"].invoke
|
100
|
+
rescue => e
|
101
|
+
message = e.message
|
102
|
+
end
|
103
|
+
assert_match /#{Regexp.escape(<<-MSG.strip).gsub("xxx", ".*?")}/, message
|
104
|
+
Loading models failed!
|
105
|
+
Error occurred while loading application: FooBar (RuntimeError)
|
106
|
+
test/unit/rake_task_test.rb:#{l1}:in `xxx'
|
107
|
+
test/unit/rake_task_test.rb:#{l2}:in `xxx'
|
108
|
+
MSG
|
109
|
+
end
|
110
|
+
|
111
|
+
test "generate task should reraise if application could not be loaded and trace option is enabled" do
|
112
|
+
create_app
|
113
|
+
Rails.application.class_eval do
|
114
|
+
define_method :eager_load! do
|
115
|
+
raise "FooBar"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
Rake::Task.define_task :environment
|
119
|
+
message = nil
|
120
|
+
begin
|
121
|
+
old_stderr, $stderr = $stderr, StringIO.new
|
122
|
+
Rake.application.options.trace = true
|
123
|
+
Rake::Task["erd:generate"].invoke
|
124
|
+
rescue => e
|
125
|
+
message = e.message
|
126
|
+
ensure
|
127
|
+
$stderr = old_stderr
|
128
|
+
end
|
129
|
+
assert_equal "FooBar", message
|
130
|
+
end
|
131
|
+
|
132
|
+
# Option processing ========================================================
|
133
|
+
test "options task should ignore unknown command line options" do
|
134
|
+
ENV["unknownoption"] = "value"
|
135
|
+
Rake::Task["erd:options"].execute
|
136
|
+
assert_nil RailsERD.options.unknownoption
|
137
|
+
end
|
138
|
+
|
139
|
+
test "options task should set known command line options" do
|
140
|
+
ENV["filetype"] = "myfiletype"
|
141
|
+
Rake::Task["erd:options"].execute
|
142
|
+
assert_equal :myfiletype, RailsERD.options.filetype
|
143
|
+
end
|
144
|
+
|
145
|
+
test "options task should set known boolean command line options if false" do
|
146
|
+
ENV["title"] = "false"
|
147
|
+
Rake::Task["erd:options"].execute
|
148
|
+
assert_equal false, RailsERD.options.title
|
149
|
+
end
|
150
|
+
|
151
|
+
test "options task should set known boolean command line options if true" do
|
152
|
+
ENV["title"] = "true"
|
153
|
+
Rake::Task["erd:options"].execute
|
154
|
+
assert_equal true, RailsERD.options.title
|
155
|
+
end
|
156
|
+
|
157
|
+
test "options task should set known boolean command line options if no" do
|
158
|
+
ENV["title"] = "no"
|
159
|
+
Rake::Task["erd:options"].execute
|
160
|
+
assert_equal false, RailsERD.options.title
|
161
|
+
end
|
162
|
+
|
163
|
+
test "options task should set known boolean command line options if yes" do
|
164
|
+
ENV["title"] = "yes"
|
165
|
+
Rake::Task["erd:options"].execute
|
166
|
+
assert_equal true, RailsERD.options.title
|
167
|
+
end
|
168
|
+
|
169
|
+
test "options task should set known array command line options" do
|
170
|
+
ENV["attributes"] = "content,timestamps"
|
171
|
+
Rake::Task["erd:options"].execute
|
172
|
+
assert_equal %w[content timestamps], RailsERD.options.attributes
|
173
|
+
end
|
174
|
+
end
|