soapforce 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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