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