Skip to content

Commit

Permalink
Merge pull request #46 from sul-dlss/43-org-endpoint
Browse files Browse the repository at this point in the history
add organization and storage endpoints (read only)
  • Loading branch information
aaron-collier authored Mar 28, 2023
2 parents ab44dde + 1987fa5 commit 3b04545
Show file tree
Hide file tree
Showing 5 changed files with 306 additions and 1 deletion.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,49 @@ data_importer.wait_until_complete
=> Success()
data_importer.instance_hrid
=> Success("in00000000010")

# Get list of organizations (filtered with an optional query)
# see https://s3.amazonaws.com/foliodocs/api/mod-organizations/p/organizations.html#organizations_organizations_get
client.organizations
=> {"organizations"=>[
{"id"=>"4b1a42f9-b310-492c-a71d-b8edcd30ac0c",
"name"=>"Seventh Art Releasing",
"code"=>"7ART-SUL",
"exportToAccounting"=>true,
"status"=>"Active",
"organizationTypes"=>[],
"aliases"=>[],
"addresses"=>],.....
"totalRecords"=>100}

client.organizations(query: 'name="Seventh"')
=> {"organizations"=>[....

# Get list of organization interface items (filtered with an optional query)
# see https://s3.amazonaws.com/foliodocs/api/mod-organizations-storage/p/interface.html#organizations_storage_interfaces_get
client.organization_interfaces
=> {"interfaces"=>
[{"id"=>"c6f7470e-6229-45ce-b3f9-32006e9affcf",
"name"=>"tes",
"type"=>["Invoices"],
.....],....
"totalRecords"=>100}

client.organization_interfaces(query: 'name="tes"')
=> {"interfaces"=>....

# Get details for a specific organization interface
# see https://s3.amazonaws.com/foliodocs/api/mod-organizations-storage/p/interface.html#organizations_storage_interfaces__id__get
client.interface_details(id: 'c6f7470e-6229-45ce-b3f9-32006e9affcf')
=>
{"id"=>"c6f7470e-6229-45ce-b3f9-32006e9affcf",
"name"=>"tes",
"type"=>["Invoices"],
"metadata"=>
{"createdDate"=>"2023-02-16T22:27:51.515+00:00",
"createdByUserId"=>"38524916-598d-4edf-a2ef-04bba7e78ad6",
"updatedDate"=>"2023-02-16T22:27:51.515+00:00",
"updatedByUserId"=>"38524916-598d-4edf-a2ef-04bba7e78ad6"}}
```

## Development
Expand Down
21 changes: 20 additions & 1 deletion lib/folio_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def configure(url:, login_params:, okapi_headers:)
end

delegate :config, :connection, :get, :post, :put, to: :instance
delegate :fetch_hrid, :fetch_external_id, :fetch_instance_info, :fetch_marc_hash, :has_instance_status?, :data_import, :edit_marc_json, to: :instance
delegate :fetch_hrid, :fetch_external_id, :fetch_instance_info, :fetch_marc_hash, :has_instance_status?, :data_import, :edit_marc_json,
:organizations, :organization_interfaces, :interface_details, to: :instance
end

attr_accessor :config
Expand Down Expand Up @@ -173,4 +174,22 @@ def edit_marc_json(...)
.new(self)
.edit_marc_json(...)
end

def organizations(...)
Organizations
.new(self)
.fetch_list(...)
end

def organization_interfaces(...)
Organizations
.new(self)
.fetch_interface_list(...)
end

def interface_details(...)
Organizations
.new(self)
.fetch_interface_details(...)
end
end
43 changes: 43 additions & 0 deletions lib/folio_client/organizations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

class FolioClient
# Query organization records in Folio; see
# https://s3.amazonaws.com/foliodocs/api/mod-organizations/p/organizations.html
# https://s3.amazonaws.com/foliodocs/api/mod-organizations-storage/p/interface.html
class Organizations
attr_accessor :client

# @param client [FolioClient] the configured client
def initialize(client)
@client = client
end

# @param query [String] an optional query to limit the number of organizations returned
# @param limit [Integer] the number of results to return (defaults to 10,000)
# @param offset [Integer] the offset for results returned (defaults to 0)
# @param lang [String] language code for returned results (defaults to 'en')
def fetch_list(query: nil, limit: 10000, offset: 0, lang: "en")
params = {limit: limit, offset: offset, lang: lang}
params[:query] = query if query
client.get("/organizations/organizations", params)
end

# @param query [String] an optional query to limit the number of organization interfaces returned
# @param limit [Integer] the number of results to return (defaults to 10,000)
# @param offset [Integer] the offset for results returned (defaults to 0)
# @param lang [String] language code for returned results (defaults to 'en')
def fetch_interface_list(query: nil, limit: 10000, offset: 0, lang: "en")
params = {limit: limit, offset: offset, lang: lang}
params[:query] = query if query
client.get("/organizations-storage/interfaces", params)
end

# @param id [String] id for requested storage interface
# @param lang [String] language code for returned result (defaults to 'en')
def fetch_interface_details(id:, lang: "en")
client.get("/organizations-storage/interfaces/#{id}", {
lang: lang
})
end
end
end
123 changes: 123 additions & 0 deletions spec/folio_client/organizations_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# frozen_string_literal: true

RSpec.describe FolioClient::Organizations do
subject(:organizations) do
described_class.new(client)
end

let(:args) { {url: url, login_params: login_params, okapi_headers: okapi_headers} }
let(:url) { "https://folio.example.org" }
let(:login_params) { {username: "username", password: "password"} }
let(:okapi_headers) { {some_bogus_headers: "here"} }
let(:token) { "a_long_silly_token" }
let(:client) { FolioClient.configure(**args) }
let(:id) { "some_long_id_that_is_long" }
let(:query) { '"active=="true"' }

before do
stub_request(:post, "#{url}/authn/login")
.to_return(status: 200, body: "{\"okapiToken\" : \"#{token}\"}")
end

context "when looking up a list of organizations" do
context "when a query is specified" do
before do
stub_request(:get, "#{url}/organizations/organizations?lang=en&limit=10000&offset=0&query=#{query}")
.to_return(status: 200, body: organization_response.to_json)
end

let(:organization_response) {
{"totalRecords" => 1,
"organizations" => [
{"id" => "12345",
"name" => "Training videos"}
]}
}

it "returns the organization list" do
expect(organizations.fetch_list(query: query)).to eq(organization_response)
end
end

context "when a query is not specified" do
before do
stub_request(:get, "#{url}/organizations/organizations?lang=en&limit=10000&offset=0")
.to_return(status: 200, body: organization_response.to_json)
end

let(:organization_response) {
{"totalRecords" => 1,
"organizations" => [
{"id" => "12345",
"name" => "Training videos"}
]}
}

it "returns the organization list" do
expect(organizations.fetch_list).to eq(organization_response)
end
end
end

context "when looking up a list of organization interfaces" do
context "when a query is specified" do
before do
stub_request(:get, "#{url}/organizations-storage/interfaces?lang=en&limit=10000&offset=0&query=#{query}")
.to_return(status: 200, body: organization_interface_response.to_json)
end

let(:organization_interface_response) {
{"totalRecords" => 1,
"interfaces" => [
{"id" => "12345",
"description" => "Training videos"}
]}
}

it "returns the organization list" do
expect(organizations.fetch_interface_list(query: query)).to eq(organization_interface_response)
end
end

context "when a query is not specified" do
before do
stub_request(:get, "#{url}/organizations-storage/interfaces?lang=en&limit=10000&offset=0")
.to_return(status: 200, body: organization_interface_response.to_json)
end

let(:organization_interface_response) {
{"totalRecords" => 1,
"interfaces" => [
{"id" => "12345",
"description" => "Training videos"}
]}
}

it "returns the organization list" do
expect(organizations.fetch_interface_list).to eq(organization_interface_response)
end
end
end

context "when looking up details of a specific organization interfaces" do
before do
stub_request(:get, "#{url}/organizations-storage/interfaces/#{id}?lang=en")
.to_return(status: 200, body: organization_interface_detail_response.to_json)
end

let(:organization_interface_detail_response) {
{"id" => id,
"name" => "tes",
"type" => ["Invoices"],
"metadata" =>
{"createdDate" => "2023-02-16T22:27:51.515+00:00",
"createdByUserId" => "38524916-598d-4edf-a2ef-04bba7e78ad6",
"updatedDate" => "2023-02-16T22:27:51.515+00:00",
"updatedByUserId" => "38524916-598d-4edf-a2ef-04bba7e78ad6"}}
}

it "returns the organization list" do
expect(organizations.fetch_interface_details(id: id)).to eq(organization_interface_detail_response)
end
end
end
77 changes: 77 additions & 0 deletions spec/folio_client_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "marc"

RSpec.describe FolioClient do
subject(:client) do
described_class.configure(**args)
Expand Down Expand Up @@ -362,6 +364,81 @@
end
end

describe ".organizations" do
before do
allow(described_class.instance).to receive(:organizations)
end

it "invokes instance#organizations" do
client.organizations
expect(client.instance).to have_received(:organizations)
end
end

describe "#organizations" do
let(:organizations) { instance_double(described_class::Organizations) }

before do
allow(described_class::Organizations).to receive(:new).and_return(organizations)
allow(organizations).to receive(:fetch_list)
end

it "invokes Organizations#fetch_list" do
client.public_send(:organizations)
expect(organizations).to have_received(:fetch_list).once
end
end

describe ".organization_interfaces" do
before do
allow(described_class.instance).to receive(:organization_interfaces).with(query: "something")
end

it "invokes instance#organization_interfaces" do
client.organization_interfaces(query: "something")
expect(client.instance).to have_received(:organization_interfaces).with(query: "something")
end
end

describe "#organization_interfaces" do
let(:organizations) { instance_double(described_class::Organizations) }

before do
allow(described_class::Organizations).to receive(:new).and_return(organizations)
allow(organizations).to receive(:fetch_interface_list).with(query: "something")
end

it "invokes Organizations#fetch_interface_list" do
client.public_send(:organization_interfaces, query: "something")
expect(organizations).to have_received(:fetch_interface_list).with(query: "something").once
end
end

describe ".interface_details" do
before do
allow(described_class.instance).to receive(:interface_details).with(id: "something")
end

it "invokes instance#interface_details" do
client.interface_details(id: "something")
expect(client.instance).to have_received(:interface_details).with(id: "something")
end
end

describe "#interface_details" do
let(:organizations) { instance_double(described_class::Organizations) }

before do
allow(described_class::Organizations).to receive(:new).and_return(organizations)
allow(organizations).to receive(:fetch_interface_details).with(id: "something")
end

it "invokes Organizations#fetch_interface_details" do
client.public_send(:interface_details, id: "something")
expect(organizations).to have_received(:fetch_interface_details).with(id: "something").once
end
end

# Tests the TokenWrapper that requests a new token, with a method that might first encounter the error
context "when token is expired" do
let(:inventory) { instance_double(FolioClient::Inventory, fetch_hrid: nil) }
Expand Down

0 comments on commit 3b04545

Please sign in to comment.