soapforce 0.1.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.
data/soapforce.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'soapforce/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "soapforce"
8
+ gem.version = Soapforce::VERSION
9
+ gem.authors = ["Joe Heth"]
10
+ gem.email = ["joeheth@gmail.com"]
11
+ gem.description = %q{A ruby client for the Salesforce SOAP API based on Savon.}
12
+ gem.summary = %q{Wraps Savon with helper methods and custom types for interacting with the Salesforce SOAP API.}
13
+ gem.homepage = "https://github.com/TinderBox/soapforce"
14
+
15
+ ignores = File.readlines('.gitignore').grep(/\S+/).map(&:chomp)
16
+ dotfiles = %w[.gitignore .travis.yml]
17
+
18
+ all_files_without_ignores = Dir['**/*'].reject { |f|
19
+ File.directory?(f) || ignores.any? { |i| File.fnmatch(i, f) }
20
+ }
21
+
22
+ gem.files = (all_files_without_ignores + dotfiles).sort
23
+
24
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
25
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
26
+ gem.require_paths = ["lib"]
27
+
28
+ gem.add_dependency("savon", "~>2.3.0")
29
+
30
+ gem.add_development_dependency 'rspec', '~> 2.14.0'
31
+ gem.add_development_dependency 'webmock', '~> 1.13.0'
32
+ gem.add_development_dependency 'simplecov', '~> 0.7.1'
33
+ end
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <createResponse>
5
+ <result>
6
+ <id>006A000000LbiizIAB</id>
7
+ <success>true</success>
8
+ </result>
9
+ </createResponse>
10
+ </soapenv:Body>
11
+ </soapenv:Envelope>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <deleteResponse>
5
+ <result>
6
+ <id>006A000000LbiizIAB</id>
7
+ <success>true</success>
8
+ </result>
9
+ </deleteResponse>
10
+ </soapenv:Body>
11
+ </soapenv:Envelope>
@@ -0,0 +1,55 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3
+ <soapenv:Body>
4
+ <describeGlobalResponse>
5
+ <result>
6
+ <encoding>UTF-8</encoding>
7
+ <maxBatchSize>200</maxBatchSize>
8
+ <sobjects>
9
+ <activateable>false</activateable>
10
+ <createable>true</createable>
11
+ <custom>false</custom>
12
+ <customSetting>false</customSetting>
13
+ <deletable>true</deletable>
14
+ <deprecatedAndHidden>false</deprecatedAndHidden>
15
+ <feedEnabled>true</feedEnabled>
16
+ <keyPrefix>001</keyPrefix>
17
+ <label>Account</label>
18
+ <labelPlural>Accounts</labelPlural>
19
+ <layoutable>true</layoutable>
20
+ <mergeable>true</mergeable>
21
+ <name>Account</name>
22
+ <queryable>true</queryable>
23
+ <replicateable>true</replicateable>
24
+ <retrieveable>true</retrieveable>
25
+ <searchable>true</searchable>
26
+ <triggerable>true</triggerable>
27
+ <undeletable>true</undeletable>
28
+ <updateable>true</updateable>
29
+ </sobjects>
30
+ <sobjects>
31
+ <activateable>false</activateable>
32
+ <createable>true</createable>
33
+ <custom>false</custom>
34
+ <customSetting>false</customSetting>
35
+ <deletable>true</deletable>
36
+ <deprecatedAndHidden>false</deprecatedAndHidden>
37
+ <feedEnabled>false</feedEnabled>
38
+ <keyPrefix>02Z</keyPrefix>
39
+ <label>Account Contact Role</label>
40
+ <labelPlural>Account Contact Role</labelPlural>
41
+ <layoutable>false</layoutable>
42
+ <mergeable>false</mergeable>
43
+ <name>AccountContactRole</name>
44
+ <queryable>true</queryable>
45
+ <replicateable>true</replicateable>
46
+ <retrieveable>true</retrieveable>
47
+ <searchable>false</searchable>
48
+ <triggerable>false</triggerable>
49
+ <undeletable>false</undeletable>
50
+ <updateable>true</updateable>
51
+ </sobjects>
52
+ </result>
53
+ </describeGlobalResponse>
54
+ </soapenv:Body>
55
+ </soapenv:Envelope>
@@ -0,0 +1,9 @@
1
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <soapenv:Body>
3
+ <describeSObjectResponse>
4
+ <result>
5
+ </result>
6
+ </describeSObjectResponse>
7
+ </soapenv:Body>
8
+ </soapenv:Envelope>
9
+
@@ -0,0 +1,9 @@
1
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <soapenv:Body>
3
+ <describeSObjectsResponse>
4
+ <result>
5
+ </result>
6
+ </describeSObjectsResponse>
7
+ </soapenv:Body>
8
+ </soapenv:Envelope>
9
+
@@ -0,0 +1,32 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3
+ <soapenv:Body>
4
+ <getUserInfoResponse>
5
+ <result>
6
+ <accessibilityMode>false</accessibilityMode>
7
+ <currencySymbol>$</currencySymbol>
8
+ <orgAttachmentFileSizeLimit>5242880</orgAttachmentFileSizeLimit>
9
+ <orgDefaultCurrencyIsoCode>USD</orgDefaultCurrencyIsoCode>
10
+ <orgDisallowHtmlAttachments>false</orgDisallowHtmlAttachments>
11
+ <orgHasPersonAccounts>false</orgHasPersonAccounts>
12
+ <organizationId>00DA0000000YpZ4MAK</organizationId>
13
+ <organizationMultiCurrency>false</organizationMultiCurrency>
14
+ <organizationName>Developer</organizationName>
15
+ <profileId>00eA0000000AAAAIA2</profileId>
16
+ <roleId xsi:nil="true"/>
17
+ <sessionSecondsValid>7200</sessionSecondsValid>
18
+ <userDefaultCurrencyIsoCode xsi:nil="true"/>
19
+ <userEmail>johndoe@email.com</userEmail>
20
+ <userFullName>John Doe</userFullName>
21
+ <userId>005A000000AAAAY</userId>
22
+ <userLanguage>en_US</userLanguage>
23
+ <userLocale>en_US</userLocale>
24
+ <userName>john.doe@email.com</userName>
25
+ <userTimeZone>America/Panama</userTimeZone>
26
+ <userType>Standard</userType>
27
+ <userUiSkin>Theme3</userUiSkin>
28
+ </result>
29
+ </getUserInfoResponse>
30
+ </soapenv:Body>
31
+ </soapenv:Envelope>
32
+
@@ -0,0 +1,39 @@
1
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <soapenv:Body>
3
+ <loginResponse>
4
+ <result>
5
+ <metadataServerUrl>https://na7.salesforce.com/services/Soap/m/28.0/00DA0000000YpZ4</metadataServerUrl>
6
+ <passwordExpired>false</passwordExpired>
7
+ <sandbox>false</sandbox>
8
+ <serverUrl>https://na7.salesforce.com/services/Soap/u/28.0/00DA0000000YpZ4</serverUrl>
9
+ <sessionId>00DA0000000YpZ4!ARAAQEH.613sgjdpLDPsev9EBTxM0PMhEzbaCE505DYFCSm8tBkdDBl.NFsmPEISjp7Ccd.t9BTTFa1DRmtbxkikZPI8FqDj</sessionId>
10
+ <userId>005A000000AAAAAIAY</userId>
11
+ <userInfo>
12
+ <accessibilityMode>false</accessibilityMode>
13
+ <currencySymbol>$</currencySymbol>
14
+ <orgAttachmentFileSizeLimit>5242880</orgAttachmentFileSizeLimit>
15
+ <orgDefaultCurrencyIsoCode>USD</orgDefaultCurrencyIsoCode>
16
+ <orgDisallowHtmlAttachments>false</orgDisallowHtmlAttachments>
17
+ <orgHasPersonAccounts>false</orgHasPersonAccounts>
18
+ <organizationId>00DA0000000YpZ4MAK</organizationId>
19
+ <organizationMultiCurrency>false</organizationMultiCurrency>
20
+ <organizationName>Developer</organizationName>
21
+ <profileId>00eA0000000AAAAAA2</profileId>
22
+ <roleId xsi:nil="true"/>
23
+ <sessionSecondsValid>7200</sessionSecondsValid>
24
+ <userDefaultCurrencyIsoCode xsi:nil="true"/>
25
+ <userEmail>john.doe@email.com</userEmail>
26
+ <userFullName>John Doe</userFullName>
27
+ <userId>005A000000AAAAAIAY</userId>
28
+ <userLanguage>en_US</userLanguage>
29
+ <userLocale>en_US</userLocale>
30
+ <userName>john.doe@email.com</userName>
31
+ <userTimeZone>America/Panama</userTimeZone>
32
+ <userType>Standard</userType>
33
+ <userUiSkin>Theme3</userUiSkin>
34
+ </userInfo>
35
+ </result>
36
+ </loginResponse>
37
+ </soapenv:Body>
38
+ </soapenv:Envelope>
39
+
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <queryResponse>
5
+ <result xsi:type="QueryResult">
6
+ <done>true</done>
7
+ <queryLocator xsi:nil="true"/>
8
+ <records xsi:type="sf:sObject">
9
+ <sf:type>Organization</sf:type>
10
+ <sf:Id>00DA0000000YpZ4MAK</sf:Id>
11
+ <sf:Id>00DA0000000YpZ4MAK</sf:Id>
12
+ </records>
13
+ <size>1</size>
14
+ </result>
15
+ </queryResponse>
16
+ </soapenv:Body>
17
+ </soapenv:Envelope>
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <queryAllResponse>
5
+ <result xsi:type="QueryResult">
6
+ <done>true</done>
7
+ <queryLocator xsi:nil="true"/>
8
+ <records xsi:type="sf:sObject">
9
+ <sf:type>Opportunity</sf:type>
10
+ <sf:Id>006A000000LZhwNIAT</sf:Id>
11
+ <sf:Id>006A000000LZhwNIAT</sf:Id>
12
+ <sf:Name>Opportunity 1</sf:Name>
13
+ <sf:StageName>Prospecting</sf:StageName>
14
+ </records>
15
+ <records xsi:type="sf:sObject">
16
+ <sf:type>Opportunity</sf:type>
17
+ <sf:Id>006A000000LaF4xIAF</sf:Id>
18
+ <sf:Id>006A000000LaF4xIAF</sf:Id>
19
+ <sf:Name>Opportunity 2</sf:Name>
20
+ <sf:StageName>Value Proposition</sf:StageName>
21
+ </records>
22
+ <size>2</size>
23
+ </result>
24
+ </queryAllResponse>
25
+ </soapenv:Body>
26
+ </soapenv:Envelope>
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <queryMoreResponse>
5
+ <result xsi:type="QueryResult">
6
+ <done>true</done>
7
+ <queryLocator xsi:nil="true"/>
8
+ <records xsi:type="sf:sObject">
9
+ <sf:type>Opportunity</sf:type>
10
+ <sf:Id>006A000000LZhwNIAT</sf:Id>
11
+ <sf:Id>006A000000LZhwNIAT</sf:Id>
12
+ <sf:Name>Opportunity 1</sf:Name>
13
+ <sf:StageName>Prospecting</sf:StageName>
14
+ </records>
15
+ <records xsi:type="sf:sObject">
16
+ <sf:type>Opportunity</sf:type>
17
+ <sf:Id>006A000000LaF4xIAF</sf:Id>
18
+ <sf:Id>006A000000LaF4xIAF</sf:Id>
19
+ <sf:Name>Opportunity 2</sf:Name>
20
+ <sf:StageName>Value Proposition</sf:StageName>
21
+ </records>
22
+ <size>2</size>
23
+ </result>
24
+ </queryMoreResponse>
25
+ </soapenv:Body>
26
+ </soapenv:Envelope>
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <queryResponse>
5
+ <result xsi:type="QueryResult">
6
+ <done>true</done>
7
+ <queryLocator xsi:nil="true"/>
8
+ <records xsi:type="sf:sObject">
9
+ <sf:type>Opportunity</sf:type>
10
+ <sf:Id>006A000000LZhwNIAT</sf:Id>
11
+ <sf:Id>006A000000LZhwNIAT</sf:Id>
12
+ <sf:Name>Opportunity 1</sf:Name>
13
+ <sf:StageName>Prospecting</sf:StageName>
14
+ </records>
15
+ <records xsi:type="sf:sObject">
16
+ <sf:type>Opportunity</sf:type>
17
+ <sf:Id>006A000000LaF4xIAF</sf:Id>
18
+ <sf:Id>006A000000LaF4xIAF</sf:Id>
19
+ <sf:Name>Opportunity 2</sf:Name>
20
+ <sf:StageName>Value Proposition</sf:StageName>
21
+ </records>
22
+ <size>2</size>
23
+ </result>
24
+ </queryResponse>
25
+ </soapenv:Body>
26
+ </soapenv:Envelope>
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:sf="urn:sobject.partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3
+ <soapenv:Body>
4
+ <retrieveResponse>
5
+ <result xsi:type="sf:sObject">
6
+ <sf:type>Opportunity</sf:type>
7
+ <sf:Id>006A000000LbkT5IAJ</sf:Id>
8
+ <sf:Name>SOAPForce Opportunity</sf:Name>
9
+ <sf:Description xsi:nil="true"/>
10
+ <sf:StageName>Prospecting</sf:StageName>
11
+ </result>
12
+ </retrieveResponse>
13
+ </soapenv:Body>
14
+ </soapenv:Envelope>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <searchResponse>
5
+ <result/>
6
+ </searchResponse>
7
+ </soapenv:Body>
8
+ </soapenv:Envelope>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <updateResponse>
5
+ <result>
6
+ <id>006A000000LbiizIAB</id>
7
+ <success>true</success>
8
+ </result>
9
+ </updateResponse>
10
+ </soapenv:Body>
11
+ </soapenv:Envelope>
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com">
3
+ <soapenv:Body>
4
+ <upsertResponse>
5
+ <result>
6
+ <created>true</created>
7
+ <id>006A000000LbiizIAB</id>
8
+ <success>true</success>
9
+ </result>
10
+ <result>
11
+ <created>false</created>
12
+ <id>006A000000LbiizIAB</id>
13
+ <success>true</success>
14
+ </result>
15
+ </upsertResponse>
16
+ </soapenv:Body>
17
+ </soapenv:Envelope>
@@ -0,0 +1,301 @@
1
+ require 'spec_helper'
2
+
3
+ describe Soapforce::Client do
4
+ let(:endpoint) { 'https://na15.salesforce.com' }
5
+
6
+ describe "#operations" do
7
+ it "should return list of operations from the wsdl" do
8
+ subject.operations.should be_a(Array)
9
+ subject.operations.should include(:login, :logout, :query, :create)
10
+ end
11
+ end
12
+
13
+ describe "#login" do
14
+ it "authenticates with username and password_and_token" do
15
+
16
+ body = "<tns:login><tns:username>testing</tns:username><tns:password>password_and_token</tns:password></tns:login>"
17
+ stub = stub_login_request({with_body: body})
18
+ stub.to_return(:status => 200, :body => fixture("login_response")) #, :headers => {})
19
+
20
+ subject.login(username: 'testing', password: 'password_and_token')
21
+ end
22
+
23
+ it "authenticates with session_id and instance_url" do
24
+
25
+ body = "<tns:getUserInfo></tns:getUserInfo>"
26
+ stub = stub_login_request({
27
+ server_url: 'https://na15.salesforce.com',
28
+ headers: {session_id: 'abcde12345'},
29
+ with_body: body}
30
+ )
31
+ stub.to_return(:status => 200, :body => fixture("get_user_info_response"))
32
+
33
+ user_info = subject.login(session_id: 'abcde12345', server_url: 'https://na15.salesforce.com')
34
+
35
+ user_info[:user_email].should == "johndoe@email.com"
36
+ user_info[:user_full_name].should == "John Doe"
37
+ end
38
+
39
+ it "should raise arugment error when no parameters are passed" do
40
+ expect { subject.login(session_id: 'something') }.to raise_error(ArgumentError)
41
+ end
42
+ end
43
+
44
+ describe "list_sobjects" do
45
+ it "should return array of object names" do
46
+
47
+ body = "<tns:describeGlobal></tns:describeGlobal>"
48
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'describe_global_response'})
49
+
50
+ subject.list_sobjects.should == ['Account', 'AccountContactRole']
51
+ end
52
+ end
53
+
54
+ describe "org_id" do
55
+ it "should return organization id" do
56
+
57
+ body = "<tns:query><tns:queryString>select id from Organization</tns:queryString></tns:query>"
58
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'org_id_response'})
59
+
60
+ subject.org_id.should == "00DA0000000YpZ4MAK"
61
+ end
62
+ end
63
+
64
+ describe "#descibeSObject" do
65
+
66
+ it "supports single sobject name" do
67
+
68
+ body = "<tns:describeSObject><tns:sObjectType>Opportunity</tns:sObjectType></tns:describeSObject>"
69
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'describe_s_object_response'})
70
+
71
+ subject.describe("Opportunity")
72
+
73
+ # Hit cache.
74
+ subject.describe("Opportunity")
75
+ end
76
+
77
+ it "supports array of sobject names" do
78
+
79
+ body = "<tns:describeSObjects><tns:sObjectType>Account</tns:sObjectType><tns:sObjectType>Opportunity</tns:sObjectType></tns:describeSObjects>"
80
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'describe_s_objects_response'})
81
+
82
+ subject.describe(["Account", "Opportunity"])
83
+ end
84
+ end
85
+
86
+ describe "#retrieve" do
87
+
88
+ it "should retrieve object by id" do
89
+ fields = {:fields => [{:name => "Id"},{:name => "Name"},{:name => "Description"},{:name => "StageName"}]}
90
+ # retrieve calls describe to get the list of available fields.
91
+ subject.should_receive(:describe).with("Opportunity").and_return(fields)
92
+
93
+ body = "<tns:retrieve><tns:fieldList>Id,Name,Description,StageName</tns:fieldList><tns:sObjectType>Opportunity</tns:sObjectType><tns:ids>006A000000LbkT5IAJ</tns:ids></tns:retrieve>"
94
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'retrieve_response'})
95
+
96
+ sobject = subject.retrieve("Opportunity", "006A000000LbkT5IAJ")
97
+
98
+ sobject.should be_a(Soapforce::SObject)
99
+ sobject.type.should == "Opportunity"
100
+ sobject.Id.should == "006A000000LbkT5IAJ"
101
+ sobject.Name.should == "SOAPForce Opportunity"
102
+ sobject.Description.should be_nil
103
+ sobject.StageName.should == "Prospecting"
104
+ end
105
+ end
106
+
107
+ describe "#find" do
108
+ it "should retrieve object by id" do
109
+
110
+ fields = {:fields => [{:name => "Id"},{:name => "Name"},{:name => "Description"},{:name => "StageName"}]}
111
+ # retrieve calls describe to get the list of available fields.
112
+ subject.should_receive(:describe).with("Opportunity").and_return(fields)
113
+
114
+ body = "<tns:retrieve><tns:fieldList>Id,Name,Description,StageName</tns:fieldList><tns:sObjectType>Opportunity</tns:sObjectType><tns:ids>006A000000LbkT5IAJ</tns:ids></tns:retrieve>"
115
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'retrieve_response'})
116
+
117
+ sobject = subject.find("Opportunity", "006A000000LbkT5IAJ")
118
+
119
+ sobject.should be_a(Soapforce::SObject)
120
+ sobject.type.should == "Opportunity"
121
+ sobject.Id.should == "006A000000LbkT5IAJ"
122
+ sobject.Name.should == "SOAPForce Opportunity"
123
+ sobject.Description.should be_nil
124
+ sobject.StageName.should == "Prospecting"
125
+ end
126
+
127
+ end
128
+
129
+ describe "#find_by_field" do
130
+
131
+ it "should retrieve object by string field" do
132
+ fields = {:fields => [{:name => "Id"},{:name => "Name"},{:name => "Description"},{:name => "StageName"}]}
133
+ # retrieve calls describe to get the list of available fields.
134
+ subject.should_receive(:describe).exactly(2).with("Opportunity").and_return(fields)
135
+
136
+ body = "<tns:query><tns:queryString>Select Id, Name, Description, StageName From Opportunity Where StageName = 'Prospecting'</tns:queryString></tns:query>"
137
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_response'})
138
+
139
+ subject.find_by_field("Opportunity", "Prospecting", "StageName")
140
+ end
141
+
142
+ it "should retrieve object by number field" do
143
+ fields = {:fields => [{:name => "Id"},{:name => "Name"},{:name => "Description"},{:name => "Amount", :type => "double"}]}
144
+ # retrieve calls describe to get the list of available fields.
145
+ subject.should_receive(:describe).exactly(2).with("Opportunity").and_return(fields)
146
+
147
+ body = "<tns:query><tns:queryString>Select Id, Name, Description, Amount From Opportunity Where Amount = 0.0</tns:queryString></tns:query>"
148
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_response'})
149
+
150
+ subject.find_by_field("Opportunity", 0.0, "Amount")
151
+ end
152
+
153
+ end
154
+
155
+ describe "#find_where" do
156
+
157
+ let(:fields) { {:fields => [{:name => "Id"},{:name => "Name"},{:name => "Description"},{:name => "StageName"}]} }
158
+ let(:body) { "<tns:query><tns:queryString>Select Id, Name, Description, StageName From Opportunity Where Id = '006A000000LbkT5IAJ' AND Amount = 0.0</tns:queryString></tns:query>" }
159
+
160
+ after(:each) do
161
+ @result.should be_a(Soapforce::QueryResult)
162
+ @result.size.should == 2
163
+ @result.first.Name == "Opportunity 1"
164
+ @result.last.Name == "Opportunity 2"
165
+ end
166
+
167
+ it "should retrieve records from hash conditions" do
168
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_response'})
169
+ # retrieve calls describe to get the list of available fields.
170
+ subject.should_receive(:describe).with("Opportunity").and_return(fields)
171
+
172
+ @result = subject.find_where("Opportunity", {Id: "006A000000LbkT5IAJ", Amount: 0.0})
173
+ end
174
+
175
+ it "should retrieve records from hash condition using IN clause" do
176
+ body = "<tns:query><tns:queryString>Select Id, Name, Description, StageName From Opportunity Where Id IN ('006A000000LbkT5IAJ', '006A000000AbkTcIAQ')</tns:queryString></tns:query>"
177
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_response'})
178
+
179
+ # retrieve calls describe to get the list of available fields.
180
+ subject.should_receive(:describe).with("Opportunity").and_return(fields)
181
+
182
+ @result = subject.find_where("Opportunity", {Id: ["006A000000LbkT5IAJ", "006A000000AbkTcIAQ"]})
183
+ end
184
+
185
+ it "should retrieve records from string condition" do
186
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_response'})
187
+ # retrieve calls describe to get the list of available fields.
188
+ subject.should_receive(:describe).with("Opportunity").and_return(fields)
189
+
190
+ @result = subject.find_where("Opportunity", "Id = '006A000000LbkT5IAJ' AND Amount = 0.0")
191
+ end
192
+
193
+ it "should retrieve records from string condition and specify fields" do
194
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_response'})
195
+ subject.should_not_receive(:describe)
196
+
197
+ @result = subject.find_where("Opportunity", "Id = '006A000000LbkT5IAJ' AND Amount = 0.0", ["Id", "Name", "Description", "StageName"])
198
+ end
199
+
200
+ end
201
+
202
+ describe "query methods" do
203
+
204
+ after(:each) do
205
+ @result.should be_a(Soapforce::QueryResult)
206
+ @result.size.should == 2
207
+ @result.first.Name == "Opportunity 1"
208
+ @result.last.Name == "Opportunity 2"
209
+ end
210
+
211
+ it "#query" do
212
+ body = "<tns:query><tns:queryString>Select Id, Name, StageName from Opportunity</tns:queryString></tns:query>"
213
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_response'})
214
+
215
+ @result = subject.query("Select Id, Name, StageName from Opportunity")
216
+ end
217
+
218
+ it "#query_all" do
219
+ body = "<tns:queryAll><tns:queryString>Select Id, Name, StageName from Opportunity</tns:queryString></tns:queryAll>"
220
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_all_response'})
221
+
222
+ @result = subject.query_all("Select Id, Name, StageName from Opportunity")
223
+ end
224
+
225
+ it "#query_more" do
226
+ body = "<tns:queryMore><tns:queryLocator>some_locator_string</tns:queryLocator></tns:queryMore>"
227
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'query_more_response'})
228
+
229
+ @result = subject.query_more("some_locator_string")
230
+ end
231
+
232
+ end
233
+
234
+ describe "#search" do
235
+
236
+ it "should return search results" do
237
+
238
+ sosl = "FIND 'Name*' IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead"
239
+
240
+ body = "<tns:search><tns:searchString>#{sosl}</tns:searchString></tns:search>"
241
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'search_response'})
242
+
243
+ subject.search(sosl)
244
+ end
245
+
246
+ end
247
+
248
+ describe "#create" do
249
+ it "should create new object" do
250
+
251
+ body = "<tns:create><tns:sObjects><ins0:type>Opportunity</ins0:type><tns:Name>SOAPForce Opportunity</tns:Name><tns:CloseDate>2013-08-12</tns:CloseDate><tns:StageName>Prospecting</tns:StageName></tns:sObjects></tns:create>"
252
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'create_response'})
253
+
254
+ params = { Name: "SOAPForce Opportunity", CloseDate: '2013-08-12', StageName: 'Prospecting' }
255
+ response = subject.create("Opportunity", params)
256
+
257
+ response[:success].should be_true
258
+ response[:id].should == "006A000000LbiizIAB"
259
+ end
260
+ end
261
+
262
+ describe "#update" do
263
+ it "should update existing object" do
264
+
265
+ body = "<tns:update><tns:sObjects><ins0:type>Opportunity</ins0:type><ins0:Id>003ABCDE</ins0:Id><tns:Name>SOAPForce Opportunity</tns:Name><tns:CloseDate>2013-08-12</tns:CloseDate><tns:StageName>Closed Won</tns:StageName></tns:sObjects></tns:update>"
266
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'update_response'})
267
+
268
+ params = { Id: '003ABCDE', Name: "SOAPForce Opportunity", CloseDate: '2013-08-12', StageName: 'Closed Won' }
269
+ response = subject.update("Opportunity", params)
270
+
271
+ response[:success].should be_true
272
+ response[:id].should == "006A000000LbiizIAB"
273
+ end
274
+ end
275
+
276
+ describe "#upsert" do
277
+ it "should insert new and update existing objects" do
278
+
279
+ body = "<tns:upsert><tns:externalIDFieldName>External_Id__c</tns:externalIDFieldName><tns:sObjects><ins0:type>Opportunity</ins0:type><tns:Name>New Opportunity</tns:Name><tns:CloseDate>2013-08-12</tns:CloseDate><tns:StageName>Prospecting</tns:StageName></tns:sObjects><tns:sObjects><ins0:type>Opportunity</ins0:type><ins0:Id>003ABCDE</ins0:Id><tns:Name>Existing Opportunity</tns:Name><tns:CloseDate>2013-08-12</tns:CloseDate><tns:StageName>Closed Won</tns:StageName></tns:sObjects></tns:upsert>"
280
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'upsert_response'})
281
+
282
+ objects = [
283
+ { Name: "New Opportunity", CloseDate: '2013-08-12', StageName: 'Prospecting' },
284
+ { Id: '003ABCDE', Name: "Existing Opportunity", CloseDate: '2013-08-12', StageName: 'Closed Won' }
285
+ ]
286
+ subject.upsert("Opportunity", "External_Id__c", objects)
287
+ end
288
+ end
289
+
290
+ describe "#delete" do
291
+ it "should delete existing objects" do
292
+ body = "<tns:delete><tns:ids>003ABCDE</tns:ids></tns:delete>"
293
+ stub = stub_api_request(endpoint, {with_body: body, fixture: 'delete_response'})
294
+ response = subject.delete("003ABCDE")
295
+
296
+ response[:success].should be_true
297
+ response[:id].should == "006A000000LbiizIAB"
298
+ end
299
+ end
300
+
301
+ end