mirror of
https://github.com/usetrmnl/trmnl-api.git
synced 2026-04-29 13:35:13 -07:00
Added client
Necessary to provide the primary client for making low-level API requests. RuboCop and Reek issues have been marked for future consideration and improvement because these issues stem from Core's API (and subsequent Firmware design) and should be fixed in the Core/Firmware implementation first.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "dry/monads"
|
||||
require "http"
|
||||
|
||||
module TRMNL
|
||||
module API
|
||||
# Provides a low level configurable and monadic API client.
|
||||
# :reek:DataClump
|
||||
class Client
|
||||
include Dry::Monads[:result]
|
||||
|
||||
HEADERS = {}.freeze
|
||||
|
||||
def initialize settings: TRMNL::API::Configuration::Loader.new.call, http: HTTP
|
||||
@settings = settings
|
||||
@http = http
|
||||
|
||||
yield settings if block_given?
|
||||
end
|
||||
|
||||
def get(path, headers: HEADERS, **params) = call(__method__, path, headers, params:)
|
||||
|
||||
def post(path, headers: HEADERS, **json) = call(__method__, path, headers, json:)
|
||||
|
||||
private
|
||||
|
||||
attr_reader :settings, :http
|
||||
|
||||
# rubocop:todo Metrics/ParameterLists
|
||||
def call method, path, headers, **options
|
||||
http.headers(settings.headers.merge(headers))
|
||||
.public_send(method, "#{settings.uri}/#{path}", options)
|
||||
.then { |response| response.status.success? ? Success(response) : Failure(response) }
|
||||
end
|
||||
# rubocop:enable Metrics/ParameterLists
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,108 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe TRMNL::API::Client do
|
||||
using Refinements::Hash
|
||||
|
||||
subject(:client) { described_class.new http: }
|
||||
|
||||
describe "#initialize" do
|
||||
it "initializes with block" do
|
||||
client = described_class.new { |settings| settings.content_type = "application/xml" }
|
||||
body = client.get("bogus").failure.to_s
|
||||
|
||||
expect(body).to include("Not Found")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#get" do
|
||||
context "with success" do
|
||||
let :http do
|
||||
HTTP::Fake::Client.new do
|
||||
get "/api/current_screen" do
|
||||
headers["Content-Type"] = "application/json"
|
||||
status 200
|
||||
|
||||
<<~JSON
|
||||
{
|
||||
"status": 200,
|
||||
"refresh_rate": 3200,
|
||||
"image_url": "https://test.io/images/test.bmp",
|
||||
"filename": "test.bmp",
|
||||
"rendered_at": null
|
||||
}
|
||||
JSON
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "answers response" do
|
||||
response = client.get "current_screen"
|
||||
payload = response.fmap(&:parse).bind(&:symbolize_keys!)
|
||||
|
||||
expect(payload).to eq(
|
||||
status: 200,
|
||||
refresh_rate: 3200,
|
||||
image_url: "https://test.io/images/test.bmp",
|
||||
filename: "test.bmp",
|
||||
rendered_at: nil
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "with custom header" do
|
||||
let(:http) { class_spy HTTP, headers: HTTP }
|
||||
let(:response) { instance_spy HTTP::Response }
|
||||
|
||||
it "includes custom header" do
|
||||
client.get "current_screen", headers: {"ID" => "123"}
|
||||
|
||||
expect(http).to have_received(:headers).with(
|
||||
"Content-Type" => "application/json",
|
||||
"ID" => "123"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "with failure" do
|
||||
let :http do
|
||||
HTTP::Fake::Client.new do
|
||||
get "/api/current_screen" do
|
||||
headers["Content-Type"] = "application/json"
|
||||
status 404
|
||||
|
||||
<<~JSON
|
||||
{
|
||||
"message": "Danger!"
|
||||
}
|
||||
JSON
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "answers failure response" do
|
||||
response = client.get "current_screen"
|
||||
payload = response.alt_map { |result| result.parse.symbolize_keys! }
|
||||
|
||||
expect(payload).to be_failure(message: "Danger!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#post" do
|
||||
let :http do
|
||||
HTTP::Fake::Client.new do
|
||||
post "/api/log" do
|
||||
headers["Content-Type"] = "application/json"
|
||||
status 204
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "answers response" do
|
||||
result = client.post "log", log: {}
|
||||
expect(result.success.status).to eq(204)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user