dynamics_crm 0.6.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -1
  3. data/CHANGELOG.md +10 -0
  4. data/dynamics_crm.gemspec +6 -5
  5. data/lib/dynamics_crm.rb +7 -0
  6. data/lib/dynamics_crm/client.rb +25 -14
  7. data/lib/dynamics_crm/fetch_xml/builder.rb +26 -27
  8. data/lib/dynamics_crm/metadata/attribute_metadata.rb +35 -2
  9. data/lib/dynamics_crm/metadata/attribute_query_expression.rb +25 -0
  10. data/lib/dynamics_crm/metadata/entity_metadata.rb +1 -1
  11. data/lib/dynamics_crm/metadata/entity_query_expression.rb +29 -0
  12. data/lib/dynamics_crm/metadata/filter_expression.rb +47 -0
  13. data/lib/dynamics_crm/metadata/properties_expression.rb +30 -0
  14. data/lib/dynamics_crm/metadata/retrieve_metadata_changes_response.rb +18 -0
  15. data/lib/dynamics_crm/version.rb +1 -1
  16. data/lib/dynamics_crm/xml/attributes.rb +28 -2
  17. data/lib/dynamics_crm/xml/entity_collection.rb +10 -0
  18. data/lib/dynamics_crm/xml/message_builder.rb +3 -3
  19. data/lib/dynamics_crm/xml/message_parser.rb +2 -0
  20. data/lib/dynamics_crm/xml/money.rb +16 -0
  21. data/spec/fixtures/retrieve_metadata_changes_response.xml +215 -0
  22. data/spec/lib/client_spec.rb +169 -70
  23. data/spec/lib/fetch_xml/builder_spec.rb +44 -0
  24. data/spec/lib/metadata/attribute_query_expression_spec.rb +29 -0
  25. data/spec/lib/metadata/entity_metadata_spec.rb +13 -13
  26. data/spec/lib/metadata/filter_expression_spec.rb +44 -0
  27. data/spec/lib/metadata/properties_expression_spec.rb +19 -0
  28. data/spec/lib/metadata/retrieve_all_entities_response_spec.rb +8 -8
  29. data/spec/lib/metadata/retrieve_attribute_response_spec.rb +23 -23
  30. data/spec/lib/metadata/retrieve_entity_response_spec.rb +7 -7
  31. data/spec/lib/metadata/retrieve_metadata_changes_response_spec.rb +52 -0
  32. data/spec/lib/model/opportunity_spec.rb +7 -7
  33. data/spec/lib/response/execute_result_spec.rb +4 -4
  34. data/spec/lib/response/retrieve_multiple_spec.rb +10 -10
  35. data/spec/lib/response/retrieve_result_spec.rb +26 -26
  36. data/spec/lib/xml/attributes_spec.rb +9 -9
  37. data/spec/lib/xml/column_set_spec.rb +4 -4
  38. data/spec/lib/xml/entity_reference_spec.rb +8 -8
  39. data/spec/lib/xml/entity_spec.rb +18 -18
  40. data/spec/lib/xml/fault_spec.rb +8 -8
  41. data/spec/lib/xml/money_spec.rb +41 -0
  42. data/spec/lib/xml/query_spec.rb +15 -15
  43. data/spec/spec_helper.rb +1 -0
  44. metadata +82 -32
@@ -0,0 +1,18 @@
1
+ module DynamicsCRM
2
+ module Metadata
3
+
4
+ class RetrieveMetadataChangesResponse < DynamicsCRM::Response::ExecuteResult
5
+ attr_reader :entities
6
+
7
+ def initialize(xml)
8
+ super
9
+ @entities = []
10
+
11
+ self.delete("EntityMetadata").each do |em_xml|
12
+ @entities << EntityMetadata.new(em_xml)
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module DynamicsCRM
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.1"
3
3
  end
@@ -23,10 +23,22 @@ module DynamicsCRM
23
23
  type = "EntityReference"
24
24
  when Entity
25
25
  type = "Entity"
26
+ when EntityCollection
27
+ type = "EntityCollection"
26
28
  when Query
27
29
  type = "QueryExpression"
28
30
  when FetchExpression
29
31
  type = "FetchExpression"
32
+ when Money
33
+ type = "Money"
34
+ when DynamicsCRM::Metadata::FilterExpression
35
+ type = "FilterExpression"
36
+ when DynamicsCRM::Metadata::PropertiesExpression
37
+ type = "PropertiesExpression"
38
+ when DynamicsCRM::Metadata::AttributeQueryExpression
39
+ type = "AttributeQueryExpression"
40
+ when DynamicsCRM::Metadata::EntityQueryExpression
41
+ type = "EntityQueryExpression"
30
42
  else
31
43
  if key.to_s == "EntityFilters"
32
44
  type = "EntityFilters"
@@ -64,6 +76,9 @@ module DynamicsCRM
64
76
  type = get_type(key, value)
65
77
  end
66
78
 
79
+ # escape strings to avoid xml parsing errors
80
+ value = CGI.escapeHTML(value) if value.is_a?(String)
81
+
67
82
  xml << build_xml(key, value, type)
68
83
  end
69
84
 
@@ -83,7 +98,7 @@ module DynamicsCRM
83
98
 
84
99
  # If we have an object that can convert itself, use it.
85
100
  if (value.respond_to?(:to_xml) && value.class.to_s.include?("DynamicsCRM"))
86
- xml << "<c:value i:type=\"a:#{type}\">\n" << value.to_xml({exclude_root: true, namespace: 'a'}) << "</c:value>"
101
+ xml << render_object_xml(type, value)
87
102
  else
88
103
  xml << render_value_xml(type, value)
89
104
  end
@@ -138,6 +153,17 @@ module DynamicsCRM
138
153
  xml
139
154
  end
140
155
 
156
+ def render_object_xml(type, value)
157
+ case type
158
+ when "EntityQueryExpression"
159
+ xml = %Q{<c:value i:type="d:#{type}" xmlns:d="http://schemas.microsoft.com/xrm/2011/Metadata/Query">} << value.to_xml({namespace: 'd'}) << "</c:value>"
160
+ else
161
+ xml = %Q{<c:value i:type="a:#{type}">} << value.to_xml({exclude_root: true, namespace: 'a'}) << "</c:value>"
162
+ end
163
+
164
+ return xml
165
+ end
166
+
141
167
  def class_name
142
168
  self.class.to_s.split("::").last
143
169
  end
@@ -169,4 +195,4 @@ module DynamicsCRM
169
195
  class FormattedValues < Attributes; end
170
196
  end
171
197
 
172
- end
198
+ end
@@ -37,6 +37,16 @@ module DynamicsCRM
37
37
  }
38
38
  end
39
39
 
40
+ def to_xml(options={})
41
+ options[:exclude_root] = true
42
+ namespace = options[:namespace] ? "#{options[:namespace]}:" : ''
43
+
44
+ entities_xml = entities.inject("") { |result,entity|
45
+ result << %Q{<#{namespace}Entity>#{entity.to_xml(options)}</#{namespace}Entity>}
46
+ }
47
+ %Q{<#{namespace}Entities>#{entities_xml}</#{namespace}Entities>}
48
+ end
49
+
40
50
  end
41
51
  # EntityCollection
42
52
  end
@@ -44,9 +44,9 @@ module DynamicsCRM
44
44
  <u:Expires>#{get_tomorrow_time}</u:Expires>
45
45
  </u:Timestamp>
46
46
  <o:UsernameToken u:Id="uuid-cdb639e6-f9b0-4c01-b454-0fe244de73af-1">
47
- <o:Username>#{username}</o:Username>
47
+ <o:Username>#{REXML::Text.new(username).to_s}</o:Username>
48
48
  <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
49
- #{password}
49
+ #{REXML::Text.new(password).to_s}
50
50
  </o:Password>
51
51
  </o:UsernameToken>
52
52
  </o:Security>
@@ -298,7 +298,7 @@ module DynamicsCRM
298
298
  # Default namespace is /crm/2011/Contracts
299
299
  ns_alias = "b"
300
300
  # Metadata Service calls are under the /xrm/2011/Contracts schema.
301
- if ["RetrieveAllEntities", "RetrieveEntityMetadata", "RetrieveEntity", "RetrieveAttribute", "RetrieveMultiple"].include?(action)
301
+ if ["RetrieveAllEntities", "RetrieveEntityMetadata", "RetrieveEntity", "RetrieveAttribute", "RetrieveMultiple", "RetrieveMetadataChanges"].include?(action)
302
302
  ns_alias = 'a'
303
303
  end
304
304
 
@@ -41,6 +41,8 @@ module DynamicsCRM
41
41
  value = value_element.get_elements("d:EntityMetadata")
42
42
  when "d:ArrayOfAttributeMetadata"
43
43
  value = value_element.get_elements("d:AttributeMetadata")
44
+ when "b:EntityMetadataCollection"
45
+ value = value_element.get_elements("b:EntityMetadata")
44
46
  when "b:AliasedValue"
45
47
  value = value_element.elements["b:Value"].text
46
48
  when "b:Money"
@@ -0,0 +1,16 @@
1
+ module DynamicsCRM
2
+ module XML
3
+ class Money
4
+
5
+ attr_accessor :value
6
+
7
+ def initialize(value, precision=2)
8
+ @value = "%.#{precision}f" % value
9
+ end
10
+
11
+ def to_xml(options={})
12
+ "<a:Value>#{@value}</a:Value>"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,215 @@
1
+ <s:Envelope xmlns:s='http://www.w3.org/2003/05/soap-envelope' xmlns:a='http://www.w3.org/2005/08/addressing' xmlns:u='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
2
+ <s:Header>
3
+ <a:Action s:mustUnderstand='1'>
4
+ http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/ExecuteResponse
5
+ </a:Action>
6
+ <a:RelatesTo>urn:uuid:5a1b5d6a-8dba-4518-9e1c-fe5c2d972221</a:RelatesTo>
7
+ <ActivityId CorrelationId='4780d5c3-f5aa-42a4-ab0b-d8d784d6c963' xmlns='http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics'>00000000-0000-0000-0000-000000000000</ActivityId>
8
+ <o:Security s:mustUnderstand='1' xmlns:o='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'>
9
+ <u:Timestamp u:Id='_0'>
10
+ <u:Created>2015-02-24T17:34:18.908Z</u:Created>
11
+ <u:Expires>2015-02-24T17:39:18.908Z</u:Expires>
12
+ </u:Timestamp>
13
+ </o:Security>
14
+ </s:Header>
15
+ <s:Body>
16
+ <ExecuteResponse xmlns='http://schemas.microsoft.com/xrm/2011/Contracts/Services'>
17
+ <ExecuteResult i:type='b:RetrieveMetadataChangesResponse' xmlns:b='http://schemas.microsoft.com/xrm/2011/Contracts' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
18
+ <b:ResponseName>RetrieveMetadataChanges</b:ResponseName>
19
+ <b:Results xmlns:c='http://schemas.datacontract.org/2004/07/System.Collections.Generic'>
20
+ <b:KeyValuePairOfstringanyType>
21
+ <c:key>ServerVersionStamp</c:key>
22
+ <c:value i:type='d:string' xmlns:d='http://www.w3.org/2001/XMLSchema'>22934563!02/24/2015 17:34:18</c:value>
23
+ </b:KeyValuePairOfstringanyType>
24
+ <b:KeyValuePairOfstringanyType>
25
+ <c:key>DeletedMetadata</c:key>
26
+ <c:value i:type='d:DeletedMetadataCollection' xmlns:d='http://schemas.microsoft.com/xrm/2011/Metadata/Query'/>
27
+ </b:KeyValuePairOfstringanyType>
28
+ <b:KeyValuePairOfstringanyType>
29
+ <c:key>EntityMetadata</c:key>
30
+ <c:value i:type='b:EntityMetadataCollection' xmlns:d='http://schemas.microsoft.com/xrm/2011/Metadata'>
31
+ <b:EntityMetadata>
32
+ <d:MetadataId>e3fe4ff2-a630-49bb-a1e9-debc3a076815</d:MetadataId>
33
+ <d:ActivityTypeMask i:nil='true'/>
34
+ <d:Attributes>
35
+ <d:AttributeMetadata i:type='d:LookupAttributeMetadata'>
36
+ <d:MetadataId>4ff40786-b76b-42bf-ab77-0f3a8fc558c5</d:MetadataId>
37
+ <d:AttributeOf i:nil='true'/>
38
+ <d:AttributeType>Lookup</d:AttributeType>
39
+ <d:Description i:nil='true'/>
40
+ <d:DisplayName>
41
+ <b:LocalizedLabels>
42
+ <b:LocalizedLabel>
43
+ <d:MetadataId>bbc675a7-c9d8-4744-9875-b6cf8f6a226a</d:MetadataId>
44
+ <b:Label>Contact</b:Label>
45
+ <b:LanguageCode>1033</b:LanguageCode>
46
+ </b:LocalizedLabel>
47
+ </b:LocalizedLabels>
48
+ <b:UserLocalizedLabel>
49
+ <d:MetadataId>bbc675a7-c9d8-4744-9875-b6cf8f6a226a</d:MetadataId>
50
+ <b:Label>Contact</b:Label>
51
+ <b:LanguageCode>1033</b:LanguageCode>
52
+ </b:UserLocalizedLabel>
53
+ </d:DisplayName>
54
+ <d:IsCustomAttribute i:nil='true'/>
55
+ <d:LogicalName>contactid</d:LogicalName>
56
+ <d:RequiredLevel>
57
+ <b:CanBeChanged>false</b:CanBeChanged>
58
+ <b:ManagedPropertyLogicalName>canmodifyrequirementlevelsettings</b:ManagedPropertyLogicalName>
59
+ <b:Value>None</b:Value>
60
+ </d:RequiredLevel>
61
+ <d:AttributeTypeName xmlns:e='http://schemas.microsoft.com/xrm/2013/Metadata'>
62
+ <e:Value>LookupType</e:Value>
63
+ </d:AttributeTypeName>
64
+ <d:Targets i:nil='true' xmlns:e='http://schemas.microsoft.com/2003/10/Serialization/Arrays'/>
65
+ </d:AttributeMetadata>
66
+ <d:AttributeMetadata>
67
+ <d:MetadataId>b7583f6b-c3af-49bb-bab1-abb9da954b2c</d:MetadataId>
68
+ <d:AttributeOf>resolvebyslastatus</d:AttributeOf>
69
+ <d:AttributeType>Virtual</d:AttributeType>
70
+ <d:Description i:nil='true'/>
71
+ <d:DisplayName>
72
+ <b:LocalizedLabels/>
73
+ <b:UserLocalizedLabel i:nil='true'/>
74
+ </d:DisplayName>
75
+ <d:IsCustomAttribute i:nil='true'/>
76
+ <d:LogicalName>resolvebyslastatusname</d:LogicalName>
77
+ <d:RequiredLevel>
78
+ <b:CanBeChanged>false</b:CanBeChanged>
79
+ <b:ManagedPropertyLogicalName>canmodifyrequirementlevelsettings</b:ManagedPropertyLogicalName>
80
+ <b:Value>None</b:Value>
81
+ </d:RequiredLevel>
82
+ <d:AttributeTypeName i:nil='true' xmlns:e='http://schemas.microsoft.com/xrm/2013/Metadata'/>
83
+ </d:AttributeMetadata>
84
+ </d:Attributes>
85
+ <d:Description i:nil='true'/>
86
+ <d:DisplayName i:nil='true'/>
87
+ <d:LogicalName>incident</d:LogicalName>
88
+ <d:ObjectTypeCode i:nil='true'/>
89
+ </b:EntityMetadata>
90
+ <b:EntityMetadata>
91
+ <d:MetadataId>608861bc-50a4-4c5f-a02c-21fe1943e2cf</d:MetadataId>
92
+ <d:ActivityTypeMask i:nil='true'/>
93
+ <d:Attributes>
94
+ <d:AttributeMetadata>
95
+ <d:MetadataId>38a3d266-1c2f-454e-8136-43439b75f094</d:MetadataId>
96
+ <d:AttributeOf>customertypecode</d:AttributeOf>
97
+ <d:AttributeType>Virtual</d:AttributeType>
98
+ <d:Description i:nil='true'/>
99
+ <d:DisplayName>
100
+ <b:LocalizedLabels/>
101
+ <b:UserLocalizedLabel i:nil='true'/>
102
+ </d:DisplayName>
103
+ <d:IsCustomAttribute i:nil='true'/>
104
+ <d:LogicalName>customertypecodename</d:LogicalName>
105
+ <d:RequiredLevel>
106
+ <b:CanBeChanged>false</b:CanBeChanged>
107
+ <b:ManagedPropertyLogicalName>canmodifyrequirementlevelsettings</b:ManagedPropertyLogicalName>
108
+ <b:Value>None</b:Value>
109
+ </d:RequiredLevel>
110
+ <d:AttributeTypeName i:nil='true' xmlns:e='http://schemas.microsoft.com/xrm/2013/Metadata'/>
111
+ </d:AttributeMetadata>
112
+ <d:AttributeMetadata>
113
+ <d:MetadataId>4e40d60b-79fb-41b7-a0cd-a62996c46688</d:MetadataId>
114
+ <d:AttributeOf i:nil='true'/>
115
+ <d:AttributeType>Uniqueidentifier</d:AttributeType>
116
+ <d:Description i:nil='true'/>
117
+ <d:DisplayName>
118
+ <b:LocalizedLabels>
119
+ <b:LocalizedLabel>
120
+ <d:MetadataId>7f6747a3-1c34-4ecf-a1ae-b766612c730f</d:MetadataId>
121
+ <b:Label>Process</b:Label>
122
+ <b:LanguageCode>1033</b:LanguageCode>
123
+ </b:LocalizedLabel>
124
+ </b:LocalizedLabels>
125
+ <b:UserLocalizedLabel>
126
+ <d:MetadataId>7f6747a3-1c34-4ecf-a1ae-b766612c730f</d:MetadataId>
127
+ <b:Label>Process</b:Label>
128
+ <b:LanguageCode>1033</b:LanguageCode>
129
+ </b:UserLocalizedLabel>
130
+ </d:DisplayName>
131
+ <d:IsCustomAttribute i:nil='true'/>
132
+ <d:LogicalName>processid</d:LogicalName>
133
+ <d:RequiredLevel>
134
+ <b:CanBeChanged>false</b:CanBeChanged>
135
+ <b:ManagedPropertyLogicalName>canmodifyrequirementlevelsettings</b:ManagedPropertyLogicalName>
136
+ <b:Value>None</b:Value>
137
+ </d:RequiredLevel>
138
+ <d:AttributeTypeName i:nil='true' xmlns:e='http://schemas.microsoft.com/xrm/2013/Metadata'/>
139
+ </d:AttributeMetadata>
140
+ </d:Attributes>
141
+ <d:Description i:nil='true'/>
142
+ <d:DisplayName i:nil='true'/>
143
+ <d:LogicalName>contact</d:LogicalName>
144
+ <d:ObjectTypeCode i:nil='true'/>
145
+ </b:EntityMetadata>
146
+ <b:EntityMetadata>
147
+ <d:MetadataId>c1961a14-d4e6-470c-8d1e-23ae6b1bbb8d</d:MetadataId>
148
+ <d:ActivityTypeMask i:nil='true'/>
149
+ <d:Attributes>
150
+ <d:AttributeMetadata i:type='d:StringAttributeMetadata'>
151
+ <d:MetadataId>181e147a-bd89-4528-a8c5-1e6971097ec3</d:MetadataId>
152
+ <d:AttributeOf>createdonbehalfby</d:AttributeOf>
153
+ <d:AttributeType>String</d:AttributeType>
154
+ <d:Description i:nil='true'/>
155
+ <d:DisplayName>
156
+ <b:LocalizedLabels/>
157
+ <b:UserLocalizedLabel i:nil='true'/>
158
+ </d:DisplayName>
159
+ <d:IsCustomAttribute i:nil='true'/>
160
+ <d:LogicalName>createdonbehalfbyyominame</d:LogicalName>
161
+ <d:RequiredLevel>
162
+ <b:CanBeChanged>false</b:CanBeChanged>
163
+ <b:ManagedPropertyLogicalName>canmodifyrequirementlevelsettings</b:ManagedPropertyLogicalName>
164
+ <b:Value>None</b:Value>
165
+ </d:RequiredLevel>
166
+ <d:AttributeTypeName xmlns:e='http://schemas.microsoft.com/xrm/2013/Metadata'>
167
+ <e:Value>StringType</e:Value>
168
+ </d:AttributeTypeName>
169
+ <d:MaxLength i:nil='true'/>
170
+ <d:YomiOf i:nil='true'/>
171
+ </d:AttributeMetadata>
172
+ <d:AttributeMetadata i:type='d:LookupAttributeMetadata'>
173
+ <d:MetadataId>59a81bda-e398-4058-957e-394e15da9ff2</d:MetadataId>
174
+ <d:AttributeOf i:nil='true'/>
175
+ <d:AttributeType>Lookup</d:AttributeType>
176
+ <d:Description i:nil='true'/>
177
+ <d:DisplayName>
178
+ <b:LocalizedLabels>
179
+ <b:LocalizedLabel>
180
+ <d:MetadataId>cd2eb1d5-438b-41e8-b422-fe738c48b518</d:MetadataId>
181
+ <b:Label>Owning User</b:Label>
182
+ <b:LanguageCode>1033</b:LanguageCode>
183
+ </b:LocalizedLabel>
184
+ </b:LocalizedLabels>
185
+ <b:UserLocalizedLabel>
186
+ <d:MetadataId>cd2eb1d5-438b-41e8-b422-fe738c48b518</d:MetadataId>
187
+ <b:Label>Owning User</b:Label>
188
+ <b:LanguageCode>1033</b:LanguageCode>
189
+ </b:UserLocalizedLabel>
190
+ </d:DisplayName>
191
+ <d:IsCustomAttribute i:nil='true'/>
192
+ <d:LogicalName>owninguser</d:LogicalName>
193
+ <d:RequiredLevel>
194
+ <b:CanBeChanged>false</b:CanBeChanged>
195
+ <b:ManagedPropertyLogicalName>canmodifyrequirementlevelsettings</b:ManagedPropertyLogicalName>
196
+ <b:Value>None</b:Value>
197
+ </d:RequiredLevel>
198
+ <d:AttributeTypeName xmlns:e='http://schemas.microsoft.com/xrm/2013/Metadata'>
199
+ <e:Value>LookupType</e:Value>
200
+ </d:AttributeTypeName>
201
+ <d:Targets i:nil='true' xmlns:e='http://schemas.microsoft.com/2003/10/Serialization/Arrays'/>
202
+ </d:AttributeMetadata>
203
+ </d:Attributes>
204
+ <d:Description i:nil='true'/>
205
+ <d:DisplayName i:nil='true'/>
206
+ <d:LogicalName>annotation</d:LogicalName>
207
+ <d:ObjectTypeCode i:nil='true'/>
208
+ </b:EntityMetadata>
209
+ </c:value>
210
+ </b:KeyValuePairOfstringanyType>
211
+ </b:Results>
212
+ </ExecuteResult>
213
+ </ExecuteResponse>
214
+ </s:Body>
215
+ </s:Envelope>
@@ -12,13 +12,13 @@ describe DynamicsCRM::Client do
12
12
  context "Online" do
13
13
  it "authenticates with username and password" do
14
14
 
15
- subject.stub(:post).and_return(fixture("request_security_token_response"))
15
+ allow(subject).to receive(:post).and_return(fixture("request_security_token_response"))
16
16
 
17
17
  subject.authenticate('testing', 'password')
18
18
 
19
- subject.instance_variable_get("@security_token0").should start_with("tMFpDJbJHcZnRVuby5cYmRbCJo2OgOFLEOrUHj+wz")
20
- subject.instance_variable_get("@security_token1").should start_with("CX7BFgRnW75tE6GiuRICjeVDV+6q4KDMKLyKmKe9A8U")
21
- subject.instance_variable_get("@key_identifier").should == "D3xjUG3HGaQuKyuGdTWuf6547Lo="
19
+ expect(subject.instance_variable_get("@security_token0")).to start_with("tMFpDJbJHcZnRVuby5cYmRbCJo2OgOFLEOrUHj+wz")
20
+ expect(subject.instance_variable_get("@security_token1")).to start_with("CX7BFgRnW75tE6GiuRICjeVDV+6q4KDMKLyKmKe9A8U")
21
+ expect(subject.instance_variable_get("@key_identifier")).to eq("D3xjUG3HGaQuKyuGdTWuf6547Lo=")
22
22
  end
23
23
 
24
24
  # This is only method in this suite that actually sends a POST message to Dynamics.
@@ -28,9 +28,9 @@ describe DynamicsCRM::Client do
28
28
  subject.authenticate('testuser@orgnam.onmicrosoft.com', 'qwerty')
29
29
  fail("Expected Fault to be raised")
30
30
  rescue DynamicsCRM::XML::Fault => f
31
- f.code.should == "S:Sender"
32
- f.subcode.should == "wst:FailedAuthentication"
33
- f.reason.should == "Authentication Failure"
31
+ expect(f.code).to eq("S:Sender")
32
+ expect(f.subcode).to eq("wst:FailedAuthentication")
33
+ expect(f.reason).to eq("Authentication Failure")
34
34
  end
35
35
  end
36
36
  end
@@ -40,17 +40,17 @@ describe DynamicsCRM::Client do
40
40
 
41
41
  it "authenticates with username and password" do
42
42
 
43
- subject.stub(:post).and_return(fixture("request_security_token_response_onpremise"))
43
+ allow(subject).to receive(:post).and_return(fixture("request_security_token_response_onpremise"))
44
44
 
45
45
  subject.authenticate('testing', 'password')
46
46
 
47
- subject.instance_variable_get("@security_token0").should start_with("ydfdQsDU9ow4XhoBi+0+n+/9Z7Dvfi")
48
- subject.instance_variable_get("@security_token1").should start_with("GcCk8ivhLAAPEbQI8qScynWLReTWE0AC5")
49
- subject.instance_variable_get("@key_identifier").should == "_ed121435-64ea-45b0-9b15-e5769afdb746"
47
+ expect(subject.instance_variable_get("@security_token0")).to start_with("ydfdQsDU9ow4XhoBi+0+n+/9Z7Dvfi")
48
+ expect(subject.instance_variable_get("@security_token1")).to start_with("GcCk8ivhLAAPEbQI8qScynWLReTWE0AC5")
49
+ expect(subject.instance_variable_get("@key_identifier")).to eq("_ed121435-64ea-45b0-9b15-e5769afdb746")
50
50
 
51
- subject.instance_variable_get("@cert_issuer_name").strip.should start_with("SERIALNUMBER=12369287, CN=Go Daddy Secure")
52
- subject.instance_variable_get("@cert_serial_number").should == "112094107365XXXXX"
53
- subject.instance_variable_get("@server_secret").should == "XZwQpJKfAy00NNWU1RwdtDpVyW/nfabuCq4H38GgKrM="
51
+ expect(subject.instance_variable_get("@cert_issuer_name").strip).to start_with("SERIALNUMBER=12369287, CN=Go Daddy Secure")
52
+ expect(subject.instance_variable_get("@cert_serial_number")).to eq("112094107365XXXXX")
53
+ expect(subject.instance_variable_get("@server_secret")).to eq("XZwQpJKfAy00NNWU1RwdtDpVyW/nfabuCq4H38GgKrM=")
54
54
  end
55
55
  end
56
56
 
@@ -58,16 +58,16 @@ describe DynamicsCRM::Client do
58
58
 
59
59
  describe "#retrieve" do
60
60
  before(:each) do
61
- subject.stub(:post).and_return(fixture("retrieve_account_all_columns"))
61
+ allow(subject).to receive(:post).and_return(fixture("retrieve_account_all_columns"))
62
62
  end
63
63
 
64
64
  let(:result) { subject.retrieve("account", "93f0325c-a592-e311-b7f3-6c3be5a8a0c8") }
65
65
 
66
66
  it "retrieves object by id and acts as hash" do
67
- result.should be_a(DynamicsCRM::Response::RetrieveResult)
68
- result.type.should == "account"
69
- result.id.should == "93f0325c-a592-e311-b7f3-6c3be5a8a0c8"
70
- result.name.should == "Adventure Works (sample)"
67
+ expect(result).to be_a(DynamicsCRM::Response::RetrieveResult)
68
+ expect(result.type).to eq("account")
69
+ expect(result.id).to eq("93f0325c-a592-e311-b7f3-6c3be5a8a0c8")
70
+ expect(result.name).to eq("Adventure Works (sample)")
71
71
  end
72
72
 
73
73
  it "exposes entity object" do
@@ -87,11 +87,11 @@ describe DynamicsCRM::Client do
87
87
  describe "#retrieve_multiple" do
88
88
  it "retrieves multiple entities by criteria" do
89
89
 
90
- subject.stub(:post).and_return(fixture("retrieve_multiple_result"))
90
+ allow(subject).to receive(:post).and_return(fixture("retrieve_multiple_result"))
91
91
 
92
92
  result = subject.retrieve_multiple("account", ["name", "Equal", "Test Account"], columns=[])
93
93
 
94
- result.should be_a(DynamicsCRM::Response::RetrieveMultipleResult)
94
+ expect(result).to be_a(DynamicsCRM::Response::RetrieveMultipleResult)
95
95
 
96
96
  expect(result['EntityName']).to eq('account')
97
97
  expect(result['MinActiveRowVersion']).to eq(-1)
@@ -100,31 +100,31 @@ describe DynamicsCRM::Client do
100
100
  expect(result['TotalRecordCount']).to eq(-1)
101
101
  expect(result['TotalRecordCountLimitExceeded']).to eq(false)
102
102
 
103
- result.entities.size.should == 3
103
+ expect(result.entities.size).to eq(3)
104
104
  entities = result.entities
105
105
 
106
106
  entities[0].logical_name == "account"
107
- entities[0].id.should == "7bf2e032-ad92-e311-9752-6c3be5a87df0"
108
- entities[0].attributes["accountid"].should == "7bf2e032-ad92-e311-9752-6c3be5a87df0"
107
+ expect(entities[0].id).to eq("7bf2e032-ad92-e311-9752-6c3be5a87df0")
108
+ expect(entities[0].attributes["accountid"]).to eq("7bf2e032-ad92-e311-9752-6c3be5a87df0")
109
109
 
110
- entities[1].attributes["accountid"].should == "dbe9d7c9-2c98-e311-9752-6c3be5a87df0"
111
- entities[2].attributes["accountid"].should == "8ff0325c-a592-e311-b7f3-6c3be5a8a0c8"
110
+ expect(entities[1].attributes["accountid"]).to eq("dbe9d7c9-2c98-e311-9752-6c3be5a87df0")
111
+ expect(entities[2].attributes["accountid"]).to eq("8ff0325c-a592-e311-b7f3-6c3be5a8a0c8")
112
112
  end
113
113
  end
114
114
 
115
115
  describe "#retrieve_attachments" do
116
116
  it "retrieves document records from annotation object" do
117
- subject.stub(:post).and_return(fixture("retrieve_multiple_result"))
117
+ allow(subject).to receive(:post).and_return(fixture("retrieve_multiple_result"))
118
118
 
119
119
  result = subject.retrieve_attachments("93f0325c-a592-e311-b7f3-6c3be5a8a0c8")
120
- result.should be_a(DynamicsCRM::Response::RetrieveMultipleResult)
120
+ expect(result).to be_a(DynamicsCRM::Response::RetrieveMultipleResult)
121
121
  end
122
122
  end
123
123
 
124
124
  describe "#fetch" do
125
125
  it "uses FetchXML to retrieve multiple" do
126
126
 
127
- subject.stub(:post).and_return(fixture("fetch_xml_response"))
127
+ allow(subject).to receive(:post).and_return(fixture("fetch_xml_response"))
128
128
 
129
129
  xml = %Q{
130
130
  <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
@@ -143,7 +143,7 @@ describe DynamicsCRM::Client do
143
143
  }
144
144
 
145
145
  entity_collection = subject.fetch(xml)
146
- entity_collection.should be_a(DynamicsCRM::XML::EntityCollection)
146
+ expect(entity_collection).to be_a(DynamicsCRM::XML::EntityCollection)
147
147
 
148
148
  expect(entity_collection.entity_name).to eq('new_tinderboxdocument')
149
149
  expect(entity_collection.min_active_row_version).to eq(-1)
@@ -155,10 +155,10 @@ describe DynamicsCRM::Client do
155
155
  expect(entity_collection.entities.size).to eq(3)
156
156
 
157
157
  entity = entity_collection.entities.first
158
- entity.id.should == "9c27cf91-ada3-e311-b64f-6c3be5a87df0"
159
- entity.logical_name.should == "new_tinderboxdocument"
160
- entity.attributes["new_tinderboxdocumentid"].should == entity.id
161
- entity.attributes["new_name"].should == "6 orders of Product SKU JJ202"
158
+ expect(entity.id).to eq("9c27cf91-ada3-e311-b64f-6c3be5a87df0")
159
+ expect(entity.logical_name).to eq("new_tinderboxdocument")
160
+ expect(entity.attributes["new_tinderboxdocumentid"]).to eq(entity.id)
161
+ expect(entity.attributes["new_name"]).to eq("6 orders of Product SKU JJ202")
162
162
  end
163
163
  end
164
164
 
@@ -166,13 +166,41 @@ describe DynamicsCRM::Client do
166
166
  describe "#create" do
167
167
  it "creates new entity with parameters" do
168
168
 
169
- subject.stub(:post).and_return(fixture("create_response"))
169
+ allow(subject).to receive(:post).and_return(fixture("create_response"))
170
170
 
171
171
  result = subject.create("account", {name: "Adventure Works"})
172
172
 
173
- result.should be_a(DynamicsCRM::Response::CreateResult)
174
- result.id.should == "c4944f99-b5a0-e311-b64f-6c3be5a87df0"
175
- result.Id.should == "c4944f99-b5a0-e311-b64f-6c3be5a87df0"
173
+ expect(result).to be_a(DynamicsCRM::Response::CreateResult)
174
+ expect(result.id).to eq("c4944f99-b5a0-e311-b64f-6c3be5a87df0")
175
+ expect(result.Id).to eq("c4944f99-b5a0-e311-b64f-6c3be5a87df0")
176
+ end
177
+
178
+ it "creates new entity with custom fields and relationship" do
179
+
180
+ params = {
181
+ :tndrbox_id => 929177,
182
+ :tndrbox_name => "TEST",
183
+ :tndrbox_description => "",
184
+ :tndrbox_status => "Draft",
185
+ :tndrbox_views => 0,
186
+ :tndrbox_category => nil,
187
+ "tndrbox_opportunity_id" => {
188
+ :id => "71a4a3af-d7ab-e411-80c7-00155dd44307",
189
+ :logical_name => "opportunity"
190
+ },
191
+ :tndrbox_value => {
192
+ :value => 0.0,
193
+ :type => "Money"
194
+ }
195
+ }
196
+
197
+ allow(subject).to receive(:post).and_return(fixture("create_response"))
198
+
199
+ result = subject.create('opportunity', params)
200
+
201
+ expect(result).to be_a(DynamicsCRM::Response::CreateResult)
202
+ expect(result.id).to eq("c4944f99-b5a0-e311-b64f-6c3be5a87df0")
203
+ expect(result.Id).to eq("c4944f99-b5a0-e311-b64f-6c3be5a87df0")
176
204
  end
177
205
  end
178
206
 
@@ -181,7 +209,7 @@ describe DynamicsCRM::Client do
181
209
 
182
210
  file = Tempfile.new(["sample-file", "pdf"])
183
211
 
184
- subject.should_receive(:create).with("annotation", {
212
+ expect(subject).to receive(:create).with("annotation", {
185
213
  objectid: {id: "f4944f99-b5a0-e311-b64f-6c3be5a87df0", logical_name: "opportunity"},
186
214
  subject: "Sample Subject",
187
215
  notetext: "Post message",
@@ -206,22 +234,22 @@ describe DynamicsCRM::Client do
206
234
  describe "#update" do
207
235
  it "updates entity by id" do
208
236
 
209
- subject.stub(:post).and_return(fixture("update_response"))
237
+ allow(subject).to receive(:post).and_return(fixture("update_response"))
210
238
 
211
239
  result = subject.update("account", "c4944f99-b5a0-e311-b64f-6c3be5a87df0", {name: "Adventure Park"})
212
240
 
213
- result.should be_a(DynamicsCRM::Response::UpdateResponse)
241
+ expect(result).to be_a(DynamicsCRM::Response::UpdateResponse)
214
242
  end
215
243
  end
216
244
 
217
245
  describe "#delete" do
218
246
  it "deletes entity by id" do
219
247
 
220
- subject.stub(:post).and_return(fixture("update_response"))
248
+ allow(subject).to receive(:post).and_return(fixture("update_response"))
221
249
 
222
250
  result = subject.delete("account", "c4944f99-b5a0-e311-b64f-6c3be5a87df0")
223
251
 
224
- result.should be_a(DynamicsCRM::Response::DeleteResponse)
252
+ expect(result).to be_a(DynamicsCRM::Response::DeleteResponse)
225
253
  end
226
254
  end
227
255
 
@@ -230,53 +258,53 @@ describe DynamicsCRM::Client do
230
258
  describe "#retrieve_all_entities" do
231
259
  it "retrieve entity list" do
232
260
 
233
- subject.stub(:post).and_return(fixture("retrieve_all_entities"))
261
+ allow(subject).to receive(:post).and_return(fixture("retrieve_all_entities"))
234
262
 
235
263
  result = subject.retrieve_all_entities
236
264
 
237
- result.should be_a(DynamicsCRM::Metadata::RetrieveAllEntitiesResponse)
238
- result.entities.should_not be_nil
265
+ expect(result).to be_a(DynamicsCRM::Metadata::RetrieveAllEntitiesResponse)
266
+ expect(result.entities).not_to be_nil
239
267
 
240
268
  entities = result.entities
241
- entities.size.should == 3
269
+ expect(entities.size).to eq(3)
242
270
 
243
- entities[0].LogicalName.should == "opportunity"
244
- entities[1].LogicalName.should == "new_tinderboxdocument"
245
- entities[2].LogicalName.should == "new_tinderboxcontent"
271
+ expect(entities[0].LogicalName).to eq("opportunity")
272
+ expect(entities[1].LogicalName).to eq("new_tinderboxdocument")
273
+ expect(entities[2].LogicalName).to eq("new_tinderboxcontent")
246
274
  end
247
275
  end
248
276
 
249
277
  describe "#retrieve_entity" do
250
278
  it "retrieve entity metadata" do
251
279
 
252
- subject.stub(:post).and_return(fixture("retrieve_entity_response"))
280
+ allow(subject).to receive(:post).and_return(fixture("retrieve_entity_response"))
253
281
 
254
282
  result = subject.retrieve_entity("opportunity")
255
283
 
256
- result.should be_a(DynamicsCRM::Metadata::RetrieveEntityResponse)
257
- result.entity.should_not be_nil
284
+ expect(result).to be_a(DynamicsCRM::Metadata::RetrieveEntityResponse)
285
+ expect(result.entity).not_to be_nil
258
286
  entity = result.entity
259
- entity.should be_a(DynamicsCRM::Metadata::EntityMetadata)
287
+ expect(entity).to be_a(DynamicsCRM::Metadata::EntityMetadata)
260
288
 
261
- entity.LogicalName.should == "opportunity"
262
- entity.PrimaryIdAttribute.should == "opportunityid"
263
- entity.PrimaryNameAttribute.should == "name"
289
+ expect(entity.LogicalName).to eq("opportunity")
290
+ expect(entity.PrimaryIdAttribute).to eq("opportunityid")
291
+ expect(entity.PrimaryNameAttribute).to eq("name")
264
292
  end
265
293
  end
266
294
 
267
295
  describe "#retrieve_attribute" do
268
296
  it "retrieve attribute metadata" do
269
297
 
270
- subject.stub(:post).and_return(fixture("retrieve_attribute_response"))
298
+ allow(subject).to receive(:post).and_return(fixture("retrieve_attribute_response"))
271
299
 
272
300
  result = subject.retrieve_attribute("new_tinderboxdocument", "new_value")
273
301
 
274
- result.should be_a(DynamicsCRM::Metadata::RetrieveAttributeResponse)
275
- result.attribute.should_not be_nil
302
+ expect(result).to be_a(DynamicsCRM::Metadata::RetrieveAttributeResponse)
303
+ expect(result.attribute).not_to be_nil
276
304
  attribute = result.attribute
277
305
 
278
- attribute.EntityLogicalName.should == "new_tinderboxdocument"
279
- attribute.LogicalName.should == "new_value"
306
+ expect(attribute.EntityLogicalName).to eq("new_tinderboxdocument")
307
+ expect(attribute.LogicalName).to eq("new_value")
280
308
  end
281
309
  end
282
310
 
@@ -288,7 +316,7 @@ describe DynamicsCRM::Client do
288
316
 
289
317
  describe "#associate" do
290
318
  it "associates contacts with account" do
291
- subject.stub(:post).and_return(fixture("associate_response"))
319
+ allow(subject).to receive(:post).and_return(fixture("associate_response"))
292
320
 
293
321
  subject.associate("account", "7BF2E032-AD92-E311-9752-6C3BE5A87DF0", "contact_customer_accounts", contacts)
294
322
  end
@@ -296,33 +324,104 @@ describe DynamicsCRM::Client do
296
324
 
297
325
  describe "#disassociate" do
298
326
  it "disassociates contacts with accounts" do
299
- subject.stub(:post).and_return(fixture("disassociate_response"))
327
+ allow(subject).to receive(:post).and_return(fixture("disassociate_response"))
300
328
 
301
329
  subject.disassociate("account", "7BF2E032-AD92-E311-9752-6C3BE5A87DF0", "contact_customer_accounts", contacts)
302
330
  end
303
331
  end
304
332
  end
305
333
 
334
+ describe "#retrieve_metadata_changes" do
335
+ it "retrieves entity metadata" do
336
+ allow(subject).to receive(:post).and_return(fixture("retrieve_metadata_changes_response"))
337
+
338
+ entity_filter = DynamicsCRM::Metadata::FilterExpression.new('Or')
339
+ entity_filter.add_condition(['SchemaName', 'Equals', 'Contact'])
340
+ entity_filter.add_condition(['SchemaName', 'Equals', 'Annotation'])
341
+ entity_filter.add_condition(['SchemaName', 'Equals', 'Incident'])
342
+ entity_properties = DynamicsCRM::Metadata::PropertiesExpression.new(['Attributes'])
343
+
344
+ attribute_filter = DynamicsCRM::Metadata::FilterExpression.new('And')
345
+ attribute_filter.add_condition(['IsCustomAttribute', 'Equals', false])
346
+ attribute_properties = DynamicsCRM::Metadata::PropertiesExpression.new(['LogicalName', 'AttributeType', 'AttributeOf', 'DisplayName', 'RequiredLevel'])
347
+ attribute_query = DynamicsCRM::Metadata::AttributeQueryExpression.new(attribute_filter, attribute_properties)
348
+
349
+ entity_query = DynamicsCRM::Metadata::EntityQueryExpression.new({
350
+ criteria: entity_filter,
351
+ properties: entity_properties,
352
+ attribute_query: attribute_query
353
+ })
354
+
355
+ result = subject.retrieve_metadata_changes(entity_query)
356
+ expect(result).to be_a(DynamicsCRM::Metadata::RetrieveMetadataChangesResponse)
357
+ entities = result.entities
358
+ expect(entities).not_to be_nil
359
+ expect(entities.size).to eq(3)
360
+
361
+ attributes = entities[0].attributes
362
+ expect(attributes.size).to eq(2)
363
+ attribute = attributes.first
364
+ expect(attribute.logical_name).to eq("contactid")
365
+ expect(attribute.attribute_of).to be_empty
366
+ expect(attribute.type).to eq("Lookup")
367
+ expect(attribute.display_name).to eq("Contact")
368
+ expect(attribute.required_level).to eq("None")
369
+
370
+ attributes = entities[1].attributes
371
+ expect(attributes.size).to eq(2)
372
+ attribute = attributes.first
373
+ expect(attribute.logical_name).to eq("customertypecodename")
374
+ expect(attribute.attribute_of).to eq("customertypecode")
375
+ expect(attribute.type).to eq("Virtual")
376
+ expect(attribute.display_name).to be_empty
377
+ expect(attribute.required_level).to eq("None")
378
+
379
+ attributes = entities[2].attributes
380
+ expect(attributes.size).to eq(2)
381
+ attribute = attributes.first
382
+ expect(attribute.logical_name).to eq("createdonbehalfbyyominame")
383
+ expect(attribute.attribute_of).to eq("createdonbehalfby")
384
+ expect(attribute.type).to eq("String")
385
+ expect(attribute.display_name).to be_empty
386
+ expect(attribute.required_level).to eq("None")
387
+ end
388
+ end
389
+
306
390
  describe "#who_am_i" do
307
391
  it "returns user information" do
308
- subject.stub(:post).and_return(fixture("who_am_i_result"))
392
+ allow(subject).to receive(:post).and_return(fixture("who_am_i_result"))
309
393
 
310
394
  response = subject.who_am_i
311
- response.UserId.should == "1bfa3886-df7e-468c-8435-b5adfb0441ed"
312
- response.BusinessUnitId.should == "4e87d619-838a-e311-89a7-6c3be5a80184"
313
- response.OrganizationId.should == "0140d597-e270-494a-89e1-bd0b43774e50"
395
+ expect(response.UserId).to eq("1bfa3886-df7e-468c-8435-b5adfb0441ed")
396
+ expect(response.BusinessUnitId).to eq("4e87d619-838a-e311-89a7-6c3be5a80184")
397
+ expect(response.OrganizationId).to eq("0140d597-e270-494a-89e1-bd0b43774e50")
314
398
  end
315
399
  end
316
400
 
317
401
  describe "#load_entity" do
318
402
  it "returns Model::Opportunity" do
319
403
  response = subject.load_entity("opportunity", "c4944f99-b5a0-e311-b64f-6c3be5a87df0")
320
- response.should be_a(DynamicsCRM::Model::Opportunity)
404
+ expect(response).to be_a(DynamicsCRM::Model::Opportunity)
321
405
  end
322
406
 
323
407
  it "returns Model::Entity" do
324
408
  response = subject.load_entity("account", "c4944f99-b5a0-e311-b64f-6c3be5a87df0")
325
- response.should be_a(DynamicsCRM::Model::Entity)
409
+ expect(response).to be_a(DynamicsCRM::Model::Entity)
410
+ end
411
+ end
412
+
413
+ describe "#determine_region" do
414
+ context "Client receives only hostname" do
415
+ it "return the correct region" do
416
+ client = DynamicsCRM::Client.new(hostname: 'xunda.api.crm2.dynamics.com')
417
+ expect(client.region).to eq('urn:crmsam:dynamics.com')
418
+ end
419
+ end
420
+ context "Client receives only organization_name" do
421
+ it "return the correct region" do
422
+ client = DynamicsCRM::Client.new(organization_name: 'xunda')
423
+ expect(client.region).to eq('urn:crmna:dynamics.com')
424
+ end
326
425
  end
327
426
  end
328
427