metaforce 0.5.3 → 1.0.0a
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/.gitignore +1 -0
- data/.rspec +1 -0
- data/Gemfile +1 -11
- data/LICENSE +22 -0
- data/README.md +91 -96
- data/Rakefile +6 -14
- data/examples/example.rb +51 -0
- data/lib/metaforce/abstract_client.rb +76 -0
- data/lib/metaforce/client.rb +27 -0
- data/lib/metaforce/config.rb +41 -19
- data/lib/metaforce/job/crud.rb +13 -0
- data/lib/metaforce/job/deploy.rb +87 -0
- data/lib/metaforce/job/retrieve.rb +92 -0
- data/lib/metaforce/job.rb +183 -0
- data/lib/metaforce/login.rb +39 -0
- data/lib/metaforce/manifest.rb +18 -93
- data/lib/metaforce/metadata/client/crud.rb +86 -0
- data/lib/metaforce/metadata/client/file.rb +113 -0
- data/lib/metaforce/metadata/client.rb +7 -225
- data/lib/metaforce/services/client.rb +45 -86
- data/lib/metaforce/version.rb +1 -1
- data/lib/metaforce.rb +27 -7
- data/metaforce.gemspec +19 -16
- data/spec/fixtures/package.xml +1 -1
- data/spec/fixtures/payload.zip +0 -0
- data/spec/fixtures/requests/{describe_layout → foo}/invalid_session.xml +0 -0
- data/spec/fixtures/requests/send_email/success.xml +1 -0
- data/spec/lib/client_spec.rb +34 -0
- data/spec/lib/config_spec.rb +8 -50
- data/spec/lib/job/deploy_spec.rb +53 -0
- data/spec/lib/job/retrieve_spec.rb +28 -0
- data/spec/lib/job_spec.rb +95 -0
- data/spec/lib/login_spec.rb +18 -0
- data/spec/lib/manifest_spec.rb +22 -168
- data/spec/lib/metadata/client_spec.rb +84 -179
- data/spec/lib/metaforce_spec.rb +20 -0
- data/spec/lib/services/client_spec.rb +22 -35
- data/spec/spec_helper.rb +24 -3
- data/spec/support/client.rb +38 -0
- data/wsdl/26.0/metadata.xml +4750 -0
- data/wsdl/26.0/partner.xml +3340 -0
- metadata +114 -77
- data/Guardfile +0 -9
- data/bin/metaforce +0 -6
- data/lib/metaforce/core_extensions/string.rb +0 -31
- data/lib/metaforce/core_extensions.rb +0 -1
- data/lib/metaforce/custom_actions.rb +0 -29
- data/lib/metaforce/error.rb +0 -3
- data/lib/metaforce/login_details.rb +0 -28
- data/lib/metaforce/metadata/crud.rb +0 -103
- data/lib/metaforce/metadata/file.rb +0 -74
- data/lib/metaforce/metadata/transaction.rb +0 -100
- data/lib/metaforce/metadata.rb +0 -4
- data/lib/metaforce/rake/deploy.rb +0 -35
- data/lib/metaforce/rake/retrieve.rb +0 -39
- data/lib/metaforce/rake/tests.rb +0 -62
- data/lib/metaforce/rake.rb +0 -43
- data/lib/metaforce/services.rb +0 -1
- data/lib/metaforce/tasks/README.md +0 -62
- data/lib/metaforce/tasks/metaforce.rake +0 -5
- data/lib/metaforce/thor/metaforce.rb +0 -117
- data/lib/metaforce/types.rb +0 -249
- data/spec/.gitignore +0 -1
- data/spec/fixtures/sample/Rakefile +0 -2
- data/spec/fixtures/sample/metaforce.yml +0 -13
- data/spec/fixtures/sample/src/classes/TestClass.cls +0 -2
- data/spec/fixtures/sample/src/classes/TestClass.cls-meta.xml +0 -5
- data/spec/fixtures/sample/src/package.xml +0 -8
- data/spec/lib/core_extensions/string_spec.rb +0 -23
- data/spec/lib/metadata/crud_spec.rb +0 -66
- data/spec/lib/metadata/file_spec.rb +0 -17
- data/spec/lib/metadata/transaction_spec.rb +0 -68
@@ -1,232 +1,14 @@
|
|
1
|
-
require 'metaforce/manifest'
|
2
|
-
require 'savon'
|
3
|
-
require 'zip/zip'
|
4
|
-
require 'base64'
|
5
|
-
require 'tmpdir'
|
6
|
-
|
7
1
|
module Metaforce
|
8
2
|
module Metadata
|
9
|
-
class Client
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
# +options+ should be hash containing the +:username+, +:password+ and
|
14
|
-
# +:security_token+ keys.
|
15
|
-
#
|
16
|
-
# == Examples
|
17
|
-
#
|
18
|
-
# Metaforce::Metadata::Client.new :username => "username",
|
19
|
-
# :password => "password",
|
20
|
-
# :security_token => "security token"
|
21
|
-
def initialize(options=nil)
|
22
|
-
@session = Services::Client.new(options).session
|
23
|
-
@client = Savon::Client.new File.expand_path("../../../../wsdl/#{Metaforce.configuration.api_version}/metadata.xml", __FILE__) do |wsdl|
|
24
|
-
wsdl.endpoint = @session[:metadata_server_url]
|
25
|
-
end
|
26
|
-
@client.http.auth.ssl.verify_mode = :none
|
27
|
-
@header = {
|
28
|
-
"ins0:SessionHeader" => {
|
29
|
-
"ins0:sessionId" => @session[:session_id]
|
30
|
-
}
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
# Specify an array of component types to list.
|
35
|
-
#
|
36
|
-
# == Examples
|
37
|
-
#
|
38
|
-
# # Get a list of apex classes on the server and output the names of each
|
39
|
-
# client.list(:type => "ApexClass").collect { |t| t[:full_name] }
|
40
|
-
# #=> ["al__SObjectPaginatorListenerForTesting", "al__IndexOutOfBoundsException", ... ]
|
41
|
-
#
|
42
|
-
# # Get a list of apex components and apex classes
|
43
|
-
# client.list([{ :type => "CustomObject" }, { :type => "ApexComponent" }])
|
44
|
-
# #=> ["ContractContactRole", "Solution", "Invoice_Statements__c", ... ]
|
45
|
-
def list(queries=[])
|
46
|
-
if queries.is_a?(Symbol)
|
47
|
-
queries = { :type => queries.to_s.camelcase }
|
48
|
-
elsif queries.is_a?(String)
|
49
|
-
queries = { :type => queries }
|
50
|
-
end
|
51
|
-
queries = [ queries ] unless queries.is_a?(Array)
|
52
|
-
response = @client.request(:list_metadata) do |soap|
|
53
|
-
soap.header = @header
|
54
|
-
soap.body = {
|
55
|
-
:queries => queries
|
56
|
-
}
|
57
|
-
end
|
58
|
-
return [] unless response.body[:list_metadata_response]
|
59
|
-
response.body[:list_metadata_response][:result]
|
60
|
-
end
|
61
|
-
|
62
|
-
# Describe the organization's metadata and cache the response
|
63
|
-
#
|
64
|
-
# == Examples
|
65
|
-
#
|
66
|
-
# # List the names of all metadata types
|
67
|
-
# client.describe[:metadata_objects].collect { |t| t[:xml_name] }
|
68
|
-
# #=> ["CustomLabels", "StaticResource", "Scontrol", "ApexComponent", ... ]
|
69
|
-
def describe(version=nil)
|
70
|
-
@describe ||= describe!(version)
|
71
|
-
end
|
72
|
-
|
73
|
-
# See +describe+
|
74
|
-
def describe!(version=nil)
|
75
|
-
response = @client.request(:describe_metadata) do |soap|
|
76
|
-
soap.header = @header
|
77
|
-
soap.body = { :api_version => version } unless version.nil?
|
78
|
-
end
|
79
|
-
@describe = response.body[:describe_metadata_response][:result]
|
80
|
-
end
|
81
|
-
|
82
|
-
# Lists all metadata objects on the org. Same as
|
83
|
-
# +client.describe[:metadata_objects]
|
84
|
-
#
|
85
|
-
# == Examples
|
86
|
-
#
|
87
|
-
# # List the names of all metadata types
|
88
|
-
# client.metadata_objects.collect { |t| t[:xml_name] }
|
89
|
-
# #=> ["CustomLabels", "StaticResource", "Scontrol", "ApexComponent", ... ]
|
90
|
-
def metadata_objects(version=nil)
|
91
|
-
describe(version)[:metadata_objects]
|
92
|
-
end
|
93
|
-
|
94
|
-
# Checks the status of an async result. If type is +:retrieve+ or +:deploy+,
|
95
|
-
# it returns the RetrieveResult or DeployResult, respectively
|
96
|
-
#
|
97
|
-
# == Examples
|
98
|
-
#
|
99
|
-
# client.status('04sU0000000Wx6KIAS')
|
100
|
-
# #=> {:done=>true, :id=>"04sU0000000Wx6KIAS", :state=>"Completed", :state_detail_last_modified_date=>#<DateTime: 2012-02-03T18:30:38+00:00 ((2455961j,66638s,0n),+0s,2299161j)>}
|
101
|
-
def status(ids, type=nil)
|
102
|
-
request = "check_status"
|
103
|
-
request = "check_#{type.to_s}_status" unless type.nil?
|
104
|
-
ids = [ ids ] unless ids.is_a?(Array)
|
105
|
-
|
106
|
-
Metaforce.log("Polling server for status on #{ids.join(', ')}")
|
107
|
-
|
108
|
-
response = @client.request(request.to_sym) do |soap|
|
109
|
-
soap.header = @header
|
110
|
-
soap.body = {
|
111
|
-
:ids => ids
|
112
|
-
}
|
113
|
-
end
|
114
|
-
response.body["#{request}_response".to_sym][:result]
|
115
|
-
end
|
116
|
-
|
117
|
-
# Returns true if the deployment with id id is done, false otherwise
|
118
|
-
#
|
119
|
-
# == Examples
|
120
|
-
#
|
121
|
-
# client.done?('04sU0000000Wx6KIAS')
|
122
|
-
# #=> true
|
123
|
-
def done?(id)
|
124
|
-
self.status(id)[:done] || false
|
125
|
-
end
|
126
|
-
|
127
|
-
# Deploys +path+ to the organisation. +path+ can either be a path to
|
128
|
-
# a directory or a path to a zip file.
|
129
|
-
#
|
130
|
-
# +options+ can contain any of the following keys:
|
131
|
-
#
|
132
|
-
# +options+:
|
133
|
-
# See http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_deploy.htm#deploy_options
|
134
|
-
# for a list of _deploy_options_. Options should be convereted from
|
135
|
-
# camelCase to an :underscored_symbol.
|
136
|
-
#
|
137
|
-
# == Examples
|
138
|
-
#
|
139
|
-
# deploy = client.deploy File.expand_path("myeclipseproj")
|
140
|
-
# #=> #<Metaforce::Transaction:0x1159bd0 @id='04sU0000000Wx6KIAS' @type=:deploy>
|
141
|
-
#
|
142
|
-
# deploy.done?
|
143
|
-
# #=> true
|
144
|
-
#
|
145
|
-
# deploy.status[:state]
|
146
|
-
# #=> "Completed"
|
147
|
-
def deploy(path, options={})
|
148
|
-
if path.is_a?(String)
|
149
|
-
zip_contents = create_deploy_file(path)
|
150
|
-
elsif path.is_a?(File)
|
151
|
-
zip_contents = Base64.encode64(path.read)
|
152
|
-
end
|
153
|
-
|
154
|
-
Metaforce.log('Executing deploy')
|
155
|
-
|
156
|
-
response = @client.request(:deploy) do |soap|
|
157
|
-
soap.header = @header
|
158
|
-
soap.body = {
|
159
|
-
:zip_file => zip_contents,
|
160
|
-
:deploy_options => options[:options] || {}
|
161
|
-
}
|
162
|
-
end
|
163
|
-
Transaction.deployment self, response[:deploy_response][:result][:id]
|
164
|
-
end
|
165
|
-
|
166
|
-
# Performs a retrieve
|
167
|
-
#
|
168
|
-
# See http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_retrieve_request.htm
|
169
|
-
# for a list of _retrieve_request_ options. Options should be convereted from
|
170
|
-
# camelCase to an :underscored_symbol. _retrieve_request_ options should
|
171
|
-
# be specified under the +:options+ key in options.
|
172
|
-
def retrieve(options={})
|
173
|
-
Metaforce.log('Executing retrieve')
|
174
|
-
|
175
|
-
response = @client.request(:retrieve) do |soap|
|
176
|
-
soap.header = @header
|
177
|
-
soap.body = {
|
178
|
-
:retrieve_request => options[:options] || {}
|
179
|
-
}
|
180
|
-
end
|
181
|
-
Transaction.retrieval(self, response[:retrieve_response][:result][:id])
|
182
|
-
end
|
183
|
-
|
184
|
-
# Retrieves files specified in the manifest file (package.xml). Specificy any extra options in +options[:options]+.
|
185
|
-
#
|
186
|
-
# == Examples
|
187
|
-
#
|
188
|
-
# retrieve = client.retrieve_unpackaged File.expand_path("spec/fixtures/sample/src/package.xml")
|
189
|
-
# #=> #<Metaforce::Transaction:0x1159bd0 @id='04sU0000000Wx6KIAS' @type=:retrieve>
|
190
|
-
def retrieve_unpackaged(manifest, options={})
|
191
|
-
if manifest.is_a?(Metaforce::Manifest)
|
192
|
-
package = manifest.to_package
|
193
|
-
elsif manifest.is_a?(String)
|
194
|
-
package = Metaforce::Manifest.new(File.open(manifest).read).to_package
|
195
|
-
end
|
196
|
-
options[:options] = {
|
197
|
-
:api_version => Metaforce.configuration.api_version,
|
198
|
-
:single_package => true,
|
199
|
-
:unpackaged => {
|
200
|
-
:types => package
|
201
|
-
}
|
202
|
-
}.merge(options[:options] || {})
|
203
|
-
retrieve(options)
|
204
|
-
end
|
205
|
-
|
206
|
-
private
|
207
|
-
|
208
|
-
def method_missing(name, *args, &block)
|
209
|
-
if name =~ /^list_(.*)$/ && metadata_objects.any? { |m| m[:xml_name] == $1.camelcase }
|
210
|
-
list("#{$1}".to_sym)
|
211
|
-
else
|
212
|
-
super
|
213
|
-
end
|
214
|
-
end
|
3
|
+
class Client < Metaforce::AbstractClient
|
4
|
+
require 'metaforce/metadata/client/file'
|
5
|
+
require 'metaforce/metadata/client/crud'
|
215
6
|
|
216
|
-
|
217
|
-
|
218
|
-
def create_deploy_file(dir)
|
219
|
-
Dir.mktmpdir do |path|
|
220
|
-
path = File.join path, 'deploy.zip'
|
221
|
-
Zip::ZipFile.open(path, Zip::ZipFile::CREATE) do |zip|
|
222
|
-
Dir["#{dir}/**/**"].each do |file|
|
223
|
-
zip.add(file.sub("#{File.dirname(dir)}/", ''), file)
|
224
|
-
end
|
225
|
-
end
|
226
|
-
Base64.encode64(File.open(path, "rb").read)
|
227
|
-
end
|
228
|
-
end
|
7
|
+
include Metaforce::Metadata::Client::File
|
8
|
+
include Metaforce::Metadata::Client::CRUD
|
229
9
|
|
10
|
+
endpoint :metadata_server_url
|
11
|
+
wsdl Metaforce.configuration.metadata_wsdl
|
230
12
|
end
|
231
13
|
end
|
232
14
|
end
|
@@ -1,106 +1,65 @@
|
|
1
|
-
require 'savon'
|
2
|
-
|
3
1
|
module Metaforce
|
4
2
|
module Services
|
5
|
-
class Client
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# Initializes a new instance of Client and logs in. _options_ should be a
|
10
|
-
# hash containing the username, password and security token. If options
|
11
|
-
# is nil, it will get the username, password and security token from the
|
12
|
-
# configuration.
|
13
|
-
def initialize(options=nil)
|
14
|
-
@options = options
|
15
|
-
# Convert string keys to hashes
|
16
|
-
@options.dup.each { |key, value| options[key.to_sym] = value } if options.is_a?(Hash)
|
3
|
+
class Client < Metaforce::AbstractClient
|
4
|
+
endpoint :server_url
|
5
|
+
wsdl Metaforce.configuration.partner_wsdl
|
17
6
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
password = "#{password}#{security_token}" unless security_token.nil?
|
34
|
-
client = Savon::Client.new File.expand_path("../../../../wsdl/#{Metaforce.configuration.api_version}/partner.xml", __FILE__) do |wsdl|
|
35
|
-
wsdl.endpoint = wsdl.endpoint.to_s.sub(/login/, 'test') if Metaforce.configuration.test
|
36
|
-
Metaforce.log("Logging in via #{wsdl.endpoint.to_s}")
|
37
|
-
end
|
38
|
-
client.http.auth.ssl.verify_mode = :none
|
39
|
-
|
40
|
-
response = client.request(:login) do
|
7
|
+
# Public: Sends an email using Salesforce.
|
8
|
+
#
|
9
|
+
# options - Hash of email options (http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_sendemail.htm)
|
10
|
+
#
|
11
|
+
# Examples
|
12
|
+
#
|
13
|
+
# client.send_email(
|
14
|
+
# to_addresses: ['foo@bar.com'],
|
15
|
+
# subject: 'Hello World',
|
16
|
+
# plain_text_body: 'Hello World'
|
17
|
+
# )
|
18
|
+
#
|
19
|
+
# Returns the result.
|
20
|
+
def send_email(options={})
|
21
|
+
request :send_email do |soap|
|
41
22
|
soap.body = {
|
42
|
-
:
|
43
|
-
:
|
23
|
+
:messages => options,
|
24
|
+
:attributes! => { 'ins0:messages' => { 'xsi:type' => 'ins0:SingleEmailMessage' } }
|
44
25
|
}
|
45
26
|
end
|
46
|
-
{ :session_id => response.body[:login_response][:result][:session_id],
|
47
|
-
:metadata_server_url => response.body[:login_response][:result][:metadata_server_url],
|
48
|
-
:services_url => response.body[:login_response][:result][:server_url] }
|
49
27
|
end
|
50
28
|
|
51
|
-
#
|
52
|
-
# If a +record_type_id+ is passed in, it will only return the layout for
|
53
|
-
# that record type.
|
29
|
+
# Public: Retrieves layout information for the specified sobject.
|
54
30
|
#
|
55
|
-
#
|
56
|
-
#
|
31
|
+
# sobject - String name of the sobject.
|
32
|
+
# record_type_id - String id of a record type to filter on.
|
57
33
|
#
|
58
|
-
#
|
34
|
+
# Examples
|
59
35
|
#
|
60
|
-
#
|
36
|
+
# client.describe_layout('Account', '012000000000000AAA')
|
61
37
|
#
|
62
|
-
#
|
63
|
-
# picklist_values = @picklists_for_record_type.select { |f| f[:picklist_name] == field }.first[:picklist_values]
|
64
|
-
# picklist_values.select { |p| p[:active] }.collect { |p| [ p[:label], p[:value] ] }
|
65
|
-
# end
|
66
|
-
#
|
67
|
-
# picklist_values_for('some_field__c')
|
68
|
-
# # => [ ['label1', 'value1'], ['label2', 'value2'] ]
|
38
|
+
# Returns the layout metadata for the sobject.
|
69
39
|
def describe_layout(sobject, record_type_id=nil)
|
70
|
-
|
71
|
-
'sObjectType' => sobject
|
72
|
-
|
73
|
-
body['recordTypeID'] = record_type_id if record_type_id
|
74
|
-
response = request(:describe_layout) do |soap|
|
75
|
-
soap.header = header
|
76
|
-
soap.body = body
|
40
|
+
request :describe_layout do |soap|
|
41
|
+
soap.body = { 'sObjectType' => sobject }
|
42
|
+
soap.body.merge!('recordTypeID' => record_type_id) if record_type_id
|
77
43
|
end
|
78
|
-
response.body[:describe_layout_response][:result]
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def header
|
84
|
-
{
|
85
|
-
"ins0:SessionHeader" => {
|
86
|
-
"ins0:sessionId" => @session[:session_id]
|
87
|
-
}
|
88
|
-
}
|
89
44
|
end
|
90
45
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
46
|
+
# Public: Get active picklists for a record type.
|
47
|
+
#
|
48
|
+
# sobject - String name of the sobject.
|
49
|
+
# record_type_id - String id of a record type to filter on.
|
50
|
+
# field - String name of the field to get picklist values for.
|
51
|
+
#
|
52
|
+
# Examples
|
53
|
+
#
|
54
|
+
# client.picklist_values('Account', '012000000000000AAA', 'Some_Field__c')
|
55
|
+
# # => [['Label', 'Value']]
|
56
|
+
#
|
57
|
+
# Returns the picklist_values
|
58
|
+
def picklist_values(sobject, record_type_id, field)
|
59
|
+
describe_layout(sobject, record_type_id).record_type_mappings.picklists_for_record_type
|
60
|
+
.select { |p| p.picklist_name == field }.first.picklist_values
|
61
|
+
.select { |p| p.active }.collect { |p| [ p.label, p.value ] }
|
102
62
|
end
|
103
|
-
|
104
63
|
end
|
105
64
|
end
|
106
65
|
end
|
data/lib/metaforce/version.rb
CHANGED
data/lib/metaforce.rb
CHANGED
@@ -1,9 +1,29 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require 'hashie'
|
3
|
+
require 'active_support/core_ext'
|
4
|
+
|
1
5
|
require 'metaforce/version'
|
2
|
-
require 'metaforce/core_extensions'
|
3
6
|
require 'metaforce/config'
|
4
|
-
require 'metaforce/
|
5
|
-
require 'metaforce/
|
6
|
-
require 'metaforce/services'
|
7
|
-
require 'metaforce/metadata'
|
8
|
-
|
9
|
-
|
7
|
+
require 'metaforce/job'
|
8
|
+
require 'metaforce/abstract_client'
|
9
|
+
require 'metaforce/services/client'
|
10
|
+
require 'metaforce/metadata/client'
|
11
|
+
|
12
|
+
module Metaforce
|
13
|
+
autoload :Manifest, 'metaforce/manifest'
|
14
|
+
autoload :Login, 'metaforce/login'
|
15
|
+
autoload :Client, 'metaforce/client'
|
16
|
+
|
17
|
+
class << self
|
18
|
+
# Public: Initializes instances of the metadata and services api clients
|
19
|
+
# and provides helper methods for deploying and retrieving code.
|
20
|
+
def new(*args)
|
21
|
+
Client.new(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Performs a login and retrurns the session
|
25
|
+
def login(options={})
|
26
|
+
Login.new(options.delete(:username), options.delete(:password), options.delete(:security_token)).login
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/metaforce.gemspec
CHANGED
@@ -1,30 +1,33 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path(
|
3
|
-
require
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'metaforce/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = 'metaforce'
|
7
7
|
s.version = Metaforce::VERSION
|
8
|
-
s.authors = [
|
9
|
-
s.email = [
|
10
|
-
s.homepage =
|
8
|
+
s.authors = ['Eric J. Holmes', 'Kevin J. Poorman']
|
9
|
+
s.email = ['eric@ejholmes.net', 'Kevinp@madronasg.com']
|
10
|
+
s.homepage = 'https://github.com/ejholmes/metaforce'
|
11
11
|
s.summary = %q{A Ruby gem for interacting with the Salesforce Metadata API}
|
12
12
|
s.description = %q{A Ruby gem for interacting with the Salesforce Metadata API}
|
13
|
+
s.post_install_message = <<-EOL
|
14
|
+
Warning! Metaforce 1.0.x is a complete rewrite and is not backwards compatible with 0.5.x
|
15
|
+
EOL
|
13
16
|
|
14
|
-
s.rubyforge_project =
|
17
|
+
s.rubyforge_project = 'metaforce'
|
15
18
|
|
16
19
|
s.files = `git ls-files`.split("\n")
|
17
20
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
21
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
s.require_paths = [
|
22
|
+
s.require_paths = ['lib']
|
20
23
|
|
21
|
-
s.add_dependency
|
22
|
-
s.add_dependency
|
23
|
-
s.add_dependency
|
24
|
-
s.add_dependency
|
24
|
+
s.add_dependency 'savon', '~> 1.2.0'
|
25
|
+
s.add_dependency 'rubyzip', '~> 0.9.9'
|
26
|
+
s.add_dependency 'activesupport'
|
27
|
+
s.add_dependency 'hashie'
|
25
28
|
|
26
|
-
s.add_development_dependency
|
27
|
-
s.add_development_dependency
|
28
|
-
s.add_development_dependency
|
29
|
-
s.add_development_dependency
|
29
|
+
s.add_development_dependency 'rake'
|
30
|
+
s.add_development_dependency 'rspec'
|
31
|
+
s.add_development_dependency 'webmock'
|
32
|
+
s.add_development_dependency 'savon_spec', '~> 1.3.0'
|
30
33
|
end
|
data/spec/fixtures/package.xml
CHANGED
Binary file
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com"><soapenv:Body><sendEmailResponse><result><success>true</success></result></sendEmailResponse></soapenv:Body></soapenv:Envelope>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metaforce::Client do
|
4
|
+
let(:options) { { session_id: 'foobar' } }
|
5
|
+
let(:client) { described_class.new(options) }
|
6
|
+
|
7
|
+
describe '.metadata' do
|
8
|
+
subject { client.metadata }
|
9
|
+
it { should be_a Metaforce::Metadata::Client }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.services' do
|
13
|
+
subject { client.services }
|
14
|
+
it { should be_a Metaforce::Services::Client }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '.method_missing' do
|
18
|
+
%w[services metadata].each do |type|
|
19
|
+
context "when the #{type} client responds to method" do
|
20
|
+
it 'proxies to the method' do
|
21
|
+
client.send(type.to_sym).should_receive(:respond_to?).with(:foobar, false).and_return(true)
|
22
|
+
client.send(type.to_sym).should_receive(:foobar)
|
23
|
+
client.foobar
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when neither client responds to method' do
|
29
|
+
it 'raises an exception' do
|
30
|
+
expect { client.foobar }.to raise_error NoMethodError
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/lib/config_spec.rb
CHANGED
@@ -1,54 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Metaforce do
|
4
|
-
describe
|
5
|
-
|
6
|
-
it
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
it
|
11
|
-
Metaforce.configuration.api_version = "21.0"
|
12
|
-
Metaforce.configuration.api_version.should eq("21.0")
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
describe ".configure" do
|
18
|
-
|
19
|
-
it "allows you to configure the api version" do
|
20
|
-
Metaforce.configure do |config|
|
21
|
-
config.api_version = "21.0"
|
22
|
-
end
|
23
|
-
Metaforce.configuration.api_version.should eq("21.0")
|
24
|
-
end
|
25
|
-
|
26
|
-
context "credentials" do
|
27
|
-
|
28
|
-
it "allows you to set the credentials via the configure block" do
|
29
|
-
Metaforce.configure do |config|
|
30
|
-
config.api_version = "23.0"
|
31
|
-
config.username = "valid"
|
32
|
-
config.password = "password"
|
33
|
-
end
|
34
|
-
savon.expects(:login).with(:username => 'valid', :password => 'password').returns(:success)
|
35
|
-
session = Metaforce::Services::Client.new.session
|
36
|
-
session.should eq({ :session_id => "00DU0000000Ilbh!AQoAQHVcube9Z6CRlbR9Eg8ZxpJlrJ6X8QDbnokfyVZItFKzJsLHIRGiqhzJkYsNYRkd3UVA9.s82sbjEbZGUqP3mG6TP_P8",
|
37
|
-
:metadata_server_url => "https://na12-api.salesforce.com/services/Soap/m/23.0/00DU0000000Albh",
|
38
|
-
:services_url => "https://na12-api.salesforce.com/services/Soap/u/23.0/00DU0000000Ilbh" })
|
39
|
-
end
|
40
|
-
|
41
|
-
it "allows you to set the credentials via the configure block" do
|
42
|
-
Metaforce.configure do |config|
|
43
|
-
config.api_version = "23.0"
|
44
|
-
config.username = "valid"
|
45
|
-
config.password = "password"
|
46
|
-
end
|
47
|
-
savon.expects(:login).with(:username => 'valid', :password => 'password').returns(:success)
|
48
|
-
expect { Metaforce::Metadata::Client.new }.to_not raise_error
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
|
4
|
+
describe '.configuration' do
|
5
|
+
subject { Metaforce.configuration }
|
6
|
+
it { should set_default(:api_version).to('26.0') }
|
7
|
+
it { should set_default(:host).to('login.salesforce.com') }
|
8
|
+
it { should set_default(:endpoint).to('https://login.salesforce.com/services/Soap/u/26.0') }
|
9
|
+
it { should set_default(:partner_wsdl).to(File.expand_path('../../../wsdl/26.0/partner.xml', __FILE__)) }
|
10
|
+
it { should set_default(:metadata_wsdl).to(File.expand_path('../../../wsdl/26.0/metadata.xml', __FILE__)) }
|
53
11
|
end
|
54
12
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metaforce::Job::Deploy do
|
4
|
+
let(:client) { double('metadata client') }
|
5
|
+
let(:path) { File.expand_path('../../../fixtures/payload.zip', __FILE__) }
|
6
|
+
let(:job) { described_class.new client, path }
|
7
|
+
|
8
|
+
describe '.payload' do
|
9
|
+
subject { job.payload }
|
10
|
+
|
11
|
+
context 'when the path is a file' do
|
12
|
+
it { should be_a String }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when the path is a directory' do
|
16
|
+
let(:path) { File.expand_path('../../../fixtures', __FILE__) }
|
17
|
+
it { should be_a String }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.perform' do
|
22
|
+
before do
|
23
|
+
client.should_receive(:_deploy).with(job.payload, {}).and_return(Hashie::Mash.new(id: '1234'))
|
24
|
+
client.should_receive(:status).any_number_of_times.and_return(Hashie::Mash.new(done: true, state: 'Completed'))
|
25
|
+
end
|
26
|
+
|
27
|
+
subject { job.perform }
|
28
|
+
it { should eq job }
|
29
|
+
its(:id) { should eq '1234' }
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '.result' do
|
33
|
+
let(:response) { Hashie::Mash.new(success: true) }
|
34
|
+
|
35
|
+
before do
|
36
|
+
client.should_receive(:status).with(job.id, :deploy).and_return(response)
|
37
|
+
end
|
38
|
+
|
39
|
+
subject { job.result }
|
40
|
+
it { should eq response }
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '.success?' do
|
44
|
+
let(:response) { Hashie::Mash.new(success: true) }
|
45
|
+
|
46
|
+
before do
|
47
|
+
client.should_receive(:status).with(job.id, :deploy).and_return(response)
|
48
|
+
end
|
49
|
+
|
50
|
+
subject { job.success? }
|
51
|
+
it { should be_true }
|
52
|
+
end
|
53
|
+
end
|