From dce2ac6ce5596acef0f118b9d41e71d622036363 Mon Sep 17 00:00:00 2001 From: Shu Fujita Date: Tue, 25 Feb 2020 23:57:58 +0900 Subject: [PATCH] Refactor test cases of AnnotateRoutes (#760) This is the final completed version of refactoring AnnotateRoutes. --- .rubocop_todo.yml | 17 +- spec/lib/annotate/annotate_routes_spec.rb | 863 +++++++++++++--------- 2 files changed, 499 insertions(+), 381 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c2d82b946..fc7c1e779 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2020-02-13 18:10:52 +0900 using RuboCop version 0.68.1. +# on 2020-02-13 20:05:34 +0900 using RuboCop version 0.68.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -64,14 +64,6 @@ Layout/ExtraSpacing: - 'lib/annotate/annotate_models.rb' - 'lib/tasks/annotate_routes.rake' -# Offense count: 4 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: aligned, indented, indented_relative_to_receiver -Layout/MultilineMethodCallIndentation: - Exclude: - - 'spec/lib/annotate/annotate_routes_spec.rb' - # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. @@ -221,7 +213,7 @@ Naming/AccessorMethodName: Exclude: - 'lib/annotate.rb' -# Offense count: 93 +# Offense count: 103 # Configuration parameters: Blacklist. # Blacklist: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$)) Naming/HeredocDelimiterNaming: @@ -478,7 +470,7 @@ Style/StderrPuts: - 'lib/annotate.rb' - 'lib/annotate/annotate_models.rb' -# Offense count: 111 +# Offense count: 107 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes @@ -490,7 +482,6 @@ Style/StringLiterals: - 'lib/tasks/annotate_models_migrate.rake' - 'lib/tasks/annotate_routes.rake' - 'spec/lib/annotate/annotate_models_spec.rb' - - 'spec/lib/annotate/annotate_routes_spec.rb' - 'spec/lib/annotate/parser_spec.rb' # Offense count: 1 @@ -528,7 +519,7 @@ Style/UnneededPercentQ: Exclude: - 'annotate.gemspec' -# Offense count: 346 +# Offense count: 377 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https diff --git a/spec/lib/annotate/annotate_routes_spec.rb b/spec/lib/annotate/annotate_routes_spec.rb index e4430e89c..dc4400a35 100644 --- a/spec/lib/annotate/annotate_routes_spec.rb +++ b/spec/lib/annotate/annotate_routes_spec.rb @@ -31,401 +31,528 @@ double(File, stubs) end - it 'should check if routes.rb exists' do - expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(false) - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_NOT_FOUND) - AnnotateRoutes.do_annotations - end - - describe 'Annotate#example' do - let :rake_routes_result do - <<-EOS - Prefix Verb URI Pattern Controller#Action - myaction1 GET /url1(.:format) mycontroller1#action - myaction2 POST /url2(.:format) mycontroller2#action - myaction3 DELETE|GET /url3(.:format) mycontroller3#action - EOS - end - - before(:each) do - expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(true).at_least(:once) - - expect(File).to receive(:read).with(ROUTE_FILE).and_return("").at_least(:once) - - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).at_least(:once) - end - - context 'without magic comments' do - before(:each) do - expect(AnnotateRoutes).to receive(:`).with('rake routes').and_return(rake_routes_result) + describe '.do_annotations' do + context 'When "config/routes.rb" does not exist' do + before :each do + expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(false).once end - it 'annotate normal' do - expected_result = <<~EOS - - # == Route Map - # - # Prefix Verb URI Pattern Controller#Action - # myaction1 GET /url1(.:format) mycontroller1#action - # myaction2 POST /url2(.:format) mycontroller2#action - # myaction3 DELETE|GET /url3(.:format) mycontroller3#action - EOS - - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with(expected_result) + it 'does not annotates any file' do + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_NOT_FOUND) AnnotateRoutes.do_annotations end - - it 'annotate markdown' do - expected_result = <<~EOS - - # ## Route Map - # - # Prefix | Verb | URI Pattern | Controller#Action - # --------- | ---------- | --------------- | -------------------- - # myaction1 | GET | /url1(.:format) | mycontroller1#action - # myaction2 | POST | /url2(.:format) | mycontroller2#action - # myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action - EOS - - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with(expected_result) - - AnnotateRoutes.do_annotations(format_markdown: true) - end - - it 'wraps annotation if wrapper is specified' do - expected_result = <<~EOS - - # START - # == Route Map - # - # Prefix Verb URI Pattern Controller#Action - # myaction1 GET /url1(.:format) mycontroller1#action - # myaction2 POST /url2(.:format) mycontroller2#action - # myaction3 DELETE|GET /url3(.:format) mycontroller3#action - # END - EOS - - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with(expected_result) - - AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END') - end end - context 'file with magic comments' do - it 'should not remove magic comments' do - MAGIC_COMMENTS.each do |magic_comment| - expected_result = <<~EOS - - #{magic_comment} + context 'When "config/routes.rb" exists' do + before :each do + expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(true).once + expect(File).to receive(:read).with(ROUTE_FILE).and_return(route_file_content).once - # == Route Map - # - # Prefix Verb URI Pattern Controller#Action - # myaction1 GET /url1(.:format) mycontroller1#action - # myaction2 POST /url2(.:format) mycontroller2#action - # myaction3 DELETE|GET /url3(.:format) mycontroller3#action - EOS - - expect(AnnotateRoutes).to receive(:`).with('rake routes') - .and_return("#{magic_comment}\n#{rake_routes_result}") - - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with(expected_result) - - AnnotateRoutes.do_annotations - end + expect(AnnotateRoutes).to receive(:`).with('rake routes').and_return(rake_routes_result).once end - it 'annotate markdown' do - MAGIC_COMMENTS.each do |magic_comment| - expected_result = <<~EOS - - #{magic_comment} - - # ## Route Map - # - # Prefix | Verb | URI Pattern | Controller#Action - # --------- | ---------- | --------------- | -------------------- - # myaction1 | GET | /url1(.:format) | mycontroller1#action - # myaction2 | POST | /url2(.:format) | mycontroller2#action - # myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action - EOS - - expect(AnnotateRoutes).to receive(:`).with('rake routes') - .and_return("#{magic_comment}\n#{rake_routes_result}") - - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with(expected_result) - - AnnotateRoutes.do_annotations(format_markdown: true) - end - end - - it 'wraps annotation if wrapper is specified' do - MAGIC_COMMENTS.each do |magic_comment| - expected_result = <<~EOS - - #{magic_comment} - - # START - # == Route Map - # - # Prefix Verb URI Pattern Controller#Action - # myaction1 GET /url1(.:format) mycontroller1#action - # myaction2 POST /url2(.:format) mycontroller2#action - # myaction3 DELETE|GET /url3(.:format) mycontroller3#action - # END - EOS - - expect(AnnotateRoutes).to receive(:`).with('rake routes') - .and_return("#{magic_comment}\n#{rake_routes_result}") - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with(expected_result) - - AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END') - end - end - end - end - - describe 'When adding' do - before(:each) do - expect(File).to receive(:exist?).with(ROUTE_FILE) - .and_return(true).at_least(:once) - expect(AnnotateRoutes).to receive(:`).with('rake routes') - .and_return('').at_least(:once) - end - - it 'should insert annotations if file does not contain annotations' do - expect(File).to receive(:read).with(ROUTE_FILE).and_return("") - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with("\n# == Route Map\n#\n") - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) - - AnnotateRoutes.do_annotations - end - - it 'should insert annotations if file does not contain annotations and ignore routes' do - expect(File).to receive(:read).with(ROUTE_FILE).and_return("") - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with("\n# == Route Map\n#\n") - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) - - AnnotateRoutes.do_annotations(ignore_routes: 'my_route') - end - - it 'should insert annotations if file does not contain annotations and position top' do - expect(File).to receive(:read).with(ROUTE_FILE).and_return("") - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(mock_file).to receive(:puts).with("# == Route Map\n#\n") - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) - - AnnotateRoutes.do_annotations(position_in_routes: 'top') - end - - it 'should skip annotations if file does already contain annotation' do - expect(File).to receive(:read).with(ROUTE_FILE).and_return("\n# == Route Map\n#\n") - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_UNCHANGED) - - AnnotateRoutes.do_annotations - end - - context 'file with magic comments' do - it 'leaves magic comment on top, adds an empty line between magic comment and annotation (position_in_routes :top)' do - expect(File).to receive(:open).with(ROUTE_FILE, 'wb') - .and_yield(mock_file).at_least(:once) - - MAGIC_COMMENTS.each do |magic_comment| - expect(File).to receive(:read).with(ROUTE_FILE).and_return("#{magic_comment}\nSomething") - expect(mock_file).to receive(:puts).with("#{magic_comment}\n\n# == Route Map\n#\n\nSomething\n") - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) - AnnotateRoutes.do_annotations(position_in_routes: 'top') - end - end - - it 'leaves magic comment on top, adds an empty line between magic comment and annotation (position_in_routes :bottom)' do - expect(File).to receive(:open).with(ROUTE_FILE, 'wb') - .and_yield(mock_file).at_least(:once) - - MAGIC_COMMENTS.each do |magic_comment| - expect(File).to receive(:read).with(ROUTE_FILE).and_return("#{magic_comment}\nSomething") - expect(mock_file).to receive(:puts).with("#{magic_comment}\nSomething\n\n# == Route Map\n#\n") - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) - AnnotateRoutes.do_annotations(position_in_routes: 'bottom') - end - end - - it 'skips annotations if file does already contain annotation' do - MAGIC_COMMENTS.each do |magic_comment| - expect(File).to receive(:read).with(ROUTE_FILE) - .and_return("#{magic_comment}\n\n# == Route Map\n#\n") - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_UNCHANGED) - - AnnotateRoutes.do_annotations - end - end - end - end - - describe 'As for Rake versions' do - before :each do - expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(true) - expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) - expect(File).to receive(:read).with(ROUTE_FILE).and_return(route_file_content) - - expect(AnnotateRoutes).to receive(:`).with('rake routes').and_return(rake_routes_result) - end - - context 'with older Rake versions' do - let :rake_routes_result do - <<~EOS.chomp - (in /bad/line) - good line - EOS - end - - context 'When the route file does not end with an empty line' do - let :route_file_content do - <<~EOS.chomp - ActionController::Routing... - foo - EOS - end - - let :expected_result do - <<~EOS - ActionController::Routing... - foo - - # == Route Map - # - # good line - EOS - end - - it 'annotates with an empty line' do - expect(mock_file).to receive(:puts).with(expected_result) - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) - - AnnotateRoutes.do_annotations - end - end - - context 'When the route file ends with an empty line' do - let :route_file_content do - <<~EOS - ActionController::Routing... - foo - EOS - end - - let :expected_result do - <<~EOS - ActionController::Routing... - foo - - # == Route Map - # - # good line - EOS - end - - it 'annotates without an empty line' do - expect(mock_file).to receive(:puts).with(expected_result) - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) - - AnnotateRoutes.do_annotations - end - end - end - - context 'with newer Rake versions' do - let :rake_routes_result do - <<~EOS.chomp - another good line - good line - EOS - end - - context 'When the route file does not end with an empty line' do - context 'When no option is passed' do - let :route_file_content do - <<~EOS.chomp - ActionController::Routing... - foo - EOS + context 'When the result of `rake routes` is present' do + context 'When the result of `rake routes` does not contain Rake version' do + context 'When the file does not contain magic comment' do + let :rake_routes_result do + <<-EOS + Prefix Verb URI Pattern Controller#Action + myaction1 GET /url1(.:format) mycontroller1#action + myaction2 POST /url2(.:format) mycontroller2#action + myaction3 DELETE|GET /url3(.:format) mycontroller3#action + EOS + end + + let :route_file_content do + '' + end + + context 'When the file does not contain annotation yet' do + context 'When no option is passed' do + let :expected_result do + <<~EOS + + # == Route Map + # + # Prefix Verb URI Pattern Controller#Action + # myaction1 GET /url1(.:format) mycontroller1#action + # myaction2 POST /url2(.:format) mycontroller2#action + # myaction3 DELETE|GET /url3(.:format) mycontroller3#action + EOS + end + + it 'annotates normally' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations + end + end + + context 'When the option "format_markdown" is passed' do + let :expected_result do + <<~EOS + + # ## Route Map + # + # Prefix | Verb | URI Pattern | Controller#Action + # --------- | ---------- | --------------- | -------------------- + # myaction1 | GET | /url1(.:format) | mycontroller1#action + # myaction2 | POST | /url2(.:format) | mycontroller2#action + # myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action + EOS + end + + it 'annotates in Markdown format' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations(format_markdown: true) + end + end + + context 'When the options "wrapper_open" and "wrapper_close" are passed' do + let :expected_result do + <<~EOS + + # START + # == Route Map + # + # Prefix Verb URI Pattern Controller#Action + # myaction1 GET /url1(.:format) mycontroller1#action + # myaction2 POST /url2(.:format) mycontroller2#action + # myaction3 DELETE|GET /url3(.:format) mycontroller3#action + # END + EOS + end + + it 'annotates and wraps annotation with specified words' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END') + end + end + end end - let :expected_result do - <<~EOS - ActionController::Routing... - foo - - # == Route Map - # - # another good line - # good line - EOS + context 'When the file contains magic comments' do + MAGIC_COMMENTS.each do |magic_comment| + describe "magic comment: #{magic_comment.inspect}" do + let :route_file_content do + <<~EOS + #{magic_comment} + EOS + end + + let :rake_routes_result do + <<-EOS + Prefix Verb URI Pattern Controller#Action + myaction1 GET /url1(.:format) mycontroller1#action + myaction2 POST /url2(.:format) mycontroller2#action + myaction3 DELETE|GET /url3(.:format) mycontroller3#action + EOS + end + + context 'When the file does not contain annotation yet' do + context 'When no option is passed' do + let :expected_result do + <<~EOS + #{magic_comment} + + # == Route Map + # + # Prefix Verb URI Pattern Controller#Action + # myaction1 GET /url1(.:format) mycontroller1#action + # myaction2 POST /url2(.:format) mycontroller2#action + # myaction3 DELETE|GET /url3(.:format) mycontroller3#action + EOS + end + + it 'annotates normally' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations + end + end + + context 'When the option "format_markdown" is passed' do + let :expected_result do + <<~EOS + #{magic_comment} + + # ## Route Map + # + # Prefix | Verb | URI Pattern | Controller#Action + # --------- | ---------- | --------------- | -------------------- + # myaction1 | GET | /url1(.:format) | mycontroller1#action + # myaction2 | POST | /url2(.:format) | mycontroller2#action + # myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action + EOS + end + + it 'annotates in Markdown format' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations(format_markdown: true) + end + end + + context 'When the options "wrapper_open" and "wrapper_close" are passed' do + let :expected_result do + <<~EOS + #{magic_comment} + + # START + # == Route Map + # + # Prefix Verb URI Pattern Controller#Action + # myaction1 GET /url1(.:format) mycontroller1#action + # myaction2 POST /url2(.:format) mycontroller2#action + # myaction3 DELETE|GET /url3(.:format) mycontroller3#action + # END + EOS + end + + it 'annotates and wraps annotation with specified words' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END') + end + end + end + end + end end + end - it 'annotates with an empty line' do - expect(mock_file).to receive(:puts).with(expected_result) - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) + context 'When the result of `rake routes` contains Rake version' do + context 'with older Rake versions' do + let :rake_routes_result do + <<~EOS.chomp + (in /bad/line) + good line + EOS + end + + context 'When the route file does not end with an empty line' do + let :route_file_content do + <<~EOS.chomp + ActionController::Routing... + foo + EOS + end + + let :expected_result do + <<~EOS + ActionController::Routing... + foo + + # == Route Map + # + # good line + EOS + end + + it 'annotates with an empty line' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations + end + end + + context 'When the route file ends with an empty line' do + let :route_file_content do + <<~EOS + ActionController::Routing... + foo + EOS + end + + let :expected_result do + <<~EOS + ActionController::Routing... + foo + + # == Route Map + # + # good line + EOS + end + + it 'annotates without an empty line' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations + end + end + end - AnnotateRoutes.do_annotations + context 'with newer Rake versions' do + let :rake_routes_result do + <<~EOS.chomp + another good line + good line + EOS + end + + context 'When the route file does not end with an empty line' do + context 'When no option is passed' do + let :route_file_content do + <<~EOS.chomp + ActionController::Routing... + foo + EOS + end + + let :expected_result do + <<~EOS + ActionController::Routing... + foo + + # == Route Map + # + # another good line + # good line + EOS + end + + it 'annotates with an empty line' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations + end + end + end + + context 'When the route file ends with an empty line' do + let :route_file_content do + <<~EOS + ActionController::Routing... + foo + EOS + end + + let :expected_result do + <<~EOS + ActionController::Routing... + foo + + # == Route Map + # + # another good line + # good line + EOS + end + + it 'annotates without an empty line' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations + end + end + + context 'When option "timestamp" is passed' do + let :route_file_content do + <<~EOS.chomp + ActionController::Routing... + foo + EOS + end + + let :expected_result do + /ActionController::Routing...\nfoo\n\n# == Route Map \(Updated \d{4}-\d{2}-\d{2} \d{2}:\d{2}\)\n#\n# another good line\n# good line\n/ + end + + it 'annotates with the timestamp and an empty line' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations timestamp: true + end + end end end end - context 'When the route file ends with an empty line' do - let :route_file_content do - <<~EOS - ActionController::Routing... - foo - EOS + context 'When the result of `rake routes` is blank' do + let :rake_routes_result do + '' end - let :expected_result do - <<~EOS - ActionController::Routing... - foo - - # == Route Map - # - # another good line - # good line - EOS - end + context 'When the file does not contain magic comment' do + context 'When the file does not contain annotation yet' do + let :route_file_content do + '' + end + + context 'When no option is specified' do + let :expected_result do + <<~EOS + + # == Route Map + # + EOS + end + + it 'inserts annotations' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations + end + end + + context 'When the option "ignore_routes" is specified' do + let :expected_result do + <<~EOS + + # == Route Map + # + EOS + end + + it 'inserts annotations' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations(ignore_routes: 'my_route') + end + end + + context 'When the option "position_in_routes" is specified as "top"' do + let :expected_result do + <<~EOS + # == Route Map + # + EOS + end + + it 'inserts annotations' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations(position_in_routes: 'top') + end + end + end - it 'annotates without an empty line' do - expect(mock_file).to receive(:puts).with(expected_result) - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) + context 'When the file already contains annotation' do + context 'When no option is specified' do + let :route_file_content do + <<~EOS - AnnotateRoutes.do_annotations - end - end + # == Route Map + # + EOS + end - context 'When option "timestamp" is passed' do - let :route_file_content do - <<~EOS.chomp - ActionController::Routing... - foo - EOS - end + it 'should skip annotations if file does already contain annotation' do + expect(File).not_to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) + expect(mock_file).not_to receive(:puts) + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_UNCHANGED).once - let :expected_result do - /ActionController::Routing...\nfoo\n\n# == Route Map \(Updated \d{4}-\d{2}-\d{2} \d{2}:\d{2}\)\n#\n# another good line\n# good line\n/ + AnnotateRoutes.do_annotations + end + end + end end - it 'annotates with the timestamp and an empty line' do - expect(mock_file).to receive(:puts).with(expected_result) - expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED) - - AnnotateRoutes.do_annotations timestamp: true + context 'When the file contains magic comments' do + MAGIC_COMMENTS.each do |magic_comment| + describe "magic comment: #{magic_comment.inspect}" do + let :route_file_content do + <<~EOS + #{magic_comment} + Something + EOS + end + + context 'When the file does not contain annotation yet' do + context 'When the option "position_in_routes" is specified as "top"' do + let :expected_result do + <<~EOS + #{magic_comment} + + # == Route Map + # + + Something + EOS + end + + it 'leaves magic comment on top and adds an empty line between magic comment and annotation' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations(position_in_routes: 'top') + end + end + + context 'When the option "position_in_routes" is specified as "bottom"' do + let :expected_result do + <<~EOS + #{magic_comment} + Something + + # == Route Map + # + EOS + end + + it 'leaves magic comment on top and adds an empty line between magic comment and annotation' do + expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file).once + expect(mock_file).to receive(:puts).with(expected_result).once + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_ANNOTATED).once + + AnnotateRoutes.do_annotations(position_in_routes: 'bottom') + end + end + end + + context 'When the file already contains annotation' do + let :route_file_content do + <<~EOS + #{magic_comment} + + # == Route Map + # + EOS + end + + it 'skips annotations' do + expect(File).not_to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file) + expect(mock_file).not_to receive(:puts) + expect(AnnotateRoutes).to receive(:puts).with(MESSAGE_UNCHANGED).once + + AnnotateRoutes.do_annotations + end + end + end + end end end end