g5_updatable 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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