diff --git a/.gitignore b/.gitignore index 1ca9e23..ad37604 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .bundle .config .yardoc +.idea Gemfile.lock InstalledFiles _yardoc @@ -16,3 +17,4 @@ test/tmp test/version_tmp tmp vendor + diff --git a/.travis.yml b/.travis.yml index bb404e1..ccc2e82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,12 @@ language: ruby rvm: - - 1.9.3 + - 2.0.0 + - 2.1.0 notifications: email: recipients: - joeheth@gmail.com on_success: never on_failure: always +before_install: + - gem install bundler diff --git a/CHANGELOG.md b/CHANGELOG.md index 437b97d..99319fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.7.0 (March 4, 2016) +* Add EntityCollection to xml attributes #24 +* Fix illegal XML characters #25 +* Dynamics optimize metadata queries #26 +* Add Money attribute #31 +* Use `request.bytesize` instead of `request.length` #32 +* Rexml sanitization on username and password for ocp request builder #33 +* Adding new regions to determine region set #34 +* Improve region determination #37 + ## 0.6.0 (December 30, 2014) * Adds support for Relationship Metadata. diff --git a/dynamics_crm.gemspec b/dynamics_crm.gemspec index 46cef5d..cc52720 100644 --- a/dynamics_crm.gemspec +++ b/dynamics_crm.gemspec @@ -18,12 +18,13 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] - spec.add_runtime_dependency 'curb', '~> 0.8', '>= 0.8.5' - spec.add_runtime_dependency 'mimemagic', '~> 0.2', '>= 0.2.1' + spec.add_runtime_dependency 'curb', '>= 0.8', '< 1.0.0' + spec.add_runtime_dependency 'mimemagic', '>= 0.2', '< 4.0.0' spec.add_runtime_dependency 'builder', '>= 3.0.0', '< 4.0.0' - spec.add_development_dependency "bundler", "~> 1.3" + spec.add_development_dependency "bundler", ">= 1.3", "< 2.0" spec.add_development_dependency 'rake', '~> 10.1' - spec.add_development_dependency 'rspec', '~> 2.14' - spec.add_development_dependency 'simplecov', '~> 0.7' + spec.add_development_dependency 'rspec', '>= 2.14', "< 4.0" + spec.add_development_dependency 'simplecov', '>= 0.7', "< 1.0" + spec.add_development_dependency 'pry', '~> 0.10.3' end diff --git a/lib/dynamics_crm.rb b/lib/dynamics_crm.rb index 6a88cb2..bbe0bf5 100644 --- a/lib/dynamics_crm.rb +++ b/lib/dynamics_crm.rb @@ -17,6 +17,7 @@ require "dynamics_crm/response/retrieve_multiple_result" require "dynamics_crm/response/create_result" require "dynamics_crm/response/execute_result" +require "dynamics_crm/response/execute_multiple_result" # Metadata require "dynamics_crm/metadata/xml_document" require "dynamics_crm/metadata/one_to_many_relationship" diff --git a/lib/dynamics_crm/client.rb b/lib/dynamics_crm/client.rb index d2d9937..9d061ff 100644 --- a/lib/dynamics_crm/client.rb +++ b/lib/dynamics_crm/client.rb @@ -18,11 +18,21 @@ class Client extend Forwardable include XML::MessageBuilder - attr_accessor :logger, :caller_id, :timeout + attr_accessor :logger, :caller_id, :timeout, :security_token0, :security_token1, :key_identifier attr_reader :hostname, :region, :organization_endpoint, :login_url OCP_LOGIN_URL = 'https://login.microsoftonline.com/RST2.srf' + REGION = { + "crm9.dynamics.com" => "urn:crmgcc:dynamics.com", + "crm7.dynamics.com" => "urn:crmjpn:dynamics.com", + "crm6.dynamics.com" => "urn:crmoce:dynamics.com", + "crm5.dynamics.com" => "urn:crmapac:dynamics.com", + "crm4.dynamics.com" => "urn:crmemea:dynamics.com", + "crm2.dynamics.com" => "urn:crmsam:dynamics.com", + "crm.dynamics.com" => "urn:crmna:dynamics.com", + } + # Initializes Client instance. # Requires: organization_name # Optional: hostname @@ -32,6 +42,7 @@ def initialize(config={organization_name: nil, hostname: nil, caller_id: nil, lo @organization_name = config[:organization_name] @hostname = config[:hostname] || "#{@organization_name}.api.crm.dynamics.com" @organization_endpoint = "https://#{@hostname}/XRMServices/2011/Organization.svc" + REGION.default = @organization_endpoint @caller_id = config[:caller_id] @timeout = config[:timeout] || 120 @@ -83,7 +94,7 @@ def authenticate(username, password) @timestamp = '' + @header_current_time + '' + @header_expires_time + '' @digest_value = Digest::SHA1.base64digest @timestamp @signature = '' + @digest_value + '' - @signature_value = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), Base64.decode64(@server_secret), @signature)).chomp + @signature_value = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), Base64.decode64(@server_secret), @signature)).chomp else cipher_values = document.get_elements("//CipherValue") @@ -112,6 +123,20 @@ def create(entity_name, attributes) return Response::CreateResult.new(xml_response) end + def create_multiple(entity_name, attributesArray) + + entities = [] + attributesArray.each do |attributes| + entity = XML::Entity.new(entity_name) + entity.attributes = XML::Attributes.new(attributes) + + entities << entity + end + xml_response = post(organization_endpoint, create_multiple_request(entities)) + + return Response::ExecuteMultipleResult.new(xml_response) + end + # http://crmtroubleshoot.blogspot.com.au/2013/07/dynamics-crm-2011-php-and-soap-calls.html def retrieve(entity_name, guid, columns=[]) @@ -160,6 +185,22 @@ def update(entity_name, guid, attributes) return Response::UpdateResponse.new(xml_response) end + def update_multiple(entity_name, guids, attributesArray) + raise "Number of 'guids' to be updated should be equal to attributes array size" if guids.count != attributesArray.count + + entities = [] + attributesArray.each_with_index do |attributes, index| + entity = XML::Entity.new(entity_name) + entity.id = guids[index] + entity.attributes = XML::Attributes.new(attributes) + + entities << entity + end + xml_response = post(organization_endpoint, update_multiple_request(entities)) + + return Response::ExecuteMultipleResult.new(xml_response) + end + def delete(entity_name, guid) request = delete_request(entity_name, guid) @@ -167,6 +208,46 @@ def delete(entity_name, guid) return Response::DeleteResponse.new(xml_response) end + def delete_multiple(entity_name, guids) + entities = [] + guids.each do |guid| + entity = XML::EntityReference.new(entity_name, guid) + entity.logical_name = entity_name + + entities << entity + end + request = delete_multiple_request(entities) + xml_response = post(organization_endpoint, request) + + return Response::ExecuteMultipleResult.new(xml_response) + end + + def bulk_delete(entity_name, emailToRecipientGuid, criteria=[], wait=false) + + query = XML::Query.new(entity_name) + query.criteria = XML::Criteria.new(criteria) + + request = bulk_delete_request(query, emailToRecipientGuid) + xml_response = post(organization_endpoint, request) + + response = Response::ExecuteResult.new(xml_response) + jobId = response['JobId'] + if wait && !jobId.nil? + while true + jobStatus = check_job_status(jobId) + if jobStatus != "Waiting For Resources" && jobStatus != "Waiting" && jobStatus != "In Progress" + break + end + sleep(2) # wait x seconds and check again + end + + if jobStatus != 'Succeeded' + response['errorMessage'] = "The job has not completed with success. The response returned a status of #{jobStatus}. Please check your query/parameters and try again." + end + end + response + end + def execute(action, parameters={}, response_class=nil) request = execute_request(action, parameters) xml_response = post(organization_endpoint, request) @@ -304,24 +385,8 @@ def login_url end def determine_region - case hostname - when /crm9\.dynamics\.com/ - "urn:crmgcc:dynamics.com" - when /crm7\.dynamics\.com/ - "urn:crmjpn:dynamics.com" - when /crm6\.dynamics\.com/ - "urn:crmoce:dynamics.com" - when /crm5\.dynamics\.com/ - "urn:crmapac:dynamics.com" - when /crm4\.dynamics\.com/ - "urn:crmemea:dynamics.com" - when /crm2\.dynamics\.com/ - "urn:crmsam:dynamics.com" - when /\.dynamics\.com/ - "urn:crmna:dynamics.com" - else - organization_endpoint - end + hostname.match(/(crm\d?\.dynamics.com)/) + REGION[$1] end def post(url, request) @@ -369,6 +434,13 @@ def formatter @formatter end + def check_job_status(job_id) + jobStatusResult = self.retrieve_multiple('asyncoperation', [["asyncoperationid", "Equal", job_id]], ["statuscode"]) + jobStatus = jobStatusResult.entities[0].formatted_values['statuscode'] if jobStatusResult.entities.count > 0 + + jobStatus + end + end end diff --git a/lib/dynamics_crm/response/execute_multiple_result.rb b/lib/dynamics_crm/response/execute_multiple_result.rb new file mode 100644 index 0000000..743b72a --- /dev/null +++ b/lib/dynamics_crm/response/execute_multiple_result.rb @@ -0,0 +1,35 @@ +module DynamicsCRM + module Response + class ExecuteMultipleResult < Result + + protected + + # Returns base element of the response document to parse. + def response_element + class_name = 'ExecuteResult' if self.is_a?(ExecuteMultipleResult) + end + + # Invoked by Result constructor + def parse_result_response(result) + h = {} + result.elements["b:Results"].each_element do |key_value_pair| + if key_value_pair.elements["c:key"].text == "Responses" + value_element = key_value_pair.elements["c:value"] + h[:entities] = [] + value_element.each_element do |response_item| + itemResults = response_item.elements["d:Response"].elements["b:Results"] + if !itemResults.nil? + h[:entities] << XML::MessageParser.parse_key_value_pairs(itemResults) + end + end + break + end + end + + h + end + + end + + end +end diff --git a/lib/dynamics_crm/response/result.rb b/lib/dynamics_crm/response/result.rb index cbf4592..cdd001c 100644 --- a/lib/dynamics_crm/response/result.rb +++ b/lib/dynamics_crm/response/result.rb @@ -11,7 +11,9 @@ def initialize(xml) @document = REXML::Document.new(xml) fault_xml = @document.get_elements("//[local-name() = 'Fault']") - raise XML::Fault.new(fault_xml) if fault_xml.any? + code = fault_xml.first.get_elements("//[local-name() = 'Code']") if fault_xml.any? + code = fault_xml.first.get_elements("//[local-name() = 'ErrorCode']") if fault_xml.any? && code.blank? + raise XML::Fault.new(fault_xml) if fault_xml.any? && !code.empty? @result_response = @document.get_elements("//#{response_element}").first diff --git a/lib/dynamics_crm/version.rb b/lib/dynamics_crm/version.rb index a9021c9..07f8657 100644 --- a/lib/dynamics_crm/version.rb +++ b/lib/dynamics_crm/version.rb @@ -1,3 +1,3 @@ module DynamicsCRM - VERSION = "0.6.0" + VERSION = "0.7.1" end diff --git a/lib/dynamics_crm/xml/attributes.rb b/lib/dynamics_crm/xml/attributes.rb index 109fcfa..5367412 100644 --- a/lib/dynamics_crm/xml/attributes.rb +++ b/lib/dynamics_crm/xml/attributes.rb @@ -11,6 +11,8 @@ def initialize(attrs) def get_type(key, value) type = "string" case value + when ::Array + type = "ArrayOfEntity" when ::Fixnum type = "int" when ::BigDecimal, ::Float @@ -77,7 +79,7 @@ def to_xml end # escape strings to avoid xml parsing errors - value = CGI.escapeHTML(value) if type == "string" + value = CGI.escapeHTML(value) if value.is_a?(String) xml << build_xml(key, value, type) end @@ -111,6 +113,13 @@ def build_xml(key, value, type) def render_value_xml(type, value) xml = "" case type + when "ArrayOfEntity" + raise "We can only serialize Entities inside of ArrayOfEntity" unless value.all?{|a| a.is_a?(DynamicsCRM::XML::Entity)} + xml << %Q{ + + #{value.map(&->(_) { _.to_xml({in_array: true}) }).join} + + } when "EntityReference" xml << %Q{ @@ -131,7 +140,11 @@ def render_value_xml(type, value) s_namespace = "http://schemas.microsoft.com/xrm/2011/Metadata" end - if type == "guid" + if value.nil? + xml << %Q{ + + } + elsif type == "guid" xml << %Q{ #{value} } @@ -154,14 +167,14 @@ def render_value_xml(type, value) end def render_object_xml(type, value) - case type - when "EntityQueryExpression" - xml = %Q{} << value.to_xml({namespace: 'd'}) << "" - else - xml = %Q{} << value.to_xml({exclude_root: true, namespace: 'a'}) << "" - end + case type + when "EntityQueryExpression" + xml = %Q{} << value.to_xml({namespace: 'd'}) << "" + else + xml = %Q{} << value.to_xml({exclude_root: true, namespace: 'a'}) << "" + end - return xml + xml end def class_name diff --git a/lib/dynamics_crm/xml/entity.rb b/lib/dynamics_crm/xml/entity.rb index a4170f2..ec7557f 100644 --- a/lib/dynamics_crm/xml/entity.rb +++ b/lib/dynamics_crm/xml/entity.rb @@ -24,11 +24,19 @@ def to_xml(options={}) return inner_xml if options[:exclude_root] - %Q{ - - #{inner_xml} - - } + if options[:in_array] + %Q{ + + #{inner_xml} + + } + else + %Q{ + + #{inner_xml} + + } + end end def to_hash diff --git a/lib/dynamics_crm/xml/fault.rb b/lib/dynamics_crm/xml/fault.rb index 7c6c088..2e8d220 100644 --- a/lib/dynamics_crm/xml/fault.rb +++ b/lib/dynamics_crm/xml/fault.rb @@ -13,8 +13,10 @@ def initialize(fault_xml) end # REXL::Element @code = fault_xml.get_text("//[local-name() = 'Code']/[local-name() = 'Value']") + @code = fault_xml.get_text("//[local-name() = 'ErrorCode']") if @code.nil? || @code.empty? @subcode = fault_xml.get_text("//[local-name() = 'Code']/[local-name() = 'Subcode']/[local-name() = 'Value']") @reason = fault_xml.get_text("//[local-name() = 'Reason']/[local-name() = 'Text']") + @reason = fault_xml.get_text("//[local-name() = 'Message']") if @reason.nil? || @reason.empty? @detail = {} detail_fragment = fault_xml.get_elements("//[local-name() = 'Detail']").first diff --git a/lib/dynamics_crm/xml/message_builder.rb b/lib/dynamics_crm/xml/message_builder.rb index 51ce59d..c9382be 100644 --- a/lib/dynamics_crm/xml/message_builder.rb +++ b/lib/dynamics_crm/xml/message_builder.rb @@ -227,6 +227,10 @@ def create_request(entity) end end + def create_multiple_request(entities) + execute_multiple_request('Create', entities) + end + def update_request(entity) build_envelope('Update') do %Q{ @@ -235,6 +239,10 @@ def update_request(entity) end end + def update_multiple_request(entities) + execute_multiple_request('Update', entities) + end + # Tag name case MATTERS! def retrieve_request(entity_name, guid, columns) build_envelope('Retrieve') do @@ -266,6 +274,57 @@ def delete_request(entity_name, guid) end end + def delete_multiple_request(entities) + execute_multiple_request('Delete', entities) + end + + def bulk_delete_request(object, emailToRecipientGuid) + build_envelope('Execute') do + %Q{ + + + + QuerySet + + + #{object.to_xml({exclude_root: true, namespace: 'a'})} + + + + + JobName + pitcherbulkdeletejob + + + SendEmailNotification + true + + + ToRecipients + + #{emailToRecipientGuid} + + + + CCRecipients + + + + RecurrencePattern + + + + StartDateTime + 0001-01-01T00:00:00 + + + + BulkDelete + + } + end + end + def associate_request(entity_name, id, relationship, relationship_entities=[]) modify_association("Associate", entity_name, id, relationship, relationship_entities) end @@ -314,6 +373,51 @@ def execute_request(action, parameters={}) end end + def execute_multiple_request(action, entities) + requests = '' + entities.each do |entity| + requests += + %Q{ + + + + Target + + #{entity.to_xml({exclude_root: true, namespace: 'a'})} + + + + + #{action} + + } + end + + build_envelope('Execute') do + %Q{ + + + + Requests + + #{requests} + + + + Settings + + false + true + + + + + ExecuteMultiple + + } + end + end + end # MessageBuilder end diff --git a/spec/fixtures/entity_array_response.xml b/spec/fixtures/entity_array_response.xml new file mode 100644 index 0000000..567d648 --- /dev/null +++ b/spec/fixtures/entity_array_response.xml @@ -0,0 +1,37 @@ + + + + + + + from + + + + + partyid + + f36aa96c-e7a5-4c70-8254-47c8ba947561 + systemuser + + + + + + + 00000000-0000-0000-0000-000000000000 + activityparty + + + + + + + + 00000000-0000-0000-0000-000000000000 + phonecall + + + + + \ No newline at end of file diff --git a/spec/lib/client_spec.rb b/spec/lib/client_spec.rb index 40a8044..ae64b1d 100644 --- a/spec/lib/client_spec.rb +++ b/spec/lib/client_spec.rb @@ -12,13 +12,13 @@ context "Online" do it "authenticates with username and password" do - subject.stub(:post).and_return(fixture("request_security_token_response")) + allow(subject).to receive(:post).and_return(fixture("request_security_token_response")) subject.authenticate('testing', 'password') - subject.instance_variable_get("@security_token0").should start_with("tMFpDJbJHcZnRVuby5cYmRbCJo2OgOFLEOrUHj+wz") - subject.instance_variable_get("@security_token1").should start_with("CX7BFgRnW75tE6GiuRICjeVDV+6q4KDMKLyKmKe9A8U") - subject.instance_variable_get("@key_identifier").should == "D3xjUG3HGaQuKyuGdTWuf6547Lo=" + expect(subject.instance_variable_get("@security_token0")).to start_with("tMFpDJbJHcZnRVuby5cYmRbCJo2OgOFLEOrUHj+wz") + expect(subject.instance_variable_get("@security_token1")).to start_with("CX7BFgRnW75tE6GiuRICjeVDV+6q4KDMKLyKmKe9A8U") + expect(subject.instance_variable_get("@key_identifier")).to eq("D3xjUG3HGaQuKyuGdTWuf6547Lo=") end # This is only method in this suite that actually sends a POST message to Dynamics. @@ -28,9 +28,9 @@ subject.authenticate('testuser@orgnam.onmicrosoft.com', 'qwerty') fail("Expected Fault to be raised") rescue DynamicsCRM::XML::Fault => f - f.code.should == "S:Sender" - f.subcode.should == "wst:FailedAuthentication" - f.reason.should == "Authentication Failure" + expect(f.code).to eq("S:Sender") + expect(f.subcode).to eq("wst:FailedAuthentication") + expect(f.reason).to eq("Authentication Failure") end end end @@ -40,17 +40,17 @@ it "authenticates with username and password" do - subject.stub(:post).and_return(fixture("request_security_token_response_onpremise")) + allow(subject).to receive(:post).and_return(fixture("request_security_token_response_onpremise")) subject.authenticate('testing', 'password') - subject.instance_variable_get("@security_token0").should start_with("ydfdQsDU9ow4XhoBi+0+n+/9Z7Dvfi") - subject.instance_variable_get("@security_token1").should start_with("GcCk8ivhLAAPEbQI8qScynWLReTWE0AC5") - subject.instance_variable_get("@key_identifier").should == "_ed121435-64ea-45b0-9b15-e5769afdb746" + expect(subject.instance_variable_get("@security_token0")).to start_with("ydfdQsDU9ow4XhoBi+0+n+/9Z7Dvfi") + expect(subject.instance_variable_get("@security_token1")).to start_with("GcCk8ivhLAAPEbQI8qScynWLReTWE0AC5") + expect(subject.instance_variable_get("@key_identifier")).to eq("_ed121435-64ea-45b0-9b15-e5769afdb746") - subject.instance_variable_get("@cert_issuer_name").strip.should start_with("SERIALNUMBER=12369287, CN=Go Daddy Secure") - subject.instance_variable_get("@cert_serial_number").should == "112094107365XXXXX" - subject.instance_variable_get("@server_secret").should == "XZwQpJKfAy00NNWU1RwdtDpVyW/nfabuCq4H38GgKrM=" + expect(subject.instance_variable_get("@cert_issuer_name").strip).to start_with("SERIALNUMBER=12369287, CN=Go Daddy Secure") + expect(subject.instance_variable_get("@cert_serial_number")).to eq("112094107365XXXXX") + expect(subject.instance_variable_get("@server_secret")).to eq("XZwQpJKfAy00NNWU1RwdtDpVyW/nfabuCq4H38GgKrM=") end end @@ -58,16 +58,16 @@ describe "#retrieve" do before(:each) do - subject.stub(:post).and_return(fixture("retrieve_account_all_columns")) + allow(subject).to receive(:post).and_return(fixture("retrieve_account_all_columns")) end let(:result) { subject.retrieve("account", "93f0325c-a592-e311-b7f3-6c3be5a8a0c8") } it "retrieves object by id and acts as hash" do - result.should be_a(DynamicsCRM::Response::RetrieveResult) - result.type.should == "account" - result.id.should == "93f0325c-a592-e311-b7f3-6c3be5a8a0c8" - result.name.should == "Adventure Works (sample)" + expect(result).to be_a(DynamicsCRM::Response::RetrieveResult) + expect(result.type).to eq("account") + expect(result.id).to eq("93f0325c-a592-e311-b7f3-6c3be5a8a0c8") + expect(result.name).to eq("Adventure Works (sample)") end it "exposes entity object" do @@ -87,11 +87,11 @@ describe "#retrieve_multiple" do it "retrieves multiple entities by criteria" do - subject.stub(:post).and_return(fixture("retrieve_multiple_result")) + allow(subject).to receive(:post).and_return(fixture("retrieve_multiple_result")) result = subject.retrieve_multiple("account", ["name", "Equal", "Test Account"], columns=[]) - result.should be_a(DynamicsCRM::Response::RetrieveMultipleResult) + expect(result).to be_a(DynamicsCRM::Response::RetrieveMultipleResult) expect(result['EntityName']).to eq('account') expect(result['MinActiveRowVersion']).to eq(-1) @@ -100,31 +100,31 @@ expect(result['TotalRecordCount']).to eq(-1) expect(result['TotalRecordCountLimitExceeded']).to eq(false) - result.entities.size.should == 3 + expect(result.entities.size).to eq(3) entities = result.entities entities[0].logical_name == "account" - entities[0].id.should == "7bf2e032-ad92-e311-9752-6c3be5a87df0" - entities[0].attributes["accountid"].should == "7bf2e032-ad92-e311-9752-6c3be5a87df0" + expect(entities[0].id).to eq("7bf2e032-ad92-e311-9752-6c3be5a87df0") + expect(entities[0].attributes["accountid"]).to eq("7bf2e032-ad92-e311-9752-6c3be5a87df0") - entities[1].attributes["accountid"].should == "dbe9d7c9-2c98-e311-9752-6c3be5a87df0" - entities[2].attributes["accountid"].should == "8ff0325c-a592-e311-b7f3-6c3be5a8a0c8" + expect(entities[1].attributes["accountid"]).to eq("dbe9d7c9-2c98-e311-9752-6c3be5a87df0") + expect(entities[2].attributes["accountid"]).to eq("8ff0325c-a592-e311-b7f3-6c3be5a8a0c8") end end describe "#retrieve_attachments" do it "retrieves document records from annotation object" do - subject.stub(:post).and_return(fixture("retrieve_multiple_result")) + allow(subject).to receive(:post).and_return(fixture("retrieve_multiple_result")) result = subject.retrieve_attachments("93f0325c-a592-e311-b7f3-6c3be5a8a0c8") - result.should be_a(DynamicsCRM::Response::RetrieveMultipleResult) + expect(result).to be_a(DynamicsCRM::Response::RetrieveMultipleResult) end end describe "#fetch" do it "uses FetchXML to retrieve multiple" do - subject.stub(:post).and_return(fixture("fetch_xml_response")) + allow(subject).to receive(:post).and_return(fixture("fetch_xml_response")) xml = %Q{ @@ -143,7 +143,7 @@ } entity_collection = subject.fetch(xml) - entity_collection.should be_a(DynamicsCRM::XML::EntityCollection) + expect(entity_collection).to be_a(DynamicsCRM::XML::EntityCollection) expect(entity_collection.entity_name).to eq('new_tinderboxdocument') expect(entity_collection.min_active_row_version).to eq(-1) @@ -155,10 +155,10 @@ expect(entity_collection.entities.size).to eq(3) entity = entity_collection.entities.first - entity.id.should == "9c27cf91-ada3-e311-b64f-6c3be5a87df0" - entity.logical_name.should == "new_tinderboxdocument" - entity.attributes["new_tinderboxdocumentid"].should == entity.id - entity.attributes["new_name"].should == "6 orders of Product SKU JJ202" + expect(entity.id).to eq("9c27cf91-ada3-e311-b64f-6c3be5a87df0") + expect(entity.logical_name).to eq("new_tinderboxdocument") + expect(entity.attributes["new_tinderboxdocumentid"]).to eq(entity.id) + expect(entity.attributes["new_name"]).to eq("6 orders of Product SKU JJ202") end end @@ -166,13 +166,41 @@ describe "#create" do it "creates new entity with parameters" do - subject.stub(:post).and_return(fixture("create_response")) + allow(subject).to receive(:post).and_return(fixture("create_response")) result = subject.create("account", {name: "Adventure Works"}) - result.should be_a(DynamicsCRM::Response::CreateResult) - result.id.should == "c4944f99-b5a0-e311-b64f-6c3be5a87df0" - result.Id.should == "c4944f99-b5a0-e311-b64f-6c3be5a87df0" + expect(result).to be_a(DynamicsCRM::Response::CreateResult) + expect(result.id).to eq("c4944f99-b5a0-e311-b64f-6c3be5a87df0") + expect(result.Id).to eq("c4944f99-b5a0-e311-b64f-6c3be5a87df0") + end + + it "creates new entity with custom fields and relationship" do + + params = { + :tndrbox_id => 929177, + :tndrbox_name => "TEST", + :tndrbox_description => "", + :tndrbox_status => "Draft", + :tndrbox_views => 0, + :tndrbox_category => nil, + "tndrbox_opportunity_id" => { + :id => "71a4a3af-d7ab-e411-80c7-00155dd44307", + :logical_name => "opportunity" + }, + :tndrbox_value => { + :value => 0.0, + :type => "Money" + } + } + + allow(subject).to receive(:post).and_return(fixture("create_response")) + + result = subject.create('opportunity', params) + + expect(result).to be_a(DynamicsCRM::Response::CreateResult) + expect(result.id).to eq("c4944f99-b5a0-e311-b64f-6c3be5a87df0") + expect(result.Id).to eq("c4944f99-b5a0-e311-b64f-6c3be5a87df0") end end @@ -181,7 +209,7 @@ file = Tempfile.new(["sample-file", "pdf"]) - subject.should_receive(:create).with("annotation", { + expect(subject).to receive(:create).with("annotation", { objectid: {id: "f4944f99-b5a0-e311-b64f-6c3be5a87df0", logical_name: "opportunity"}, subject: "Sample Subject", notetext: "Post message", @@ -206,22 +234,22 @@ describe "#update" do it "updates entity by id" do - subject.stub(:post).and_return(fixture("update_response")) + allow(subject).to receive(:post).and_return(fixture("update_response")) result = subject.update("account", "c4944f99-b5a0-e311-b64f-6c3be5a87df0", {name: "Adventure Park"}) - result.should be_a(DynamicsCRM::Response::UpdateResponse) + expect(result).to be_a(DynamicsCRM::Response::UpdateResponse) end end describe "#delete" do it "deletes entity by id" do - subject.stub(:post).and_return(fixture("update_response")) + allow(subject).to receive(:post).and_return(fixture("update_response")) result = subject.delete("account", "c4944f99-b5a0-e311-b64f-6c3be5a87df0") - result.should be_a(DynamicsCRM::Response::DeleteResponse) + expect(result).to be_a(DynamicsCRM::Response::DeleteResponse) end end @@ -230,53 +258,53 @@ describe "#retrieve_all_entities" do it "retrieve entity list" do - subject.stub(:post).and_return(fixture("retrieve_all_entities")) + allow(subject).to receive(:post).and_return(fixture("retrieve_all_entities")) result = subject.retrieve_all_entities - result.should be_a(DynamicsCRM::Metadata::RetrieveAllEntitiesResponse) - result.entities.should_not be_nil + expect(result).to be_a(DynamicsCRM::Metadata::RetrieveAllEntitiesResponse) + expect(result.entities).not_to be_nil entities = result.entities - entities.size.should == 3 + expect(entities.size).to eq(3) - entities[0].LogicalName.should == "opportunity" - entities[1].LogicalName.should == "new_tinderboxdocument" - entities[2].LogicalName.should == "new_tinderboxcontent" + expect(entities[0].LogicalName).to eq("opportunity") + expect(entities[1].LogicalName).to eq("new_tinderboxdocument") + expect(entities[2].LogicalName).to eq("new_tinderboxcontent") end end describe "#retrieve_entity" do it "retrieve entity metadata" do - subject.stub(:post).and_return(fixture("retrieve_entity_response")) + allow(subject).to receive(:post).and_return(fixture("retrieve_entity_response")) result = subject.retrieve_entity("opportunity") - result.should be_a(DynamicsCRM::Metadata::RetrieveEntityResponse) - result.entity.should_not be_nil + expect(result).to be_a(DynamicsCRM::Metadata::RetrieveEntityResponse) + expect(result.entity).not_to be_nil entity = result.entity - entity.should be_a(DynamicsCRM::Metadata::EntityMetadata) + expect(entity).to be_a(DynamicsCRM::Metadata::EntityMetadata) - entity.LogicalName.should == "opportunity" - entity.PrimaryIdAttribute.should == "opportunityid" - entity.PrimaryNameAttribute.should == "name" + expect(entity.LogicalName).to eq("opportunity") + expect(entity.PrimaryIdAttribute).to eq("opportunityid") + expect(entity.PrimaryNameAttribute).to eq("name") end end describe "#retrieve_attribute" do it "retrieve attribute metadata" do - subject.stub(:post).and_return(fixture("retrieve_attribute_response")) + allow(subject).to receive(:post).and_return(fixture("retrieve_attribute_response")) result = subject.retrieve_attribute("new_tinderboxdocument", "new_value") - result.should be_a(DynamicsCRM::Metadata::RetrieveAttributeResponse) - result.attribute.should_not be_nil + expect(result).to be_a(DynamicsCRM::Metadata::RetrieveAttributeResponse) + expect(result.attribute).not_to be_nil attribute = result.attribute - attribute.EntityLogicalName.should == "new_tinderboxdocument" - attribute.LogicalName.should == "new_value" + expect(attribute.EntityLogicalName).to eq("new_tinderboxdocument") + expect(attribute.LogicalName).to eq("new_value") end end @@ -288,7 +316,7 @@ describe "#associate" do it "associates contacts with account" do - subject.stub(:post).and_return(fixture("associate_response")) + allow(subject).to receive(:post).and_return(fixture("associate_response")) subject.associate("account", "7BF2E032-AD92-E311-9752-6C3BE5A87DF0", "contact_customer_accounts", contacts) end @@ -296,7 +324,7 @@ describe "#disassociate" do it "disassociates contacts with accounts" do - subject.stub(:post).and_return(fixture("disassociate_response")) + allow(subject).to receive(:post).and_return(fixture("disassociate_response")) subject.disassociate("account", "7BF2E032-AD92-E311-9752-6C3BE5A87DF0", "contact_customer_accounts", contacts) end @@ -305,7 +333,7 @@ describe "#retrieve_metadata_changes" do it "retrieves entity metadata" do - subject.stub(:post).and_return(fixture("retrieve_metadata_changes_response")) + allow(subject).to receive(:post).and_return(fixture("retrieve_metadata_changes_response")) entity_filter = DynamicsCRM::Metadata::FilterExpression.new('Or') entity_filter.add_condition(['SchemaName', 'Equals', 'Contact']) @@ -325,60 +353,75 @@ }) result = subject.retrieve_metadata_changes(entity_query) - result.should be_a(DynamicsCRM::Metadata::RetrieveMetadataChangesResponse) + expect(result).to be_a(DynamicsCRM::Metadata::RetrieveMetadataChangesResponse) entities = result.entities - entities.should_not be_nil - entities.size.should eq(3) + expect(entities).not_to be_nil + expect(entities.size).to eq(3) attributes = entities[0].attributes - attributes.size.should eq(2) + expect(attributes.size).to eq(2) attribute = attributes.first - attribute.logical_name.should eq("contactid") - attribute.attribute_of.should be_empty - attribute.type.should eq("Lookup") - attribute.display_name.should eq("Contact") - attribute.required_level.should eq("None") + expect(attribute.logical_name).to eq("contactid") + expect(attribute.attribute_of).to be_empty + expect(attribute.type).to eq("Lookup") + expect(attribute.display_name).to eq("Contact") + expect(attribute.required_level).to eq("None") attributes = entities[1].attributes - attributes.size.should eq(2) + expect(attributes.size).to eq(2) attribute = attributes.first - attribute.logical_name.should eq("customertypecodename") - attribute.attribute_of.should eq("customertypecode") - attribute.type.should eq("Virtual") - attribute.display_name.should be_empty - attribute.required_level.should eq("None") + expect(attribute.logical_name).to eq("customertypecodename") + expect(attribute.attribute_of).to eq("customertypecode") + expect(attribute.type).to eq("Virtual") + expect(attribute.display_name).to be_empty + expect(attribute.required_level).to eq("None") attributes = entities[2].attributes - attributes.size.should eq(2) + expect(attributes.size).to eq(2) attribute = attributes.first - attribute.logical_name.should eq("createdonbehalfbyyominame") - attribute.attribute_of.should eq("createdonbehalfby") - attribute.type.should eq("String") - attribute.display_name.should be_empty - attribute.required_level.should eq("None") + expect(attribute.logical_name).to eq("createdonbehalfbyyominame") + expect(attribute.attribute_of).to eq("createdonbehalfby") + expect(attribute.type).to eq("String") + expect(attribute.display_name).to be_empty + expect(attribute.required_level).to eq("None") end end describe "#who_am_i" do it "returns user information" do - subject.stub(:post).and_return(fixture("who_am_i_result")) + allow(subject).to receive(:post).and_return(fixture("who_am_i_result")) response = subject.who_am_i - response.UserId.should == "1bfa3886-df7e-468c-8435-b5adfb0441ed" - response.BusinessUnitId.should == "4e87d619-838a-e311-89a7-6c3be5a80184" - response.OrganizationId.should == "0140d597-e270-494a-89e1-bd0b43774e50" + expect(response.UserId).to eq("1bfa3886-df7e-468c-8435-b5adfb0441ed") + expect(response.BusinessUnitId).to eq("4e87d619-838a-e311-89a7-6c3be5a80184") + expect(response.OrganizationId).to eq("0140d597-e270-494a-89e1-bd0b43774e50") end end describe "#load_entity" do it "returns Model::Opportunity" do response = subject.load_entity("opportunity", "c4944f99-b5a0-e311-b64f-6c3be5a87df0") - response.should be_a(DynamicsCRM::Model::Opportunity) + expect(response).to be_a(DynamicsCRM::Model::Opportunity) end it "returns Model::Entity" do response = subject.load_entity("account", "c4944f99-b5a0-e311-b64f-6c3be5a87df0") - response.should be_a(DynamicsCRM::Model::Entity) + expect(response).to be_a(DynamicsCRM::Model::Entity) + end + end + + describe "#determine_region" do + context "Client receives only hostname" do + it "return the correct region" do + client = DynamicsCRM::Client.new(hostname: 'xunda.api.crm2.dynamics.com') + expect(client.region).to eq('urn:crmsam:dynamics.com') + end + end + context "Client receives only organization_name" do + it "return the correct region" do + client = DynamicsCRM::Client.new(organization_name: 'xunda') + expect(client.region).to eq('urn:crmna:dynamics.com') + end end end diff --git a/spec/lib/metadata/attribute_query_expression_spec.rb b/spec/lib/metadata/attribute_query_expression_spec.rb index 44b700c..b0b970c 100644 --- a/spec/lib/metadata/attribute_query_expression_spec.rb +++ b/spec/lib/metadata/attribute_query_expression_spec.rb @@ -11,18 +11,18 @@ } context "generate attribute query expression" do - it { subject.to_xml.should include("") } - it { subject.to_xml.should include("") } - it { subject.to_xml.should include("IsCustomAttribute") } - it { subject.to_xml.should include("Equals") } - it { subject.to_xml.should match(/true<\/b:Value>/) } - it { subject.to_xml.should include("And") } - it { subject.to_xml.should include("") } - it { subject.to_xml.should include("false") } - it { subject.to_xml.should include("LogicalName") } - it { subject.to_xml.should include("AttributeType") } - it { subject.to_xml.should include("DisplayName") } + it { expect(subject.to_xml).to include("") } + it { expect(subject.to_xml).to include("") } + it { expect(subject.to_xml).to include("IsCustomAttribute") } + it { expect(subject.to_xml).to include("Equals") } + it { expect(subject.to_xml).to match(/true<\/b:Value>/) } + it { expect(subject.to_xml).to include("And") } + it { expect(subject.to_xml).to include("") } + it { expect(subject.to_xml).to include("false") } + it { expect(subject.to_xml).to include("LogicalName") } + it { expect(subject.to_xml).to include("AttributeType") } + it { expect(subject.to_xml).to include("DisplayName") } end end diff --git a/spec/lib/metadata/entity_metadata_spec.rb b/spec/lib/metadata/entity_metadata_spec.rb index 04b61fb..71978ec 100644 --- a/spec/lib/metadata/entity_metadata_spec.rb +++ b/spec/lib/metadata/entity_metadata_spec.rb @@ -10,13 +10,13 @@ } context "parse attributes according to their type" do - it { subject.MetadataId.should == "30b0cd7e-0081-42e1-9a48-688442277fae" } - it { subject.LogicalName.should == "opportunity" } - it { subject.ObjectTypeCode.should == "3" } - it { subject.OwnershipType.should == "UserOwned" } - it { subject.PrimaryIdAttribute.should == "opportunityid" } - it { subject.PrimaryNameAttribute.should == "name" } - it { subject.attributes.should == [] } + it { expect(subject.MetadataId).to eq("30b0cd7e-0081-42e1-9a48-688442277fae") } + it { expect(subject.LogicalName).to eq("opportunity") } + it { expect(subject.ObjectTypeCode).to eq("3") } + it { expect(subject.OwnershipType).to eq("UserOwned") } + it { expect(subject.PrimaryIdAttribute).to eq("opportunityid") } + it { expect(subject.PrimaryNameAttribute).to eq("name") } + it { expect(subject.attributes).to eq([]) } end end @@ -29,12 +29,12 @@ } context "parse attributes and relationships according to their type" do - it { subject.MetadataId.should == "30b0cd7e-0081-42e1-9a48-688442277fae" } - it { subject.LogicalName.should == "opportunity" } - it { subject.ObjectTypeCode.should == "3" } - it { subject.OwnershipType.should == "UserOwned" } - it { subject.PrimaryIdAttribute.should == "opportunityid" } - it { subject.PrimaryNameAttribute.should == "name" } + it { expect(subject.MetadataId).to eq("30b0cd7e-0081-42e1-9a48-688442277fae") } + it { expect(subject.LogicalName).to eq("opportunity") } + it { expect(subject.ObjectTypeCode).to eq("3") } + it { expect(subject.OwnershipType).to eq("UserOwned") } + it { expect(subject.PrimaryIdAttribute).to eq("opportunityid") } + it { expect(subject.PrimaryNameAttribute).to eq("name") } it { expect(subject.one_to_many.size).to eq 7 } it { expect(subject.many_to_many.size).to eq 1 } it { expect(subject.many_to_one.size).to eq 8 } diff --git a/spec/lib/metadata/filter_expression_spec.rb b/spec/lib/metadata/filter_expression_spec.rb index 01b5c85..c6e5cb5 100644 --- a/spec/lib/metadata/filter_expression_spec.rb +++ b/spec/lib/metadata/filter_expression_spec.rb @@ -13,13 +13,13 @@ filter } - it { subject.to_xml.should include("") } - it { subject.to_xml.should include("SchemaName") } - it { subject.to_xml.should include("Equals") } - it { subject.to_xml.should match(/Contact<\/a:Value>/) } - it { subject.to_xml.should match(/Annotation<\/a:Value>/) } - it { subject.to_xml.should match(/Incident<\/a:Value>/) } - it { subject.to_xml.should include("Or") } + it { expect(subject.to_xml).to include("") } + it { expect(subject.to_xml).to include("SchemaName") } + it { expect(subject.to_xml).to include("Equals") } + it { expect(subject.to_xml).to match(/Contact<\/a:Value>/) } + it { expect(subject.to_xml).to match(/Annotation<\/a:Value>/) } + it { expect(subject.to_xml).to match(/Incident<\/a:Value>/) } + it { expect(subject.to_xml).to include("Or") } end context "generate AND filter expression XML" do @@ -31,13 +31,13 @@ filter } - it { subject.to_xml.should include("") } - it { subject.to_xml.should include("SchemaName") } - it { subject.to_xml.should include("Equals") } - it { subject.to_xml.should match(/Contact<\/a:Value>/) } - it { subject.to_xml.should match(/Annotation<\/a:Value>/) } - it { subject.to_xml.should match(/Incident<\/a:Value>/) } - it { subject.to_xml.should include("And") } + it { expect(subject.to_xml).to include("") } + it { expect(subject.to_xml).to include("SchemaName") } + it { expect(subject.to_xml).to include("Equals") } + it { expect(subject.to_xml).to match(/Contact<\/a:Value>/) } + it { expect(subject.to_xml).to match(/Annotation<\/a:Value>/) } + it { expect(subject.to_xml).to match(/Incident<\/a:Value>/) } + it { expect(subject.to_xml).to include("And") } end end diff --git a/spec/lib/metadata/properties_expression_spec.rb b/spec/lib/metadata/properties_expression_spec.rb index 50d3989..cb46f92 100644 --- a/spec/lib/metadata/properties_expression_spec.rb +++ b/spec/lib/metadata/properties_expression_spec.rb @@ -8,12 +8,12 @@ } context "generate properties expression XML" do - it { subject.to_xml({namespace: 'd'}).should include("false") } - it { subject.to_xml.should include("false") } - it { subject.to_xml.should include("LogicalName") } - it { subject.to_xml.should include("AttributeType") } - it { subject.to_xml.should include("DisplayName") } - it { subject.to_xml.should include("Description") } + it { expect(subject.to_xml({namespace: 'd'})).to include("false") } + it { expect(subject.to_xml).to include("false") } + it { expect(subject.to_xml).to include("LogicalName") } + it { expect(subject.to_xml).to include("AttributeType") } + it { expect(subject.to_xml).to include("DisplayName") } + it { expect(subject.to_xml).to include("Description") } end end end diff --git a/spec/lib/metadata/retrieve_all_entities_response_spec.rb b/spec/lib/metadata/retrieve_all_entities_response_spec.rb index 3840d59..154627b 100644 --- a/spec/lib/metadata/retrieve_all_entities_response_spec.rb +++ b/spec/lib/metadata/retrieve_all_entities_response_spec.rb @@ -10,14 +10,14 @@ context "parse execute result" do let(:opportunity) { subject.entities.first } - it { subject.ResponseName.should == "RetrieveAllEntities" } - it { subject.entities.size.should == 3 } - it { opportunity.MetadataId.should == "30b0cd7e-0081-42e1-9a48-688442277fae" } - it { opportunity.LogicalName.should == "opportunity" } - it { opportunity.ObjectTypeCode.should == "3" } - it { opportunity.OwnershipType.should == "UserOwned" } - it { opportunity.PrimaryIdAttribute.should == "opportunityid" } - it { opportunity.PrimaryNameAttribute.should == "name" } + it { expect(subject.ResponseName).to eq("RetrieveAllEntities") } + it { expect(subject.entities.size).to eq(3) } + it { expect(opportunity.MetadataId).to eq("30b0cd7e-0081-42e1-9a48-688442277fae") } + it { expect(opportunity.LogicalName).to eq("opportunity") } + it { expect(opportunity.ObjectTypeCode).to eq("3") } + it { expect(opportunity.OwnershipType).to eq("UserOwned") } + it { expect(opportunity.PrimaryIdAttribute).to eq("opportunityid") } + it { expect(opportunity.PrimaryNameAttribute).to eq("name") } end diff --git a/spec/lib/metadata/retrieve_attribute_response_spec.rb b/spec/lib/metadata/retrieve_attribute_response_spec.rb index 1c2b57a..64b1a37 100644 --- a/spec/lib/metadata/retrieve_attribute_response_spec.rb +++ b/spec/lib/metadata/retrieve_attribute_response_spec.rb @@ -9,13 +9,13 @@ } context "parse execute result" do - it { subject.ResponseName.should == "RetrieveAttribute" } - it { subject.attribute.MetadataId.should == "79194881-c699-e311-9752-6c3be5a87df0" } - it { subject.attribute.AttributeType.should == "Money" } - it { subject.attribute.LogicalName.should == "new_value" } - it { subject.attribute.IsPrimaryId.should == "false" } - it { subject.attribute.AttributeTypeName.Value.should == "MoneyType" } - it { subject.attribute.DisplayName.LocalizedLabels.LocalizedLabel.Label.should == "Value" } + it { expect(subject.ResponseName).to eq("RetrieveAttribute") } + it { expect(subject.attribute.MetadataId).to eq("79194881-c699-e311-9752-6c3be5a87df0") } + it { expect(subject.attribute.AttributeType).to eq("Money") } + it { expect(subject.attribute.LogicalName).to eq("new_value") } + it { expect(subject.attribute.IsPrimaryId).to eq("false") } + it { expect(subject.attribute.AttributeTypeName.Value).to eq("MoneyType") } + it { expect(subject.attribute.DisplayName.LocalizedLabels.LocalizedLabel.Label).to eq("Value") } end end @@ -27,20 +27,20 @@ } context "parse execute result" do - it { subject.ResponseName.should == "RetrieveAttribute" } - it { subject.attribute.MetadataId.should == "ae00233e-70c0-4a1f-803f-03ff723e5440" } - it { subject.attribute.AttributeType.should == "Picklist" } - it { subject.attribute.LogicalName.should == "industrycode" } - it { subject.attribute.EntityLogicalName.should == "account" } - it { subject.attribute.AttributeTypeName.Value.should == "PicklistType" } - it { subject.attribute.picklist_options.should be_a(Hash) } + it { expect(subject.ResponseName).to eq("RetrieveAttribute") } + it { expect(subject.attribute.MetadataId).to eq("ae00233e-70c0-4a1f-803f-03ff723e5440") } + it { expect(subject.attribute.AttributeType).to eq("Picklist") } + it { expect(subject.attribute.LogicalName).to eq("industrycode") } + it { expect(subject.attribute.EntityLogicalName).to eq("account") } + it { expect(subject.attribute.AttributeTypeName.Value).to eq("PicklistType") } + it { expect(subject.attribute.picklist_options).to be_a(Hash) } it { - subject.attribute.picklist_options.should have_key(1) - subject.attribute.picklist_options[1].should == "Accounting" + expect(subject.attribute.picklist_options).to have_key(1) + expect(subject.attribute.picklist_options[1]).to eq("Accounting") } it { - subject.attribute.picklist_options.should have_key(33) - subject.attribute.picklist_options[33].should == "Wholesale" + expect(subject.attribute.picklist_options).to have_key(33) + expect(subject.attribute.picklist_options[33]).to eq("Wholesale") } end @@ -53,11 +53,11 @@ } context "parse execute result" do - it { subject.ResponseName.should == "RetrieveAttribute" } - it { subject.attribute.MetadataId.should == "f8cd5db9-cee8-4845-8cdd-cd4f504957e7" } - it { subject.attribute.AttributeType.should == "Uniqueidentifier" } - it { subject.attribute.LogicalName.should == "accountid" } - it { subject.attribute.EntityLogicalName.should == "account" } + it { expect(subject.ResponseName).to eq("RetrieveAttribute") } + it { expect(subject.attribute.MetadataId).to eq("f8cd5db9-cee8-4845-8cdd-cd4f504957e7") } + it { expect(subject.attribute.AttributeType).to eq("Uniqueidentifier") } + it { expect(subject.attribute.LogicalName).to eq("accountid") } + it { expect(subject.attribute.EntityLogicalName).to eq("account") } end end diff --git a/spec/lib/metadata/retrieve_entity_response_spec.rb b/spec/lib/metadata/retrieve_entity_response_spec.rb index aef1304..bd0a866 100644 --- a/spec/lib/metadata/retrieve_entity_response_spec.rb +++ b/spec/lib/metadata/retrieve_entity_response_spec.rb @@ -9,13 +9,13 @@ } context "parse execute result" do - it { subject.ResponseName.should == "RetrieveEntity" } - it { subject.entity.MetadataId.should == "30b0cd7e-0081-42e1-9a48-688442277fae" } - it { subject.entity.LogicalName.should == "opportunity" } - it { subject.entity.ObjectTypeCode.should == "3" } - it { subject.entity.OwnershipType.should == "UserOwned" } - it { subject.entity.PrimaryIdAttribute.should == "opportunityid" } - it { subject.entity.PrimaryNameAttribute.should == "name" } + it { expect(subject.ResponseName).to eq("RetrieveEntity") } + it { expect(subject.entity.MetadataId).to eq("30b0cd7e-0081-42e1-9a48-688442277fae") } + it { expect(subject.entity.LogicalName).to eq("opportunity") } + it { expect(subject.entity.ObjectTypeCode).to eq("3") } + it { expect(subject.entity.OwnershipType).to eq("UserOwned") } + it { expect(subject.entity.PrimaryIdAttribute).to eq("opportunityid") } + it { expect(subject.entity.PrimaryNameAttribute).to eq("name") } end diff --git a/spec/lib/metadata/retrieve_metadata_changes_response_spec.rb b/spec/lib/metadata/retrieve_metadata_changes_response_spec.rb index 593756e..43a7ef8 100644 --- a/spec/lib/metadata/retrieve_metadata_changes_response_spec.rb +++ b/spec/lib/metadata/retrieve_metadata_changes_response_spec.rb @@ -9,44 +9,44 @@ } it "parses execute result" do - subject.ResponseName.should eq("RetrieveMetadataChanges") - subject.entities.size.should eq(3) + expect(subject.ResponseName).to eq("RetrieveMetadataChanges") + expect(subject.entities.size).to eq(3) entity = subject.entities[0] - entity.MetadataId.should eq("e3fe4ff2-a630-49bb-a1e9-debc3a076815") - entity.LogicalName.should eq("incident") + expect(entity.MetadataId).to eq("e3fe4ff2-a630-49bb-a1e9-debc3a076815") + expect(entity.LogicalName).to eq("incident") attributes = entity.attributes - attributes.should_not be_nil - attributes.size.should eq(2) - attributes.first.logical_name.should eq('contactid') - attributes.first.display_name.should eq('Contact') - attributes.first.type.should eq('Lookup') - attributes.first.attribute_of.should be_empty - attributes.first.required_level.should eq('None') + expect(attributes).not_to be_nil + expect(attributes.size).to eq(2) + expect(attributes.first.logical_name).to eq('contactid') + expect(attributes.first.display_name).to eq('Contact') + expect(attributes.first.type).to eq('Lookup') + expect(attributes.first.attribute_of).to be_empty + expect(attributes.first.required_level).to eq('None') entity = subject.entities[1] - entity.MetadataId.should eq("608861bc-50a4-4c5f-a02c-21fe1943e2cf") - entity.LogicalName.should eq("contact") + expect(entity.MetadataId).to eq("608861bc-50a4-4c5f-a02c-21fe1943e2cf") + expect(entity.LogicalName).to eq("contact") attributes = entity.attributes - attributes.should_not be_nil - attributes.size.should eq(2) - attributes.first.logical_name.should eq("customertypecodename") - attributes.first.attribute_of.should eq("customertypecode") - attributes.first.display_name.should be_empty - attributes.first.type.should eq("Virtual") - attributes.first.required_level.should eq("None") + expect(attributes).not_to be_nil + expect(attributes.size).to eq(2) + expect(attributes.first.logical_name).to eq("customertypecodename") + expect(attributes.first.attribute_of).to eq("customertypecode") + expect(attributes.first.display_name).to be_empty + expect(attributes.first.type).to eq("Virtual") + expect(attributes.first.required_level).to eq("None") entity = subject.entities[2] - entity.MetadataId.should eq("c1961a14-d4e6-470c-8d1e-23ae6b1bbb8d") - entity.LogicalName.should eq("annotation") + expect(entity.MetadataId).to eq("c1961a14-d4e6-470c-8d1e-23ae6b1bbb8d") + expect(entity.LogicalName).to eq("annotation") attributes = entity.attributes - attributes.should_not be_nil - attributes.size.should eq(2) - attributes.first.logical_name.should eq("createdonbehalfbyyominame") - attributes.first.attribute_of.should eq("createdonbehalfby") - attributes.first.display_name.should be_empty - attributes.first.type.should eq("String") - attributes.first.required_level.should eq("None") + expect(attributes).not_to be_nil + expect(attributes.size).to eq(2) + expect(attributes.first.logical_name).to eq("createdonbehalfbyyominame") + expect(attributes.first.attribute_of).to eq("createdonbehalfby") + expect(attributes.first.display_name).to be_empty + expect(attributes.first.type).to eq("String") + expect(attributes.first.required_level).to eq("None") end end end diff --git a/spec/lib/model/opportunity_spec.rb b/spec/lib/model/opportunity_spec.rb index fa1c71b..ee84b9d 100644 --- a/spec/lib/model/opportunity_spec.rb +++ b/spec/lib/model/opportunity_spec.rb @@ -10,9 +10,9 @@ describe '#initialize' do context "default instance" do - it { subject.logical_name.should == "opportunity" } - it { subject.id.should == "2dc8d7bb-149f-e311-ba8d-6c3be5a8ad64" } - it { subject.client.should_not be_nil } + it { expect(subject.logical_name).to eq("opportunity") } + it { expect(subject.id).to eq("2dc8d7bb-149f-e311-ba8d-6c3be5a8ad64") } + it { expect(subject.client).not_to be_nil } end end @@ -22,16 +22,16 @@ context "#set_as_won" do it "sets as won" do - subject.client.stub(:post).and_return(fixture("win_opportunity_response")) - subject.set_as_won.should == {"ResponseName"=>"WinOpportunity"} + allow(subject.client).to receive(:post).and_return(fixture("win_opportunity_response")) + expect(subject.set_as_won).to eq({"ResponseName"=>"WinOpportunity"}) end end context "#set_as_lost" do it "set as lost" do - subject.client.stub(:post).and_return(fixture("lose_opportunity_response")) - subject.set_as_lost.should == {"ResponseName"=>"LoseOpportunity"} + allow(subject.client).to receive(:post).and_return(fixture("lose_opportunity_response")) + expect(subject.set_as_lost).to eq({"ResponseName"=>"LoseOpportunity"}) end end end diff --git a/spec/lib/response/execute_result_spec.rb b/spec/lib/response/execute_result_spec.rb index 77a323a..b27bbbe 100644 --- a/spec/lib/response/execute_result_spec.rb +++ b/spec/lib/response/execute_result_spec.rb @@ -9,10 +9,10 @@ } context "parse execute result" do - it { subject.ResponseName.should == "WhoAmI" } - it { subject.UserId.should == "1bfa3886-df7e-468c-8435-b5adfb0441ed" } - it { subject.BusinessUnitId.should == "4e87d619-838a-e311-89a7-6c3be5a80184" } - it { subject.OrganizationId.should == "0140d597-e270-494a-89e1-bd0b43774e50" } + it { expect(subject.ResponseName).to eq("WhoAmI") } + it { expect(subject.UserId).to eq("1bfa3886-df7e-468c-8435-b5adfb0441ed") } + it { expect(subject.BusinessUnitId).to eq("4e87d619-838a-e311-89a7-6c3be5a80184") } + it { expect(subject.OrganizationId).to eq("0140d597-e270-494a-89e1-bd0b43774e50") } end end diff --git a/spec/lib/response/retrieve_multiple_spec.rb b/spec/lib/response/retrieve_multiple_spec.rb index f19e5ca..3cb479e 100644 --- a/spec/lib/response/retrieve_multiple_spec.rb +++ b/spec/lib/response/retrieve_multiple_spec.rb @@ -10,21 +10,21 @@ context "parse attributes according to their type" do - it { subject.EntityName.should == "account" } - it { subject.MinActiveRowVersion.should == -1} - it { subject.MoreRecords.should == false } - it { subject.PagingCookie.should include("cookie page=") } - it { subject.TotalRecordCount.should == -1 } - it { subject.TotalRecordCountLimitExceeded.should == false } - it { subject.entities.size.should == 3 } - - it { subject.entities.first.to_hash.should == { + it { expect(subject.EntityName).to eq("account") } + it { expect(subject.MinActiveRowVersion).to eq(-1)} + it { expect(subject.MoreRecords).to eq(false) } + it { expect(subject.PagingCookie).to include("cookie page=") } + it { expect(subject.TotalRecordCount).to eq(-1) } + it { expect(subject.TotalRecordCountLimitExceeded).to eq(false) } + it { expect(subject.entities.size).to eq(3) } + + it { expect(subject.entities.first.to_hash).to eq({ :attributes => {"accountid"=>"7bf2e032-ad92-e311-9752-6c3be5a87df0"}, :entity_state => nil, :formatted_values => nil, :id => "7bf2e032-ad92-e311-9752-6c3be5a87df0", :logical_name => "account", - :related_entities => nil} + :related_entities => nil}) } end diff --git a/spec/lib/response/retrieve_result_spec.rb b/spec/lib/response/retrieve_result_spec.rb index aac4403..c6103b4 100644 --- a/spec/lib/response/retrieve_result_spec.rb +++ b/spec/lib/response/retrieve_result_spec.rb @@ -10,53 +10,53 @@ context "parse attributes according to their type" do - it { subject.id.should == "93f0325c-a592-e311-b7f3-6c3be5a8a0c8" } - it { subject.type.should == "account" } - it { subject.exchangerate.should == 1.0 } # decimal - it { subject.modifiedon.should be_a(Time) } # datetime - it { subject.territorycode.should == 1} # OptionType - it { subject.importsequencenumber.should == 1} # int - it { subject.donotemail.should == false} # boolean - it { subject.revenue.should == 60000.00 } # Money - it { subject.modifiedby.should == { + it { expect(subject.id).to eq("93f0325c-a592-e311-b7f3-6c3be5a8a0c8") } + it { expect(subject.type).to eq("account") } + it { expect(subject.exchangerate).to eq(1.0) } # decimal + it { expect(subject.modifiedon).to be_a(Time) } # datetime + it { expect(subject.territorycode).to eq(1)} # OptionType + it { expect(subject.importsequencenumber).to eq(1)} # int + it { expect(subject.donotemail).to eq(false)} # boolean + it { expect(subject.revenue).to eq(60000.00) } # Money + it { expect(subject.modifiedby).to eq({ "Id" => "1bfa3886-df7e-468c-8435-b5adfb0441ed", "LogicalName" => "systemuser", - "Name" => "Joe Heth"} } + "Name" => "Joe Heth"}) } - it { subject["id"].should == "93f0325c-a592-e311-b7f3-6c3be5a8a0c8" } - it { subject["type"].should == "account" } + it { expect(subject["id"]).to eq("93f0325c-a592-e311-b7f3-6c3be5a8a0c8") } + it { expect(subject["type"]).to eq("account") } end context "parses Attributes list" do - it { subject.name.should == "Adventure Works (sample)" } - it { subject.websiteurl.should == "http://www.adventure-works.com/" } - it { subject.address1_city.should == "Santa Cruz" } + it { expect(subject.name).to eq("Adventure Works (sample)") } + it { expect(subject.websiteurl).to eq("http://www.adventure-works.com/") } + it { expect(subject.address1_city).to eq("Santa Cruz") } - it { subject["name"].should == "Adventure Works (sample)" } - it { subject["websiteurl"].should == "http://www.adventure-works.com/" } - it { subject["address1_city"].should == "Santa Cruz" } + it { expect(subject["name"]).to eq("Adventure Works (sample)") } + it { expect(subject["websiteurl"]).to eq("http://www.adventure-works.com/") } + it { expect(subject["address1_city"]).to eq("Santa Cruz") } end context "assignment" do it "should assign through hash index" do - subject[:nothing].should be_nil + expect(subject[:nothing]).to be_nil subject[:nothing] = "New Value" - subject[:nothing].should == "New Value" - subject.nothing.should == "New Value" - subject.Nothing.should == "New Value" + expect(subject[:nothing]).to eq("New Value") + expect(subject.nothing).to eq("New Value") + expect(subject.Nothing).to eq("New Value") end end context "respond to hash methods" do it "should has_key?" do - subject.has_key?("name").should be_true - subject.has_key?("type").should be_true - subject.has_key?("nothing").should be_false + expect(subject.key?("name")).to be true + expect(subject.key?("type")).to be true + expect(subject.key?("nothing")).to be false end it "should return keys" do - subject.keys.should include("type", "id", "accountid", "address1_city", + expect(subject.keys).to include("type", "id", "accountid", "address1_city", "address1_stateorprovince", "address1_postalcode", "websiteurl", "name", "address1_line1", "address1_country", "address1_composite") end diff --git a/spec/lib/xml/attributes_spec.rb b/spec/lib/xml/attributes_spec.rb index 373d16a..a670fc3 100644 --- a/spec/lib/xml/attributes_spec.rb +++ b/spec/lib/xml/attributes_spec.rb @@ -9,7 +9,8 @@ "modifiedon" => Time.now, "donotemail" => true, "id" => "1bfa3886-df7e-468c-8435-b5adfb0441ed", - "reference" => {"Id" => "someid", "Name" => "entityname", "LogicalName" => "opportunity"} + "reference" => {"Id" => "someid", "Name" => "entityname", "LogicalName" => "opportunity"}, + "expireson" => nil } } subject { @@ -17,21 +18,22 @@ } context "attributes extends hash" do - it { subject.should == attrs } + it { expect(subject).to eq(attrs) } end context "attributes uses method_missing for hash access" do - it { subject.telephone1.should == attrs["telephone1"]} - it { subject.modifiedon.should == attrs["modifiedon"]} - it { subject.donotemail.should == attrs["donotemail"]} - it { subject.id.should == attrs["id"]} - it { subject.reference.should == attrs["reference"]} + it { expect(subject.telephone1).to eq(attrs["telephone1"])} + it { expect(subject.modifiedon).to eq(attrs["modifiedon"])} + it { expect(subject.donotemail).to eq(attrs["donotemail"])} + it { expect(subject.id).to eq(attrs["id"])} + it { expect(subject.reference).to eq(attrs["reference"])} end context "parse attributes according to their type" do - it { subject.to_xml.should include("telephone1") } - it { subject.to_xml.should include("donotemail") } - it { subject.to_xml.should include("modifiedon") } + it { expect(subject.to_xml).to include("telephone1") } + it { expect(subject.to_xml).to include("donotemail") } + it { expect(subject.to_xml).to include("modifiedon") } + it { expect(subject.to_xml).to include('') } end end diff --git a/spec/lib/xml/column_set_spec.rb b/spec/lib/xml/column_set_spec.rb index 456b51a..00e8290 100644 --- a/spec/lib/xml/column_set_spec.rb +++ b/spec/lib/xml/column_set_spec.rb @@ -8,10 +8,10 @@ } context "generate ColumnSet XML" do - it { subject.to_xml.should include("false") } - it { subject.to_xml.should include("accountid") } - it { subject.to_xml.should include("donotemail") } - it { subject.to_xml.should include("telephone1") } + it { expect(subject.to_xml).to include("false") } + it { expect(subject.to_xml).to include("accountid") } + it { expect(subject.to_xml).to include("donotemail") } + it { expect(subject.to_xml).to include("telephone1") } end end diff --git a/spec/lib/xml/entity_reference_spec.rb b/spec/lib/xml/entity_reference_spec.rb index 2ff0eac..ed73256 100644 --- a/spec/lib/xml/entity_reference_spec.rb +++ b/spec/lib/xml/entity_reference_spec.rb @@ -8,9 +8,9 @@ } context "default instance" do - it { subject.logical_name.should == "opportunity" } - it { subject.id.should == "9BF1325C-A592-E311-B7F3-6C3BE5A8A0C8" } - it { subject.name.should be_nil } + it { expect(subject.logical_name).to eq("opportunity") } + it { expect(subject.id).to eq("9BF1325C-A592-E311-B7F3-6C3BE5A8A0C8") } + it { expect(subject.name).to be_nil } end context "#to_xml" do @@ -23,7 +23,7 @@ #{@name} } - subject.to_xml.should == expected_xml + expect(subject.to_xml).to eq(expected_xml) end it "outputs EntityReference with namespace" do @@ -35,7 +35,7 @@ #{@name} } - subject.to_xml(namespace: 'b', camel_case: true).should == expected_xml + expect(subject.to_xml(namespace: 'b', camel_case: true)).to eq(expected_xml) end end @@ -50,9 +50,9 @@ DynamicsCRM::XML::EntityReference.from_xml(xml.root) } - it { subject.logical_name.should == "opportunity" } - it { subject.id.should == "9BF1325C-A592-E311-B7F3-6C3BE5A8A0C8" } - it { subject.name.should == "Sample Opportunity Name" } + it { expect(subject.logical_name).to eq("opportunity") } + it { expect(subject.id).to eq("9BF1325C-A592-E311-B7F3-6C3BE5A8A0C8") } + it { expect(subject.name).to eq("Sample Opportunity Name") } end end diff --git a/spec/lib/xml/entity_spec.rb b/spec/lib/xml/entity_spec.rb index 44c32dc..406158d 100644 --- a/spec/lib/xml/entity_spec.rb +++ b/spec/lib/xml/entity_spec.rb @@ -8,17 +8,17 @@ } context "default instance" do - it { subject.logical_name.should == "account" } - it { subject.id.should == "00000000-0000-0000-0000-000000000000" } - it { subject.attributes.should be_nil } - it { subject.entity_state.should be_nil } - it { subject.formatted_values.should be_nil } - it { subject.related_entities.should be_nil } + it { expect(subject.logical_name).to eq("account") } + it { expect(subject.id).to eq("00000000-0000-0000-0000-000000000000") } + it { expect(subject.attributes).to be_nil } + it { expect(subject.entity_state).to be_nil } + it { expect(subject.formatted_values).to be_nil } + it { expect(subject.related_entities).to be_nil } end context "#to_xml" do - it { subject.to_xml.should include("00000000-0000-0000-0000-000000000000") } - it { subject.to_xml.should include("account") } + it { expect(subject.to_xml).to include("00000000-0000-0000-0000-000000000000") } + it { expect(subject.to_xml).to include("account") } end end @@ -34,10 +34,10 @@ context "#to_xml" do # Contains nested Attributes with EntityReference - it { subject.to_xml.should include('') } - it { subject.to_xml.should include("2dc8d7bb-149f-e311-ba8d-6c3be5a8ad64") } - it { subject.to_xml.should include("opportunity") } - it { subject.to_xml.should include("00000000-0000-0000-0000-000000000000") } + it { expect(subject.to_xml).to include('') } + it { expect(subject.to_xml).to include("2dc8d7bb-149f-e311-ba8d-6c3be5a8ad64") } + it { expect(subject.to_xml).to include("opportunity") } + it { expect(subject.to_xml).to include("00000000-0000-0000-0000-000000000000") } end end @@ -51,12 +51,26 @@ } context "parses XML document into instance variables" do - it { subject.id.should == "7bf2e032-ad92-e311-9752-6c3be5a87df0" } - it { subject.attributes.should == {"accountid" => "7bf2e032-ad92-e311-9752-6c3be5a87df0"} } - it { subject.entity_state.should be_nil } - it { subject.formatted_values.should be_nil } - it { subject.logical_name.should == "account" } - it { subject.related_entities.should be_nil } + it { expect(subject.id).to eq("7bf2e032-ad92-e311-9752-6c3be5a87df0") } + it { expect(subject.attributes).to eq({"accountid" => "7bf2e032-ad92-e311-9752-6c3be5a87df0"}) } + it { expect(subject.entity_state).to be_nil } + it { expect(subject.formatted_values).to be_nil } + it { expect(subject.logical_name).to eq("account") } + it { expect(subject.related_entities).to be_nil } + end + end + + describe "entity with array" do + subject { + entity = DynamicsCRM::XML::Entity.new("activityparty") + entity.attributes = DynamicsCRM::XML::Attributes.new( + partyid: DynamicsCRM::XML::EntityReference.new("systemuser", "f36aa96c-e7a5-4c70-8254-47c8ba947561") + ) + entity + } + + context "#to_xml" do + it { expect(DynamicsCRM::XML::Attributes.new({to: [subject]}).to_xml).to include('') } end end diff --git a/spec/lib/xml/fault_spec.rb b/spec/lib/xml/fault_spec.rb index a4ef361..9b5a13e 100644 --- a/spec/lib/xml/fault_spec.rb +++ b/spec/lib/xml/fault_spec.rb @@ -12,10 +12,10 @@ } context "generate ColumnSet XML" do - it { subject.code.should == "s:Receiver" } - it { subject.subcode.should == "a:InternalServiceFault" } - it { subject.reason.should == "The server was unable to process the request due to an internal error." } - it { subject.message.should == "#{subject.code}[#{subject.subcode}] #{subject.reason}" } + it { expect(subject.code).to eq("s:Receiver") } + it { expect(subject.subcode).to eq("a:InternalServiceFault") } + it { expect(subject.reason).to eq("The server was unable to process the request due to an internal error.") } + it { expect(subject.message).to eq("#{subject.code}[#{subject.subcode}] #{subject.reason}") } end end @@ -28,10 +28,10 @@ } context "generate ColumnSet XML" do - it { subject.code.should == "s:Sender" } - it { subject.subcode.should be_nil } - it { subject.reason.should == "'account' entity doesn't contain attribute with Name = 'ticketsymbol'." } - it { subject.message.should start_with("#{subject.code}[#{subject.subcode}] #{subject.reason} (Detail =>") } + it { expect(subject.code).to eq("s:Sender") } + it { expect(subject.subcode).to be_nil } + it { expect(subject.reason).to eq("'account' entity doesn't contain attribute with Name = 'ticketsymbol'.") } + it { expect(subject.message).to start_with("#{subject.code}[#{subject.subcode}] #{subject.reason} (Detail =>") } end end diff --git a/spec/lib/xml/money_spec.rb b/spec/lib/xml/money_spec.rb index 8b9112b..a9b42ac 100644 --- a/spec/lib/xml/money_spec.rb +++ b/spec/lib/xml/money_spec.rb @@ -9,31 +9,31 @@ context "with a string" do let(:value) { "250.00" } - it { subject.to_xml.should eq("250.00") } + it { expect(subject.to_xml).to eq("250.00") } context "and precision is 1" do let(:precision) { 1 } - it { subject.to_xml.should eq("250.0") } + it { expect(subject.to_xml).to eq("250.0") } end end context "with a number" do let(:value) { 250 } - it { subject.to_xml.should eq("250.00") } + it { expect(subject.to_xml).to eq("250.00") } context "and precision is 1" do let(:precision) { 1 } - it { subject.to_xml.should eq("250.0") } + it { expect(subject.to_xml).to eq("250.0") } end end context "with a float" do let(:value) { 250.00 } - it { subject.to_xml.should eq("250.00") } + it { expect(subject.to_xml).to eq("250.00") } context "and precision is 1" do let(:precision) { 1 } - it { subject.to_xml.should eq("250.0") } + it { expect(subject.to_xml).to eq("250.0") } end end diff --git a/spec/lib/xml/query_spec.rb b/spec/lib/xml/query_spec.rb index b6062f2..7761700 100644 --- a/spec/lib/xml/query_spec.rb +++ b/spec/lib/xml/query_spec.rb @@ -8,12 +8,12 @@ } context "generate empty Query fragment" do - it { subject.to_xml.should include("\s+<\/b:Conditions>/) } - it { subject.to_xml.should include("true") } - it { subject.to_xml.should include("false") } - it { subject.to_xml.should include("opportunity") } - it { subject.to_xml.should include("And") } + it { expect(subject.to_xml).to include("\s+<\/b:Conditions>/) } + it { expect(subject.to_xml).to include("true") } + it { expect(subject.to_xml).to include("false") } + it { expect(subject.to_xml).to include("opportunity") } + it { expect(subject.to_xml).to include("And") } end end @@ -27,15 +27,15 @@ } context "generate empty Query fragment" do - it { subject.to_xml.should include("nameEqualTest Opp') } - it { subject.to_xml.should include("true") } - it { subject.to_xml.should include("false") } - it { subject.to_xml.should include("opportunity") } - it { subject.to_xml.should include("And") } + it { expect(subject.to_xml).to include("nameEqualTest Opp') } + it { expect(subject.to_xml).to include("true") } + it { expect(subject.to_xml).to include("false") } + it { expect(subject.to_xml).to include("opportunity") } + it { expect(subject.to_xml).to include("And") } end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 78fc9f5..2ddf5cd 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,5 @@ require 'simplecov' +require 'pry' SimpleCov.start do add_filter "/vendor/" end