From 636249bf0329eece5dab2137b0afa7d7b404751a Mon Sep 17 00:00:00 2001 From: Ernie Brodeur Date: Tue, 20 Nov 2018 12:36:19 -0800 Subject: [PATCH] wip --- Guardfile | 5 +- lib/cts/mpx/driver/exceptions.rb | 5 +- lib/cts/mpx/driver/helpers.rb | 2 +- lib/cts/mpx/services/data.rb | 1 - spec/cts/mpx/driver/exceptions_spec.rb | 2 - spec/cts/mpx/entry_spec.rb | 2 - spec/cts/mpx/query_spec.rb | 2 +- spec/cts/mpx/services/data_spec.rb | 228 ++++++++++++------ spec/cts/mpx/services/web_spec.rb | 1 - spec/matchers/raise_argument_exception.rb | 2 +- .../raise_error_without_user_token.rb | 4 +- spec/matchers/require_keyword_arguments.rb | 4 +- spec/spec_helper_shared_contexts.rb | 138 ++++++----- spec/spec_helper_shared_examples.rb | 136 ++++++----- 14 files changed, 316 insertions(+), 216 deletions(-) diff --git a/Guardfile b/Guardfile index c65b1e0..1c62d1e 100644 --- a/Guardfile +++ b/Guardfile @@ -27,15 +27,12 @@ guard :rspec, cmd: "bundle exec rspec" do require "guard/rspec/dsl" dsl = Guard::RSpec::Dsl.new(self) - # Feel free to open issues for suggestions and improvements - - # RSpec files rspec = dsl.rspec watch(rspec.spec_helper) { rspec.spec_dir } watch(rspec.spec_support) { rspec.spec_dir } + watch(%r{spec\/spec_*}) { rspec.spec_dir } watch(rspec.spec_files) - # Ruby files ruby = dsl.ruby dsl.watch_spec_files_for(ruby.lib_files) end diff --git a/lib/cts/mpx/driver/exceptions.rb b/lib/cts/mpx/driver/exceptions.rb index 273c8af..d973e61 100644 --- a/lib/cts/mpx/driver/exceptions.rb +++ b/lib/cts/mpx/driver/exceptions.rb @@ -39,8 +39,9 @@ def raise_unless_reference?(argument) # @param [Object] keyword keyword to assure is supplied # @raise [ArgumentError] if the keyword is not suppplied # @return [nil] - def raise_unless_required_keyword?(keyword: nil) - raise ArgumentError, "#{keyword} is a required keyword." unless keyword + def raise_unless_required_keyword?(a_binding, keyword) + value = a_binding.local_variable_get(keyword) + raise ArgumentError, "#{keyword} is a required keyword." unless value end end end diff --git a/lib/cts/mpx/driver/helpers.rb b/lib/cts/mpx/driver/helpers.rb index d4fe3a8..4b31184 100644 --- a/lib/cts/mpx/driver/helpers.rb +++ b/lib/cts/mpx/driver/helpers.rb @@ -58,7 +58,7 @@ def raise_if_not_a_hash(objects) # @return [nil] nil # def required_arguments(keywords, a_binding) - keywords.each { |arg| Exceptions.raise_unless_required_keyword?(keyword: a_binding.local_variable_get(arg)) } + keywords.each { |keyword| Exceptions.raise_unless_required_keyword?(a_binding, keyword) } nil end end diff --git a/lib/cts/mpx/services/data.rb b/lib/cts/mpx/services/data.rb index 5dfa37d..599105f 100644 --- a/lib/cts/mpx/services/data.rb +++ b/lib/cts/mpx/services/data.rb @@ -74,7 +74,6 @@ def get(user: nil, account_id: nil, service: nil, fields: nil, endpoint: nil, so # @return [Response] Response of the call def post(user: nil, account_id: nil, service: nil, endpoint: nil, extra_path: nil, query: {}, page: nil, headers: {}, method: :post) prep_call(user: user, account_id: account_id, service: service, query: query, headers: headers, required_arguments: ['user', 'service', 'endpoint', 'page'], page: page, binding: binding) - host = Driver::Assemblers.host user: user, service: service path = Driver::Assemblers.path service: service, endpoint: endpoint, extra_path: extra_path query = Driver::Assemblers.query user: user, account_id: account_id, service: service, endpoint: endpoint, query: query diff --git a/spec/cts/mpx/driver/exceptions_spec.rb b/spec/cts/mpx/driver/exceptions_spec.rb index 03276e9..d66a945 100644 --- a/spec/cts/mpx/driver/exceptions_spec.rb +++ b/spec/cts/mpx/driver/exceptions_spec.rb @@ -12,7 +12,6 @@ module Driver describe "::raise_unless_account_id" do context "when the argument is not an account_id" do - it "is expected to raise a ArgumentError with is not a valid account_id " do expect { described_class.raise_unless_account_id(reference) }.to raise_error ArgumentError, /#{reference} is not a valid account_id/ end @@ -46,7 +45,6 @@ module Driver describe "::raise_unless_reference?" do it { expect(described_class).to respond_to(:raise_unless_reference?).with(1).argument } context "when the argument is not a reference" do - it "is expected to raise a ArgumentError with is not a valid reference " do expect { described_class.raise_unless_reference?(reference) }.to raise_error ArgumentError, /#{reference} is not a valid reference/ end diff --git a/spec/cts/mpx/entry_spec.rb b/spec/cts/mpx/entry_spec.rb index b677559..9b6547a 100644 --- a/spec/cts/mpx/entry_spec.rb +++ b/spec/cts/mpx/entry_spec.rb @@ -158,9 +158,7 @@ module Mpx expect(media_entry.save(user: user)).to be media_entry end - context "when fields['ownerId'] is not set" do - before { entry.fields['ownerId'] = nil } it { expect { entry.save user: user }.to raise_error ArgumentError, "fields['ownerId'] must be set" } diff --git a/spec/cts/mpx/query_spec.rb b/spec/cts/mpx/query_spec.rb index 4da11dd..63390af 100644 --- a/spec/cts/mpx/query_spec.rb +++ b/spec/cts/mpx/query_spec.rb @@ -3,7 +3,7 @@ module Cts module Mpx describe Query do - include_context "with fields" + include_context "with fields objects" include_context "with media objects" include_context "with user objects" include_context "with empty objects" diff --git a/spec/cts/mpx/services/data_spec.rb b/spec/cts/mpx/services/data_spec.rb index 8961c3b..ad50e66 100644 --- a/spec/cts/mpx/services/data_spec.rb +++ b/spec/cts/mpx/services/data_spec.rb @@ -1,104 +1,182 @@ require 'spec_helper' -module Cts - module Mpx - module Services - describe Data do - include_context "with request and response objects" - include_context "with media objects" - include_context "with user objects" - - let(:root_domain) { Driver.load_json_file('config/root_registry_sea1.json')['resolveDomainResponse'] } - let(:call_params) { { user: user, service: media_service, endpoint: media_endpoint, query: {} } } - let(:with_params) { { method: call_method, url: "http://data.media.theplatform.com/media/data/Media/feed", query: {}, headers: {} } } - - before do - allow(Driver::Request).to receive(:new).and_return request - allow(request).to receive(:call).and_return response - allow(Registry).to receive(:fetch_and_store_domain).and_return root_domain - Registry.initialize - end +module Cts::Mpx::Services + describe Data do + include_context "with data parameters" + include_context "with request and response objects" + include_context "with media objects" + include_context "with user objects" + + let(:root_domain) { Driver.load_json_file('config/root_registry_sea1.json')['resolveDomainResponse'] } + let(:call_params) { { user: user, service: media_service, endpoint: media_endpoint, query: {} } } + let(:with_params) { { method: call_method, url: "http://data.media.theplatform.com/media/data/Media/feed", query: { form: "cjson", schema: "1.7.0", token: "carpe diem" }, headers: {} } } + + before do + allow(Driver::Request).to receive(:new).and_return request + allow(request).to receive(:call).and_return response + allow(Registry).to receive(:fetch_and_store_domain).and_return root_domain + Registry.initialize + end - it { expect(described_class.class).to be Module } + it { expect(described_class.class).to be Module } - describe "Responds to" do - it { is_expected.to respond_to(:[]).with(0..1).arguments } - it { is_expected.to respond_to(:delete).with_keywords(:user, :account_id, :service, :endpoint, :sort, :extra_path, :range, :ids, :query, :headers, :count, :entries) } - it { is_expected.to respond_to(:get).with_keywords(:user, :account_id, :service, :endpoint, :sort, :extra_path, :range, :ids, :query, :headers, :count, :entries, :fields) } - it { is_expected.to respond_to(:post).with_keywords(:user, :account_id, :service, :endpoint, :extra_path, :query, :page, :headers) } - it { is_expected.to respond_to(:put).with_keywords(:user, :account_id, :service, :endpoint, :extra_path, :query, :page, :headers) } - end + describe "Responds to" do + it { is_expected.to respond_to(:[]).with(0..1).arguments } + it { is_expected.to respond_to(:delete).with_keywords(:user, :account_id, :service, :endpoint, :sort, :extra_path, :range, :ids, :query, :headers, :count, :entries) } + it { is_expected.to respond_to(:get).with_keywords(:user, :account_id, :service, :endpoint, :sort, :extra_path, :range, :ids, :query, :headers, :count, :entries, :fields) } + it { is_expected.to respond_to(:post).with_keywords(:user, :account_id, :service, :endpoint, :extra_path, :query, :page, :headers) } + it { is_expected.to respond_to(:put).with_keywords(:user, :account_id, :service, :endpoint, :extra_path, :query, :page, :headers) } + end - describe "::[] (addressable method)" do - let(:service) { 'Media Data Service' } + describe "::[] (addressable method)" do + let(:service) { 'Media Data Service' } - context "when the key is not a string" do - it { expect { described_class[1] }.to raise_error(ArgumentError, /key must be a string/) } - end + context "when the key is not a string" do + it { expect { described_class[1] }.to raise_error(ArgumentError, /key must be a string/) } + end - context "when the key is not a service name" do - it { expect { described_class['1'] }.to raise_error(ArgumentError, /must be a service name/) } - end + context "when the key is not a service name" do + it { expect { described_class['1'] }.to raise_error(ArgumentError, /must be a service name/) } + end - context "when a key is not provided" do - it { expect(described_class[]).to be_instance_of Array } - end + context "when a key is not provided" do + it { expect(described_class[]).to be_instance_of Array } + end - it "is expected to search for services that are type: data only" do - expect(described_class[].count).to eq 29 - end + it "is expected to search for services that are type: data only" do + expect(described_class[].count).to eq 29 + end - it { expect(described_class[service]).to be_instance_of Driver::Service } - end + it { expect(described_class[service]).to be_instance_of Driver::Service } + end - describe '::delete', focus: true do - let(:call_method) { :delete } + describe '::delete' do + let(:call_method) { :delete } - include_examples 'call_constraints' - include_examples 'call_request', :delete + include_examples 'call_constraints' + include_examples 'call_request', :delete + end + + describe "::get" do + let(:call_method) { :get } + + context "when fields is provided" do + before { call_params[:fields] = 'id,guid' } + + it "is expected to pass them to Request.call" do + allow(Driver::Request).to receive(:create).and_call_original + described_class.send call_method, call_params + expect(Driver::Request).to have_received(:create).with(a_hash_including(query: a_hash_including(fields: call_params[:fields]))) end + end + + include_examples 'call_constraints' + include_examples 'call_request', :get + end - describe "::get" do - let(:call_method) { :get } + shared_context "with data call setup" do + let(:call_params) { { user: user, service: service, endpoint: endpoint, query: {} } } + let(:call_parent) { Cts::Mpx::Services::Data } + let(:create_with_params) { { method: described_class, url: "http://data.media.theplatform.com/media/data/Media/feed", query: { form: "cjson", schema: "1.7.0", token: "carpe diem" }, headers: {} } } - context "when fields is provided" do - before { call_params[:fields] = 'id,guid' } + before do + call_params[:page] = Driver::Page.create + create_with_params[:payload] = Oj.dump('xmlns' => {}, 'entries' => []) + end + end - it "is expected to pass them to Request.call" do - allow(Driver::Request).to receive(:create).and_call_original - described_class.send call_method, call_params - expect(Driver::Request).to have_received(:create).with(a_hash_including(query: a_hash_including(fields: call_params[:fields]))) - end - end + [:put, :post].each do |verb| + describe verb, method: verb, focus: true, required_keywords: ['user', 'service', 'endpoint', 'page'], keyword_types: { user: User, query: Hash, page: Driver::Page } do + include_context "with data call setup", described_class + include_examples "when the user is not logged in", described_class + include_examples "when a required keyword isn't set", described_class + include_examples "when a keyword is not a type of", described_class - include_examples 'call_constraints' - include_examples 'call_request', :get - end + it { expect(call_parent.send described_class, (call_params)).to be_a_kind_of(Driver::Response) } - describe "::post" do - let(:call_method) { :post } + it "is expected to call Assemblers::host with user, service" do + allow(Driver::Assemblers).to receive(:host).and_call_original + call_parent.send described_class, call_params + expect(Driver::Assemblers).to have_received(:host).with service: service, user: user + end - before do - call_params[:page] = Driver::Page.create - with_params[:payload] = Oj.dump(xmlns: {}, entries: []) - end + it "is expected to call Assemblers::path with service, endpoint, and extra_path" do + allow(Driver::Assemblers).to receive(:path).and_call_original + call_parent.send described_class, call_params + expect(Driver::Assemblers).to have_received(:path).with service: service, endpoint: endpoint, extra_path: nil + end - include_examples 'call_constraints' - include_examples 'call_request', :post + it "is expected to call Assemblers::query with user, service, endpoint, query" do + allow(Driver::Assemblers).to receive(:query).and_call_original + call_parent.send described_class, call_params + expect(Driver::Assemblers).to have_received(:query).with account_id: nil, service: service, user: user, endpoint: endpoint, query: {} end - describe "::put" do - let(:call_method) { :put } + it "is expected to call assembler_payload" - before do - call_params[:page] = Driver::Page.create - with_params[:payload] = Oj.dump(xmlns: {}, entries: []) - end + it "is expected to call Request.create with '...'" do + allow(Driver::Request).to receive(:create).and_call_original + call_parent.send described_class, call_params + expect(Driver::Request).to have_received(:create).with create_with_params + end - include_examples 'call_constraints', :put - include_examples 'call_request', :put + it "is expected to call request.call" do + call_parent.send described_class, call_params + expect(request).to have_received(:call).with(no_args) end end end + + describe "::post", method: :post, required_keywords: ['user', 'service', 'endpoint', 'page'], keyword_types: { user: User, query: Hash, page: Driver::Page } do + include_context "with data call setup", metadata[:method] + include_examples "when the user is not logged in" + include_examples "when a required keyword isn't set" + include_examples "when a keyword is not a type of" + + it { expect(Data.post(call_params)).to be_a_kind_of(Driver::Response) } + + it "is expected to call Assemblers::host with user, service" do + allow(Driver::Assemblers).to receive(:host).and_call_original + Data.post call_params + expect(Driver::Assemblers).to have_received(:host).with service: service, user: user + end + + it "is expected to call Assemblers::path with service, endpoint, and extra_path" do + allow(Driver::Assemblers).to receive(:path).and_call_original + Data.post call_params + expect(Driver::Assemblers).to have_received(:path).with service: service, endpoint: endpoint, extra_path: nil + end + + it "is expected to call Assemblers::query with user, service, endpoint, query" do + allow(Driver::Assemblers).to receive(:query).and_call_original + Data.post call_params + expect(Driver::Assemblers).to have_received(:query).with account_id: nil, service: service, user: user, endpoint: endpoint, query: {} + end + + it "is expected to call assembler_payload" + + it "is expected to call Request.create with '...'" do + allow(Driver::Request).to receive(:create).and_call_original + Data.post call_params + expect(Driver::Request).to have_received(:create).with create_with_params + end + + it "is expected to call request.call" do + Data.post call_params + expect(request).to have_received(:call).with(no_args) + end + end + + describe "::put" do + let(:call_method) { :put } + + before do + call_params[:page] = Driver::Page.create + create_with_params[:payload] = Oj.dump(xmlns: {}, entries: []) + end + + include_examples 'call_constraints' + include_examples 'call_request', :put + end end end diff --git a/spec/cts/mpx/services/web_spec.rb b/spec/cts/mpx/services/web_spec.rb index d227f41..4ace447 100644 --- a/spec/cts/mpx/services/web_spec.rb +++ b/spec/cts/mpx/services/web_spec.rb @@ -73,7 +73,6 @@ module Services end end - describe "::post" do let(:call_method) { :post } let(:request_params) do diff --git a/spec/matchers/raise_argument_exception.rb b/spec/matchers/raise_argument_exception.rb index c67d41d..6094882 100644 --- a/spec/matchers/raise_argument_exception.rb +++ b/spec/matchers/raise_argument_exception.rb @@ -1,4 +1,4 @@ -RSpec::Matchers.define :raise_argument_error do |variable, variable_type| +RSpec::Matchers.define :raise_argument_exception do |variable, variable_type| match do begin actual.call diff --git a/spec/matchers/raise_error_without_user_token.rb b/spec/matchers/raise_error_without_user_token.rb index 5e43a70..fbace27 100644 --- a/spec/matchers/raise_error_without_user_token.rb +++ b/spec/matchers/raise_error_without_user_token.rb @@ -5,10 +5,10 @@ begin actual.call rescue RuntimeError => e - user.token = token + user.instance_variable_set :@token, token return e.message.match?(/#{user.username} is not signed in, \(token is set to nil\)\./) end - user.token = token + user.instance_variable_set :@token, token false end diff --git a/spec/matchers/require_keyword_arguments.rb b/spec/matchers/require_keyword_arguments.rb index e90f33f..6267763 100644 --- a/spec/matchers/require_keyword_arguments.rb +++ b/spec/matchers/require_keyword_arguments.rb @@ -1,9 +1,9 @@ -RSpec::Matchers.define :require_keyword_arguments do |method, params| +RSpec::Matchers.define :require_keyword_arguments do |call_class, method, params| match do params.each do |_arg| dup_params = Oj.load Oj.dump params begin - described_class.send(method, dup_params) + call_class.send(method, dup_params) rescue ArgumentError => e return e.message.match?(/is a required keyword./) end diff --git a/spec/spec_helper_shared_contexts.rb b/spec/spec_helper_shared_contexts.rb index 0a873b9..c2c9f20 100644 --- a/spec/spec_helper_shared_contexts.rb +++ b/spec/spec_helper_shared_contexts.rb @@ -1,12 +1,63 @@ require 'rspec' +RSpec.shared_context "with data parameters" do + include_context "with user objects" + include_context "with media parameters" + + let(:post_parameters) { { user: user, service: media_service, endpoint: media_endpoint, query: {} } } + let(:endpoint) { media_endpoint } + let(:payload) { {} } + let(:service) { media_service } +end + RSpec.shared_context "with parameters" do let(:account_id) { "http://access.auth.theplatform.com/data/Account/1" } - let(:ident_service) { 'User Data Service'} + let(:ident_service) { 'User Data Service' } let(:ident_endpoint) { "https://identity.auth.theplatform.com/idm" } let(:root_account_id) { 'urn:theplatform:auth:root' } end +RSpec.shared_context "with authentication parameters" do + let(:parameters) { { user: user, service: 'User Data Service', endpoint: 'Authentication', method: 'signIn', arguments: {}, headers: { "Authorization"=>"Basic YTpi" } } } + let(:parameters) { { user: user, service: 'User Data Service', endpoint: 'Authentication', method: 'signOut', arguments: { "token" => token } } } +end + +RSpec.shared_context "with excon parameters" do + let(:excon_body) { Oj.dump(excon_response_hash) } + let(:excon_headers) { {} } + let(:excon_status) { 200 } + let(:excon_response_hash) { { "xmlns" => {}, "entries" => [] } } + let(:populated_excon_body) { Oj.dump(populated_excon_response_hash) } + let(:populated_excon_response_hash) { { "xmlns" => {}, "entries" => ["id" => media_id] } } + let(:headers) do + { "Access-Control-Allow-Origin" => "*", + "X-Cache" => "MISS from data.media.theplatform.com:80", + "Cache-Control" => "max-age=0", + "Date" => "Tue, 15 May 2018 00:25:24 GMT", + "Content-Type" => "application/json; charset=UTF-8", + "Content-Length" => "2050", + "Server" => "Jetty(8.1.16.2)" } + end + let(:service_exception) do + { + "title" => "ObjectNotFoundException", + "description" => "Could not find object with ID q", + "isException" => true, + "responseCode" => 404, + "correlationId" => "9a23ea0a-0975-4633-9af0-5f7fe3e83f2b", + "serverStackTrace" => "com.theplatform.data.api.exception.ObjectNotFoundException: ..." + } + end +end + +RSpec.shared_context "with field parameters" do + let(:field_name) { 'guid' } + let(:field_value) { 'carpe diem' } + let(:custom_field_value) { 'a_custom_field_value' } + let(:custom_field_name) { 'custom$guid' } + let(:custom_field_xmlns) { { 'custom' => 'uuid' } } +end + RSpec.shared_context "with media parameters" do let(:media_endpoint) { 'Media' } let(:media_id) { 'http://data.media.theplatform.com/media/data/Media/1' } @@ -14,31 +65,21 @@ let(:media_service) { 'Media Data Service' } end -RSpec.shared_context "with media objects" do - include_context "with media parameters" - let(:media_entry) { Cts::Mpx::Entry.create(id: media_id) { |object| object.id = object.id } } -end - -RSpec.shared_context "with entries objects" do - include_context "with media objects" - let(:media_entries) { Cts::Mpx::Entries.create collection: [media_entry] } -end - -RSpec.shared_context "with authentication parameters" do - let(:parameters) { { user: user, service: 'User Data Service', endpoint: 'Authentication', method: 'signIn', arguments: {}, headers: { "Authorization"=>"Basic YTpi" } } } - let(:parameters) { { user: user, service: 'User Data Service', endpoint: 'Authentication', method: 'signOut', arguments: { "token" => token } } } +RSpec.shared_context "with page parameters" do + let(:page_parameters) { { xmlns: {}, entries: {} } } + let(:populated_page_parameters) { media_entries.to_h } end RSpec.shared_context "with web parameters" do include_context "with user objects" - let(:web_arguments) { { 'username' => user_name, 'password' => user_password } } - let(:web_assembler_parameters) { { service: web_service, endpoint: web_endpoint, method: web_method, arguments: web_arguments } } - let(:web_endpoint) { 'Authentication' } - let(:web_method) { 'signIn' } - let(:web_payload) { {} } - let(:web_post_parameters) { web_assembler_parameters.merge(user: user, query: {}) } - let(:web_service) { 'User Data Service' } + let(:arguments) { { 'username' => user_name, 'password' => user_password } } + let(:assembler_parameters) { { service: service, endpoint: endpoint, method: method, arguments: arguments } } + let(:endpoint) { 'Authentication' } + let(:method) { 'signIn' } + let(:payload) { {} } + let(:post_parameters) { assembler_parameters.merge(user: user, query: {}) } + let(:service) { 'User Data Service' } end RSpec.shared_context "with user parameters" do @@ -47,68 +88,37 @@ let(:user_token) { "carpe diem" } end +RSpec.shared_context "with media objects" do + include_context "with media parameters" + let(:media_entry) { Cts::Mpx::Entry.create(id: media_id) { |object| object.id = object.id } } +end + +RSpec.shared_context "with entries objects" do + include_context "with media objects" + let(:media_entries) { Cts::Mpx::Entries.create collection: [media_entry] } +end + RSpec.shared_context "with user objects" do include_context "with user parameters" let(:user) { Cts::Mpx::User.create username: user_name, password: user_password, token: user_token } end -RSpec.shared_context "with field parameters" do - let(:field_name) { 'guid' } - let(:field_value) { 'carpe diem' } - let(:custom_field_value) { 'a_custom_field_value' } - let(:custom_field_name) { 'custom$guid' } - let(:custom_field_xmlns) { { 'custom' => 'uuid' } } -end - RSpec.shared_context "with field objects" do include_context "with field parameters" let(:field) { Cts::Mpx::Field.create name: field_name, value: field_value } - let(:custom_field) { Cts::Mpx::Field.create name: custom_field_name, value: custom_field_value , xmlns: custom_field_xmlns } + let(:custom_field) { Cts::Mpx::Field.create name: custom_field_name, value: custom_field_value, xmlns: custom_field_xmlns } end -RSpec.shared_context "with fields" do +RSpec.shared_context "with fields objects" do include_context "with field objects" end -RSpec.shared_context "with excon parameters" do - let(:excon_body) { Oj.dump(excon_response_hash) } - let(:excon_headers) { {} } - let(:excon_status) { 200 } - let(:excon_response_hash) { { "xmlns" => {}, "entries" => []}} - let(:populated_excon_body) { Oj.dump(populated_excon_response_hash) } - let(:populated_excon_response_hash) { { "xmlns" => {}, "entries" => [ "id" => media_id]}} - let(:headers) do - { "Access-Control-Allow-Origin" => "*", - "X-Cache" => "MISS from data.media.theplatform.com:80", - "Cache-Control" => "max-age=0", - "Date" => "Tue, 15 May 2018 00:25:24 GMT", - "Content-Type" => "application/json; charset=UTF-8", - "Content-Length" => "2050", - "Server" => "Jetty(8.1.16.2)" } - end - let(:service_exception) do - { - "title" => "ObjectNotFoundException", - "description" => "Could not find object with ID q", - "isException" => true, - "responseCode" => 404, - "correlationId" => "9a23ea0a-0975-4633-9af0-5f7fe3e83f2b", - "serverStackTrace" => "com.theplatform.data.api.exception.ObjectNotFoundException: ..." - } - end -end - RSpec.shared_context "with excon objects" do include_context "with excon parameters" let(:excon_response) { Excon::Response.new body: excon_body, headers: excon_headers, status: excon_status } let(:populated_excon_response) { Excon::Response.new body: populated_excon_body, headers: excon_headers, status: excon_status } end -RSpec.shared_context "with page parameters" do - let(:page_parameters) { { xmlns: {}, entries: {} } } - let(:populated_page_parameters) { media_entries.to_h } -end - RSpec.shared_context "with page objects" do include_context "with page parameters" include_context "with excon objects" diff --git a/spec/spec_helper_shared_examples.rb b/spec/spec_helper_shared_examples.rb index 9427b9d..1e80012 100644 --- a/spec/spec_helper_shared_examples.rb +++ b/spec/spec_helper_shared_examples.rb @@ -1,80 +1,100 @@ -module RSpec - include Cts::Mpx +include Cts::Mpx - shared_examples 'registry_check' do |method| - context "when the url is not availble locally" do - before do - allow(Registry).to receive(:fetch_and_store_domain).and_throw :yo - allow(Services[web_post_parameters[:service]]).to receive(:url?).and_return nil - end +RSpec.shared_examples 'registry_check' do |method| + include_context "with web parameters" - # rubocop: disable RSpec/MultipleExpectations - # reason: the first expect stops the execution after fetch_and_store_domain. The second one assures it's called correctly. - it "is expected to call Registry.fetch_and_store_domain with the user and account" do - expect { described_class.send method, web_post_parameters }.to raise_error(UncaughtThrowError) - expect(Registry).to have_received(:fetch_and_store_domain).with(user, nil) - end - # rubocop: enable RSpec/MultipleExpectations + context "when the url is not availble locally" do + before do + allow(Registry).to receive(:fetch_and_store_domain).and_throw :yo + allow(Services[post_parameters[:service]]).to receive(:url?).and_return nil + end + # reason: the first expect stops the execution after fetch_and_store_domain. The second one assures it's called correctly. + it "is expected to call Registry.fetch_and_store_domain with the user and account" do + expect { described_class.send method, post_parameters }.to raise_error(UncaughtThrowError) + expect(Registry).to have_received(:fetch_and_store_domain).with(user, nil) end end +end - shared_examples "call_constraints" do - it { expect { described_class.send call_method, web_post_parameters }.to raise_error_without_user_token(web_post_parameters[:user]) } - it { is_expected.to require_keyword_arguments(call_method, web_post_parameters) } +RSpec.shared_examples "call_constraints" do + it { expect { described_class.send method, post_parameters }.to raise_error_without_user_token(post_parameters[:user]) } + it { is_expected.to require_keyword_arguments(method, post_parameters) } - context "when headers is provided" do - before { web_post_parameters[:headers] = { test: 1 } } + context "when headers is provided" do + before { post_parameters[:headers] = { test: 1 } } - it "is expected to pass them to Request.call" do - allow(Driver::Request).to receive(:create).and_call_original - described_class.send call_method, web_post_parameters - expect(Driver::Request).to have_received(:create).with(a_hash_including(headers: { test: 1 })) - end + it "is expected to pass them to Request.call" do + allow(Driver::Request).to receive(:create).and_call_original + described_class.send method, post_parameters + expect(Driver::Request).to have_received(:create).with(a_hash_including(headers: { test: 1 })) end + end - context "when the url is not availble locally" do - before do - allow(Registry).to receive(:fetch_and_store_domain).and_throw :yo - allow(Services[web_post_parameters[:service]]).to receive(:url?).and_return nil - end - - # rubocop: disable RSpec/MultipleExpectations - # reason: the first expect stops the execution after fetch_and_store_domain. The second one assures it's called correctly. - it "is expected to call Registry.fetch_and_store_domain with the user and account" do - expect { described_class.send(call_method, web_post_parameters) }.to raise_error(UncaughtThrowError) - expect(Registry).to have_received(:fetch_and_store_domain).with(user, nil) - end - # rubocop: enable RSpec/MultipleExpectations + context "when the url is not availble locally" do + before do + allow(Registry).to receive(:fetch_and_store_domain).and_throw :yo + allow(Services[post_parameters[:service]]).to receive(:url?).and_return nil end + # reason: the first expect stops the execution after fetch_and_store_domain. The second one assures it's called correctly. + it "is expected to call Registry.fetch_and_store_domain with the user and account" do + expect { described_class.send(method, post_parameters) }.to raise_error(UncaughtThrowError) + expect(Registry).to have_received(:fetch_and_store_domain).with(user, nil) + end + end + + include_examples 'call_assembler', :host, %i[user service] + include_examples 'call_assembler', :path, %i[service endpoint] + include_examples 'call_assembler', :query, %i[user service endpoint query] +end - include_examples 'call_assembler', :host, %i[user service] - include_examples 'call_assembler', :path, %i[service endpoint] - include_examples 'call_assembler', :query, %i[user service endpoint query] +RSpec.shared_examples "call_assembler" do |method, param_list| + it "is expected to call Driver::Assemblers.#{method} with #{param_list.join(', ')}" do + allow(Driver::Assemblers).to receive(method).and_call_original + described_class.send method, post_parameters + param_hash = {} + param_list.each { |param| param_hash[param] = post_parameters[param] } + expect(Driver::Assemblers).to have_received(method).with(a_hash_including(param_hash)) end +end - shared_examples "call_assembler" do |method, param_list| - include_context "with web parameters" +RSpec.shared_examples "call_request" do |method| + it "is expected to call Request.create with #{method.upcase} with '...'" do + allow(Driver::Request).to receive(:create).and_call_original + described_class.send method, post_parameters + expect(Driver::Request).to have_received(:create) + end - it "is expected to call Driver::Assemblers.#{method} with #{param_list.join(', ')}" do - allow(Driver::Assemblers).to receive(method).and_call_original - described_class.send call_method, web_post_parameters - param_hash = {} - param_list.each { |param| param_hash[param] = web_post_parameters[param]} + it "is expected to return a response.data" do + described_class.send method, post_parameters + expect(request).to have_received(:call) + end +end - expect(Driver::Assemblers).to have_received(method).with(a_hash_including(param_hash)) - end +RSpec.shared_examples "when the user is not logged in" do |method| + context "when the user is not logged in" do + before { user.instance_variable_set :@token, nil } + + it { expect { Services::Data.send method.to_sym, call_params }.to raise_error_without_user_token } end +end - shared_examples "call_request" do |method| - it "is expected to call Request.create with #{method.upcase} with '...'" do - allow(Driver::Request).to receive(:create).and_call_original - described_class.send method, web_post_parameters - expect(Driver::Request).to have_received(:create) +RSpec.shared_examples "when a required keyword isn't set" do + context "when a required keyword isn't set" do + metadata[:required_keywords].each do |keyword| + it "#{keyword} is expected to raise a specific message" do + call_params.delete keyword + expect(Services::Data.send(described_class, call_params)).to require_keyword_arguments call_parent, described_class, call_params + end end + end +end + +RSpec.shared_examples "when a keyword is not a type of" do |method| + metadata[:keyword_types].each do |k, v| + context "when #{k} is not a type of #{v}" do + before { call_params[k] = '' } - it "is expected to return a response.data" do - described_class.send call_method, web_post_parameters - expect(request).to have_received(:call) + it { expect { Services::Data.send method, call_params }.to raise_argument_exception call_params[k], v } end end end