spec/praxis/router_spec.rb in praxis-2.0.pre.18 vs spec/praxis/router_spec.rb in praxis-2.0.pre.19

- old
+ new

@@ -1,187 +1,181 @@ +# frozen_string_literal: true + require 'spec_helper' describe Praxis::Router do describe Praxis::Router::VersionMatcher do - let(:endpoint_definition){ double("endpoint_definition", version_options: { using: [:header, :params] }) } - let(:action){ double("action", endpoint_definition: endpoint_definition ) } - let(:target){ double("target", action: action ) } - let(:args){ {version: "1.0"} } - subject(:matcher){ Praxis::Router::VersionMatcher.new(target,**args) } + let(:endpoint_definition) { double('endpoint_definition', version_options: { using: %i[header params] }) } + let(:action) { double('action', endpoint_definition: endpoint_definition) } + let(:target) { double('target', action: action) } + let(:args) { { version: '1.0' } } + subject(:matcher) { Praxis::Router::VersionMatcher.new(target, **args) } context '.initialize' do - let(:args){ {} } + let(:args) { {} } it 'defaults to no version' do - expect( matcher.instance_variable_get(:@version) ).to eq("n/a") + expect(matcher.instance_variable_get(:@version)).to eq('n/a') end end context '.call' do - let(:env){ {"HTTP_X_API_VERSION" => request_version } } - let(:request) {Praxis::Request.new(env)} + let(:env) { { 'HTTP_X_API_VERSION' => request_version } } + let(:request) { Praxis::Request.new(env) } context 'with matching versions' do - let(:request_version) { "1.0" } + let(:request_version) { '1.0' } it 'calls the target' do expect(target).to receive(:call).with(request) matcher.call(request) end end context 'with non-matching versions' do - let(:request_version) { "4.0" } + let(:request_version) { '4.0' } before do expect { matcher.call(request) }.to throw_symbol(:pass) end it 'does not call the target' do - expect( target ).not_to receive(:call).with(request) + expect(target).not_to receive(:call).with(request) end it 'saves the unmatched version' do - expect( request.unmatched_versions ).to include(args[:version]) + expect(request.unmatched_versions).to include(args[:version]) end end - end end describe Praxis::Router::RequestRouter do + let(:request) { double('request', route_params: '', path: 'path') } + let(:callback) { double('callback') } - let(:request) {double("request", route_params: '', path: 'path')} - let(:callback) {double("callback")} + subject(:request_router) { Praxis::Router::RequestRouter.new } - subject(:request_router) {Praxis::Router::RequestRouter.new} - - context ".invoke" do - it "update request and call request for callback" do + context '.invoke' do + it 'update request and call request for callback' do allow(request).to receive(:route_params=) allow(callback).to receive(:call).and_return(1) - invoke_call = request_router.invoke(callback, request, "params", "pattern") + invoke_call = request_router.invoke(callback, request, 'params', 'pattern') expect(invoke_call).to eq(1) end end - context ".string_for" do - it "returns request path string" do + context '.string_for' do + it 'returns request path string' do expect(request_router.string_for(request)).to eq('path') end end end - let(:application) { instance_double('Praxis::Application')} - subject(:router) {Praxis::Router.new(application)} + let(:application) { instance_double('Praxis::Application') } + subject(:router) { Praxis::Router.new(application) } - context "attributes" do - its(:request_class) {should be(Praxis::Request)} + context 'attributes' do + its(:request_class) { should be(Praxis::Request) } end - context ".add_route" do + context '.add_route' do + let(:route) { double('route', options: [1], version: 1, verb: 'verb', path: 'path') } + let(:target) { double('target') } + let(:verb_router) { double('verb_router') } - let(:route){ double('route', options: [1], version: 1, verb: 'verb', path: 'path')} - let(:target){ double('target') } - let(:verb_router){ double('verb_router') } - - let(:endpoint_definition) { double('endpoint_definition', version_options: {using: [:header, :params]} ) } + let(:endpoint_definition) { double('endpoint_definition', version_options: { using: %i[header params] }) } let(:action) { double('action', endpoint_definition: endpoint_definition) } let(:target) { double('target', action: action) } - context 'with params or header versioning' do it 'wraps the target with a VersionMatcher' do - router.instance_variable_set( :@routes, {'verb'=>verb_router} ) # Ugly, but no need to have a reader - expect(verb_router).to receive(:on) do|path, args|# .with(route.path, call: "foo") + router.instance_variable_set(:@routes, { 'verb' => verb_router }) # Ugly, but no need to have a reader + expect(verb_router).to receive(:on) do |path, args| # .with(route.path, call: "foo") expect(path).to eq(route.path) expect(args).to be_kind_of(Hash) expect(args[:call]).to be_kind_of(Praxis::Router::VersionMatcher) end router.add_route(target, route) end end - end - context ".call" do - let(:env){ {"PATH_INFO"=>request_path_info, "REQUEST_METHOD"=>request_verb} } + context '.call' do + let(:env) { { 'PATH_INFO' => request_path_info, 'REQUEST_METHOD' => request_verb } } let(:request_verb) { 'POST' } let(:request_path_info) { '/' } - let(:request_version){ nil } - let(:request) {Praxis::Request.new(env)} - let(:router_response){ 1 } - let(:router_response_for_post){ "POST result" } - let(:router_response_for_wildcard){ "* result" } - let(:post_target_router){ double("POST target", call: router_response_for_post) } - let(:any_target_router){ double("ANY target", call: router_response_for_wildcard) } + let(:request_version) { nil } + let(:request) { Praxis::Request.new(env) } + let(:router_response) { 1 } + let(:router_response_for_post) { 'POST result' } + let(:router_response_for_wildcard) { '* result' } + let(:post_target_router) { double('POST target', call: router_response_for_post) } + let(:any_target_router) { double('ANY target', call: router_response_for_wildcard) } - let(:endpoint_definition) { double('endpoint_definition', version_options: {using: [:header, :params]} ) } + let(:endpoint_definition) { double('endpoint_definition', version_options: { using: %i[header params] }) } let(:action) { double('action', endpoint_definition: endpoint_definition) } let(:target) { double('target', action: action) } before do env['HTTP_X_API_VERSION'] = request_version if request_version - allow_any_instance_of(Praxis::Router::RequestRouter). - to receive(:call).with(request).and_return(router_response) - router.add_route(target,double("route1", verb: 'POST', path: '/', options: {} , version: request_version)) + allow_any_instance_of(Praxis::Router::RequestRouter) + .to receive(:call).with(request).and_return(router_response) + router.add_route(target, double('route1', verb: 'POST', path: '/', options: {}, version: request_version)) # Hijack the callable block in the routes (since there's no way to point back to the registered route object) router.instance_variable_get(:@routes)['POST'] = post_target_router - end context 'for routes without wildcards (a single POST route)' do - context 'and an incoming POST request' do - it "finds a match and invokes it the route" do + it 'finds a match and invokes it the route' do expect(router.call(request)).to eq(router_response_for_post) end end context 'and an incoming PUT request' do let(:request_verb) { 'PUT' } - it "does not find a route" do - response_code, _ , _ = router.call(request) + it 'does not find a route' do + response_code, = router.call(request) expect(response_code).to be(404) end end end context 'for routes with wildcards (a POST and a * route)' do - let(:endpoint_definition) { double('endpoint_definition', version_options: {using: [:header, :params]} ) } + let(:endpoint_definition) { double('endpoint_definition', version_options: { using: %i[header params] }) } let(:action) { double('action', endpoint_definition: endpoint_definition) } let(:target) { double('target', action: action) } before do - router.add_route(target,double("route2", verb: 'ANY', path: '/*', options: {} , version: request_version)) + router.add_route(target, double('route2', verb: 'ANY', path: '/*', options: {}, version: request_version)) # Hijack the callable block in the routes (since there's no way to point back to the registered route object) - router.instance_variable_get( :@routes )['ANY'] = any_target_router + router.instance_variable_get(:@routes)['ANY'] = any_target_router end context 'and an incoming PUT request' do let(:request_verb) { 'PUT' } - it "it can successfully find a match using the wildcard target" do + it 'it can successfully find a match using the wildcard target' do expect(router.call(request)).to eq(router_response_for_wildcard) end end context 'and an incoming POST request' do - it 'matches the most specific POST route, rather than the wildcard'do + it 'matches the most specific POST route, rather than the wildcard' do expect(router.call(request)).to eq(router_response_for_post) end end context 'and an incoming POST request (but that does not match other route conditions)' do - let(:router_response_for_post){ :not_found } + let(:router_response_for_post) { :not_found } it 'still matches wildcard verb if that was route conditions-compatible' do expect(post_target_router).to receive(:call).once # try the match cause it's a POST expect(any_target_router).to receive(:call).once # fallback to wildcard upon a not_found expect(router.call(request)).to eq(router_response_for_wildcard) end end end - context "when not_found is returned" do + context 'when not_found is returned' do let(:request_verb) { 'DELETE' } - let(:router_response){ :not_found } + let(:router_response) { :not_found } - it 'sets X-Cascade: pass by default' do - _, headers, _ = router.call(request) + _, headers, = router.call(request) expect(headers).to have_key('X-Cascade') expect(headers['X-Cascade']).to eq('pass') end context 'with X-Cascade disabled' do @@ -189,54 +183,50 @@ before do expect(config).to receive(:x_cascade).and_return(false) end it 'does not set X-Cascade: pass' do - _, headers, _ = router.call(request) - expect(headers).to_not have_key("X-Cascade") + _, headers, = router.call(request) + expect(headers).to_not have_key('X-Cascade') end - end context 'with versioning' do before do request.instance_variable_set(:@unmatched_versions, unmatched_versions) end - context "having passed no version in the request" do + context 'having passed no version in the request' do context 'and no controllers matching the path' do let(:unmatched_versions) { Set.new([]) } it 'returns a basic "NotFound" response: 404 status, text/plain content and "NotFound" body' do - expect( router.call(request) ).to eq([404, {"Content-Type" => "text/plain","X-Cascade"=>"pass"}, ["NotFound"]]) + expect(router.call(request)).to eq([404, { 'Content-Type' => 'text/plain', 'X-Cascade' => 'pass' }, ['NotFound']]) end end context 'and some controllers matching the path' do - let(:unmatched_versions) { Set.new(["1.0"]) } + let(:unmatched_versions) { Set.new(['1.0']) } it 'returns a specific body response noting which request versions would matched if passed in' do _, _, body = router.call(request) - expect( body.first ).to eq('NotFound. Your request did not specify an API version. Available versions = "1.0".') + expect(body.first).to eq('NotFound. Your request did not specify an API version. Available versions = "1.0".') end end end - context "having passed a version in the request" do - + context 'having passed a version in the request' do context 'but having no controllers matching the path part' do - let(:request_version) { "50.0" } - let(:unmatched_versions) { Set.new(["1.0","2.0"]) } + let(:request_version) { '50.0' } + let(:unmatched_versions) { Set.new(['1.0', '2.0']) } it 'returns a specific body response noting that the version might be wrong (and which could be right)' do code, headers, body = router.call(request) expect(code).to eq(404) expect(headers['Content-Type']).to eq('text/plain') expect(body.first).to eq("NotFound. Your request specified API version = \"#{request_version}\". Available versions = \"1.0\", \"2.0\".") end end end end - - end end end