From d5d2080515a88ea5e8a9af3c1dd4b0fe1f0da6b1 Mon Sep 17 00:00:00 2001 From: Zoran Pesic Date: Thu, 28 Dec 2023 22:49:55 -0800 Subject: [PATCH] make util methods private Updated specs to test the private methods directly, which is typically considered a smell. In this case we're leaving the specs to test the implementation of these methods directly as there is still value in having their logic be covered explicitly. Might come back to rework the util methods if time permits (e.g extract to a dedicated module perhaps). --- CHANGELOG.md | 1 + lib/fitbit_api/helpers/utils.rb | 2 ++ spec/helpers/utils_spec.rb | 61 ++++++++++++++++++--------------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b77f46d..efdd0ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ UNRELEASED ----- - BREAKING: Upgrade `oauth2` dependency to v2.0 - BREAKING: Minimum required Ruby version 2.7.0 +- BREAKING: Make utility methods private (e.g. `format_date`) - Fix response parsing error for `revoke_token!` 0.17.1 diff --git a/lib/fitbit_api/helpers/utils.rb b/lib/fitbit_api/helpers/utils.rb index cc6d2a0..2e29e6b 100644 --- a/lib/fitbit_api/helpers/utils.rb +++ b/lib/fitbit_api/helpers/utils.rb @@ -4,6 +4,8 @@ module FitbitAPI class Client PERIODS = %w[1d 7d 30d 1w 1m 3m 6m 1y max].freeze + private + def format_date(date) if [Date, Time, DateTime].include?(date.class) date.strftime('%Y-%m-%d') diff --git a/spec/helpers/utils_spec.rb b/spec/helpers/utils_spec.rb index 4b77270..e2c6106 100644 --- a/spec/helpers/utils_spec.rb +++ b/spec/helpers/utils_spec.rb @@ -14,18 +14,18 @@ date_time = DateTime.parse('21-09-1991') [date, time, date_time].each do |obj| - expect(client.format_date(obj)).to eq('1991-09-21') + expect(client.send(:format_date, obj)).to eq('1991-09-21') end end it 'verifies string input to be of yyyy-MM-dd format' do string = '91-9-21' - expect { client.format_date string }.to raise_error(FitbitAPI::InvalidArgumentError) + expect { client.send(:format_date, string) }.to raise_error(FitbitAPI::InvalidArgumentError) end it 'returns unaltered argument if argument is properly formatted' do string = '1991-09-21' - expect(client.format_date(string)).to eq(string) + expect(client.send(:format_date, string)).to eq(string) end end @@ -35,130 +35,135 @@ date_time = DateTime.parse('12:45') [time, date_time].each do |obj| - expect(client.format_time(obj)).to eq('12:45') + expect(client.send(:format_time, obj)).to eq('12:45') end end it 'verifies string input to be of HH:mm format' do string = '2:45' - expect { client.format_time string }.to raise_error(FitbitAPI::InvalidArgumentError) + expect { client.send(:format_time, string) }.to raise_error(FitbitAPI::InvalidArgumentError) end it 'returns unaltered argument if argument is properly formatted' do string = '12:45' - expect(client.format_time(string)).to eq(string) + expect(client.send(:format_time, string)).to eq(string) end end describe '#format_scope' do it 'returns elements of an Array as single space delimited string' do scope = %w[one two three] - expect(client.format_scope(scope)).to eq('one two three') + expect(client.send(:format_scope, scope)).to eq('one two three') end it 'returns unaltered argument if argument is not an Array' do scope = 'one two three' - expect(client.format_scope(scope)).to eq(scope) + expect(client.send(:format_scope, scope)).to eq(scope) end end describe '#strip_root_key' do it 'returns the original argument if not a Hash' do object = %w[foo bar baz] - expect(client.strip_root_key(object)).to eq(object) + expect(client.send(:strip_root_key, object)).to eq(object) end it 'returns the original argument if it is a Hash with multiple root-level keys' do object = { foo: 1, bar: [2, 3, 4], baz: { biz: 5 } } - expect(client.strip_root_key(object)).to eq(object) + expect(client.send(:strip_root_key, object)).to eq(object) end it 'returns the object without the root key' do object = { data: { foo: 1, bar: 2, baz: 3 } } - expect(client.strip_root_key(object)).to eq(object[:data]) + expect(client.send(:strip_root_key, object)).to eq(object[:data]) end end describe '#deep_keys_to_snake_case!' do it 'converts keys of hash to snake case format' do object = { 'keyOne' => 1, 'keyTwo' => 2, 'keyThree' => 3 } - expect(client.deep_keys_to_snake_case!(object)).to eq({ 'key_one' => 1, 'key_two' => 2, 'key_three' => 3 }) + expect(client.send(:deep_keys_to_snake_case!, object)).to eq( + { 'key_one' => 1, 'key_two' => 2, 'key_three' => 3 } + ) end it 'converts nested keys of hash to snake case format' do object = { 'keyOne' => 1, 'keyTwo' => { 'keyThree' => 3, 'keyFour' => 4 } } - expect(client.deep_keys_to_snake_case!(object)).to eq({ 'key_one' => 1, - 'key_two' => { 'key_three' => 3, 'key_four' => 4 } }) + expect(client.send(:deep_keys_to_snake_case!, object)).to eq( + { 'key_one' => 1, 'key_two' => { 'key_three' => 3, 'key_four' => 4 } } + ) end end describe '#deep_keys_to_camel_case!' do it 'converts keys of hash to camel case format' do object = { 'key_one' => 1, 'key_two' => 2, 'key_three' => 3 } - expect(client.deep_keys_to_camel_case!(object)).to eq({ 'keyOne' => 1, 'keyTwo' => 2, 'keyThree' => 3 }) + expect(client.send(:deep_keys_to_camel_case!, object)).to eq({ 'keyOne' => 1, 'keyTwo' => 2, 'keyThree' => 3 }) end it 'converts nested keys of hash to camel case format' do object = { 'key_one' => 1, 'key_two' => { 'key_three' => 3, 'key_four' => 4 } } - expect(client.deep_keys_to_camel_case!(object)).to eq({ 'keyOne' => 1, - 'keyTwo' => { 'keyThree' => 3, 'keyFour' => 4 } }) + expect(client.send(:deep_keys_to_camel_case!, object)).to eq( + { 'keyOne' => 1, 'keyTwo' => { 'keyThree' => 3, 'keyFour' => 4 } } + ) end it 'handles mixed input of camel cased and snake cased keys' do object = { 'key_one' => 1, 'keyTwo' => { 'key_three' => 3, keyFour: 4 } } - expect(client.deep_keys_to_camel_case!(object)).to eq({ 'keyOne' => 1, - 'keyTwo' => { 'keyThree' => 3, 'keyFour' => 4 } }) + expect(client.send(:deep_keys_to_camel_case!, object)).to eq( + { 'keyOne' => 1, 'keyTwo' => { 'keyThree' => 3, 'keyFour' => 4 } } + ) end end describe '#deep_symbolize_keys!' do it 'converts keys of hash to symbol' do object = { 'keyOne' => 1, 'keyTwo' => 2, 'keyThree' => 3 } - expect(client.deep_symbolize_keys!(object)).to eq({ keyOne: 1, keyTwo: 2, keyThree: 3 }) + expect(client.send(:deep_symbolize_keys!, object)).to eq({ keyOne: 1, keyTwo: 2, keyThree: 3 }) end it 'converts nested keys of hash to symbol' do object = { 'keyOne' => 1, 'keyTwo' => { 'keyThree' => 3, 'keyFour' => 4 } } - expect(client.deep_symbolize_keys!(object)).to eq({ keyOne: 1, keyTwo: { keyThree: 3, keyFour: 4 } }) + expect(client.send(:deep_symbolize_keys!, object)).to eq({ keyOne: 1, keyTwo: { keyThree: 3, keyFour: 4 } }) end end describe '#to_snake_case' do it 'converts camelCased words to snake_case format' do word = 'imMrMeeseeksLookAtMe' - expect(client.to_snake_case(word)).to eq 'im_mr_meeseeks_look_at_me' + expect(client.send(:to_snake_case, word)).to eq 'im_mr_meeseeks_look_at_me' end it 'properly recognizes series of capital letters as single word' do word = 'iThinkNASAIsCool' - expect(client.to_snake_case(word)).to eq 'i_think_nasa_is_cool' + expect(client.send(:to_snake_case, word)).to eq 'i_think_nasa_is_cool' end it 'processes dashes to underscore if :replace_dashes option is provided' do word = 'some-dashesAndSnakes' - expect(client.to_snake_case(word, replace_dashes: true)).to eq 'some_dashes_and_snakes' + expect(client.send(:to_snake_case, word, replace_dashes: true)).to eq 'some_dashes_and_snakes' end end describe '#to_camel_case' do it 'returns original string if already camelCased' do word = 'AlreadyCamel' - expect(client.to_camel_case(word)).to eq 'AlreadyCamel' + expect(client.send(:to_camel_case, word)).to eq 'AlreadyCamel' end it 'returns original string if already lowerCamelCased' do word = 'alreadyLowerCamel' - expect(client.to_camel_case(word, lower: true)).to eq 'alreadyLowerCamel' + expect(client.send(:to_camel_case, word, lower: true)).to eq 'alreadyLowerCamel' end it 'converts snake_cased words to CamelCase format' do word = 'im_mr_meeseeks_look_at_me' - expect(client.to_camel_case(word)).to eq 'ImMrMeeseeksLookAtMe' + expect(client.send(:to_camel_case, word)).to eq 'ImMrMeeseeksLookAtMe' end it 'converts snake_cased words to lowerCamelCase format' do word = 'lower_camel' - expect(client.to_camel_case(word, lower: true)).to eq 'lowerCamel' + expect(client.send(:to_camel_case, word, lower: true)).to eq 'lowerCamel' end end end