leap_salesforce 0.2.28 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c713a2f3052a5b335fb56963091508d652a4b1d570a6283e2ad775e2e062dd9b
4
- data.tar.gz: a845f0ee3220c1d88ae9086a529e61612b25cc79ccdacf2bae0296b12ade189e
3
+ metadata.gz: 524899b1fcc374750dcb570db5de67ad6aaea98e8d9fd1381ed5c68cec0ea34a
4
+ data.tar.gz: d950d41267bbfde2fa9e7765b1f89a7b72cf61c47589567adef70b0a62e0566c
5
5
  SHA512:
6
- metadata.gz: b8b6b99d725267fe4e89f32cfd513aadea6ee83e9ac1220052882988e88fa5bd1762ecaafc9ac23a8698f2645beea1bb2dce7cd1d38ae2b101bdb947588c1258
7
- data.tar.gz: 93bcc18ead3300a227163fd19e18e5f9b7bbcc0c19c71cd0f32136ce3e176eb2b1515e00815507f438f94e84853a3d4c7f921edb3a9f76ded23d122b94035c43
6
+ metadata.gz: 5717e4bc877a62fa921abe70c0a2ee12d4a29e46941d6e0283f8665dc49d76d9a78be697ba4be609f6567d545b29e2d8cf6a7c965a4924e328feff71b090b891
7
+ data.tar.gz: 37adfa1837d29609c6aee8f2195ca0e41c134b94d5ced4be994064e4720eb12fe7930276fb296a9794a452a9ce21633c913fa507dfce24a88a51504b6cdecf95
data/.gitlab-ci.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  include:
2
2
  - template: Code-Quality.gitlab-ci.yml
3
3
 
4
- image: ruby:2.6
4
+ image: ruby:2.7
5
5
 
6
6
  stages:
7
7
  - test
@@ -18,7 +18,7 @@ variables:
18
18
  pages:
19
19
  stage: deploy
20
20
  dependencies:
21
- - test
21
+ - test_2.7
22
22
  script:
23
23
  - mv coverage/ public
24
24
  artifacts:
@@ -600,25 +600,38 @@ pages:
600
600
  done
601
601
  }
602
602
 
603
- test:
604
- stage: test
603
+ function setup_integration_env() {
604
+ # Decrypt server key
605
+ openssl aes-256-cbc -d -md md5 -in assets/server.key.enc -out assets/server.key -k $SERVER_KEY_PASSWORD
606
+ ls -la assets
607
+ install_jq
608
+ install_salesforce_cli
609
+ # Integrated test
610
+ gem install bundler rake
611
+ bundle install
612
+ sfdx force:auth:jwt:grant --clientid "$SF_CONSUMER_KEY" --jwtkeyfile assets/server.key --username "$SF_USERNAME" --setdefaultdevhubusername --setalias HubOrg
613
+ }
614
+
615
+ test_2.7:
605
616
  script:
606
617
  # Decrypt server key
607
618
  - *sfdx_helpers
608
- - openssl aes-256-cbc -d -md md5 -in assets/server.key.enc -out assets/server.key -k $SERVER_KEY_PASSWORD
609
- - ls -la assets
610
- - install_jq
611
- - install_salesforce_cli
612
- # Integrated test
613
- - ruby -v
614
- - which ruby
615
- - gem install bundler rake
616
- - bundle install
617
- - sfdx force:auth:jwt:grant --clientid "$SF_CONSUMER_KEY" --jwtkeyfile assets/server.key --username "$SF_USERNAME" --setdefaultdevhubusername --setalias HubOrg
619
+ - setup_integration_env
618
620
  - bundle exec rake check_oauth # Check OAuth
619
621
  - bundle exec rake leaps:create_soql_objects
620
622
  - bundle exec rake leaps:create_enums
621
- - bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL
623
+ - bundle exec rspec
622
624
  artifacts:
623
625
  paths:
624
626
  - coverage/
627
+
628
+ test_3.0:
629
+ image: ruby:3.0
630
+ script:
631
+ # Decrypt server key
632
+ - *sfdx_helpers
633
+ - setup_integration_env
634
+ - bundle exec rake check_oauth # Check OAuth
635
+ - bundle exec rake leaps:create_soql_objects
636
+ - bundle exec rake leaps:create_enums
637
+ - bundle exec rspec
data/ChangeLog CHANGED
@@ -1,3 +1,26 @@
1
+ Version 1.0.4
2
+ * Enhancement
3
+ * Strip out ':' from user key for when it is accidentally added
4
+
5
+ Version 1.0.3
6
+ * Enhancement
7
+ * Allow templates to be sourced from external gems for generator
8
+
9
+ Version 1.0.2
10
+ * Enhancement
11
+ * Only load sub folders of leap_salesforce.lib_folder that are needed by this gem, allowing room for UI
12
+ and other gems to use other folders independently
13
+ * New method 'accessors' on object to make it easy to pass list of fields for an object
14
+
15
+ Version 1.0.1
16
+ * Bug fix
17
+ * Fix #28 allowing !nil for query by non null values
18
+
19
+ Version 1.0.0
20
+ * Enhancement
21
+ * Disable rubocop output for pending ops when creating/fixing files
22
+ * Specify that working with Ruby 3 is a work in progress
23
+
1
24
  Version 0.2.28
2
25
  * Enhancement
3
26
  * Make exclude method able to use class name in exclusion filter (hence easier to use)
@@ -226,4 +249,4 @@ Version 0.1.1
226
249
  * Suggestions for generated factory
227
250
  * Begin unit tests
228
251
  * Handle Macrons by ensuring they're not copied into Ruby names / Modules
229
- * Created executable
252
+ * Created executable
data/PITCHME.md CHANGED
@@ -80,7 +80,7 @@ metadata.
80
80
  @[3](Declare what it is you're testing)
81
81
  @[5](Define what 'it' is, a the object under test must do)
82
82
  @[6](Create an instance of the object class - nothing sent to Salesforce yet)
83
- @[7-8](Set the first and last name to random names)
83
+ @[4,7-8](Set the first and last name to random names)
84
84
  @[9](Create the object in Salesforce by sending request via API)
85
85
  @[10](Verify creation was successful)
86
86
  @[11](Verify first name set as expected)
@@ -92,8 +92,8 @@ metadata.
92
92
 
93
93
  ---?code=spec/integration/query_spec.rb&lang=ruby&title=Querying entities
94
94
 
95
- @[6](Find an object using a specific attribute specific value)
96
- @[19](Find an object using a comparator)
95
+ @[21](Find an object using a specific attribute specific value)
96
+ @[29-30](Find list of objects meeting condition)
97
97
 
98
98
  ---
99
99
 
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Welcome to LeapSalesforce gem. This gem helps ones to perform integration tests on Salesforce. It reads the Metadata
4
4
  from Salesforce and creates the foundation for API tests.
5
5
 
6
- In the future it will also planned to be used to create page objects based on metadata to support UI testing.
6
+ Support for UI testing is being worked on in another gem [leap_salesforce_ui](https://gitlab.com/leap-dojo/leap_salesforce_ui)
7
7
 
8
8
  ## Is this for you?
9
9
 
@@ -258,6 +258,22 @@ This method can be used directly with the backend name. E.g, `contact[:FieldName
258
258
  This method in turn sets a value of the `@override_parameters[:body]` variable within the entity.
259
259
  The value of request body can be interrogated with `entity.request_parameters.body`.
260
260
 
261
+ ##### Logging
262
+
263
+ By default, API traffic will be logged in a log file in a `logs` folder. The gem `soaspec` is
264
+ used to log this traffic.
265
+
266
+ Following is an example of changing some of the default logging.
267
+
268
+ ```ruby
269
+ # Turn this true if you need debug authentication
270
+ Soaspec::OAuth2.debug_oauth = true
271
+ # Turn this to true if you want to see API traffic on the terminal
272
+ Soaspec::SpecLogger.output_to_terminal = true
273
+ ```
274
+
275
+ See more configuration parameters in the [Soaspec repo](https://gitlab.com/samuel-garratt/soaspec#logging)
276
+
261
277
  ### CRUD of data
262
278
 
263
279
  To work data in Salesforce, an object inheriting from the `SoqlData` class is always used. The idea is
@@ -560,3 +576,5 @@ Everyone interacting in the LeapSalesforce project’s codebases, issue trackers
560
576
 
561
577
  * Presentation on this library [here](https://gitpitch.com/leap-dojo/leap_salesforce?grs=gitlab)
562
578
  * Example of this library within a CI/CD pipeline [here](https://gitlab.com/iqa_public/labs/salesforce_cicd_demo)
579
+ * Using `leap_salesforce` to download event log files [here](https://gitlab.com/samuel-garratt/leap_salesforce_event_log_files)
580
+
data/Rakefile CHANGED
@@ -34,3 +34,21 @@ YARD::Doctest::RakeTask.new do |task|
34
34
  # TODO: Get all examples working in this way
35
35
  task.pattern = 'lib/leap_salesforce/ext/string.rb'
36
36
  end
37
+
38
+ desc 'Task to enter pry terminal and types commands using the standard library code'
39
+ task :pry do
40
+ require 'pry'
41
+ Pry.start
42
+ end
43
+
44
+ desc 'Example of cleaning up data'
45
+ task :remove_contacts do
46
+ contacts = Contact.where first_name: '!null'
47
+ puts "Deleting #{contacts.size} contacts"
48
+ contacts.each do |contact|
49
+ contact.delete
50
+ print '.'
51
+ end
52
+ contacts = Contact.where first_name: '!null'
53
+ puts "#{contacts.size} contacts left"
54
+ end
@@ -74,7 +74,10 @@ module LeapSalesforce
74
74
  require 'leap_salesforce/limits'
75
75
 
76
76
  FileUtils.mkdir_p lib_folder unless Dir.exist? lib_folder
77
- require_all lib_folder
77
+ %w[factories metadata soql_data].each do |folder|
78
+ sub_folder = File.join(lib_folder, folder)
79
+ require_all sub_folder if Dir.exist? sub_folder
80
+ end
78
81
 
79
82
  self.objects_to_verify = SoqlData.descendants if objects_to_verify.empty?
80
83
  end
@@ -3,12 +3,16 @@
3
3
  module LeapSalesforce
4
4
  # Any error specific to LeapSalesforce
5
5
  class Error < StandardError; end
6
+
6
7
  # Error related to handling a request
7
8
  class RequestError < StandardError; end
9
+
8
10
  # Error related to handling a response
9
11
  class ResponseError < StandardError; end
12
+
10
13
  # Error related to setup of test automation suite
11
14
  class SetupError < Error; end
15
+
12
16
  # Error related to Test Users
13
17
  class UserError < Error; end
14
18
  end
@@ -27,8 +27,8 @@ class String
27
27
  def to_ruby_friendly
28
28
  tr('&|=', '_').gsub('<', '_lt_').gsub('>', '_gt_')
29
29
  .remove_macrons
30
- .gsub(/[\s]+/, '_')
31
- .gsub(/[\W]/, '') # Remove any other special characters
30
+ .gsub(/\s+/, '_')
31
+ .gsub(/\W/, '') # Remove any other special characters
32
32
  .handle_initial_characters # Previous step could have removed all characters
33
33
  .humanize_numbered_string
34
34
  end
@@ -23,7 +23,7 @@ module LeapSalesforce
23
23
  when 'boolean' then set('true')
24
24
  when 'picklist' then set("#{class_name}::#{field['label'].to_class_name}.sample")
25
25
  when 'reference'
26
- return set('User.find(CreatedDate: "<#{0.days.ago}").id') if field['name'] == 'OwnerId'
26
+ return set(%{User.find(CreatedDate: "<#{0.days.ago}").id}) if field['name'] == 'OwnerId'
27
27
 
28
28
  soql_obj = LeapSalesforce.soql_objects.find { |so| so.backend_name == field['relationshipName'] }&.reference
29
29
  if soql_obj
@@ -34,8 +34,8 @@ module LeapSalesforce
34
34
  def verify_oauth
35
35
  unless LeapSalesforce.sfdx
36
36
  LeapSalesforce.client_id = options[:client_id] || input_for('Client id (Customer Id)')
37
- LeapSalesforce.client_secret = options[:client_secret] || STDIN.getpass('Client secret (Consumer Secret)')
38
- LeapSalesforce.password = options[:password] || STDIN.getpass('Password (Recommendation is that 1 password' \
37
+ LeapSalesforce.client_secret = options[:client_secret] || $stdin.getpass('Client secret (Consumer Secret)')
38
+ LeapSalesforce.password = options[:password] || $stdin.getpass('Password (Recommendation is that 1 password' \
39
39
  ' be shared across all test users to be easier to manage):')
40
40
  end
41
41
  LeapSalesforce.api_user = ERB.new(options[:username] || input_for('Salesforce username. It is ideal to start with a System admin' \
@@ -50,7 +50,7 @@ module LeapSalesforce
50
50
  ' leap_salesforce testing repo'.colorize(:green)
51
51
  verify_environment
52
52
  verify_oauth
53
- @user_key = options[:user_key] || input_for('Enter a key to refer to this user (This will be stored as a Symbol)')
53
+ @user_key = options[:user_key] || input_for('Enter a key to refer to this user (This will be stored as a Symbol)').delete(':')
54
54
  end
55
55
  end
56
56
  end
@@ -8,11 +8,20 @@ require 'colorize'
8
8
  module LeapSalesforce
9
9
  # Generators for creating code
10
10
  module Generator
11
+ # @param [String] filename Relative filename to this file
12
+ # @param [String] folder Folder where templates are stored (for external gems)
13
+ # @return [String] Location of template file
14
+ def template_loc(filename, folder: nil)
15
+ template_dir = folder || __dir__
16
+ File.join(template_dir, 'templates', filename)
17
+ end
18
+
11
19
  # @param [String] filename Relative filename to this file
12
20
  # @param [Binding] binding Binding object used for ERB variables
21
+ # @param [String] folder Folder where templates are stored (for external gems)
13
22
  # @return [String] Interpreted file after calculating ERB for template file passed
14
- def read_template(filename, binding)
15
- ERB.new(File.read(File.join(__dir__, 'templates', filename))).result(binding)
23
+ def read_template(filename, binding, folder: nil)
24
+ ERB.new(File.read(template_loc(filename, folder: folder))).result(binding)
16
25
  end
17
26
 
18
27
  # Generate file creating necessary folder if necessary
@@ -70,7 +70,7 @@ module LeapSalesforce
70
70
 
71
71
  # Clean up files generated for all picklists
72
72
  def cleanup_files_created
73
- `rubocop -a #{ENUM_FOLDER}`
73
+ `rubocop -A #{ENUM_FOLDER} --display-only-fail-level-offenses --enable-pending-cops`
74
74
  end
75
75
  end
76
76
  end
@@ -62,8 +62,8 @@ module LeapSalesforce
62
62
  generate_field_module
63
63
  generate_factory
64
64
  end
65
- `rubocop -a #{SOQL_OBJECT_FOLDER}`
66
- `rubocop -a #{FACTORY_FOLDER}`
65
+ `rubocop -A #{SOQL_OBJECT_FOLDER} --enable-pending-cops`
66
+ `rubocop -A #{FACTORY_FOLDER} --enable-pending-cops`
67
67
  end
68
68
 
69
69
  private
@@ -4,8 +4,8 @@
4
4
  # Depending on validation rules and mandatory fields this may or may not work
5
5
 
6
6
  RSpec.describe 'Contact CRUD' do
7
- let(:uniq_value) { 'UNIQ FIRST NAME' }
8
- let(:updated_value) { 'New Value' }
7
+ let(:uniq_value) { "UNIQ #{Faker::Name.first_name} #{Faker::Name.middle_name}" }
8
+ let(:updated_value) { "New #{Faker::Name.first_name} #{Faker::Name.neutral_first_name}" }
9
9
  it 'Create using factory bot' do
10
10
  @contact = FactoryBot.create(:contact)
11
11
  end
@@ -17,7 +17,7 @@ module LeapSalesforce
17
17
  @client_secret = ENV['client_secret']
18
18
  @password = ENV['password']
19
19
  @environment = nil
20
- @logger = Logger.new STDOUT
20
+ @logger = Logger.new $stdout
21
21
  @sfdx = false
22
22
  # @access_token = nil
23
23
  @instance_url = nil
@@ -98,7 +98,7 @@ module LeapSalesforce
98
98
  else
99
99
  LeapSalesforce::Users.where(user)&.username
100
100
  end
101
- Soaspec::SpecLogger.info "Using user '#{@api_user}'"
101
+ Soaspec::SpecLogger.info "Using user '#{@api_user}' for API"
102
102
  end
103
103
 
104
104
  # @return [String] Salesforce username used to execute API tests. This can be changed during tests
@@ -128,6 +128,7 @@ module LeapSalesforce
128
128
  attr_reader :soql_objects
129
129
  # @return [Logger] Logger used by LeapSalesforce
130
130
  attr_accessor :logger
131
+
131
132
  # @return [Array] list_of_soql_objects Array describing Soql objects taken from .leap_salesforce.yml
132
133
  def soql_objects=(list_of_soql_objects)
133
134
  @soql_objects = list_of_soql_objects.collect do |soql_object_desc|
@@ -150,7 +150,8 @@ module LeapSalesforce
150
150
  elsif value[0] == 'I' # 'N' not 2nd character
151
151
  ['=', value]
152
152
  elsif value[0] == '!'
153
- ['!=', value[1..-1]]
153
+ remaining = value[1..-1] == 'nil' ? 'null' : value[1..-1]
154
+ ['!=', remaining]
154
155
  else
155
156
  [value[0], value[1..-1]]
156
157
  end
@@ -72,13 +72,13 @@ module SoqlGlobalObjectData
72
72
  # @param [Hash] lookup Key value pair unique to Salesforce to query for
73
73
  # @yield [id] Perform block for each id returned. The 'id' parameter in a block represents an id matching the query
74
74
  # @return [Array] List of ids matching criteria. Only used if no block given
75
- def ids_where(lookup = {})
75
+ def ids_where(lookup = {}, &block)
76
76
  lookup[:limit] ||= nil # Don't limit results returned
77
77
  SoqlHandler.new("Each Id where #{self}").use
78
78
  results = soql.query soql.soql_id(lookup), wait: false
79
79
  ids = results.ids
80
80
  if block_given?
81
- ids.each { |id| yield(id) }
81
+ ids.each(&block)
82
82
  else
83
83
  ids
84
84
  end
@@ -98,4 +98,27 @@ module SoqlObjectDescribe
98
98
  def field_names
99
99
  fields.collect { |field| field['name'] }
100
100
  end
101
+
102
+ # @return [Hash] List of accessors for an object and what they relate to
103
+ def accessors
104
+ return @attr_hash if @attr_hash
105
+
106
+ @attr_hash = {}
107
+ fields.each do |field|
108
+ @attr_hash[field['label'].unused_ruby_name.to_sym] = important_attributes_for(field)
109
+ end
110
+ @attr_hash
111
+ end
112
+
113
+ private
114
+
115
+ # @return [Hash] Important attributes for a field
116
+ def important_attributes_for(field)
117
+ important_attributes = { backend: field['name'],
118
+ label: field['label'],
119
+ type: field['type'] }
120
+ relationship_name = field['relationshipName']
121
+ important_attributes[:related_object] = relationship_name if relationship_name
122
+ important_attributes
123
+ end
101
124
  end
@@ -16,9 +16,9 @@ module LeapSalesforce
16
16
 
17
17
  # @param [String, Symbol] key Key used to identify a test user
18
18
  # @param [String] username Name used to login with user. In email address format.
19
- def initialize(key, username, description: nil)
20
- self.key = key
21
- self.username = username
19
+ def initialize(*user_params, description: nil)
20
+ self.key = user_params[0]
21
+ self.username = user_params[1]
22
22
  self.description = description
23
23
  end
24
24
 
@@ -85,11 +85,9 @@ module LeapSalesforce
85
85
  private
86
86
 
87
87
  # Execute block as admin user, raising error if User class is not defined
88
- def admin_query_user
88
+ def admin_query_user(&block)
89
89
  if defined? ::User
90
- Users.execute_as_if_present key: :admin do
91
- yield
92
- end
90
+ Users.execute_as_if_present key: :admin, &block
93
91
  else
94
92
  raise LeapSalesforce::SetupError, "'User' class must be defined " \
95
93
  " to check presence of user in environment #{LeapSalesforce.environment}"
@@ -23,8 +23,12 @@ module LeapSalesforce
23
23
  raise LeapSalesforce::UserError, "Incorrect type #{user.class} for user. Expected either " \
24
24
  'type LeapSalesforce::User or Array'
25
25
  end
26
+ if user[2]
27
+ desc = user[2].is_a?(Hash) ? user[2].values[0] : user[2].dup
28
+ user[2] = nil
29
+ end
26
30
 
27
- @list << User.new(*user)
31
+ @list << User.new(*user, description: desc)
28
32
  end
29
33
 
30
34
  # @example Filter user by key of :admin
@@ -34,14 +38,16 @@ module LeapSalesforce
34
38
  # @example Filter user by username
35
39
  # where(username: 'username@domain.com')
36
40
  # @param [Symbol, Hash, String, Regexp, LeapSalesforce::User] filter Filter to find users by
37
- # @param [Boolean] all Whether to return all users matching criteria, not just first
41
+ # @param_key [Boolean] all Whether to return all users matching criteria, not just first
38
42
  # @return [LeapSalesforce::User, Array] A user that meets the criteria.
39
43
  # If all is true this returns array of users
40
- def where(filter, all: false)
41
- @all = all
44
+ def where(filter)
45
+ @all = false
42
46
  case filter
43
47
  when :default then list.first # Will then use first user defined
44
- when Hash then match_params filter
48
+ when Hash
49
+ @all = filter[:all] || false
50
+ match_params filter
45
51
  when String then match_params(username: filter)
46
52
  when Symbol then match_params(key: filter)
47
53
  when Regexp then match_params(description: filter)
@@ -54,11 +60,11 @@ module LeapSalesforce
54
60
  alias [] where
55
61
 
56
62
  # Iterate through each user, narrowing on filter if provided
57
- def each(filter = nil)
63
+ def each(filter = nil, &block)
58
64
  if filter
59
- where(filter, all: true).each { yield }
65
+ where({ **filter, all: true }).each(&block)
60
66
  else
61
- list.each { yield }
67
+ list.each(&block)
62
68
  end
63
69
  end
64
70
 
@@ -86,11 +92,11 @@ module LeapSalesforce
86
92
  # Execute block as user matching filter if that user is present
87
93
  # If user is not present the current user will be used
88
94
  # @return [Object] Result of block
89
- def execute_as_if_present(user_filter)
95
+ def execute_as_if_present(user_filter, &block)
90
96
  raise ArgumentError, 'Pass block to :execute_as_if_present method' unless block_given?
91
97
 
92
98
  if any? user_filter
93
- execute_as(user_filter) { yield }
99
+ execute_as(user_filter, &block)
94
100
  else
95
101
  LeapSalesforce.logger.warn "No user found user filter #{user_filter}, using '#{LeapSalesforce.api_user}'"
96
102
  yield
@@ -2,5 +2,5 @@
2
2
 
3
3
  module LeapSalesforce
4
4
  # @return [String] Version of leap salesforce
5
- VERSION = '0.2.28'
5
+ VERSION = '1.0.4'
6
6
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leap_salesforce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.28
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - IQA
8
8
  - Samuel Garratt
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-04-29 00:00:00.000000000 Z
12
+ date: 2021-02-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -355,7 +355,7 @@ homepage: https://gitlab.com/leap-dojo/leap_salesforce
355
355
  licenses:
356
356
  - MIT
357
357
  metadata: {}
358
- post_install_message:
358
+ post_install_message:
359
359
  rdoc_options: []
360
360
  require_paths:
361
361
  - lib
@@ -371,7 +371,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
371
371
  version: '0'
372
372
  requirements: []
373
373
  rubygems_version: 3.0.6
374
- signing_key:
374
+ signing_key:
375
375
  specification_version: 4
376
376
  summary: Helps with setting up integrated automated test frameworks against Salesforce.
377
377
  test_files: []