leap_salesforce 0.1.13 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +7 -6
- data/.idea/.rakeTasks +2 -2
- data/.idea/dictionaries/iqa.xml +1 -0
- data/.idea/leap-salesforce.iml +3 -1
- data/ChangeLog +10 -0
- data/README.md +47 -7
- data/Rakefile +10 -0
- data/leap_salesforce.gemspec +1 -0
- data/lib/leap_salesforce/error.rb +2 -0
- data/lib/leap_salesforce/ext/string.rb +6 -1
- data/lib/leap_salesforce/soql_data/soql_enum.rb +2 -0
- data/lib/leap_salesforce/soql_data/soql_global_object_data.rb +33 -21
- data/lib/leap_salesforce/version.rb +1 -1
- data/support/doctest_helper.rb +3 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9ac3a7c96d31655ef2684afb14ba1088656bfba4bdba621d1c282163783b6a4
|
4
|
+
data.tar.gz: 5aad78509c4ef1844c58bd0dbe600f81248126e4570eec154ef0a35abe1091a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1efdda645ee1103bce00418fd65f75badfc570191a60f7f6d5b44dca2eda1d38a395c3b9f164ec4a10a8a7f980401e1a88d031663fa76ef3d1c752626d2fca10
|
7
|
+
data.tar.gz: 917b74365cc67fe2d4ec7d9ab6bb3e723c8a7a4b3cdcf2cfcdfa7f42d901d37807c689d940f7be933f764117160016e8595a54e348eb8053dc9b4bb872791f1d
|
data/.gitlab-ci.yml
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
include:
|
2
|
+
- template: Code-Quality.gitlab-ci.yml
|
3
|
+
|
1
4
|
image: ruby:2.5
|
2
5
|
|
3
6
|
stages:
|
@@ -8,15 +11,13 @@ variables:
|
|
8
11
|
client_id: $client_id
|
9
12
|
client_secret: $client_secret
|
10
13
|
|
11
|
-
before_script:
|
12
|
-
- ruby -v
|
13
|
-
- which ruby
|
14
|
-
- gem install bundler rake
|
15
|
-
- bundle install
|
16
|
-
|
17
14
|
test:
|
18
15
|
stage: test
|
19
16
|
script:
|
17
|
+
- ruby -v
|
18
|
+
- which ruby
|
19
|
+
- gem install bundler rake
|
20
|
+
- bundle install
|
20
21
|
- bundle exec rake leaps:create_soql_objects
|
21
22
|
- bundle exec rake leaps:create_enums
|
22
23
|
- bundle exec rake
|
data/.idea/.rakeTasks
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<Settings><!--This file was automatically generated by Ruby plugin.
|
3
3
|
You are allowed to:
|
4
4
|
1. Remove rake task
|
5
5
|
2. Add existing rake tasks
|
6
6
|
To add existing rake tasks automatically delete this file and reload the project.
|
7
|
-
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build leap_salesforce-0.1.
|
7
|
+
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build leap_salesforce-0.1.14.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Check Salesforce OAuth2 authentication is working" fullCmd="check_oauth" taksId="check_oauth" /><RakeTask description="Remove any temporary products" fullCmd="clean" taksId="clean" /><RakeTask description="Remove any generated files" fullCmd="clobber" taksId="clobber" /><RakeTask description="Build and install leap_salesforce-0.1.14.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install leap_salesforce-0.1.14.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="leaps"><RakeTask description="Create objects, fields, enums" fullCmd="leaps:create_all" taksId="create_all" /><RakeTask description="Create Enumeration objects for picklists from Salesforce Metadata" fullCmd="leaps:create_enums" taksId="create_enums" /><RakeTask description="Create Soql Data objects" fullCmd="leaps:create_soql_objects" taksId="create_soql_objects" /></RakeGroup><RakeTask description="Create tag v0.1.14 and build and push leap_salesforce-0.1.14.gem to rubygems.org" fullCmd="release[remote]" taksId="release[remote]" /><RakeTask description="Run RSpec code examples" fullCmd="spec" taksId="spec" /><RakeTask description="Create stubs for dynamic methods so they're picked up by the IDE" fullCmd="stub" taksId="stub" /><RakeGroup description="" fullCmd="" taksId="yard"><RakeTask description="Run YARD doctests" fullCmd="yard:doctest" taksId="doctest" /></RakeGroup><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
|
data/.idea/dictionaries/iqa.xml
CHANGED
data/.idea/leap-salesforce.iml
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.3, RVM: ruby-2.6.0) [gem]" level="application" />
|
23
23
|
<orderEntry type="library" scope="PROVIDED" name="domain_name (v0.5.20190701, RVM: ruby-2.6.0) [gem]" level="application" />
|
24
24
|
<orderEntry type="library" scope="PROVIDED" name="factory_bot (v5.0.2, RVM: ruby-2.6.0) [gem]" level="application" />
|
25
|
-
<orderEntry type="library" scope="PROVIDED" name="faker (v2.
|
25
|
+
<orderEntry type="library" scope="PROVIDED" name="faker (v2.1.0, RVM: ruby-2.6.0) [gem]" level="application" />
|
26
26
|
<orderEntry type="library" scope="PROVIDED" name="gyoku (v1.3.1, RVM: ruby-2.6.0) [gem]" level="application" />
|
27
27
|
<orderEntry type="library" scope="PROVIDED" name="hashie (v3.6.0, RVM: ruby-2.6.0) [gem]" level="application" />
|
28
28
|
<orderEntry type="library" scope="PROVIDED" name="http-cookie (v1.0.3, RVM: ruby-2.6.0) [gem]" level="application" />
|
@@ -80,5 +80,7 @@
|
|
80
80
|
<orderEntry type="library" scope="PROVIDED" name="unicode-display_width (v1.6.0, RVM: ruby-2.6.0) [gem]" level="application" />
|
81
81
|
<orderEntry type="library" scope="PROVIDED" name="wasabi (v3.5.0, RVM: ruby-2.6.0) [gem]" level="application" />
|
82
82
|
<orderEntry type="library" scope="PROVIDED" name="xml-simple (v1.1.5, RVM: ruby-2.6.0) [gem]" level="application" />
|
83
|
+
<orderEntry type="library" scope="PROVIDED" name="yard (v0.9.19, RVM: ruby-2.6.0) [gem]" level="application" />
|
84
|
+
<orderEntry type="library" scope="PROVIDED" name="yard-doctest (v0.1.16, RVM: ruby-2.6.0) [gem]" level="application" />
|
83
85
|
</component>
|
84
86
|
</module>
|
data/ChangeLog
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
Version 0.1.15
|
2
|
+
* Enhancements
|
3
|
+
* Handle greater than/less than equal comparator in query
|
4
|
+
* Fail before request is sent if querying based on a field that is not on object
|
5
|
+
* Don't wait by default for an object to appear
|
6
|
+
|
7
|
+
Version 0.1.14
|
8
|
+
* Bug Fix
|
9
|
+
* Fixed order of picklist comparison so error message shows error correctly
|
10
|
+
|
1
11
|
Version 0.1.13
|
2
12
|
* Bug Fix
|
3
13
|
* Updated 'Delete' where must_pass of true was calling 'successful?' method on wrong object
|
data/README.md
CHANGED
@@ -152,19 +152,59 @@ For example
|
|
152
152
|
```
|
153
153
|
|
154
154
|
The `log` for this call will look like the following:
|
155
|
+
(Note that explanations are in ALL CAPS and line numbers have been added)
|
155
156
|
|
156
157
|
```verilog
|
157
|
-
Leaps, [13:39:14] : Example Factory for 'Contact'
|
158
|
-
Leaps, [13:39:14] : request body: {"
|
159
|
-
Leaps, [13:39:14] : RestClient.post "https://
|
158
|
+
1. Leaps, [13:39:14] : Example Factory for 'Contact'
|
159
|
+
2. Leaps, [13:39:14] : request body: {"LastName":"Gleichner"}
|
160
|
+
3. Leaps, [13:39:14] : RestClient.post "https://SALESFORCE_INSTANCE_URL/services/data/v45.0/sobjects/Contact", "{\"FirstName\":\"Lewis\"}", HEADERS INFO
|
160
161
|
|
161
|
-
Leaps, [13:39:16] : # => 201 Created | application/json 71 bytes
|
162
|
+
4. Leaps, [13:39:16] : # => 201 Created | application/json 71 bytes
|
162
163
|
|
163
|
-
Leaps, [13:39:16] : response:
|
164
|
-
headers: {:date=>"Thu, 01 Aug 2019 01:39:15 GMT",
|
165
|
-
body: {"id":"0032v00002qU3hvAAC","success":true,"errors":[]}
|
164
|
+
5. Leaps, [13:39:16] : response:
|
165
|
+
6. headers: {:date=>"Thu, 01 Aug 2019 01:39:15 GMT", OTHER_HEADER_INFO}
|
166
|
+
7. body: {"id":"0032v00002qU3hvAAC","success":true,"errors":[]}
|
166
167
|
```
|
167
168
|
|
169
|
+
Following is a step by step explanation of each log line:
|
170
|
+
1. Brief description of what's being done. Creating a Contact.
|
171
|
+
2. Parameters used in HTTP request. This will be the fields set on the object created
|
172
|
+
3. The actual REST Post made to the Salesforce API showing the URL, payload, headers, etc
|
173
|
+
4. A brief summary of the response. Object has been created successfully
|
174
|
+
5. A more in depth description of the response follows in next two lines
|
175
|
+
6. Headers of the response
|
176
|
+
7. Body of the response
|
177
|
+
|
178
|
+
Representation of the details for created an entity can be handled much neater by `FactoryBot`.
|
179
|
+
If we had the following `factory` for Contact
|
180
|
+
```ruby
|
181
|
+
FactoryBot.define do
|
182
|
+
factory :contact do
|
183
|
+
first_name { 'Test Person' }
|
184
|
+
end
|
185
|
+
end
|
186
|
+
```
|
187
|
+
then we could perform the same creation of a contact with simply
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
@contact = FactoryBot.create(:contact)
|
191
|
+
```
|
192
|
+
|
193
|
+
FactoryBot has traits, associations, after blocks for helping with creating objects with fast number
|
194
|
+
of relationships. See FactoryBot's getting started for more information and have a look at the
|
195
|
+
examples in the `spec` folder.
|
196
|
+
|
197
|
+
To create an object using a factory, the `create` method can also be used on the object itself. For
|
198
|
+
example:
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
@contact = Contact.create
|
202
|
+
```
|
203
|
+
|
204
|
+
##### Reading entities
|
205
|
+
|
206
|
+
|
207
|
+
|
168
208
|
## Structure
|
169
209
|
|
170
210
|
Following is the general structure of test automation suite that uses this approach. Details may vary depending on the
|
data/Rakefile
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require 'bundler/gem_tasks'
|
4
4
|
require 'rspec/core/rake_task'
|
5
5
|
require 'rake/clean'
|
6
|
+
require 'yard'
|
7
|
+
require 'yard/doctest/rake'
|
6
8
|
|
7
9
|
require 'leap_salesforce/rake'
|
8
10
|
|
@@ -24,3 +26,11 @@ task :stub do
|
|
24
26
|
require 'topoisomerase'
|
25
27
|
Topoisomerase.create_stubs_based_on SoqlData
|
26
28
|
end
|
29
|
+
|
30
|
+
desc 'Test examples shown in documentation'
|
31
|
+
YARD::Doctest::RakeTask.new do |task|
|
32
|
+
task.doctest_opts = %w[-v]
|
33
|
+
# task.pattern = 'lib/**/*.rb'
|
34
|
+
# TODO: Get all examples working in this way
|
35
|
+
task.pattern = 'lib/leap_salesforce/ext/string.rb'
|
36
|
+
end
|
data/leap_salesforce.gemspec
CHANGED
@@ -30,6 +30,7 @@ It reads the Metadata from Salesforce and creates the foundation for API tests.'
|
|
30
30
|
spec.add_development_dependency 'pry'
|
31
31
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
32
|
spec.add_development_dependency 'topoisomerase'
|
33
|
+
spec.add_development_dependency 'yard-doctest'
|
33
34
|
spec.add_dependency 'activerecord'
|
34
35
|
spec.add_dependency 'colorize'
|
35
36
|
spec.add_dependency 'factory_bot'
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module LeapSalesforce
|
2
2
|
# Any error specific to LeapSalesforce
|
3
3
|
class Error < StandardError; end
|
4
|
+
# Error related to handling a request
|
5
|
+
class RequestError < StandardError; end
|
4
6
|
# Error related to handling a response
|
5
7
|
class ResponseError < StandardError; end
|
6
8
|
# Error related to setup of test automation suite
|
@@ -19,7 +19,12 @@ class String
|
|
19
19
|
.humanize_numbered_string
|
20
20
|
end
|
21
21
|
|
22
|
-
# @
|
22
|
+
# @example Remove stripped characters
|
23
|
+
# ''.handle_initial_characters # => 'X'
|
24
|
+
# @example Remove leading underscores
|
25
|
+
# '_leading'.handle_initial_characters # => 'leading'
|
26
|
+
# @return [String] If all characters were stripped out, put a placeholder 'X'.
|
27
|
+
# If starts with underscore remove it
|
23
28
|
def handle_initial_characters
|
24
29
|
if size.zero?
|
25
30
|
+'X'
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
# Module all SoqlEnums include
|
4
4
|
module SoqlEnum
|
5
|
+
# @param [Class] object Object inheriting from SoqlData that has picklists underneath it
|
6
|
+
# @return [Array] List of picklist classes that inherit from SoqlEnum and relate to provided class
|
5
7
|
def self.values_for(object)
|
6
8
|
ObjectSpace.each_object(Module).select { |class_name| class_name < self && class_name.to_s.start_with?("#{object}::") }
|
7
9
|
end
|
@@ -24,12 +24,11 @@ module SoqlGlobalObjectData
|
|
24
24
|
# (see https://www.w3schools.com/tags/ref_urlencode.asp)
|
25
25
|
# @param [String] soql_query String representing SOQL query
|
26
26
|
# @param [Boolean] wait Whether to wait for record if no result returned
|
27
|
-
# @example
|
28
|
-
#
|
29
|
-
#
|
30
|
-
# perform_query "SELECT+Name+from+Account+WHERE+Name+=+'TEST+Org+001'"
|
27
|
+
# @example Find an account with test organisation name
|
28
|
+
# my_query = "SELECT Name from Account WHERE Name = 'TEST Org 001'"
|
29
|
+
# query my_query # => "SELECT+Name+from+Account+WHERE+Name+=+'TEST+Org+001'"
|
31
30
|
# @return [Exchange] Exchange object from which JSON response can be obtained (i.e, with exchange.response)
|
32
|
-
def query(soql_query, wait:
|
31
|
+
def query(soql_query, wait: false)
|
33
32
|
rest_query = soql_query.gsub('%', '%25').gsub('+', '%2B').tr(' ', '+')
|
34
33
|
if wait
|
35
34
|
new("SOQL Query: #{soql_query}", method: :get, suburl: "query/?q=#{rest_query}").until(timeout: 20, interval: 1) do
|
@@ -56,6 +55,10 @@ module SoqlGlobalObjectData
|
|
56
55
|
conditional = ''
|
57
56
|
lookup.each do |key, value|
|
58
57
|
conditional_term = conditional.empty? ? 'WHERE' : 'AND'
|
58
|
+
unless field_names.include? key.to_s
|
59
|
+
raise LeapSalesforce::RequestError, "#{key} not in #{self}. " \
|
60
|
+
" Must be one of #{field_names}"
|
61
|
+
end
|
59
62
|
conditional += "#{conditional_term} #{key} #{condition_for(value)} "
|
60
63
|
end
|
61
64
|
query = conditional + 'ORDER BY CreatedDate DESC NULLS FIRST'
|
@@ -73,10 +76,10 @@ module SoqlGlobalObjectData
|
|
73
76
|
# Contact.find CreatedDate: "<#{10.days.ago}"
|
74
77
|
# @param [Hash] lookup Key value pair unique to Salesforce to query for
|
75
78
|
# @option lookup [Boolean] :teardown Whether to remove id after scenario finished
|
76
|
-
# @return [
|
79
|
+
# @return [self] Instance of itself storing reference to found object
|
77
80
|
def find(lookup)
|
78
81
|
teardown = lookup.delete(:teardown)
|
79
|
-
wait = lookup.delete(:wait) ||
|
82
|
+
wait = lookup.delete(:wait) || false
|
80
83
|
SoqlHandler.new("Query on #{self}").use
|
81
84
|
instance_to_get = if lookup.key? :Id
|
82
85
|
new("Lookup id: #{lookup[:Id]}", method: :get, suburl: "sobjects/#{soql_object_name}/#{lookup[:Id]}")
|
@@ -206,25 +209,34 @@ module SoqlGlobalObjectData
|
|
206
209
|
# rubocop:enable Metrics/MethodLength
|
207
210
|
# rubocop:enable Metrics/AbcSize
|
208
211
|
|
209
|
-
|
210
|
-
|
211
|
-
#
|
212
|
-
# @param [String] value Value to search for. Certain
|
213
|
-
#
|
212
|
+
# Returns SOQL condition for value passed to be used in SOQL query
|
213
|
+
# @example Greater than or equal to yesterday's date
|
214
|
+
# condition_for("<=#{Time.mktime(2019,1,1)}") # => '<= 2019-01-01T00:00:00.000Z'
|
215
|
+
# @param [String] value Value to search for. Certain characters modify this to be more of a complex
|
216
|
+
# check
|
217
|
+
# @return [String] Condition criteria to match value using SOQL
|
214
218
|
def condition_for(value)
|
215
|
-
operator = case value[0]
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
return "= '#{value}'" unless value.type_of_time?
|
219
|
+
operator, value = case value[0]
|
220
|
+
when '>', '<' then extract_comparator(value)
|
221
|
+
when '~' then ['LIKE', value[1..-1]]
|
222
|
+
else
|
223
|
+
return "= '#{value}'" unless value.type_of_time?
|
221
224
|
|
222
|
-
|
223
|
-
|
225
|
+
return "= #{value.to_zulu_date_string}"
|
226
|
+
end
|
224
227
|
|
225
|
-
value = value[1..-1]
|
226
228
|
return "#{operator} #{value.to_zulu_date_string}" if value.type_of_time?
|
227
229
|
|
228
230
|
"#{operator} '#{value}'"
|
229
231
|
end
|
232
|
+
|
233
|
+
# @param [String] value Value to extract comparator for
|
234
|
+
# @return [Array] Extract of >, >, >= from string and rest of string
|
235
|
+
def extract_comparator(value)
|
236
|
+
if value[1] == '='
|
237
|
+
[value[0..1], value[2..-1]]
|
238
|
+
else
|
239
|
+
[value[0], value[1..-1]]
|
240
|
+
end
|
241
|
+
end
|
230
242
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: leap_salesforce
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- IQA
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-08-
|
12
|
+
date: 2019-08-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -67,6 +67,20 @@ dependencies:
|
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: yard-doctest
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
70
84
|
- !ruby/object:Gem::Dependency
|
71
85
|
name: activerecord
|
72
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -303,6 +317,7 @@ files:
|
|
303
317
|
- lib/leap_salesforce/users/user.rb
|
304
318
|
- lib/leap_salesforce/users/users.rb
|
305
319
|
- lib/leap_salesforce/version.rb
|
320
|
+
- support/doctest_helper.rb
|
306
321
|
homepage: https://gitlab.com/leap-dojo/leap_salesforce
|
307
322
|
licenses:
|
308
323
|
- MIT
|