dynamics_crm 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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