Skip to content

Commit

Permalink
complete all_categories call
Browse files Browse the repository at this point in the history
  • Loading branch information
mmenanno committed Jan 18, 2024
1 parent 4508b7f commit c039a20
Showing 6 changed files with 177 additions and 17 deletions.
27 changes: 16 additions & 11 deletions lib/lunchmoney/categories/category.rb
Original file line number Diff line number Diff line change
@@ -12,48 +12,53 @@ class Category < LunchMoney::DataObject
sig { returns(T.nilable(String)) }
attr_accessor :description, :archived_on, :updated_at, :created_at

sig { returns(T.nilable(T::Boolean)) }
attr_accessor :archived

sig { returns(T::Boolean) }
attr_accessor :is_income, :exclude_from_budget, :exclude_from_totals, :archived, :is_group
attr_accessor :is_income, :exclude_from_budget, :exclude_from_totals, :is_group

sig { returns(T.nilable(Integer)) }
attr_accessor :group_id
attr_accessor :group_id, :order

sig { returns(T::Array[LunchMoney::Category]) }
sig { returns(T.nilable(T::Array[LunchMoney::Category])) }
attr_accessor :children

sig do
params(
name: String,
id: Integer,
children: T::Array[LunchMoney::Category],
name: String,
is_income: T::Boolean,
exclude_from_budget: T::Boolean,
exclude_from_totals: T::Boolean,
archived: T::Boolean,
is_group: T::Boolean,
archived: T.nilable(T::Boolean),
archived_on: T.nilable(String),
updated_at: T.nilable(String),
created_at: T.nilable(String),
group_id: T.nilable(Integer),
order: T.nilable(Integer),
description: T.nilable(String),
children: T.nilable(T::Array[LunchMoney::Category]),
).void
end
def initialize(name:, id:, children:, is_income:, exclude_from_budget:, exclude_from_totals:, archived:, is_group:,
archived_on: nil, updated_at: nil, created_at: nil, group_id: nil, description: nil)
def initialize(id:, name:, is_income:, exclude_from_budget:, exclude_from_totals:, is_group:, archived: nil,
archived_on: nil, updated_at: nil, created_at: nil, group_id: nil, order: nil, description: nil, children: nil)
super()
@name = name
@id = id
@children = children
@name = name
@is_income = is_income
@exclude_from_budget = exclude_from_budget
@exclude_from_totals = exclude_from_totals
@archived = archived
@is_group = is_group
@archived = archived
@archived_on = archived_on
@updated_at = updated_at
@created_at = created_at
@group_id = group_id
@order = order
@description = description
@children = children
end
end
end
30 changes: 26 additions & 4 deletions lib/lunchmoney/categories/category_calls.rb
Original file line number Diff line number Diff line change
@@ -2,13 +2,24 @@
# frozen_string_literal: true

require_relative "category"
require "pry"

module LunchMoney
class CategoryCalls < ApiCall
sig { returns(T.any(T::Array[LunchMoney::Category], LunchMoney::Errors)) }
def all_categories
response = get("categories")
VALID_FORMATS = T.let(
[
"flattened",
"nested",
],
T::Array[String],
)

sig do
params(
format: T.nilable(T.any(String, Symbol)),
).returns(T.any(T::Array[LunchMoney::Category], LunchMoney::Errors))
end
def all_categories(format: nil)
response = get("categories", query_params: all_categories_params(format:))

api_errors = errors(response)
return api_errors if api_errors.present?
@@ -171,5 +182,16 @@ def force_delete_category(category_id)

response.body
end

private

sig { params(format: T.nilable(T.any(String, Symbol))).returns(T.nilable(T::Hash[String, String])) }
def all_categories_params(format:)
return unless format

raise(InvalidQueryParameter, "format must be either flattened or nested") if VALID_FORMATS.exclude?(format.to_s)

{ format: format.to_s }
end
end
end
2 changes: 0 additions & 2 deletions lib/lunchmoney/data_object.rb
Original file line number Diff line number Diff line change
@@ -3,8 +3,6 @@

module LunchMoney
class DataObject
require "pry"

sig { params(symbolize_keys: T::Boolean).returns(T::Hash[String, T.untyped]) }
def serialize(symbolize_keys: false)
ivars = instance_variables
2 changes: 2 additions & 0 deletions lib/lunchmoney/exceptions.rb
Original file line number Diff line number Diff line change
@@ -7,4 +7,6 @@ class Exception < StandardError; end
class InvalidApiKey < Exception; end

class InvalidObjectAttribute < Exception; end

class InvalidQueryParameter < Exception; end
end
66 changes: 66 additions & 0 deletions test/helpers/fake_response_data_helper.rb
Original file line number Diff line number Diff line change
@@ -112,4 +112,70 @@ def fake_budget_summary_response
},
]
end

sig { returns(T::Hash[String, T.untyped]) }
def fake_all_categories_response
{
"categories": [
{
"id": 83,
"name": "Test 1",
"description": "Test description",
"is_income": false,
"exclude_from_budget": true,
"exclude_from_totals": false,
"updated_at": "2020-01-28T09:49:03.225Z",
"created_at": "2020-01-28T09:49:03.225Z",
"is_group": false,
"group_id": nil,
"order": 0,
},
{
"id": 84,
"name": "Test 2",
"description": nil,
"is_income": true,
"exclude_from_budget": false,
"exclude_from_totals": true,
"updated_at": "2020-01-28T09:49:03.238Z",
"created_at": "2020-01-28T09:49:03.238Z",
"is_group": true,
"group_id": 83,
"order": 1,
"children": [
{
"id": 315162,
"name": "Alcohol, Bars",
"description": nil,
"is_income": false,
"exclude_from_budget": false,
"exclude_from_totals": false,
"created_at": "2022-03-06T20:11:36.066Z",
"is_group": false,
},
{
"id": 315169,
"name": "Groceries",
"description": nil,
"is_income": false,
"exclude_from_budget": false,
"exclude_from_totals": false,
"created_at": "2022-03-06T20:11:36.120Z",
"is_group": false,
},
{
"id": 315172,
"name": "Restaurants",
"description": nil,
"is_income": false,
"exclude_from_budget": false,
"exclude_from_totals": false,
"created_at": "2022-03-06T20:11:36.146Z",
"is_group": false,
},
],
},
],
}
end
end
67 changes: 67 additions & 0 deletions test/lunchmoney/categories/category_calls_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# typed: strict
# frozen_string_literal: true

require "test_helper"

class CategoryCallsTest < ActiveSupport::TestCase
include MockResponseHelper
include FakeResponseDataHelper

test "all_categories returns an array of Category objects on success response" do
response = mock_faraday_response(fake_all_categories_response)

LunchMoney::CategoryCalls.any_instance.stubs(:get).returns(response)

api_call = LunchMoney::CategoryCalls.new.all_categories

assert_kind_of(LunchMoney::Category, api_call.first)
end

test "all_categories returns an array of Error objects on error response" do
response = mock_faraday_response(fake_general_error)

LunchMoney::CategoryCalls.any_instance.stubs(:get).returns(response)

api_call = LunchMoney::CategoryCalls.new.all_categories(format: "flattened")

assert_kind_of(LunchMoney::Error, api_call.first)
end

test "all_categories does not raise an error when called with flattened format" do
response = mock_faraday_response(fake_all_categories_response)

query_params = { format: "flattened" }

LunchMoney::CategoryCalls.any_instance.stubs(:get).with("categories", query_params:).returns(response)

assert_nothing_raised do
LunchMoney::CategoryCalls.new.all_categories(**query_params)
end
end

test "all_categories does not raise an error when called with nested format" do
response = mock_faraday_response(fake_all_categories_response)

query_params = { format: "nested" }

LunchMoney::CategoryCalls.any_instance.stubs(:get).with("categories", query_params:).returns(response)

assert_nothing_raised do
LunchMoney::CategoryCalls.new.all_categories(**query_params)
end
end

test "all_categories raises an exception when called with invalid format" do
response = mock_faraday_response(fake_all_categories_response)

query_params = { format: "not_a_valid_format" }

LunchMoney::CategoryCalls.any_instance.stubs(:get).with("categories", query_params:).returns(response)

error = assert_raises(LunchMoney::InvalidQueryParameter) do
LunchMoney::CategoryCalls.new.all_categories(**query_params)
end

assert_equal("format must be either flattened or nested", error.message)
end
end

0 comments on commit c039a20

Please sign in to comment.