From eca4ae4f54eb5c25a2fd4fd990d928d207699339 Mon Sep 17 00:00:00 2001 From: Brooke Kuhlmann Date: Thu, 11 Dec 2025 11:42:04 -0700 Subject: [PATCH] Added IP addresses endpoint Necessary to request IP address data. As addressed in the previous contract and model commits, RuboCop is updated to ignore the IP addresses in the specs since this can't be avoided. Milestone: minor --- .config/rubocop/config.yml | 1 + lib/trmnl/api/client.rb | 4 ++ lib/trmnl/api/endpoints/container.rb | 1 + lib/trmnl/api/endpoints/ip_address.rb | 30 +++++++++ spec/lib/trmnl/api/client_spec.rb | 10 +++ .../trmnl/api/endpoints/ip_address_spec.rb | 66 +++++++++++++++++++ 6 files changed, 112 insertions(+) create mode 100644 lib/trmnl/api/endpoints/ip_address.rb create mode 100644 spec/lib/trmnl/api/endpoints/ip_address_spec.rb diff --git a/.config/rubocop/config.yml b/.config/rubocop/config.yml index d19cf14..089e133 100644 --- a/.config/rubocop/config.yml +++ b/.config/rubocop/config.yml @@ -13,3 +13,4 @@ Style/IpAddresses: Exclude: - spec/lib/trmnl/api/types_spec.rb - spec/lib/trmnl/api/models/ip_address_spec.rb + - spec/lib/trmnl/api/endpoints/ip_address_spec.rb diff --git a/lib/trmnl/api/client.rb b/lib/trmnl/api/client.rb index 45228ed..b41d97a 100644 --- a/lib/trmnl/api/client.rb +++ b/lib/trmnl/api/client.rb @@ -13,6 +13,7 @@ module TRMNL endpoint_current_screen: :current_screen, endpoint_display: :display, endpoint_firmware: :firmware, + endpoint_ip_addresses: :ip_addresses, endpoint_log: :log, endpoint_models: :models, endpoint_setup: :setup @@ -23,6 +24,7 @@ module TRMNL endpoint_current_screen: :class, endpoint_display: :class, endpoint_firmware: :class, + endpoint_ip_addresses: :class, endpoint_log: :class, endpoint_models: :class, endpoint_setup: :class @@ -41,6 +43,8 @@ module TRMNL def firmware = endpoint_firmware.call + def ip_addresses = endpoint_ip_addresses.call + def log(**) = endpoint_log.call(**) def models(**) = endpoint_models.call(**) diff --git a/lib/trmnl/api/endpoints/container.rb b/lib/trmnl/api/endpoints/container.rb index 4886896..3ab1294 100644 --- a/lib/trmnl/api/endpoints/container.rb +++ b/lib/trmnl/api/endpoints/container.rb @@ -13,6 +13,7 @@ module TRMNL register(:current_screen) { CurrentScreen.new } register(:display) { Display.new } register(:firmware) { Firmware.new } + register(:ip_addresses) { IPAddress.new } register(:log) { Log.new } register(:models) { Model.new } register(:setup) { Setup.new } diff --git a/lib/trmnl/api/endpoints/ip_address.rb b/lib/trmnl/api/endpoints/ip_address.rb new file mode 100644 index 0000000..5fe652e --- /dev/null +++ b/lib/trmnl/api/endpoints/ip_address.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require "inspectable" +require "pipeable" + +module TRMNL + module API + module Endpoints + # Handles API request/response. + class IPAddress + include TRMNL::API::Dependencies[ + :requester, + contract: "contracts.ip_address", + model: "models.ip_address" + ] + + include Inspectable[contract: :class] + include Pipeable + + def call + pipe requester.get("ips"), + try(:parse, catch: JSON::ParserError), + validate(contract, as: :to_h), + as(:fetch, :data), + to(model, :for) + end + end + end + end +end diff --git a/spec/lib/trmnl/api/client_spec.rb b/spec/lib/trmnl/api/client_spec.rb index 1bceef7..ee34433 100644 --- a/spec/lib/trmnl/api/client_spec.rb +++ b/spec/lib/trmnl/api/client_spec.rb @@ -67,6 +67,15 @@ RSpec.describe TRMNL::API::Client do end end + describe "#ip_addresses" do + let(:endpoint) { instance_spy TRMNL::API::Endpoints::IPAddress } + + it "messages endpoint" do + client = described_class.new endpoint_ip_addresses: endpoint + expect(client.ip_addresses).to have_received(:call) + end + end + describe "#log" do let(:endpoint) { instance_spy TRMNL::API::Endpoints::Log } @@ -100,6 +109,7 @@ RSpec.describe TRMNL::API::Client do "@endpoint_current_screen=TRMNL::API::Endpoints::CurrentScreen, " \ "@endpoint_display=TRMNL::API::Endpoints::Display, " \ "@endpoint_firmware=TRMNL::API::Endpoints::Firmware, " \ + "@endpoint_ip_addresses=TRMNL::API::Endpoints::IPAddress, " \ "@endpoint_log=TRMNL::API::Endpoints::Log, " \ "@endpoint_models=TRMNL::API::Endpoints::Model, " \ "@endpoint_setup=TRMNL::API::Endpoints::Setup, " diff --git a/spec/lib/trmnl/api/endpoints/ip_address_spec.rb b/spec/lib/trmnl/api/endpoints/ip_address_spec.rb new file mode 100644 index 0000000..4ca56cd --- /dev/null +++ b/spec/lib/trmnl/api/endpoints/ip_address_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe TRMNL::API::Endpoints::IPAddress do + subject(:endpoint) { described_class.new requester: } + + include_context "with application dependencies" + + let(:requester) { TRMNL::API::Requester.new http: } + + describe "#call" do + let :http do + HTTP::Fake::Client.new do + get "/api/ips" do + headers["Content-Type"] = "application/json" + status 200 + + <<~JSON + { + "data": { + "ipv4": ["192.168.1.10"], + "ipv6": ["1a00:100:100:1000::1"] + } + } + JSON + end + end + end + + it "answers success" do + result = endpoint.call + + expect(result).to be_success( + TRMNL::API::Models::IPAddress[ + version_4: ["192.168.1.10"], + version_6: ["1a00:100:100:1000::1"] + ] + ) + end + + context "with failure" do + let :http do + HTTP::Fake::Client.new do + get "/api/ips" do + headers["Content-Type"] = "application/json" + status 404 + + <<~JSON + {"error": "Danger!"} + JSON + end + end + end + + it "answers failure" do + result = described_class.new(requester:).call + expect(result).to match(Failure(be_a(HTTP::Response))) + end + end + end + + describe "#inspect" do + it_behaves_like "an inspectable endpoint", described_class.new + end +end