Skip to content

Commit 0e9f301

Browse files
authored
Improve some model annotator tests (#49)
Some general project improvements * Removes the `new_annotations` arg from `FileBuilder#new` as it was redundant * Extracts a lot of specs out of `annotate_models_annotating_a_file_spec.rb`
1 parent 5a4a8ce commit 0e9f301

File tree

9 files changed

+736
-250
lines changed

9 files changed

+736
-250
lines changed

lib/annotate_rb/model_annotator/annotation_builder.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class AnnotationBuilder
1212
MD_NAMES_OVERHEAD = 6
1313
MD_TYPE_ALLOWANCE = 18
1414

15-
def initialize(klass, options = {})
15+
def initialize(klass, options)
1616
@model = ModelWrapper.new(klass, options)
1717
@options = options
1818
@info = "" # TODO: Make array and build string that way

lib/annotate_rb/model_annotator/file_builder.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ module AnnotateRb
44
module ModelAnnotator
55
# Generates the text file content with annotations, these are then to be written to filesystem.
66
class FileBuilder
7-
def initialize(file_components, new_annotations, annotation_position, options)
7+
def initialize(file_components, annotation_position, options)
88
@file_components = file_components
9-
@new_annotations = new_annotations
109
@annotation_position = annotation_position
1110
@options = options
1211

13-
@new_wrapped_annotations = wrapped_content(new_annotations)
12+
@new_wrapped_annotations = wrapped_content(@file_components.new_annotations)
1413
end
1514

1615
def generate_content_with_new_annotations

lib/annotate_rb/model_annotator/file_components.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ class FileComponents
66
SKIP_ANNOTATION_STRING = "# -*- SkipSchemaAnnotations"
77
SOME_PATTERN = /\A(?<start>\s*).*?\n(?<end>\s*)\z/m # Unsure what this pattern is
88

9+
attr_reader :new_annotations
10+
911
def initialize(file_content, new_annotations, options)
1012
@file_content = file_content
1113
@diff = AnnotationDiffGenerator.new(file_content, new_annotations).generate
1214
@options = options
1315
@annotation_pattern = AnnotationPatternGenerator.call(options)
16+
@new_annotations = new_annotations
1417
end
1518

1619
def current_file_content

lib/annotate_rb/model_annotator/single_file_annotator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def call(file_name, annotation, annotation_position, options = {})
2626
old_content = File.read(file_name)
2727

2828
file_components = FileComponents.new(old_content, annotation, options)
29-
builder = FileBuilder.new(file_components, annotation, annotation_position, options)
29+
builder = FileBuilder.new(file_components, annotation_position, options)
3030

3131
return false if file_components.has_skip_string?
3232
return false if !file_components.annotations_changed? && !options[:force]

spec/lib/annotate_rb/annotate_models/annotate_models_annotating_a_file_frozen_spec.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
include AnnotateTestHelpers
33

44
describe "annotating a file" do
5+
let(:options) { AnnotateRb::Options.new({}) }
6+
57
before do
68
@model_dir = Dir.mktmpdir("annotate_models")
79
(@model_file_name, @file_content) = write_model "user.rb", <<~EOS
@@ -15,7 +17,7 @@ class User < ActiveRecord::Base
1517
mock_column("id", :integer),
1618
mock_column("name", :string, limit: 50)
1719
])
18-
@schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(@klass).build
20+
@schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(@klass, options).build
1921
end
2022

2123
# TODO: Check out why this test fails due to test pollution
@@ -28,7 +30,8 @@ class User < ActiveRecord::Base
2830
annotate_one_file
2931

3032
another_schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(
31-
mock_class(:users, :id, [mock_column("id", :integer)])
33+
mock_class(:users, :id, [mock_column("id", :integer)]),
34+
options
3235
).build
3336

3437
@schema_info = another_schema_info

spec/lib/annotate_rb/annotate_models/annotate_models_annotating_a_file_spec.rb

Lines changed: 5 additions & 243 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
include AnnotateTestConstants
44

55
describe "annotating a file" do
6+
let(:options) { AnnotateRb::Options.new({}) }
7+
68
before do
79
@model_dir = Dir.mktmpdir("annotate_models")
810
(@model_file_name, @file_content) = write_model "user.rb", <<~EOS
@@ -16,193 +18,7 @@ class User < ActiveRecord::Base
1618
mock_column("id", :integer),
1719
mock_column("name", :string, limit: 50)
1820
])
19-
@schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(@klass).build
20-
end
21-
22-
context "with 'before'" do
23-
let(:position) { "before" }
24-
25-
it "should put annotation before class if :position == 'before'" do
26-
annotate_one_file position: position
27-
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
28-
end
29-
end
30-
31-
context "with :before" do
32-
let(:position) { :before }
33-
34-
it "should put annotation before class if :position == :before" do
35-
annotate_one_file position: position
36-
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
37-
end
38-
end
39-
40-
context "with 'top'" do
41-
let(:position) { "top" }
42-
43-
it "should put annotation before class if :position == 'top'" do
44-
annotate_one_file position: position
45-
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
46-
end
47-
end
48-
49-
context "with :top" do
50-
let(:position) { :top }
51-
52-
it "should put annotation before class if :position == :top" do
53-
annotate_one_file position: position
54-
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
55-
end
56-
end
57-
58-
context "with 'after'" do
59-
let(:position) { "after" }
60-
61-
it "should put annotation after class if position: 'after'" do
62-
annotate_one_file position: position
63-
expect(File.read(@model_file_name)).to eq("#{@file_content}\n#{@schema_info}")
64-
end
65-
end
66-
67-
context "with :after" do
68-
let(:position) { :after }
69-
70-
it "should put annotation after class if position: :after" do
71-
annotate_one_file position: position
72-
expect(File.read(@model_file_name)).to eq("#{@file_content}\n#{@schema_info}")
73-
end
74-
end
75-
76-
context "with 'bottom'" do
77-
let(:position) { "bottom" }
78-
79-
it "should put annotation after class if position: 'bottom'" do
80-
annotate_one_file position: position
81-
expect(File.read(@model_file_name)).to eq("#{@file_content}\n#{@schema_info}")
82-
end
83-
end
84-
85-
context "with :bottom" do
86-
let(:position) { :bottom }
87-
88-
it "should put annotation after class if position: :bottom" do
89-
annotate_one_file position: position
90-
expect(File.read(@model_file_name)).to eq("#{@file_content}\n#{@schema_info}")
91-
end
92-
end
93-
94-
it "should wrap annotation if wrapper is specified" do
95-
annotate_one_file wrapper_open: "START", wrapper_close: "END"
96-
expect(File.read(@model_file_name)).to eq("# START\n#{@schema_info}# END\n#{@file_content}")
97-
end
98-
99-
describe "with existing annotation" do
100-
context "of a foreign key" do
101-
before do
102-
klass = mock_class(:users,
103-
:id,
104-
[
105-
mock_column("id", :integer),
106-
mock_column("foreign_thing_id", :integer)
107-
],
108-
[],
109-
[
110-
mock_foreign_key("fk_rails_cf2568e89e",
111-
"foreign_thing_id",
112-
"foreign_things",
113-
"id",
114-
on_delete: :cascade)
115-
])
116-
@schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(
117-
klass, show_foreign_keys: true
118-
).build
119-
120-
annotate_one_file
121-
end
122-
123-
it "should update foreign key constraint" do
124-
klass = mock_class(:users,
125-
:id,
126-
[
127-
mock_column("id", :integer),
128-
mock_column("foreign_thing_id", :integer)
129-
],
130-
[],
131-
[
132-
mock_foreign_key("fk_rails_cf2568e89e",
133-
"foreign_thing_id",
134-
"foreign_things",
135-
"id",
136-
on_delete: :restrict)
137-
])
138-
@schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(
139-
klass, show_foreign_keys: true
140-
).build
141-
142-
annotate_one_file
143-
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
144-
end
145-
end
146-
end
147-
148-
describe "with existing annotation => :before" do
149-
before do
150-
annotate_one_file position: :before
151-
another_schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(
152-
mock_class(:users, :id, [mock_column("id", :integer)])
153-
).build
154-
155-
@schema_info = another_schema_info
156-
end
157-
158-
it "should retain current position" do
159-
annotate_one_file
160-
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
161-
end
162-
163-
it "should retain current position even when :position is changed to :after" do
164-
annotate_one_file position: :after
165-
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
166-
end
167-
168-
it "should change position to :after when force: true" do
169-
annotate_one_file position: :after, force: true
170-
expect(File.read(@model_file_name)).to eq("#{@file_content}\n#{@schema_info}")
171-
end
172-
end
173-
174-
describe "with existing annotation => :after" do
175-
before do
176-
annotate_one_file position: :after
177-
another_schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(
178-
mock_class(:users, :id, [mock_column("id", :integer)])
179-
).build
180-
181-
@schema_info = another_schema_info
182-
end
183-
184-
it "should retain current position" do
185-
annotate_one_file
186-
expect(File.read(@model_file_name)).to eq("#{@file_content}\n#{@schema_info}")
187-
end
188-
189-
it "should retain current position even when :position is changed to :before" do
190-
annotate_one_file position: :before
191-
expect(File.read(@model_file_name)).to eq("#{@file_content}\n#{@schema_info}")
192-
end
193-
194-
it "should change position to :before when force: true" do
195-
annotate_one_file position: :before, force: true
196-
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
197-
end
198-
end
199-
200-
it "should skip columns with option[:ignore_columns] set" do
201-
output = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(
202-
@klass, ignore_columns: "(id|updated_at|created_at)"
203-
).build
204-
205-
expect(output.match(/id/)).to be_nil
21+
@schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(@klass, options).build
20622
end
20723

20824
it "works with namespaced models (i.e. models inside modules/subdirectories)" do
@@ -218,68 +34,14 @@ class Foo::User < ActiveRecord::Base
21834
mock_column("name", :string, limit: 50)
21935
])
22036
schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(
221-
klass
37+
klass,
38+
options
22239
).build
22340

22441
AnnotateRb::ModelAnnotator::SingleFileAnnotator.call(model_file_name, schema_info, position: :before)
22542
expect(File.read(model_file_name)).to eq("#{schema_info}#{file_content}")
22643
end
22744

228-
it "should not touch magic comments" do
229-
AnnotateTestConstants::MAGIC_COMMENTS.each do |magic_comment|
230-
write_model "user.rb", <<~EOS
231-
#{magic_comment}
232-
class User < ActiveRecord::Base
233-
end
234-
EOS
235-
236-
annotate_one_file position: :before
237-
238-
lines = magic_comment.split("\n")
239-
File.open @model_file_name do |file|
240-
lines.count.times do |index|
241-
expect(file.readline).to eq "#{lines[index]}\n"
242-
end
243-
end
244-
end
245-
end
246-
247-
it "adds an empty line between magic comments and annotation (position :before)" do
248-
content = "class User < ActiveRecord::Base\nend\n"
249-
AnnotateTestConstants::MAGIC_COMMENTS.each do |magic_comment|
250-
model_file_name, = write_model "user.rb", "#{magic_comment}\n#{content}"
251-
252-
annotate_one_file position: :before
253-
schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(@klass).build
254-
255-
expect(File.read(model_file_name)).to eq("#{magic_comment}\n\n#{schema_info}#{content}")
256-
end
257-
end
258-
259-
it "only keeps a single empty line around the annotation (position :before)" do
260-
content = "class User < ActiveRecord::Base\nend\n"
261-
AnnotateTestConstants::MAGIC_COMMENTS.each do |magic_comment|
262-
schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(@klass).build
263-
model_file_name, = write_model "user.rb", "#{magic_comment}\n\n\n\n#{content}"
264-
265-
annotate_one_file position: :before
266-
267-
expect(File.read(model_file_name)).to eq("#{magic_comment}\n\n#{schema_info}#{content}")
268-
end
269-
end
270-
271-
it "does not change whitespace between magic comments and model file content (position :after)" do
272-
content = "class User < ActiveRecord::Base\nend\n"
273-
AnnotateTestConstants::MAGIC_COMMENTS.each do |magic_comment|
274-
model_file_name, = write_model "user.rb", "#{magic_comment}\n#{content}"
275-
276-
annotate_one_file position: :after
277-
schema_info = AnnotateRb::ModelAnnotator::AnnotationBuilder.new(@klass).build
278-
279-
expect(File.read(model_file_name)).to eq("#{magic_comment}\n#{content}\n#{schema_info}")
280-
end
281-
end
282-
28345
describe "if a file can't be annotated" do
28446
before do
28547
allow(AnnotateRb::ModelAnnotator::ModelClassGetter).to receive(:get_loaded_model_by_path).with("user").and_return(nil)

0 commit comments

Comments
 (0)