restforce-db 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rubocop/custom/method_documentation.rb +65 -0
  4. data/.rubocop.yml +39 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +68 -0
  9. data/Rakefile +13 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +7 -0
  12. data/lib/generators/restforce_generator.rb +19 -0
  13. data/lib/generators/templates/config.yml +8 -0
  14. data/lib/generators/templates/script +6 -0
  15. data/lib/restforce/db/command.rb +98 -0
  16. data/lib/restforce/db/configuration.rb +50 -0
  17. data/lib/restforce/db/instances/active_record.rb +48 -0
  18. data/lib/restforce/db/instances/base.rb +66 -0
  19. data/lib/restforce/db/instances/salesforce.rb +46 -0
  20. data/lib/restforce/db/mapping.rb +106 -0
  21. data/lib/restforce/db/model.rb +50 -0
  22. data/lib/restforce/db/record_type.rb +77 -0
  23. data/lib/restforce/db/record_types/active_record.rb +80 -0
  24. data/lib/restforce/db/record_types/base.rb +44 -0
  25. data/lib/restforce/db/record_types/salesforce.rb +94 -0
  26. data/lib/restforce/db/synchronizer.rb +57 -0
  27. data/lib/restforce/db/version.rb +10 -0
  28. data/lib/restforce/db/worker.rb +156 -0
  29. data/lib/restforce/db.rb +77 -0
  30. data/lib/restforce/extensions.rb +19 -0
  31. data/restforce-db.gemspec +41 -0
  32. data/test/cassettes/Restforce_DB/accessing_Salesforce/uses_the_configured_credentials.yml +43 -0
  33. data/test/cassettes/Restforce_DB_Instances_Salesforce/_copy_/updates_the_record_with_the_attributes_from_the_copied_object.yml +193 -0
  34. data/test/cassettes/Restforce_DB_Instances_Salesforce/_update_/updates_the_local_record_with_the_passed_attributes.yml +193 -0
  35. data/test/cassettes/Restforce_DB_Instances_Salesforce/_update_/updates_the_record_in_Salesforce_with_the_passed_attributes.yml +232 -0
  36. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/creates_a_record_in_Salesforce_from_the_passed_database_record_s_attributes.yml +158 -0
  37. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/updates_the_database_record_with_the_Salesforce_record_s_ID.yml +158 -0
  38. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/finds_existing_records_in_Salesforce.yml +157 -0
  39. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/returns_nil_when_no_matching_record_exists.yml +81 -0
  40. data/test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_existing_record_in_the_database/updates_the_database_record.yml +158 -0
  41. data/test/cassettes/Restforce_DB_Synchronizer/_run/given_an_existing_Salesforce_record/populates_the_database_with_the_new_record.yml +158 -0
  42. data/test/cassettes/Restforce_DB_Synchronizer/_run/given_an_existing_database_record/populates_Salesforce_with_the_new_record.yml +235 -0
  43. data/test/lib/restforce/db/configuration_test.rb +38 -0
  44. data/test/lib/restforce/db/instances/active_record_test.rb +39 -0
  45. data/test/lib/restforce/db/instances/salesforce_test.rb +51 -0
  46. data/test/lib/restforce/db/mapping_test.rb +70 -0
  47. data/test/lib/restforce/db/model_test.rb +48 -0
  48. data/test/lib/restforce/db/record_type_test.rb +26 -0
  49. data/test/lib/restforce/db/record_types/active_record_test.rb +85 -0
  50. data/test/lib/restforce/db/record_types/salesforce_test.rb +46 -0
  51. data/test/lib/restforce/db/synchronizer_test.rb +84 -0
  52. data/test/lib/restforce/db_test.rb +24 -0
  53. data/test/support/active_record.rb +20 -0
  54. data/test/support/database_cleaner.rb +3 -0
  55. data/test/support/salesforce.rb +48 -0
  56. data/test/support/vcr.rb +23 -0
  57. data/test/test_helper.rb +25 -0
  58. metadata +287 -0
@@ -0,0 +1,39 @@
1
+ require_relative "../../../../test_helper"
2
+
3
+ describe Restforce::DB::Instances::ActiveRecord do
4
+
5
+ configure!
6
+
7
+ let(:record) { CustomObject.create! }
8
+ let(:mapping) { Restforce::DB::Mapping.new(example: "Example_Field__c") }
9
+ let(:instance) { Restforce::DB::Instances::ActiveRecord.new(record, mapping) }
10
+
11
+ describe "#update!" do
12
+ let(:text) { "Some new text" }
13
+
14
+ before do
15
+ instance.update!(example: text)
16
+ end
17
+
18
+ it "updates the local record with the passed attributes" do
19
+ expect(record.example).to_equal text
20
+ end
21
+
22
+ it "updates the record in Salesforce with the passed attributes" do
23
+ expect(record.reload.example).to_equal text
24
+ end
25
+ end
26
+
27
+ describe "#copy!" do
28
+ let(:text) { "Copied text" }
29
+ let(:copy_from) { Struct.new(:attributes).new(example: text) }
30
+
31
+ before do
32
+ instance.copy!(copy_from)
33
+ end
34
+
35
+ it "updates the record with the attributes from the copied object" do
36
+ expect(record.example).to_equal text
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,51 @@
1
+ require_relative "../../../../test_helper"
2
+
3
+ describe Restforce::DB::Instances::Salesforce do
4
+
5
+ configure!
6
+
7
+ let(:mapping) { Restforce::DB::Mapping.new(example: "Example_Field__c") }
8
+ let(:record_type) { Restforce::DB::RecordTypes::Salesforce.new("CustomObject__c", mapping) }
9
+ let(:id) { Salesforce.create!("CustomObject__c") }
10
+ let(:instance) { record_type.find(id) }
11
+
12
+ describe "#update!", :vcr do
13
+ let(:text) { "Some new text" }
14
+
15
+ before do
16
+ instance.update!("Example_Field__c" => text)
17
+ end
18
+
19
+ it "updates the local record with the passed attributes" do
20
+ expect(instance.record.Example_Field__c).to_equal text
21
+ end
22
+
23
+ it "updates the record in Salesforce with the passed attributes" do
24
+ expect(record_type.find(id).record.Example_Field__c).to_equal text
25
+ end
26
+ end
27
+
28
+ describe "#copy!", :vcr do
29
+ let(:text) { "Copied text" }
30
+ let(:copy_from) { Struct.new(:attributes).new(example: text) }
31
+
32
+ before do
33
+ instance.copy!(copy_from)
34
+ end
35
+
36
+ it "updates the record with the attributes from the copied object" do
37
+ expect(instance.record.Example_Field__c).to_equal text
38
+ end
39
+ end
40
+
41
+ describe "#last_update" do
42
+ let(:timestamp) { "2015-03-18T20:28:24.000+0000" }
43
+ let(:record) { Struct.new(:SystemModstamp).new(timestamp) }
44
+ let(:instance) { Restforce::DB::Instances::Salesforce.new(record) }
45
+
46
+ it "parses a time from the record's system modification timestamp" do
47
+ expect(instance.last_update).to_equal(Time.new(2015, 3, 18, 20, 28, 24, 0))
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,70 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ describe Restforce::DB::Mapping do
4
+
5
+ configure!
6
+
7
+ let(:mapping) { Restforce::DB::Mapping.new(mappings) }
8
+ let(:mappings) do
9
+ {
10
+ column_one: "SF_Field_One__c",
11
+ column_two: "SF_Field_Two__c",
12
+ }
13
+ end
14
+
15
+ describe "#initialize" do
16
+
17
+ it "assigns the passed mappings to the object" do
18
+ expect(mapping.mappings).to_equal(mappings)
19
+ end
20
+ end
21
+
22
+ describe "#add_mappings" do
23
+ let(:new_mappings) { { a: "few", more: "mappings" } }
24
+
25
+ before do
26
+ mapping.add_mappings new_mappings
27
+ end
28
+
29
+ it "appends the passed mappings to the object's internal collection" do
30
+ expect(mapping.mappings).to_equal(mappings.merge(new_mappings))
31
+ end
32
+ end
33
+
34
+ describe "#attributes" do
35
+
36
+ it "builds a normalized Hash of database attribute values" do
37
+ attributes = mapping.attributes(:database) do |attribute|
38
+ expect(mapping.database_fields.include?(attribute)).to_equal true
39
+ attribute
40
+ end
41
+
42
+ expect(attributes.keys).to_equal(mapping.database_fields)
43
+ expect(attributes.values).to_equal(mapping.database_fields)
44
+ end
45
+
46
+ it "builds a normalized Hash of Salesforce field values" do
47
+ attributes = mapping.attributes(:salesforce) do |attribute|
48
+ expect(mapping.salesforce_fields.include?(attribute)).to_equal true
49
+ attribute
50
+ end
51
+
52
+ expect(attributes.keys).to_equal(mapping.database_fields)
53
+ expect(attributes.values).to_equal(mapping.salesforce_fields)
54
+ end
55
+ end
56
+
57
+ describe "#convert" do
58
+ let(:attributes) { { column_one: "some value" } }
59
+
60
+ it "converts an attribute Hash to a Salesforce-compatible form" do
61
+ expect(mapping.convert(:salesforce, attributes)).to_equal(
62
+ mappings[attributes.keys.first] => attributes.values.first,
63
+ )
64
+ end
65
+
66
+ it "performs no special conversion for database columns" do
67
+ expect(mapping.convert(:database, attributes)).to_equal(attributes)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ describe Restforce::DB::Model do
4
+
5
+ configure!
6
+
7
+ let(:database_model) { CustomObject }
8
+ let(:salesforce_model) { "CustomObject__c" }
9
+ let(:mappings) do
10
+ {
11
+ name: "Name",
12
+ example: "Example_Field__c",
13
+ }
14
+ end
15
+
16
+ before do
17
+ database_model.send(:include, Restforce::DB::Model)
18
+ end
19
+
20
+ describe ".map_to" do
21
+ before do
22
+ database_model.map_to(salesforce_model, mappings)
23
+ end
24
+
25
+ it "creates a mapping in Restforce::DB::RecordType" do
26
+ expect(Restforce::DB::RecordType[database_model])
27
+ .to_be_instance_of(Restforce::DB::RecordType)
28
+ end
29
+
30
+ it "applies the passed attribute mappings to the registered RecordType" do
31
+ expect(Restforce::DB::RecordType[database_model].mapping.mappings)
32
+ .to_equal(mappings)
33
+ end
34
+ end
35
+
36
+ describe ".add_mappings" do
37
+ before do
38
+ database_model.map_to(salesforce_model)
39
+ database_model.add_mappings(mappings)
40
+ end
41
+
42
+ it "applies the passed attribute mappings to the registered RecordType" do
43
+ expect(Restforce::DB::RecordType[database_model].mapping.mappings)
44
+ .to_equal(mappings)
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,26 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ describe Restforce::DB::RecordType do
4
+
5
+ configure!
6
+
7
+ let(:database_model) { CustomObject }
8
+ let(:salesforce_model) { "CustomObject__c" }
9
+ let!(:record_type) { Restforce::DB::RecordType.new(database_model, salesforce_model) }
10
+
11
+ describe "#initialize" do
12
+
13
+ it "registers the record type in the master collection" do
14
+ expect(Restforce::DB::RecordType[database_model]).to_equal(record_type)
15
+ end
16
+ end
17
+
18
+ describe ".each" do
19
+
20
+ # Restforce::DB::RecordType actually implements Enumerable, so we're just
21
+ # going with a trivially testable portion of the Enumerable API.
22
+ it "yields the registered record types" do
23
+ expect(Restforce::DB::RecordType.first).to_equal [database_model.name, record_type]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,85 @@
1
+ require_relative "../../../../test_helper"
2
+
3
+ describe Restforce::DB::RecordTypes::ActiveRecord do
4
+
5
+ configure!
6
+
7
+ let(:mapping) { Restforce::DB::Mapping.new }
8
+ let(:record_type) { Restforce::DB::RecordTypes::ActiveRecord.new(CustomObject, mapping) }
9
+ let(:salesforce_id) { "a001a000001E1vREAL" }
10
+
11
+ describe "#sync!" do
12
+ let(:sync_from) do
13
+ Struct.new(:id, :attributes).new(
14
+ salesforce_id,
15
+ name: "Some name",
16
+ example: "Some text",
17
+ )
18
+ end
19
+ let(:instance) { record_type.sync!(sync_from).record }
20
+
21
+ before do
22
+ mapping.add_mappings(name: "Name", example: "Example_Field__c")
23
+ end
24
+
25
+ describe "without an existing database record" do
26
+
27
+ it "creates a new database record from the passed Salesforce record" do
28
+ expect(instance.salesforce_id).to_equal salesforce_id
29
+ expect(instance.name).to_equal sync_from.attributes[:name]
30
+ expect(instance.example).to_equal sync_from.attributes[:example]
31
+ end
32
+ end
33
+
34
+ describe "with an existing database record" do
35
+ let(:sync_to) do
36
+ CustomObject.create!(
37
+ name: "Existing name",
38
+ example: "Existing sample text",
39
+ salesforce_id: salesforce_id,
40
+ )
41
+ end
42
+
43
+ before { sync_to }
44
+
45
+ it "updates the existing database record" do
46
+ expect(instance).to_equal sync_to.reload
47
+ expect(instance.name).to_equal sync_from.attributes[:name]
48
+ expect(instance.example).to_equal sync_from.attributes[:example]
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "#create!" do
54
+ let(:create_from) do
55
+ Struct.new(:id, :attributes).new(
56
+ salesforce_id,
57
+ name: "Some name",
58
+ example: "Some text",
59
+ )
60
+ end
61
+ let(:instance) { record_type.create!(create_from).record }
62
+
63
+ before do
64
+ mapping.add_mappings(name: "Name", example: "Example_Field__c")
65
+ end
66
+
67
+ it "creates a record in the database from the passed Salesforce record's attributes" do
68
+ expect(instance.salesforce_id).to_equal salesforce_id
69
+ expect(instance.name).to_equal create_from.attributes[:name]
70
+ expect(instance.example).to_equal create_from.attributes[:example]
71
+ end
72
+ end
73
+
74
+ describe "#find" do
75
+
76
+ it "finds existing records in the database by their salesforce id" do
77
+ CustomObject.create!(salesforce_id: salesforce_id)
78
+ expect(record_type.find(salesforce_id)).to_be_instance_of Restforce::DB::Instances::ActiveRecord
79
+ end
80
+
81
+ it "returns nil when no matching record exists" do
82
+ expect(record_type.find("a001a000001E1vFAKE")).to_be_nil
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,46 @@
1
+ require_relative "../../../../test_helper"
2
+
3
+ describe Restforce::DB::RecordTypes::Salesforce do
4
+
5
+ configure!
6
+
7
+ let(:mapping) { Restforce::DB::Mapping.new }
8
+ let(:record_type) { Restforce::DB::RecordTypes::Salesforce.new("CustomObject__c", mapping) }
9
+
10
+ describe "#create!", :vcr do
11
+ let(:database_record) do
12
+ CustomObject.create!(
13
+ name: "Something",
14
+ example: "Something else",
15
+ )
16
+ end
17
+ let(:sync_from) { Restforce::DB::Instances::ActiveRecord.new(database_record, mapping) }
18
+ let(:instance) { record_type.create!(sync_from).record }
19
+
20
+ before do
21
+ mapping.add_mappings name: "Name", example: "Example_Field__c"
22
+ Salesforce.records << ["CustomObject__c", instance.Id]
23
+ end
24
+
25
+ it "creates a record in Salesforce from the passed database record's attributes" do
26
+ expect(instance.Name).to_equal database_record.name
27
+ expect(instance.Example_Field__c).to_equal database_record.example
28
+ end
29
+
30
+ it "updates the database record with the Salesforce record's ID" do
31
+ expect(sync_from.synced?).to_equal(true)
32
+ end
33
+ end
34
+
35
+ describe "#find", :vcr do
36
+ let(:id) { Salesforce.create!("CustomObject__c") }
37
+
38
+ it "finds existing records in Salesforce" do
39
+ expect(record_type.find(id)).to_be_instance_of Restforce::DB::Instances::Salesforce
40
+ end
41
+
42
+ it "returns nil when no matching record exists" do
43
+ expect(record_type.find("a001a000001E1vFAKE")).to_be_nil
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,84 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ describe Restforce::DB::Synchronizer do
4
+
5
+ configure!
6
+
7
+ let(:mapping) { Restforce::DB::Mapping.new(name: "Name", example: "Example_Field__c") }
8
+ let(:database_type) { Restforce::DB::RecordTypes::ActiveRecord.new(CustomObject, mapping) }
9
+ let(:salesforce_type) { Restforce::DB::RecordTypes::Salesforce.new("CustomObject__c", mapping) }
10
+ let(:synchronizer) { Restforce::DB::Synchronizer.new(database_type, salesforce_type) }
11
+
12
+ describe "#run", vcr: { match_requests_on: [:method, VCR.request_matchers.uri_without_param(:q)] } do
13
+ let(:attributes) do
14
+ {
15
+ name: "Custom object",
16
+ example: "Some sample text",
17
+ }
18
+ end
19
+ let(:salesforce_id) do
20
+ Salesforce.create!(
21
+ "CustomObject__c",
22
+ mapping.convert(:salesforce, attributes),
23
+ )
24
+ end
25
+
26
+ describe "given an existing Salesforce record" do
27
+ before do
28
+ salesforce_id
29
+ synchronizer.run
30
+ end
31
+
32
+ it "populates the database with the new record" do
33
+ record = CustomObject.last
34
+
35
+ expect(record.name).to_equal attributes[:name]
36
+ expect(record.example).to_equal attributes[:example]
37
+ expect(record.salesforce_id).to_equal salesforce_id
38
+ end
39
+ end
40
+
41
+ describe "given an existing database record" do
42
+ let(:database_record) { CustomObject.create!(attributes) }
43
+ let(:salesforce_id) { database_record.reload.salesforce_id }
44
+
45
+ before do
46
+ database_record
47
+ synchronizer.run
48
+
49
+ Salesforce.records << ["CustomObject__c", salesforce_id]
50
+ end
51
+
52
+ it "populates Salesforce with the new record" do
53
+ record = salesforce_type.find(salesforce_id).record
54
+
55
+ expect(record.Name).to_equal attributes[:name]
56
+ expect(record.Example_Field__c).to_equal attributes[:example]
57
+ end
58
+ end
59
+
60
+ describe "given a Salesforce record with an existing record in the database" do
61
+ let(:database_record) do
62
+ CustomObject.create!(
63
+ name: "Some existing name",
64
+ example: "Some existing sample text",
65
+ salesforce_id: salesforce_id,
66
+ )
67
+ end
68
+
69
+ before do
70
+ database_record
71
+ salesforce_id
72
+ synchronizer.run
73
+ end
74
+
75
+ it "updates the database record" do
76
+ record = database_record.reload
77
+
78
+ expect(record.name).to_equal attributes[:name]
79
+ expect(record.example).to_equal attributes[:example]
80
+ end
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "../../test_helper"
2
+
3
+ describe Restforce::DB do
4
+
5
+ configure!
6
+
7
+ describe "#configure" do
8
+
9
+ it "yields a Configuration" do
10
+ Restforce::DB.configure do |config|
11
+ expect(config).to_be_instance_of(Restforce::DB::Configuration)
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "accessing Salesforce", :vcr do
17
+
18
+ it "uses the configured credentials" do
19
+ expect(Restforce::DB.client.authenticate!.access_token).to_not_be_nil
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,20 @@
1
+ require "active_record"
2
+
3
+ ActiveRecord::Base.logger = Logger.new("/dev/null")
4
+ ActiveRecord::Base.establish_connection(
5
+ adapter: "sqlite3",
6
+ database: ":memory:",
7
+ )
8
+
9
+ ActiveRecord::Schema.define do
10
+ create_table :custom_objects do |table|
11
+ table.column :name, :string
12
+ table.column :example, :string
13
+ table.column :salesforce_id, :string
14
+ table.timestamps null: false
15
+ end
16
+
17
+ add_index :custom_objects, :salesforce_id
18
+ end
19
+
20
+ class CustomObject < ActiveRecord::Base; end
@@ -0,0 +1,3 @@
1
+ require "database_cleaner"
2
+
3
+ DatabaseCleaner.strategy = :truncation
@@ -0,0 +1,48 @@
1
+ # A small utility class to allow for transactional Salesforce record creation.
2
+ class Salesforce
3
+
4
+ class << self
5
+
6
+ attr_accessor :records
7
+
8
+ end
9
+
10
+ self.records = []
11
+
12
+ # Public: Configure Restforce::DB for purposes of test execution.
13
+ #
14
+ # Returns nothing.
15
+ def self.configure!
16
+ Restforce::DB.configure { |config| config.load(Secrets["client"]) }
17
+ end
18
+
19
+ # Public: Create a basic instance of the passed Salesforce model.
20
+ #
21
+ # salesforce_model - The name of the model which should be created.
22
+ # attributes - A Hash of attributes to assign to the created object.
23
+ #
24
+ # Returns a Salesforce record ID.
25
+ def self.create!(salesforce_model, attributes = nil)
26
+ attributes ||= { "Name" => "Sample object" }
27
+ salesforce_id = Restforce::DB.client.create(salesforce_model, attributes)
28
+ Salesforce.records << [salesforce_model, salesforce_id]
29
+
30
+ salesforce_id
31
+ end
32
+
33
+ # Public: Clean up any data which was added to Salesforce during the current
34
+ # test run. For consistency in our tests, we reset the configuration and discard
35
+ # our current client session each time this method is run.
36
+ #
37
+ # Returns nothing.
38
+ def self.clean!
39
+ # raise Salesforce.records.inspect unless Salesforce.records.empty?
40
+ Salesforce.records.each do |entry|
41
+ Restforce::DB.client.destroy entry[0], entry[1]
42
+ end
43
+ Salesforce.records = []
44
+
45
+ Restforce::DB.reset
46
+ end
47
+
48
+ end
@@ -0,0 +1,23 @@
1
+ require "minitest-vcr"
2
+ require "vcr"
3
+ require "webmock"
4
+
5
+ VCR.configure do |c|
6
+ c.cassette_library_dir = "test/cassettes"
7
+ c.hook_into :webmock
8
+
9
+ %w(
10
+ username
11
+ password
12
+ security_token
13
+ client_id
14
+ client_secret
15
+ host
16
+ ).each do |secret|
17
+ c.filter_sensitive_data("<#{secret}>") do
18
+ CGI.escape(Secrets["client"][secret])
19
+ end
20
+ end
21
+ end
22
+
23
+ MinitestVcr::Spec.configure!
@@ -0,0 +1,25 @@
1
+ require "cgi"
2
+ require "minitest/autorun"
3
+ require "minitest/bang"
4
+ require "minitest/spec/expect"
5
+ require "yaml"
6
+
7
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
8
+ require "restforce/db"
9
+
10
+ secrets_file = File.expand_path("../config/secrets.yml", __FILE__)
11
+ Secrets = YAML.load_file(secrets_file)
12
+
13
+ Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
14
+
15
+ # :nodoc:
16
+ def configure!
17
+ before do
18
+ Salesforce.configure!
19
+ end
20
+
21
+ after do
22
+ DatabaseCleaner.clean
23
+ Salesforce.clean!
24
+ end
25
+ end