PageRenderTime 78ms CodeModel.GetById 14ms app.highlight 61ms RepoModel.GetById 2ms app.codeStats 0ms

/spec/rails_best_practices/analyzer_spec.rb

http://github.com/flyerhzm/rails_best_practices
Ruby | 229 lines | 196 code | 32 blank | 1 comment | 1 complexity | c2729ff796be6052a4591c1838209bb7 MD5 | raw file
  1# frozen_string_literal: true
  2
  3require 'spec_helper'
  4require 'tmpdir'
  5
  6module RailsBestPractices
  7  describe Analyzer do
  8    subject { described_class.new('.') }
  9
 10    describe '::new' do
 11      it 'expands a relative path to an absolute' do
 12        expect(subject.path).to eq File.expand_path('.')
 13      end
 14    end
 15
 16    describe 'expand_dirs_to_files' do
 17      it 'expands all files in spec directory' do
 18        dir = File.dirname(__FILE__)
 19        expect(subject.expand_dirs_to_files(dir)).to be_include(dir + '/analyzer_spec.rb')
 20      end
 21    end
 22
 23    describe 'file_sort' do
 24      it 'gets models first, mailers, helpers and then others' do
 25        files = [
 26          'app/controllers/users_controller.rb',
 27          'app/mailers/user_mailer.rb',
 28          'app/helpers/users_helper.rb',
 29          'app/models/user.rb',
 30          'app/views/users/index.html.haml',
 31          'app/views/users/show.html.slim',
 32          'lib/user.rb'
 33        ]
 34        expect(subject.file_sort(files)).to eq(
 35          [
 36            'app/models/user.rb',
 37            'app/mailers/user_mailer.rb',
 38            'app/helpers/users_helper.rb',
 39            'app/controllers/users_controller.rb',
 40            'app/views/users/index.html.haml',
 41            'app/views/users/show.html.slim',
 42            'lib/user.rb'
 43          ]
 44        )
 45      end
 46    end
 47
 48    describe 'file_ignore' do
 49      before do
 50        @all = [
 51          'app/controllers/users_controller.rb',
 52          'app/mailers/user_mailer.rb',
 53          'app/models/user.rb',
 54          'app/views/users/index.html.haml',
 55          'app/views/users/show.html.slim',
 56          'lib/user.rb'
 57        ]
 58        @filtered = [
 59          'app/controllers/users_controller.rb',
 60          'app/mailers/user_mailer.rb',
 61          'app/models/user.rb',
 62          'app/views/users/index.html.haml',
 63          'app/views/users/show.html.slim'
 64        ]
 65      end
 66
 67      it 'ignores lib' do
 68        expect(subject.file_ignore(@all, 'lib/')).to eq(@filtered)
 69      end
 70
 71      it 'ignores regexp patterns' do
 72        expect(subject.file_ignore(@all, /lib/)).to eq(@filtered)
 73      end
 74    end
 75
 76    describe 'output' do
 77      subject { described_class.new('.', 'format' => format) }
 78
 79      before do
 80        subject.stub(:output_terminal_errors)
 81        subject.stub(:output_html_errors)
 82        subject.stub(:output_yaml_errors)
 83        subject.stub(:output_xml_errors)
 84
 85        subject.output
 86      end
 87
 88      context 'when format is not set' do
 89        let(:format) { nil }
 90
 91        it 'runs text output' do
 92          expect(subject).to have_received(:output_terminal_errors)
 93        end
 94      end
 95
 96      context 'when format is yaml' do
 97        let(:format) { 'yaml' }
 98
 99        it 'runs yaml output' do
100          expect(subject).to have_received(:output_yaml_errors)
101        end
102      end
103
104      context 'when format is html' do
105        let(:format) { 'html' }
106
107        it 'runs html output' do
108          expect(subject).to have_received(:output_html_errors)
109        end
110      end
111
112      context 'when format is xml' do
113        let(:format) { 'xml' }
114
115        it 'runs xml output' do
116          expect(subject).to have_received(:output_xml_errors)
117        end
118      end
119    end
120
121    describe 'output_terminal_errors' do
122      it 'outputs errors in terminal' do
123        check1 = Reviews::LawOfDemeterReview.new
124        check2 = Reviews::UseQueryAttributeReview.new
125        runner = Core::Runner.new(reviews: [check1, check2])
126        check1.add_error 'law of demeter', 'app/models/user.rb', 10
127        check2.add_error 'use query attribute', 'app/models/post.rb', 100
128        subject.runner = runner
129        subject.instance_variable_set('@options', 'without-color' => false)
130
131        $origin_stdout = $stdout
132        $stdout = StringIO.new
133        subject.output_terminal_errors
134        result = $stdout.string
135        $stdout = $origin_stdout
136        expect(result).to eq(
137          [
138            "\e[31mapp/models/user.rb:10 - law of demeter\e[0m",
139            "\e[31mapp/models/post.rb:100 - use query attribute\e[0m",
140            "\e[32m\nPlease go to https://rails-bestpractices.com to see more useful Rails Best Practices.\e[0m",
141            "\e[31m\nFound 2 warnings.\e[0m"
142          ].join("\n") + "\n"
143        )
144      end
145    end
146
147    describe 'output_json_errors' do
148      let(:output_file) { 'rails_best_practices_output.json' }
149
150      subject do
151        described_class.new('.', 'format' => 'json', 'output-file' => output_file)
152      end
153
154      let(:check1) { Reviews::LawOfDemeterReview.new }
155      let(:check2) { Reviews::UseQueryAttributeReview.new }
156      let(:runner) { Core::Runner.new(reviews: [check1, check2]) }
157      let(:result) { File.read(output_file) }
158
159      before do
160        check1.add_error('law of demeter', 'app/models/user.rb', 10)
161        check2.add_error('use query attribute', 'app/models/post.rb', 100)
162        subject.runner = runner
163        subject.output
164      end
165
166      after do
167        File.delete(output_file) if File.exist?(output_file)
168      end
169
170      it 'saves output as json into output file' do
171        expect(
172          result
173        ).to eq '[{"filename":"app/models/user.rb","line_number":"10","message":"law of demeter"},{"filename":"app/models/post.rb","line_number":"100","message":"use query attribute"}]'
174      end
175    end
176
177    describe 'parse_files' do
178      it 'does not filter out all files when the path contains "vendor"' do
179        Dir.mktmpdir do |random_dir|
180          Dir.mkdir(File.join(random_dir, 'vendor'))
181          Dir.mkdir(File.join(random_dir, 'vendor', 'my_project'))
182          File.open(File.join(random_dir, 'vendor', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
183          analyzer = described_class.new(File.join(random_dir, 'vendor', 'my_project'))
184          expect(analyzer.parse_files).to be_include File.join(random_dir, 'vendor', 'my_project', 'my_file.rb')
185        end
186      end
187
188      it 'does not filter out all files when the path contains "spec"' do
189        Dir.mktmpdir do |random_dir|
190          Dir.mkdir(File.join(random_dir, 'spec'))
191          Dir.mkdir(File.join(random_dir, 'spec', 'my_project'))
192          File.open(File.join(random_dir, 'spec', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
193          analyzer = described_class.new(File.join(random_dir, 'spec', 'my_project'))
194          expect(analyzer.parse_files).to be_include File.join(random_dir, 'spec', 'my_project', 'my_file.rb')
195        end
196      end
197
198      it 'does not filter out all files when the path contains "test"' do
199        Dir.mktmpdir do |random_dir|
200          Dir.mkdir(File.join(random_dir, 'test'))
201          Dir.mkdir(File.join(random_dir, 'test', 'my_project'))
202          File.open(File.join(random_dir, 'test', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
203          analyzer = described_class.new(File.join(random_dir, 'test', 'my_project'))
204          expect(analyzer.parse_files).to be_include File.join(random_dir, 'test', 'my_project', 'my_file.rb')
205        end
206      end
207
208      it 'does not filter out all files when the path contains "features"' do
209        Dir.mktmpdir do |random_dir|
210          Dir.mkdir(File.join(random_dir, 'test'))
211          Dir.mkdir(File.join(random_dir, 'test', 'my_project'))
212          File.open(File.join(random_dir, 'test', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
213          analyzer = described_class.new(File.join(random_dir, 'test', 'my_project'))
214          expect(analyzer.parse_files).to be_include File.join(random_dir, 'test', 'my_project', 'my_file.rb')
215        end
216      end
217
218      it 'does not filter out all files when the path contains "tmp"' do
219        Dir.mktmpdir do |random_dir|
220          Dir.mkdir(File.join(random_dir, 'tmp'))
221          Dir.mkdir(File.join(random_dir, 'tmp', 'my_project'))
222          File.open(File.join(random_dir, 'tmp', 'my_project', 'my_file.rb'), 'w') { |file| file << 'woot' }
223          analyzer = described_class.new(File.join(random_dir, 'tmp', 'my_project'))
224          expect(analyzer.parse_files).to be_include File.join(random_dir, 'tmp', 'my_project', 'my_file.rb')
225        end
226      end
227    end
228  end
229end