-
-
Notifications
You must be signed in to change notification settings - Fork 909
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Why: * The `route` matcher can not only be used within controller example groups but also routing example groups. * Now that we are mixing matchers into specific example groups, `route` is no longer available in routing example groups. To satisfy the above: * Create a new module that contains a `route` method and returns a new instance of RouteMatcher. (RouteMatcher still lives in the ActionController namespace.) * Mix this module into routing example groups when the gem configuration block is run.
- Loading branch information
Showing
6 changed files
with
283 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
module Shoulda | ||
module Matchers | ||
module Integrations | ||
module Libraries | ||
# @private | ||
class Routing | ||
Integrations.register_library(self, :routing) | ||
|
||
include Integrations::Inclusion | ||
include Integrations::Rails | ||
|
||
def integrate_with(test_framework) | ||
test_framework.include(matchers_module, type: :routing) | ||
|
||
include_into(::ActionController::TestCase, matchers_module) | ||
end | ||
|
||
private | ||
|
||
def matchers_module | ||
Shoulda::Matchers::Routing | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module Shoulda | ||
module Matchers | ||
module Routing | ||
# @private | ||
def route(method, path) | ||
ActionController::RouteMatcher.new(method, path, self) | ||
end | ||
end | ||
end | ||
end |
242 changes: 242 additions & 0 deletions
242
spec/unit/shoulda/matchers/routing/route_matcher_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
require 'unit_spec_helper' | ||
|
||
describe 'Shoulda::Matchers::Routing::RouteMatcher', type: :routing do | ||
before do | ||
define_controller('ThingsController') | ||
end | ||
|
||
shared_examples_for 'core tests' do | ||
context 'when the given method, path, controller, and action match an existing route' do | ||
it 'accepts' do | ||
define_routes { get '/', to: 'things#index' } | ||
|
||
assert_accepts add_target_to( | ||
route(:get, '/'), | ||
controller: 'things', | ||
action: 'index' | ||
) | ||
end | ||
|
||
context 'and the expected controller is specified as a symbol' do | ||
it 'accepts' do | ||
define_routes { get '/', to: 'things#index' } | ||
|
||
assert_accepts add_target_to( | ||
route(:get, '/'), | ||
controller: :things, | ||
action: 'index' | ||
) | ||
end | ||
end | ||
|
||
context 'and the expected action is specified as a symbol' do | ||
it 'accepts' do | ||
define_routes { get '/', to: 'things#index' } | ||
|
||
assert_accepts add_target_to( | ||
route(:get, '/'), | ||
controller: 'things', | ||
action: :index | ||
) | ||
end | ||
end | ||
end | ||
|
||
context 'when the given method, path, controller, and action do not match an existing route' do | ||
it 'rejects' do | ||
assert_rejects add_target_to( | ||
route(:get, '/non_existent_route'), | ||
controller: 'no_controller', | ||
action: 'no_action' | ||
) | ||
end | ||
end | ||
|
||
context 'when the given path, controller, and action match an existing route but the method does not' do | ||
it 'rejects' do | ||
define_routes { post '/', to: 'things#index' } | ||
|
||
assert_rejects add_target_to( | ||
route(:get, '/'), | ||
controller: 'things', | ||
action: 'index' | ||
) | ||
end | ||
end | ||
|
||
context 'when the given method, controller, and action match an existing route but the path does not' do | ||
it 'rejects' do | ||
define_routes { get '/', to: 'things#index' } | ||
|
||
assert_rejects add_target_to( | ||
route(:get, '/different_path'), | ||
controller: 'things', | ||
action: 'index' | ||
) | ||
end | ||
end | ||
|
||
context 'when the given method and path match an existing route but the controller does not' do | ||
it 'rejects' do | ||
define_routes { get '/', to: 'another_controller#index' } | ||
|
||
assert_rejects add_target_to( | ||
route(:get, '/'), | ||
controller: 'things', | ||
action: 'index' | ||
) | ||
end | ||
end | ||
|
||
context 'when the given method, path, and controller match an existing route but the action does not' do | ||
it 'rejects' do | ||
define_routes { get '/', to: 'things#index' } | ||
|
||
assert_rejects add_target_to( | ||
route(:get, '/'), | ||
controller: 'things', | ||
action: 'another_action' | ||
) | ||
end | ||
end | ||
|
||
context 'when the actual route has a param' do | ||
context 'and the expected params include that param' do | ||
it 'accepts' do | ||
define_routes { get '/things/:id', to: 'things#show' } | ||
|
||
assert_accepts add_target_to( | ||
route(:get, '/things/1'), | ||
controller: 'things', | ||
action: 'show', | ||
id: '1' | ||
) | ||
end | ||
|
||
context 'but its value was not specified as a string' do | ||
it 'accepts, treating it as a string' do | ||
define_routes { get '/things/:id', to: 'things#show' } | ||
|
||
assert_accepts add_target_to( | ||
route(:get, '/things/1'), | ||
controller: 'things', | ||
action: 'show', | ||
id: 1 | ||
) | ||
end | ||
end | ||
end | ||
|
||
context 'and the expected params do not match the actual params' do | ||
it 'rejects' do | ||
define_routes { get '/things/:id', to: 'things#show' } | ||
|
||
params = { | ||
controller: 'things', | ||
action: 'show', | ||
some: 'other', | ||
params: 'here' | ||
} | ||
assert_rejects add_target_to( | ||
route(:get, '/things/:id'), | ||
params | ||
) | ||
end | ||
end | ||
end | ||
|
||
context 'when the actual route has a default param whose value is a symbol' do | ||
context 'and the expected params include a value for it' do | ||
context 'as a symbol' do | ||
it 'accepts' do | ||
define_routes do | ||
post '/things(.:format)', | ||
to: 'things#create', | ||
defaults: { format: :json } | ||
end | ||
|
||
assert_accepts add_target_to( | ||
route(:post, '/things'), | ||
controller: 'things', | ||
action: 'create', | ||
format: :json | ||
) | ||
end | ||
end | ||
|
||
context 'as a string' do | ||
it 'accepts' do | ||
define_routes do | ||
post '/things(.:format)', | ||
to: 'things#create', | ||
defaults: { format: :json } | ||
end | ||
|
||
assert_accepts add_target_to( | ||
route(:post, '/things'), | ||
controller: 'things', | ||
action: 'create', | ||
format: 'json' | ||
) | ||
end | ||
end | ||
end | ||
end | ||
|
||
context 'when the existing route has a glob segment' do | ||
context 'and a param is given which represents the segment' do | ||
it 'accepts' do | ||
define_routes { get '/things/*id', to: 'things#whatever' } | ||
|
||
assert_accepts add_target_to( | ||
route(:get, '/things/foo/bar'), | ||
controller: 'things', | ||
action: 'whatever', | ||
id: 'foo/bar' | ||
) | ||
end | ||
end | ||
|
||
context 'and no param is given which represents the segment' do | ||
it 'rejects' do | ||
define_routes { get '/things/*id', to: 'things#whatever' } | ||
|
||
assert_rejects add_target_to( | ||
route(:get, '/things'), | ||
controller: 'things', | ||
action: 'whatever' | ||
) | ||
end | ||
end | ||
end | ||
end | ||
|
||
context 'given a controller and action specified as individual options' do | ||
include_examples 'core tests' | ||
|
||
def add_target_to(route_matcher, params) | ||
route_matcher.to(params) | ||
end | ||
end | ||
|
||
context 'given a controller and action joined together in a string' do | ||
include_examples 'core tests' | ||
|
||
def add_target_to(route_matcher, args) | ||
controller = args.fetch(:controller) | ||
action = args.fetch(:action) | ||
route_matcher.to( | ||
"#{controller}##{action}", | ||
args.except(:controller, :action) | ||
) | ||
end | ||
end | ||
|
||
def assert_accepts(matcher) | ||
should(matcher) | ||
end | ||
|
||
def assert_rejects(matcher) | ||
should_not(matcher) | ||
end | ||
end |