diff --git a/README.md b/README.md index f983e36..e7582bb 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,7 @@ Not all objects which the Netbox API exposes are currently implemented. Implemen * Front Ports: `NetboxClientRuby.dcim.front_ports` * Interfaces: `NetboxClientRuby.dcim.interfaces` * Interface Connections: `NetboxClientRuby.dcim.interface_connections` + * Locations: `NetboxClientRuby.dcim.locations` * Manufacturers: `NetboxClientRuby.dcim.manufacturers` * Platforms: `NetboxClientRuby.dcim.platforms` * Power Connections: `NetboxClientRuby.dcim.power_connections` diff --git a/lib/netbox_client_ruby/api/dcim.rb b/lib/netbox_client_ruby/api/dcim.rb index a3cbe86..a64c61d 100644 --- a/lib/netbox_client_ruby/api/dcim.rb +++ b/lib/netbox_client_ruby/api/dcim.rb @@ -13,6 +13,7 @@ module DCIM interfaces: Interfaces, interface_connections: InterfaceConnections, inventory_items: InventoryItems, + locations: Locations, mac_addresses: MacAddresses, manufacturers: Manufacturers, platforms: Platforms, @@ -42,6 +43,7 @@ module DCIM interface: Interface, interface_connection: InterfaceConnection, inventory_item: InventoryItem, + location: Location, mac_address: MacAddress, manufacturer: Manufacturer, platform: Platform, diff --git a/lib/netbox_client_ruby/api/dcim/location.rb b/lib/netbox_client_ruby/api/dcim/location.rb new file mode 100644 index 0000000..576da1f --- /dev/null +++ b/lib/netbox_client_ruby/api/dcim/location.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module DCIM + class Location + include Entity + + id id: :id + deletable true + path 'dcim/locations/:id/' + creation_path 'dcim/locations/' + end + end +end diff --git a/lib/netbox_client_ruby/api/dcim/locations.rb b/lib/netbox_client_ruby/api/dcim/locations.rb new file mode 100644 index 0000000..aa00c32 --- /dev/null +++ b/lib/netbox_client_ruby/api/dcim/locations.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module NetboxClientRuby + module DCIM + class Locations + include Entities + + path 'dcim/locations/' + data_key 'results' + count_key 'count' + entity_creator :entity_creator + + private + + def entity_creator(raw_entity) + Location.new raw_entity['id'] + end + end + end +end diff --git a/spec/fixtures/dcim/location_1.json b/spec/fixtures/dcim/location_1.json new file mode 100644 index 0000000..c2f2e49 --- /dev/null +++ b/spec/fixtures/dcim/location_1.json @@ -0,0 +1,6 @@ +{ + "id": 1, + "name": "1", + "slug": "1", + "description": "The location of my office" +} \ No newline at end of file diff --git a/spec/fixtures/dcim/locations.json b/spec/fixtures/dcim/locations.json new file mode 100644 index 0000000..9b0c579 --- /dev/null +++ b/spec/fixtures/dcim/locations.json @@ -0,0 +1,13 @@ +{ + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "id": 1, + "name": "1", + "slug": "1", + "description": "The location of my office" + } + ] +} \ No newline at end of file diff --git a/spec/netbox_client_ruby/api/dcim/location_spec.rb b/spec/netbox_client_ruby/api/dcim/location_spec.rb new file mode 100644 index 0000000..a262bf0 --- /dev/null +++ b/spec/netbox_client_ruby/api/dcim/location_spec.rb @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::DCIM::Location, faraday_stub: true do + subject { sut.new entity_id } + + let(:entity_id) { 1 } + let(:expected_name) { '1' } + let(:sut) { described_class } + let(:base_url) { '/api/dcim/locations/' } + + let(:request_url) { "#{base_url}#{entity_id}/" } + let(:response) { File.read("spec/fixtures/dcim/location_#{entity_id}.json") } + + describe '#id' do + it 'shall be the expected id' do + expect(subject.id).to eq(entity_id) + end + end + + describe '#name' do + it 'fetches the data' do + expect(faraday).to receive(:get).and_call_original + + expect(subject.name).to_not be_nil + end + + it 'shall be the expected name' do + expect(subject.name).to eq(expected_name) + end + end + + describe '.delete' do + let(:request_method) { :delete } + let(:response_status) { 204 } + let(:response) { nil } + + it 'deletes the object' do + expect(faraday).to receive(request_method).and_call_original + subject.delete + end + end + + describe '.update' do + let(:request_method) { :patch } + let(:request_params) { { 'name' => 'noob' } } + + it 'updates the object' do + expect(faraday).to receive(request_method).and_call_original + expect(subject.update(name: 'noob').name).to eq(expected_name) + end + end + + describe '.reload' do + it 'reloads the object' do + expect(faraday).to receive(request_method).twice.and_call_original + + subject.reload + subject.reload + end + end + + describe '.save' do + let(:name) { 'foobar' } + let(:slug) { name } + let(:request_params) { { 'name' => name, 'slug' => slug } } + + context 'update' do + subject do + region = sut.new entity_id + region.name = name + region.slug = slug + region + end + + let(:request_method) { :patch } + + it 'does not call PATCH until save is called' do + expect(faraday).to_not receive(request_method) + expect(faraday).to_not receive(:get) + + expect(subject.name).to eq(name) + expect(subject.slug).to eq(slug) + end + + it 'calls PATCH when save is called' do + expect(faraday).to receive(request_method).and_call_original + + expect(subject.save).to be(subject) + end + + it 'Reads the answer from the PATCH answer' do + expect(faraday).to receive(request_method).and_call_original + + subject.save + expect(subject.name).to eq(expected_name) + expect(subject.slug).to eq(expected_name) + end + end + + context 'create' do + subject do + region = sut.new + region.name = name + region.slug = slug + region + end + + let(:request_method) { :post } + let(:request_url) { base_url } + + it 'does not POST until save is called' do + expect(faraday).to_not receive(request_method) + expect(faraday).to_not receive(:get) + + expect(subject.name).to eq(name) + expect(subject.slug).to eq(slug) + end + + it 'POSTs the data upon a call of save' do + expect(faraday).to receive(request_method).and_call_original + + expect(subject.save).to be(subject) + end + + it 'Reads the answer from the POST' do + expect(faraday).to receive(request_method).and_call_original + + subject.save + + expect(subject.id).to be(1) + expect(subject.name).to eq(expected_name) + expect(subject.slug).to eq(expected_name) + end + end + end +end diff --git a/spec/netbox_client_ruby/api/dcim/locations_spec.rb b/spec/netbox_client_ruby/api/dcim/locations_spec.rb new file mode 100644 index 0000000..84338e7 --- /dev/null +++ b/spec/netbox_client_ruby/api/dcim/locations_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NetboxClientRuby::DCIM::Locations, faraday_stub: true do + let(:expected_length) { 1 } + let(:singular_type) { NetboxClientRuby::DCIM::Location } + + let(:response) { File.read('spec/fixtures/dcim/locations.json') } + let(:request_url) { '/api/dcim/locations/' } + let(:request_url_params) do + { limit: NetboxClientRuby.config.netbox.pagination.default_limit } + end + + context 'unpaged fetch' do + describe '#length' do + it 'shall be the expected length' do + expect(subject.length).to be expected_length + end + end + + describe '#total' do + it 'shall be the expected total' do + expect(subject.total).to be expected_length + end + end + end + + describe '#reload' do + it 'fetches the correct data' do + expect(faraday).to receive(:get).and_call_original + subject.reload + end + + it 'caches the data' do + expect(faraday).to receive(:get).and_call_original + subject.total + subject.total + end + + it 'reloads the data' do + expect(faraday).to receive(:get).twice.and_call_original + subject.reload + subject.reload + end + end + + describe '#as_array' do + it 'return the correct amount' do + expect(subject.to_a.length).to be expected_length + end + + it 'returns Location instances' do + subject.to_a.each do |element| + expect(element).to be_a singular_type + end + end + end +end