Skip to content
This repository was archived by the owner on Dec 12, 2023. It is now read-only.

Commit 24f28f0

Browse files
committed
Implement some specs
1 parent 7b42440 commit 24f28f0

File tree

10 files changed

+488
-47
lines changed

10 files changed

+488
-47
lines changed

lib/freshdesk_api_v2/base.rb

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,43 @@ def initialize(http)
44
@http = http
55
end
66

7-
def list(options = {})
8-
per_page = value_from_options(options, :per_page) || Utils::MAX_PAGE_SIZE
7+
def list(pagination_options = {})
8+
per_page = pagination_options[:per_page] || Utils::MAX_PAGE_SIZE
99
raise PaginationException, "Max per page is #{Utils::MAX_PAGE_SIZE}" if per_page.to_i > Utils::MAX_PAGE_SIZE
10-
first_page, last_page = extract_pagination(options)
11-
validate_pagination!(first_page, last_page)
12-
http_list(first_page, last_page, per_page)
10+
first_page, last_page = extract_list_pagination(pagination_options)
11+
validate_list_pagination!(first_page, last_page)
12+
paginated_get(first_page, last_page, per_page)
1313
end
1414

1515
# TODO - Note that queries that by email or things that have special characters to not work yet in
1616
# Freshdesk
17-
def search(query, options = {})
17+
def search(query, pagination_options = {})
1818
raise SearchException, 'You must provide a query' if query.nil?
1919
raise SearchException, 'You must provide a query of type FreshdeskApiV2::SearchArgs' unless query.is_a?(FreshdeskApiV2::SearchArgs)
2020
raise SearchException, 'You must provide a query' unless query.valid?
21-
first_page, last_page = extract_pagination(options)
22-
validate_pagination!(first_page, last_page)
23-
http_search(query.to_query, first_page, last_page)
21+
first_page, last_page = extract_search_pagination(pagination_options)
22+
validate_search_pagination!(first_page, last_page)
23+
paginated_search(query.to_query, first_page, last_page)
2424
end
2525

2626
def show(id)
27-
http_show(id)
27+
get(id)
2828
end
2929

3030
def create(attributes)
3131
validate_create_attributes!(attributes)
3232
attributes = prepare_attributes!(attributes)
33-
http_create(attributes)
33+
post(attributes)
3434
end
3535

3636
def update(id, attributes)
3737
validate_update_attributes!(attributes)
3838
attributes = prepare_attributes!(attributes)
39-
http_update(id, attributes)
39+
put(id, attributes)
4040
end
4141

4242
def destroy(id)
43-
http_destroy(id)
43+
delete(id)
4444
end
4545

4646
protected
@@ -59,11 +59,19 @@ def validate_update_attributes!(attributes)
5959
raise UpdateException, 'Please provide attributes' if attributes.nil? || attributes.count == 0
6060
end
6161

62-
def validate_pagination!(first_page, last_page)
62+
def validate_list_pagination!(first_page, last_page)
6363
raise PaginationException, 'first_page must be a number greater than 0' if first_page.to_i <= 0
6464
raise PaginationException, 'last_page must be a number greater than or equal to first_page' if last_page.to_i < first_page.to_i
6565
end
6666

67+
def validate_search_pagination!(first_page, last_page)
68+
raise PaginationException, 'first_page must be a number greater than 0' if first_page.to_i <= 0
69+
unless last_page.nil?
70+
raise PaginationException, "last_page cannot exceed #{Utils::MAX_SEARCH_PAGES}" if last_page.to_i > Utils::MAX_SEARCH_PAGES
71+
raise PaginationException, 'last_page must be a number greater than or equal to first_page' if last_page.to_i < first_page.to_i
72+
end
73+
end
74+
6775
def prepare_attributes!(attributes)
6876
clean = attributes.reject { |key, value | !allowed_attributes.include?(key) || value.nil? }
6977
custom_fields = clean['custom_fields']
@@ -76,47 +84,47 @@ def prepare_attributes!(attributes)
7684

7785
private
7886

79-
def http_show(id)
87+
def get(id)
8088
response = @http.get("#{api_url}/#{id}")
8189
JSON.parse(response.body)
8290
end
8391

84-
def http_create(attributes)
92+
def post(attributes)
8593
response = @http.post("#{api_url}", attributes)
8694
JSON.parse(response.body)
8795
end
8896

89-
def http_destroy(id)
97+
def delete(id)
9098
response = @http.delete("#{api_url}/#{id}")
9199
response.status
92100
end
93101

94-
def http_update(id, attributes)
102+
def put(id, attributes)
95103
response = @http.put("#{api_url}/#{id}", attributes)
96104
JSON.parse(response.body)
97105
end
98106

99-
def http_list(first_page, last_page, per_page)
107+
def paginated_get(first_page, last_page, per_page)
100108
url = "#{api_url}?page=#{first_page}&per_page=#{per_page}"
101-
@http.paginate(url, last_page)
109+
@http.paginated_get(url, last_page)
102110
end
103111

104112
# For example, see: https://developers.freshdesk.com/api/#filter_contacts
105-
def http_search(query, first_page, last_page)
113+
def paginated_search(query, first_page, last_page)
106114
url = "#{base_api_url}/search/#{endpoint}?page=#{first_page}&query=#{query}"
107-
@http.search_paginate(url, last_page)
115+
@http.paginated_search(url, last_page)
108116
end
109117

110-
def extract_pagination(options)
111-
first_page = value_from_options(options, :first_page)
112-
last_page = value_from_options(options, :last_page)
113-
first_page ||= Utils::DEFAULT_PAGE
114-
last_page ||= Utils::INTEGER_MAX
118+
def extract_list_pagination(options)
119+
first_page = options[:first_page] || Utils::DEFAULT_PAGE
120+
last_page = options[:last_page] || Utils::INTEGER_MAX
115121
[first_page, last_page]
116122
end
117123

118-
def value_from_options(options, key)
119-
options[key.to_s] || options[key.to_sym]
124+
def extract_search_pagination(options)
125+
first_page = options[:first_page] || Utils::DEFAULT_PAGE
126+
last_page = options[:last_page]
127+
[first_page, last_page]
120128
end
121129

122130
def base_api_url

lib/freshdesk_api_v2/companies.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
module FreshdeskApiV2
22
class Companies < Base
3-
ALLOWED_ATTRIBUTES = %w[
4-
custom_fields
5-
description
6-
domains
7-
name
8-
note
9-
health_score
10-
account_tier
11-
renewal_date
12-
industry
3+
ALLOWED_ATTRIBUTES = [
4+
:custom_fields,
5+
:description,
6+
:domains,
7+
:name,
8+
:note,
9+
:health_score,
10+
:account_tier,
11+
:renewal_date,
12+
:industry
1313
].freeze
1414

1515
protected

lib/freshdesk_api_v2/http.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def initialize(configuration)
77

88
# Freshdesk's search API uses a different pagination mechanism than their
99
# regular pagination mechanism, so this implementation needs to be different.
10-
def search_paginate(url, last_page, collection = [])
10+
def paginate_search(url, last_page, collection = [])
1111
current_page = 1
1212
page_count, items = do_search(url)
1313
collection += items
@@ -27,7 +27,7 @@ def search_paginate(url, last_page, collection = [])
2727

2828
# This is Freshdesk's normal pagination. It always returns a link to the next
2929
# page in a header called 'link' with a rel of 'next'
30-
def paginate(url, last_page, collection = [])
30+
def paginated_get(url, last_page, collection = [])
3131
response = get(url)
3232
links = @link_parser.parse(response)
3333
collection += JSON.parse(response.body)

spec/freshdesk_api_v2/base_spec.rb

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 202 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,204 @@
1+
require 'byebug'
12
RSpec.describe FreshdeskApiV2::Companies do
2-
#Nothing to test here
3+
before do
4+
@mock_http = double('Mock HTTP', domain: 'test')
5+
end
6+
7+
subject { FreshdeskApiV2::Companies.new(@mock_http) }
8+
9+
def company_attributes(overrides = {})
10+
{
11+
custom_fields: { name: 1 },
12+
description: 'A company',
13+
domains: ['test.company.com'],
14+
name: 'A Company',
15+
note: '',
16+
health_score: 'A',
17+
account_tier: 'Silver',
18+
renewal_date: '2019-01-01',
19+
industry: 'Stuff'
20+
}.merge(overrides)
21+
end
22+
23+
context 'list' do
24+
let(:companies) { [company_attributes(id: 1, name: 'Company 1'), company_attributes(id: 1, name: 'Company 2')] }
25+
26+
before do
27+
allow(@mock_http).to receive(:paginated_get).and_return(companies)
28+
end
29+
30+
it 'returns a list of companies' do
31+
expect(subject.list).to be_instance_of(Array)
32+
end
33+
34+
it 'raises an exception when last_page is less than first_page' do
35+
expect do
36+
subject.list(first_page: 2, last_page: 1)
37+
end.to raise_error(FreshdeskApiV2::PaginationException)
38+
end
39+
40+
it "raises an exception when per_page is greater than #{FreshdeskApiV2::Utils::MAX_PAGE_SIZE}" do
41+
expect do
42+
subject.list(first_page: 1, per_page: 101)
43+
end.to raise_error(FreshdeskApiV2::PaginationException)
44+
end
45+
end
46+
47+
context 'search' do
48+
let(:query) do
49+
q = FreshdeskApiV2::SearchArgs.new
50+
q.add('name', 'Bob')
51+
q
52+
end
53+
54+
let(:companies) { [company_attributes(id: 1, name: 'Company 1'), company_attributes(id: 1, name: 'Company 2')] }
55+
56+
before do
57+
allow(@mock_http).to receive(:paginated_search).and_return(companies)
58+
end
59+
60+
it 'returns a list of companies matching the query' do
61+
expect(subject.search(query)).to be_instance_of(Array)
62+
end
63+
64+
it 'raises an exception when a query is not given' do
65+
expect do
66+
subject.search(nil)
67+
end.to raise_error(FreshdeskApiV2::SearchException)
68+
end
69+
70+
it 'raises an exception when the query given is invalid' do
71+
q = FreshdeskApiV2::SearchArgs.new
72+
expect do
73+
subject.search(q)
74+
end.to raise_error(FreshdeskApiV2::SearchException)
75+
end
76+
77+
it 'raises an exception when last_page is less than first_page' do
78+
expect do
79+
subject.search(query, first_page: 2, last_page: 1)
80+
end.to raise_error(FreshdeskApiV2::PaginationException)
81+
end
82+
83+
it "raises an exception when last_page is greater than #{FreshdeskApiV2::Utils::MAX_SEARCH_PAGES}" do
84+
expect do
85+
subject.search(query, first_page: 1, last_page: 11)
86+
end.to raise_error(FreshdeskApiV2::PaginationException)
87+
end
88+
end
89+
90+
context 'show' do
91+
let(:response) { double('Mock HTTP Response', body: company_attributes.to_json) }
92+
93+
before do
94+
allow(@mock_http).to receive(:get).and_return(response)
95+
end
96+
97+
it 'returns the company' do
98+
expect(subject.show(1)).not_to be_nil
99+
end
100+
end
101+
102+
context 'destroy' do
103+
let(:response) { double('Mock HTTP Response', status: 204) }
104+
105+
before do
106+
allow(@mock_http).to receive(:delete).and_return(response)
107+
end
108+
109+
it 'deletes the company' do
110+
expect(@mock_http).to receive(:delete).and_return(response)
111+
subject.destroy(1)
112+
end
113+
114+
it 'returns a status code of 204' do
115+
expect(subject.destroy(1)).to eq(204)
116+
end
117+
end
118+
119+
context 'create' do
120+
let(:endpoint) { 'https://test.freshdesk.com/api/v2/companies' }
121+
let(:response) { double('Mock HTTP Response', body: company_attributes.to_json) }
122+
123+
before do
124+
allow(@mock_http).to receive(:post).and_return(response)
125+
end
126+
127+
it 'creates the company' do
128+
expect(@mock_http).to receive(:post).with(endpoint, company_attributes).and_return(response)
129+
subject.create(company_attributes)
130+
end
131+
132+
it 'returns the company' do
133+
response = subject.create(company_attributes)
134+
expect(response).not_to be_nil
135+
end
136+
137+
it 'filters out non-whitelisted properties' do
138+
expect(@mock_http).to receive(:post).with(endpoint, company_attributes)
139+
subject.create(company_attributes(monkey: 'Yes'))
140+
end
141+
142+
it 'filters out nil properties' do
143+
altered_attributes = company_attributes.dup
144+
altered_attributes.delete(:description)
145+
expect(@mock_http).to receive(:post).with(endpoint, altered_attributes)
146+
subject.create(company_attributes(description: nil))
147+
end
148+
149+
it 'raises an exception when no attributes are given' do
150+
expect do
151+
subject.create(nil)
152+
end.to raise_error(FreshdeskApiV2::CreationException)
153+
end
154+
155+
it 'raises an exception when empty attributes are given' do
156+
expect do
157+
subject.create({})
158+
end.to raise_error(FreshdeskApiV2::CreationException)
159+
end
160+
end
161+
162+
context 'update' do
163+
let(:endpoint) { 'https://test.freshdesk.com/api/v2/companies/1' }
164+
let(:response) { double('Mock HTTP Response', body: company_attributes(id: 1).to_json) }
165+
166+
before do
167+
allow(@mock_http).to receive(:put).and_return(response)
168+
end
169+
170+
it 'updates the company' do
171+
expect(@mock_http).to receive(:put).with(endpoint, company_attributes).and_return(response)
172+
subject.update(1, company_attributes)
173+
end
174+
175+
it 'returns the company' do
176+
response = subject.update(1, company_attributes)
177+
expect(response).not_to be_nil
178+
end
179+
180+
it 'filters out non-whitelisted properties' do
181+
expect(@mock_http).to receive(:put).with(endpoint, company_attributes)
182+
subject.update(1, company_attributes(monkey: 'Yes'))
183+
end
184+
185+
it 'filters out nil properties' do
186+
altered_attributes = company_attributes.dup
187+
altered_attributes.delete(:description)
188+
expect(@mock_http).to receive(:put).with(endpoint, altered_attributes)
189+
subject.update(1, company_attributes(description: nil))
190+
end
191+
192+
it 'raises an exception when no attributes are given' do
193+
expect do
194+
subject.update(1, nil)
195+
end.to raise_error(FreshdeskApiV2::UpdateException)
196+
end
197+
198+
it 'raises an exception when empty attributes are given' do
199+
expect do
200+
subject.update(1, {})
201+
end.to raise_error(FreshdeskApiV2::UpdateException)
202+
end
203+
end
3204
end

0 commit comments

Comments
 (0)