restforce-db 0.1.4

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.
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