g5_updatable 0.2.1 → 0.3.1

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -34
  3. data/app/concerns/g5_updatable/belongs_to_location.rb +14 -0
  4. data/app/concerns/g5_updatable/first_class_properties.rb +25 -0
  5. data/app/concerns/g5_updatable/urn_as_parameter.rb +7 -0
  6. data/app/controllers/g5_updatable/feed_controller.rb +1 -1
  7. data/app/models/g5_updatable/client.rb +12 -0
  8. data/app/models/g5_updatable/integration_setting.rb +20 -0
  9. data/app/models/g5_updatable/location.rb +16 -0
  10. data/app/serializers/g5_updatable/location_serializer.rb +12 -0
  11. data/db/migrate/20140709222005_create_g5_updatable_clients_and_locations.rb +24 -0
  12. data/db/migrate/20141030211945_create_integration_setting.rb +18 -0
  13. data/lib/g5_updatable/client_feed_processor.rb +34 -12
  14. data/lib/g5_updatable/client_updater.rb +7 -16
  15. data/lib/g5_updatable/engine.rb +2 -13
  16. data/lib/g5_updatable/integration_settings_updater.rb +21 -0
  17. data/lib/g5_updatable/locations_updater.rb +14 -21
  18. data/lib/g5_updatable/rspec/factories.rb +19 -0
  19. data/lib/g5_updatable/rspec.rb +3 -0
  20. data/lib/g5_updatable/version.rb +1 -1
  21. data/lib/g5_updatable.rb +2 -1
  22. data/lib/generators/g5_updatable/install/USAGE +0 -3
  23. data/lib/generators/g5_updatable/install/install_generator.rb +0 -6
  24. data/lib/tasks/g5_updatable_tasks.rake +12 -4
  25. data/spec/concerns/g5_updatable/belongs_to_location_spec.rb +30 -0
  26. data/spec/dummy/app/models/favorite_food.rb +3 -0
  27. data/spec/dummy/config/database.sample.yml +9 -0
  28. data/spec/dummy/config/database.travis.yml +4 -0
  29. data/spec/dummy/db/migrate/20140709220627_drop_clients_and_locations.rb +10 -0
  30. data/spec/dummy/db/migrate/20140714225203_create_favorite_foods.rb +10 -0
  31. data/spec/dummy/db/schema.rb +39 -21
  32. data/spec/dummy/log/test.log +18589 -920
  33. data/spec/lib/g5_updatable/client_feed_processor_spec.rb +77 -22
  34. data/spec/lib/g5_updatable/client_updater_spec.rb +28 -41
  35. data/spec/lib/g5_updatable/integration_settings_updater_spec.rb +48 -0
  36. data/spec/lib/g5_updatable/locations_updater_spec.rb +29 -52
  37. data/spec/lib/generators/g5_updatable/install_generator_spec.rb +0 -12
  38. data/spec/models/g5_updatable/client_spec.rb +25 -0
  39. data/spec/models/g5_updatable/integration_setting_spec.rb +33 -0
  40. data/spec/models/g5_updatable/location_spec.rb +34 -0
  41. data/spec/serializers/g5_updatable/location_serializer_spec.rb +21 -0
  42. data/spec/spec_helper.rb +13 -5
  43. data/spec/support/shared_example_for_urn_as_parameter.rb +7 -0
  44. data/spec/support/shared_examples_for_first_class_properties_json.rb +29 -0
  45. metadata +104 -42
  46. data/lib/g5_updatable/feed_mapper.rb +0 -58
  47. data/lib/g5_updatable/g5_client.rb +0 -10
  48. data/lib/g5_updatable/g5_location.rb +0 -22
  49. data/lib/generators/g5_updatable/install/templates/g5_updatable.rb +0 -25
  50. data/spec/dummy/config/database.yml +0 -25
  51. data/spec/dummy/config/initializers/g5_updatable.rb +0 -4
  52. data/spec/dummy/db/development.sqlite3 +0 -0
  53. data/spec/dummy/log/development.log +0 -6434
  54. data/spec/dummy/spec/fabricators/client_fabricator.rb +0 -6
  55. data/spec/dummy/spec/fabricators/location_fabricator.rb +0 -9
  56. data/spec/dummy/spec/models/client_spec.rb +0 -0
  57. data/spec/dummy/spec/models/location_spec.rb +0 -0
  58. data/spec/dummy/spec/support/client_feed.html +0 -97
  59. data/spec/dummy/spec/support/updated_client_feed.html +0 -148
  60. data/spec/fabricators/client_fabricator.rb +0 -6
  61. data/spec/fabricators/location_fabricator.rb +0 -9
  62. data/spec/lib/g5_updatable/feed_mapper_spec.rb +0 -119
  63. data/spec/lib/tmp/config/initializers/g5_updatable.rb +0 -25
@@ -1,38 +1,93 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe G5Updatable::ClientFeedProcessor do
4
- let(:client_updater) { double(update: nil) }
5
- let(:locations_updater) { double(update: nil) }
4
+ describe ".new" do
5
+ let(:processor) { described_class.new(passed_uid) }
6
+ subject(:client_uid) { processor.client_uid }
7
+ let(:configured_client_uid) { nil }
6
8
 
7
- before do
8
- allow(G5Updatable::ClientUpdater).to receive(:new) { client_updater }
9
- allow(G5Updatable::LocationsUpdater).to receive(:new) { locations_updater }
10
- end
11
-
12
- describe "#work" do
13
- after { described_class.new(urn).work }
14
- let(:urn) { nil }
9
+ context "when CLIENT_UID is unset" do
10
+ context "with a passed-in client_uid" do
11
+ let(:passed_uid) { "passed" }
12
+ it { should eq("passed") }
13
+ end
15
14
 
16
- context "a nil urn" do
17
- before { allow(G5Updatable).to receive(:client_identifier) { nil } }
15
+ context "with no passed-in client_uid" do
16
+ let(:passed_uid) { nil }
18
17
 
19
- it "does not call update on the client updater" do
20
- expect(client_updater).to_not receive(:update)
18
+ it "explodes helpfully" do
19
+ expect { client_uid }.to raise_error(/client_uid/)
20
+ end
21
21
  end
22
+ end
22
23
 
23
- it "does not call update on the locations updater" do
24
- expect(locations_updater).to_not receive(:update)
24
+ context "when CLIENT_UID is set" do
25
+ before do
26
+ @old_client_uid = ENV["CLIENT_UID"]
27
+ ENV["CLIENT_UID"] = "configured"
25
28
  end
26
- end
29
+ after { ENV["CLIENT_UID"] = @old_client_uid }
27
30
 
28
- context "a present urn" do
29
- it "calls update on the client updater" do
30
- expect(client_updater).to receive(:update)
31
+ context "with a passed-in client_uid" do
32
+ let(:passed_uid) { "passed" }
33
+ it { should eq("passed") }
31
34
  end
32
35
 
33
- it "calls update on the locations updater" do
34
- expect(locations_updater).to receive(:update)
36
+ context "with no passed-in client_uid" do
37
+ let(:passed_uid) { nil }
38
+ it { should eq("configured") }
35
39
  end
36
40
  end
37
41
  end
42
+
43
+ describe "#work" do
44
+ let(:client_updater) { double(update: nil) }
45
+ let(:locations_updater) { double(update: nil) }
46
+ let(:integration_settings_updater) { double(update: nil) }
47
+
48
+ let(:client) { G5FoundationClient::Client.new(uid: client_uid,
49
+ urn: "urn",
50
+ name: "Client Name",
51
+ locations: [{uid: location_uid, locations_integration_settings: [{uid: integration_setting_uid, vendor_action: 'inventory'}]}]) }
52
+ let(:client_uid) { "http://example.com/cilent_uid" }
53
+ let(:location_uid) { "http://example.com/cilent_uid/locations/location_uid" }
54
+ let(:integration_setting_uid) { "http://example.com/cilent_uid/locations/location_uid/integration_setting_uid" }
55
+
56
+ before do
57
+ stub_client_for_uid(client_uid, client)
58
+ allow(G5Updatable::ClientUpdater).to receive(:new) { client_updater }
59
+ allow(G5Updatable::LocationsUpdater).to receive(:new) { locations_updater }
60
+ allow(G5Updatable::IntegrationSettingsUpdater).to receive(:new) { integration_settings_updater }
61
+ G5Updatable::ClientFeedProcessor.new(client_uid).work
62
+ end
63
+
64
+ it "updates with the found client" do
65
+ expect(G5Updatable::ClientUpdater).to have_received(:new).with(client)
66
+ expect(client_updater).to have_received(:update)
67
+ end
68
+
69
+ it "updates with the client's associated locations" do
70
+ expect(G5Updatable::LocationsUpdater).to have_received(:new).with(client.locations)
71
+ expect(locations_updater).to have_received(:update)
72
+ end
73
+
74
+ it "updates with location's associated integration settings" do
75
+ expect(G5Updatable::IntegrationSettingsUpdater).to have_received(:new).with(client.locations.first.integration_settings)
76
+ expect(integration_settings_updater).to have_received(:update)
77
+ end
78
+ end
79
+
80
+ describe :load_all_clients do
81
+ let(:clients_url) { 'http://g5-hub-clients-url' }
82
+ let(:client_uids) { %w(uid-1 uid-2) }
83
+ before do
84
+ expect(G5FoundationClient::Client).to receive(:all_client_uids).with(clients_url).and_return(client_uids)
85
+ expect(G5Updatable::ClientFeedProcessor).to receive(:new).with('uid-1').and_return(double(:work1, work: 'work-1'))
86
+ expect(G5Updatable::ClientFeedProcessor).to receive(:new).with('uid-2').and_return(double(:work1, work: 'work-2'))
87
+ end
88
+
89
+ it 'loads every client' do
90
+ expect(G5Updatable::ClientFeedProcessor.load_all_clients(clients_url)).to eq(%w(work-1 work-2))
91
+ end
92
+ end
38
93
  end
@@ -1,58 +1,45 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe G5Updatable::ClientUpdater do
4
- let(:feed_endpoint) { "#{Rails.root}/spec/support/" }
5
- let(:client_identifier) { "client_feed.html" }
6
- let(:client_uid) { "#{Rails.root}/spec/support/client_feed.html" }
7
- let(:g5_client) { G5Updatable::FeedMapper.new(client_identifier).client }
8
- let(:updater) { described_class.new(g5_client) }
4
+ let(:uid) { "http://example.com/uid" }
5
+ let(:properties) { {uid: uid,
6
+ urn: "urn",
7
+ name: "Client Name", } }
8
+ let(:g5_client) { G5FoundationClient::Client.new(properties) }
9
9
 
10
- before do
11
- allow(G5Updatable).to receive(:feed_endpoint) { feed_endpoint }
12
- allow(G5Updatable).to receive(:client_identifier) { client_identifier }
13
- end
10
+ let(:updater) { described_class.new(g5_client) }
14
11
 
15
12
  describe "#update" do
16
- let!(:client) do
17
- Fabricate(:client, uid: client_uid, name: "Foo", vertical: "Self-Storage")
18
- end
13
+ subject { G5Updatable::Client.first }
19
14
 
20
- context "update client disabled" do
21
- it "does nothing" do
22
- expect(client).to_not receive(:save)
23
- updater.update
24
- end
25
- end
15
+ context "with no existing Client records" do
16
+ before { updater.update }
26
17
 
27
- context "update client enabled" do
28
- before { allow(G5Updatable).to receive(:update_client) { true } }
29
-
30
- context "default parameters" do
31
- it "updates the name attribute" do
32
- expect { updater.update }.to change { client.reload.name }.
33
- from("Foo").to("Farmhouse")
34
- end
18
+ it "creates a Client" do
19
+ expect(G5Updatable::Client.count).to eq(1)
20
+ end
35
21
 
36
- it "does not update other attributes" do
37
- expect { updater.update }.not_to change { client.reload.vertical }
38
- end
22
+ it 'does not redact keys in properties' do
23
+ expect(subject.properties.keys.collect(&:to_sym)).to eq(properties.keys)
39
24
  end
40
25
 
41
- context "custom parameters" do
42
- before do
43
- allow(G5Updatable).to receive(:client_parameters) { [:name, :vertical] }
44
- end
26
+ its(:uid) { should eq(uid) }
27
+ its(:urn) { should eq("urn") }
28
+ its(:name) { should eq("Client Name") }
29
+ end
45
30
 
46
- it "updates the name attribute" do
47
- expect { updater.update }.to change { client.reload.name }.
48
- from("Foo").to("Farmhouse")
49
- end
31
+ context "with an existing Client record" do
32
+ before do
33
+ FactoryGirl.create(:client, uid: uid, urn: "old")
34
+ updater.update
35
+ end
50
36
 
51
- it "updates other attributes" do
52
- expect { updater.update }.to change { client.reload.vertical }.
53
- from("Self-Storage").to("Apartments")
54
- end
37
+ it "does not create a new Client" do
38
+ expect(G5Updatable::Client.count).to eq(1)
55
39
  end
40
+
41
+ its(:urn) { should eq("urn") }
42
+ its(:name) { should eq("Client Name") }
56
43
  end
57
44
  end
58
45
  end
@@ -0,0 +1,48 @@
1
+ require "spec_helper"
2
+
3
+ describe G5Updatable::IntegrationSettingsUpdater do
4
+ let(:uid) { "http://example.com/uid" }
5
+ let(:name) { "integration setting name" }
6
+ let(:properties) { {uid: uid,
7
+ urn: "urn",
8
+ vendor_action: "inventory",
9
+ location_uid: "location_uid",
10
+ job_frequency_in_minutes: 22,
11
+ name: name} }
12
+ let(:integration_setting) { G5FoundationClient::IntegrationSetting.new(properties) }
13
+
14
+ let(:updater) { described_class.new([integration_setting]) }
15
+
16
+ describe "#update" do
17
+ subject { G5Updatable::IntegrationSetting.first }
18
+
19
+ context "with no existing integration-setting records" do
20
+ before { updater.update }
21
+
22
+ it "creates a Location" do
23
+ expect(G5Updatable::IntegrationSetting.count).to eq(1)
24
+ end
25
+
26
+ its(:job_frequency_in_minutes) { should eq(22) }
27
+ its(:uid) { should eq(uid) }
28
+ its(:urn) { should eq("urn") }
29
+ its(:location_uid) { should eq("location_uid") }
30
+ its(:name) { should eq(name) }
31
+ its(:vendor_action) { should eq("inventory") }
32
+ end
33
+
34
+ context "with an existing integration-setting record" do
35
+ before do
36
+ create(:integration_setting, uid: uid, urn: "old")
37
+ updater.update
38
+ end
39
+
40
+ it "does not create a new IntegrationSetting" do
41
+ expect(G5Updatable::IntegrationSetting.count).to eq(1)
42
+ end
43
+
44
+ its(:urn) { should eq("urn") }
45
+ its(:name) { should eq(name) }
46
+ end
47
+ end
48
+ end
@@ -1,71 +1,48 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe G5Updatable::LocationsUpdater do
4
- let(:feed_endpoint) { "#{Rails.root}/spec/support/" }
5
- let(:client_identifier) { "updated_client_feed.html" }
6
- let(:locations) { G5Updatable::FeedMapper.new(client_identifier).locations }
7
- let(:g5_location) { locations.first }
8
- let(:urn) { g5_location.uid.to_s.split("/").last }
9
- let(:updater) { described_class.new(locations) }
4
+ let(:uid) { "http://example.com/uid" }
5
+ let(:properties) { {uid: uid,
6
+ urn: "urn",
7
+ client_uid: "client_uid",
8
+ name: "Location Name"} }
9
+ let(:g5_location) { G5FoundationClient::Location.new(properties) }
10
10
 
11
- before do
12
- allow(G5Updatable).to receive(:feed_endpoint) { feed_endpoint }
13
- allow(G5Updatable).to receive(:client_identifier) { client_identifier }
14
- end
11
+ let(:updater) { described_class.new([g5_location]) }
15
12
 
16
13
  describe "#update" do
17
- let!(:location) do
18
- Fabricate(:location, urn: urn, name: "Foo", neighborhood: "Eastside")
19
- end
20
-
21
- context "update locations disabled" do
22
- before { allow(G5Updatable).to receive(:update_locations) { false } }
14
+ subject { G5Updatable::Location.first }
23
15
 
24
- it "does not update existing locations" do
25
- expect(locations).to_not receive(:save)
26
- updater.update
27
- end
16
+ context "with no existing Location records" do
17
+ before { updater.update }
28
18
 
29
- it "creates new locations" do
30
- expect { updater.update }.to change { Location.all.size }.from(1).to(2)
19
+ it "creates a Location" do
20
+ expect(G5Updatable::Location.count).to eq(1)
31
21
  end
32
- end
33
22
 
34
- context "update locations enabled" do
35
- context "default parameters" do
36
- it "updates the name attribute" do
37
- expect { updater.update }.to change { location.reload.name }.
38
- from("Foo").to("Hollywood")
39
- end
40
23
 
41
- it "does not update other attributes" do
42
- expect { updater.update }.not_to change { location.reload.neighborhood }
43
- end
44
-
45
- it "creates new locations" do
46
- expect { updater.update }.to change { Location.all.size }.from(1).to(2)
47
- end
24
+ it 'does not redact keys in properties' do
25
+ expect(subject.properties.keys.collect(&:to_sym)).to eq(properties.keys)
48
26
  end
49
27
 
50
- context "custom parameters" do
51
- before do
52
- allow(G5Updatable).to receive(:location_parameters) { [:name, :neighborhood] }
53
- end
54
-
55
- it "updates the name attribute" do
56
- expect { updater.update }.to change { location.reload.name }.
57
- from("Foo").to("Hollywood")
58
- end
28
+ its(:uid) { should eq(uid) }
29
+ its(:urn) { should eq("urn") }
30
+ its(:client_uid) { should eq("client_uid") }
31
+ its(:name) { should eq("Location Name") }
32
+ end
59
33
 
60
- it "updates other attributes" do
61
- expect { updater.update }.to change { location.reload.neighborhood }.
62
- from("Eastside").to("River West")
63
- end
34
+ context "with an existing Location record" do
35
+ before do
36
+ FactoryGirl.create(:location, uid: uid, urn: "old")
37
+ updater.update
38
+ end
64
39
 
65
- it "creates new locations" do
66
- expect { updater.update }.to change { Location.all.size }.from(1).to(2)
67
- end
40
+ it "does not create a new Location" do
41
+ expect(G5Updatable::Location.count).to eq(1)
68
42
  end
43
+
44
+ its(:urn) { should eq("urn") }
45
+ its(:name) { should eq("Location Name") }
69
46
  end
70
47
  end
71
48
  end
@@ -11,18 +11,6 @@ describe G5Updatable::InstallGenerator, type: :generator do
11
11
  run_generator
12
12
  end
13
13
 
14
- it "should copy the g5_updatable initializer" do
15
- expect(destination_root).to have_structure {
16
- directory "config" do
17
- directory "initializers" do
18
- file "g5_updatable.rb" do
19
- contains "G5Updatable.setup do |config|"
20
- end
21
- end
22
- end
23
- }
24
- end
25
-
26
14
  it "should mount the engine" do
27
15
  expect(destination_root).to have_structure {
28
16
  directory "config" do
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe G5Updatable::Client do
4
+ describe "validations" do
5
+ subject(:client) { G5Updatable::Client.new }
6
+
7
+ it { expect(client).to validate_presence_of(:uid) }
8
+ it { expect(client).to validate_presence_of(:urn) }
9
+ end
10
+
11
+ it_behaves_like "a model with first-class properties" do
12
+ let(:instance_factory_name) { :client }
13
+ end
14
+
15
+ it_behaves_like "a model that uses its URN as its parameter" do
16
+ let(:instance_factory_name) { :client }
17
+ end
18
+
19
+ describe :locations do
20
+ let!(:location) { create(:location, client_uid: subject.uid) }
21
+ subject { create(:client) }
22
+
23
+ its(:locations) { is_expected.to eq([location]) }
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe G5Updatable::IntegrationSetting do
4
+ describe 'validations' do
5
+ subject(:integration_setting) { G5Updatable::IntegrationSetting.new }
6
+ it { expect(integration_setting).to validate_presence_of(:location_uid) }
7
+ it { expect(integration_setting).to validate_presence_of(:uid) }
8
+ end
9
+
10
+ it_behaves_like 'a model with first-class properties' do
11
+ let(:instance_factory_name) { :integration_setting }
12
+ end
13
+
14
+ it_behaves_like 'a model that uses its URN as its parameter' do
15
+ let(:instance_factory_name) { :client }
16
+ end
17
+
18
+ describe "#location" do
19
+ let(:integration_setting) { create(:integration_setting, location_uid: location.uid) }
20
+ let(:location) { create(:location) }
21
+ subject { integration_setting.location }
22
+
23
+ it { should eq(location) }
24
+ end
25
+
26
+ describe :by_vendor_action do
27
+ let!(:inventory) { create(:integration_setting, vendor_action: G5Updatable::IntegrationSetting::INVENTORY) }
28
+ let!(:lead) { create(:integration_setting, vendor_action: G5Updatable::IntegrationSetting::LEAD) }
29
+
30
+ it { expect(G5Updatable::IntegrationSetting.by_lead).to eq([lead]) }
31
+ it { expect(G5Updatable::IntegrationSetting.by_inventory).to eq([inventory]) }
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe G5Updatable::Location do
4
+ describe "validations" do
5
+ subject(:location) { G5Updatable::Location.new }
6
+
7
+ it { expect(location).to validate_presence_of(:uid) }
8
+ it { expect(location).to validate_presence_of(:urn) }
9
+ it { expect(location).to validate_presence_of(:client_uid) }
10
+ end
11
+
12
+ it_behaves_like "a model with first-class properties" do
13
+ let(:instance_factory_name) { :location }
14
+ end
15
+
16
+ it_behaves_like "a model that uses its URN as its parameter" do
17
+ let(:instance_factory_name) { :location }
18
+ end
19
+
20
+ describe "#client" do
21
+ let(:client) { FactoryGirl.create(:client) }
22
+ let(:location) { FactoryGirl.create(:location, client_uid: client.uid) }
23
+ subject { location.client }
24
+
25
+ it { should eq(client) }
26
+ end
27
+
28
+ describe :integration_settings do
29
+ let!(:integration_setting) { create(:integration_setting, location_uid: subject.uid) }
30
+ subject { create(:location) }
31
+
32
+ its(:integration_settings) { is_expected.to eq([integration_setting]) }
33
+ end
34
+ end