fortnox-api 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.codeclimate.yml +3 -2
- data/.env.test +3 -0
- data/.rubocop.yml +32 -23
- data/.travis.yml +3 -2
- data/Guardfile +2 -2
- data/LICENSE.txt +165 -22
- data/README.md +56 -37
- data/fortnox-api.gemspec +9 -6
- data/lib/fortnox/api.rb +18 -2
- data/lib/fortnox/api/base.rb +5 -3
- data/lib/fortnox/api/environment_validation.rb +51 -6
- data/lib/fortnox/api/mappers.rb +49 -0
- data/lib/fortnox/api/mappers/base.rb +47 -0
- data/lib/fortnox/api/mappers/base/from_json.rb +78 -0
- data/lib/fortnox/api/mappers/base/to_json.rb +65 -0
- data/lib/fortnox/api/mappers/customer.rb +27 -0
- data/lib/fortnox/api/mappers/default_delivery_types.rb +13 -0
- data/lib/fortnox/api/mappers/default_templates.rb +15 -0
- data/lib/fortnox/api/mappers/edi_information.rb +22 -0
- data/lib/fortnox/api/mappers/email_information.rb +18 -0
- data/lib/fortnox/api/mappers/invoice.rb +27 -0
- data/lib/fortnox/api/mappers/invoice_row.rb +20 -0
- data/lib/fortnox/api/mappers/order.rb +23 -0
- data/lib/fortnox/api/mappers/order_row.rb +16 -0
- data/lib/fortnox/api/models.rb +2 -0
- data/lib/fortnox/api/models/base.rb +56 -13
- data/lib/fortnox/api/models/customer.rb +112 -101
- data/lib/fortnox/api/models/document_base.rb +189 -0
- data/lib/fortnox/api/models/invoice.rb +29 -195
- data/lib/fortnox/api/models/label.rb +17 -0
- data/lib/fortnox/api/models/order.rb +27 -0
- data/lib/fortnox/api/repositories.rb +2 -0
- data/lib/fortnox/api/repositories/base.rb +4 -5
- data/lib/fortnox/api/repositories/base/loaders.rb +22 -14
- data/lib/fortnox/api/repositories/base/savers.rb +30 -16
- data/lib/fortnox/api/repositories/customer.rb +3 -25
- data/lib/fortnox/api/repositories/invoice.rb +3 -22
- data/lib/fortnox/api/repositories/order.rb +16 -0
- data/lib/fortnox/api/request_handling.rb +3 -3
- data/lib/fortnox/api/types.rb +44 -0
- data/lib/fortnox/api/types/default_delivery_types.rb +20 -0
- data/lib/fortnox/api/types/default_templates.rb +23 -0
- data/lib/fortnox/api/types/defaulted.rb +11 -0
- data/lib/fortnox/api/types/document_row.rb +65 -0
- data/lib/fortnox/api/types/edi_information.rb +29 -0
- data/lib/fortnox/api/types/email_information.rb +26 -0
- data/lib/fortnox/api/types/enums.rb +75 -0
- data/lib/fortnox/api/types/invoice_row.rb +19 -0
- data/lib/fortnox/api/types/model.rb +40 -0
- data/lib/fortnox/api/types/nullable.rb +21 -0
- data/lib/fortnox/api/types/order_row.rb +16 -0
- data/lib/fortnox/api/types/required.rb +13 -0
- data/lib/fortnox/api/types/sized.rb +25 -0
- data/lib/fortnox/api/version.rb +1 -1
- data/spec/fortnox/api/base_spec.rb +85 -14
- data/spec/fortnox/api/mappers/base/from_json_spec.rb +70 -0
- data/spec/fortnox/api/mappers/base/to_json_spec.rb +76 -0
- data/spec/fortnox/api/mappers/base_spec.rb +156 -0
- data/spec/fortnox/api/mappers/contexts/json_conversion.rb +56 -0
- data/spec/fortnox/api/mappers/customer_spec.rb +25 -0
- data/spec/fortnox/api/mappers/default_delivery_types_spec.rb +12 -0
- data/spec/fortnox/api/mappers/edi_information_spec.rb +21 -0
- data/spec/fortnox/api/mappers/email_information_spec.rb +17 -0
- data/spec/fortnox/api/mappers/examples/mapper.rb +26 -0
- data/spec/fortnox/api/mappers/invoice_row_spec.rb +19 -0
- data/spec/fortnox/api/mappers/invoice_spec.rb +24 -0
- data/spec/fortnox/api/mappers/order_row_spec.rb +14 -0
- data/spec/fortnox/api/mappers/order_spec.rb +20 -0
- data/spec/fortnox/api/models/base_spec.rb +44 -22
- data/spec/fortnox/api/models/customer_spec.rb +9 -0
- data/spec/fortnox/api/models/examples/document_base.rb +13 -0
- data/spec/fortnox/api/models/examples/model.rb +13 -0
- data/spec/fortnox/api/models/invoice_spec.rb +7 -31
- data/spec/fortnox/api/models/order_spec.rb +13 -0
- data/spec/fortnox/api/repositories/customer_spec.rb +20 -76
- data/spec/fortnox/api/repositories/examples/all.rb +17 -0
- data/spec/fortnox/api/repositories/examples/find.rb +25 -0
- data/spec/fortnox/api/repositories/examples/only.rb +42 -0
- data/spec/fortnox/api/repositories/examples/save.rb +69 -0
- data/spec/fortnox/api/repositories/examples/save_with_nested_model.rb +32 -0
- data/spec/fortnox/api/repositories/examples/save_with_specially_named_attribute.rb +27 -0
- data/spec/fortnox/api/repositories/examples/search.rb +31 -0
- data/spec/fortnox/api/repositories/invoice_spec.rb +36 -5
- data/spec/fortnox/api/repositories/order_spec.rb +35 -0
- data/spec/fortnox/api/types/account_number_spec.rb +28 -0
- data/spec/fortnox/api/types/default_delivery_types_spec.rb +10 -0
- data/spec/fortnox/api/types/edi_information_spec.rb +13 -0
- data/spec/fortnox/api/types/email_information_spec.rb +13 -0
- data/spec/fortnox/api/types/email_spec.rb +29 -0
- data/spec/fortnox/api/types/enums_spec.rb +13 -0
- data/spec/fortnox/api/types/examples/document_row.rb +15 -0
- data/spec/fortnox/api/types/examples/enum.rb +48 -0
- data/spec/fortnox/api/types/examples/types.rb +9 -0
- data/spec/fortnox/api/types/house_work_types_spec.rb +60 -0
- data/spec/fortnox/api/types/invoice_row_spec.rb +9 -0
- data/spec/fortnox/api/types/model_spec.rb +56 -0
- data/spec/fortnox/api/types/nullable_spec.rb +57 -0
- data/spec/fortnox/api/types/order_row_spec.rb +13 -0
- data/spec/fortnox/api/types/required_spec.rb +42 -0
- data/spec/fortnox/api/types/sized_spec.rb +74 -0
- data/spec/fortnox/api_spec.rb +16 -15
- data/spec/spec_helper.rb +19 -9
- data/spec/support/helpers/dummy_class_helper.rb +19 -0
- data/spec/support/helpers/environment_helper.rb +7 -0
- data/spec/support/helpers/repository_helper.rb +8 -0
- data/spec/support/helpers/when_performing_helper.rb +5 -0
- data/spec/support/matchers.rb +1 -1
- data/spec/support/matchers/type.rb +17 -0
- data/spec/support/matchers/type/attribute_matcher.rb +39 -0
- data/spec/support/matchers/type/enum_matcher.rb +21 -0
- data/spec/support/matchers/type/have_account_number_matcher.rb +21 -0
- data/spec/support/matchers/type/have_country_code_matcher.rb +13 -0
- data/spec/support/matchers/type/have_currency_matcher.rb +7 -0
- data/spec/support/matchers/type/have_customer_type_matcher.rb +13 -0
- data/spec/support/matchers/type/have_default_delivery_type_matcher.rb +7 -0
- data/spec/support/matchers/type/have_discount_type_matcher.rb +7 -0
- data/spec/support/matchers/type/have_email_matcher.rb +22 -0
- data/spec/support/matchers/type/have_house_work_type_matcher.rb +7 -0
- data/spec/support/matchers/type/have_nullable_date_matcher.rb +58 -0
- data/spec/support/matchers/type/have_nullable_matcher.rb +52 -0
- data/spec/support/matchers/type/have_nullable_string_matcher.rb +49 -0
- data/spec/support/matchers/type/have_sized_float_matcher.rb +8 -0
- data/spec/support/matchers/type/have_sized_integer_matcher.rb +8 -0
- data/spec/support/matchers/type/have_sized_string_matcher.rb +35 -0
- data/spec/support/matchers/type/have_vat_type_matcher.rb +7 -0
- data/spec/support/matchers/type/numeric_matcher.rb +50 -0
- data/spec/support/matchers/type/require_attribute_matcher.rb +69 -0
- data/spec/support/matchers/type/type_matcher.rb +38 -0
- data/spec/vcr_cassettes/customers/all.yml +119 -9
- data/spec/vcr_cassettes/customers/find_id_1.yml +8 -9
- data/spec/vcr_cassettes/customers/find_new.yml +46 -0
- data/spec/vcr_cassettes/customers/save_new.yml +9 -11
- data/spec/vcr_cassettes/customers/save_old.yml +9 -12
- data/spec/vcr_cassettes/customers/save_with_specially_named_attribute.yml +45 -0
- data/spec/vcr_cassettes/customers/search_by_name.yml +66 -0
- data/spec/vcr_cassettes/customers/search_miss.yml +45 -0
- data/spec/vcr_cassettes/invoices/all.yml +104 -0
- data/spec/vcr_cassettes/invoices/filter_hit.yml +46 -0
- data/spec/vcr_cassettes/invoices/filter_invalid.yml +42 -0
- data/spec/vcr_cassettes/invoices/find_id_1.yml +47 -0
- data/spec/vcr_cassettes/invoices/find_new.yml +49 -0
- data/spec/vcr_cassettes/invoices/save_new.yml +48 -0
- data/spec/vcr_cassettes/invoices/save_old.yml +49 -0
- data/spec/vcr_cassettes/invoices/save_with_nested_model.yml +47 -0
- data/spec/vcr_cassettes/invoices/save_with_specially_named_attribute.yml +47 -0
- data/spec/vcr_cassettes/invoices/search_by_name.yml +48 -0
- data/spec/vcr_cassettes/invoices/search_miss.yml +45 -0
- data/spec/vcr_cassettes/orders/all.yml +144 -0
- data/spec/vcr_cassettes/orders/filter_hit.yml +48 -0
- data/spec/vcr_cassettes/orders/filter_invalid.yml +42 -0
- data/spec/vcr_cassettes/orders/find_id_1.yml +48 -0
- data/spec/vcr_cassettes/orders/find_new.yml +49 -0
- data/spec/vcr_cassettes/orders/house_work_type_babysitting.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_cleaning.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_construction.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_cooking.yml +43 -0
- data/spec/vcr_cassettes/orders/house_work_type_electricity.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_gardening.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_glassmetalwork.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_grounddrainagework.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_hvac.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_masonry.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_othercare.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_othercosts.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_paintingwallpapering.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_snowplowing.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_textileclothing.yml +47 -0
- data/spec/vcr_cassettes/orders/house_work_type_tutoring.yml +43 -0
- data/spec/vcr_cassettes/orders/save_new.yml +48 -0
- data/spec/vcr_cassettes/orders/save_old.yml +49 -0
- data/spec/vcr_cassettes/orders/save_with_nested_model.yml +47 -0
- data/spec/vcr_cassettes/orders/search_by_name.yml +47 -0
- data/spec/vcr_cassettes/orders/search_miss.yml +45 -0
- metadata +301 -71
- data/lib/fortnox/api/models/attributes/country_code.rb +0 -17
- data/lib/fortnox/api/models/attributes/currency.rb +0 -17
- data/lib/fortnox/api/models/edi_information.rb +0 -28
- data/lib/fortnox/api/models/email_information.rb +0 -25
- data/lib/fortnox/api/models/row.rb +0 -82
- data/lib/fortnox/api/repositories/base/json_convertion.rb +0 -68
- data/lib/fortnox/api/repositories/base/options.rb +0 -33
- data/lib/fortnox/api/validators.rb +0 -1
- data/lib/fortnox/api/validators/attributes/country_code.rb +0 -42
- data/lib/fortnox/api/validators/attributes/currency.rb +0 -38
- data/lib/fortnox/api/validators/base.rb +0 -70
- data/lib/fortnox/api/validators/constant.rb +0 -21
- data/lib/fortnox/api/validators/customer.rb +0 -29
- data/lib/fortnox/api/validators/edi_information.rb +0 -11
- data/lib/fortnox/api/validators/email_information.rb +0 -19
- data/lib/fortnox/api/validators/invoice.rb +0 -33
- data/lib/fortnox/api/validators/row.rb +0 -22
- data/spec/fortnox/api/models/attributes/country_code_spec.rb +0 -23
- data/spec/fortnox/api/models/attributes/currency_spec.rb +0 -23
- data/spec/fortnox/api/models/attributes/dummy_model_context.rb +0 -9
- data/spec/fortnox/api/models/row_spec.rb +0 -13
- data/spec/fortnox/api/repositories/context.rb +0 -10
- data/spec/fortnox/api/repositories/examples.rb +0 -16
- data/spec/fortnox/api/validators/attributes/country_code_spec.rb +0 -9
- data/spec/fortnox/api/validators/attributes/currency_spec.rb +0 -9
- data/spec/fortnox/api/validators/attributes/examples_for_validate.rb +0 -29
- data/spec/fortnox/api/validators/base_spec.rb +0 -61
- data/spec/fortnox/api/validators/constant_spec.rb +0 -12
- data/spec/fortnox/api/validators/context.rb +0 -102
- data/spec/fortnox/api/validators/customer_spec.rb +0 -31
- data/spec/fortnox/api/validators/edi_information_spec.rb +0 -18
- data/spec/fortnox/api/validators/email_information_spec.rb +0 -26
- data/spec/fortnox/api/validators/invoice_spec.rb +0 -36
- data/spec/fortnox/api/validators/row_spec.rb +0 -27
- data/spec/fortnox/api/validators/validator_examples.rb +0 -20
- data/spec/support/matchers/models.rb +0 -27
- data/spec/support/matchers/validators.rb +0 -36
@@ -0,0 +1,13 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
def have_country_code( attribute, valid_hash = {} )
|
4
|
+
HaveCountryCodeMatcher.new( attribute, valid_hash )
|
5
|
+
end
|
6
|
+
|
7
|
+
class HaveCountryCodeMatcher < EnumMatcher
|
8
|
+
def initialize( attribute, valid_hash )
|
9
|
+
super( attribute, valid_hash, 'CountryCode', 'CountryCodes', nonsense_value: 'XX'.freeze )
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
def have_customer_type( attribute, valid_hash = {} )
|
4
|
+
HaveCustomerTypeMatcher.new( attribute, valid_hash )
|
5
|
+
end
|
6
|
+
|
7
|
+
class HaveCustomerTypeMatcher < EnumMatcher
|
8
|
+
def initialize( attribute, valid_hash )
|
9
|
+
super( attribute, valid_hash, 'CustomerType', 'CustomerTypes' )
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
def have_email( attribute, valid_hash = {} )
|
4
|
+
HaveEmailMatcher.new( attribute, valid_hash )
|
5
|
+
end
|
6
|
+
|
7
|
+
class HaveEmailMatcher < TypeMatcher
|
8
|
+
def initialize( attribute, valid_hash )
|
9
|
+
super( attribute, valid_hash, 'email', 'valid@email.com', 'invalid@email_without_top_domain' )
|
10
|
+
@expected_error = "Exception missing for invalid value #{ @invalid_value.inspect }"
|
11
|
+
@expected_type = Fortnox::API::Types::Email
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def expected_type?
|
17
|
+
@actual_type = @klass.schema[@attribute]
|
18
|
+
@actual_type == Fortnox::API::Types::Email
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
def have_nullable_date( attribute, valid_value, invalid_value )
|
4
|
+
HaveNullableDateMatcher.new( attribute, valid_value, invalid_value )
|
5
|
+
end
|
6
|
+
|
7
|
+
class HaveNullableDateMatcher < HaveNullableMatcher
|
8
|
+
def initialize( attribute, valid_value, invalid_value )
|
9
|
+
@attribute = attribute
|
10
|
+
@valid_value = valid_value
|
11
|
+
@invalid_value = invalid_value
|
12
|
+
@expected_error = ArgumentError
|
13
|
+
@expected_error_message = 'invalid date'
|
14
|
+
@failure_description = ''
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches?( klass )
|
18
|
+
@klass = klass
|
19
|
+
|
20
|
+
accepts_nil? && accepts_valid_value? && rejects_invalid_value?
|
21
|
+
end
|
22
|
+
|
23
|
+
def description
|
24
|
+
"have nullable attribute #{ @attribute.inspect }"
|
25
|
+
end
|
26
|
+
|
27
|
+
def failure_message
|
28
|
+
"Expected class to have nullable attribute #{ @attribute.inspect }" << @failure_description
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def accepts_nil?
|
34
|
+
@klass.new(@attribute => nil)
|
35
|
+
end
|
36
|
+
|
37
|
+
def accepts_valid_value?
|
38
|
+
model = @klass.new(@attribute => @valid_value)
|
39
|
+
model.send(@attribute) == @valid_value
|
40
|
+
end
|
41
|
+
|
42
|
+
def rejects_invalid_value?
|
43
|
+
@klass.new(@attribute => @invalid_value)
|
44
|
+
|
45
|
+
@failure_description << " (Expected #{ @expected_error }, but got none)"
|
46
|
+
return false
|
47
|
+
rescue @expected_error => error
|
48
|
+
if error.message == @expected_error_message
|
49
|
+
return true
|
50
|
+
else
|
51
|
+
fail_message = "Expected error message to include #{ expected_message.inspect }, "\
|
52
|
+
"but was #{ error.message.inspect }"
|
53
|
+
fail(fail_message)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
def have_nullable( attribute, valid_value, invalid_value, default_value )
|
4
|
+
HaveNullableMatcher.new( attribute, valid_value, invalid_value, default_value )
|
5
|
+
end
|
6
|
+
|
7
|
+
class HaveNullableMatcher
|
8
|
+
def initialize( attribute, valid_value, invalid_value, default_value )
|
9
|
+
@attribute = attribute
|
10
|
+
@valid_value = valid_value
|
11
|
+
@invalid_value = invalid_value
|
12
|
+
@default_value = default_value
|
13
|
+
@failure_description = ''
|
14
|
+
end
|
15
|
+
|
16
|
+
def matches?( klass )
|
17
|
+
@klass = klass
|
18
|
+
|
19
|
+
accepts_nil? && accepts_valid_value? && defaults_invalid_value?
|
20
|
+
end
|
21
|
+
|
22
|
+
def description
|
23
|
+
"have nullable attribute #{ @attribute.inspect }"
|
24
|
+
end
|
25
|
+
|
26
|
+
def failure_message
|
27
|
+
"Expected class to have nullable attribute #{ @attribute.inspect }" << @failure_description
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def accepts_nil?
|
33
|
+
@klass.new(@attribute => nil)
|
34
|
+
end
|
35
|
+
|
36
|
+
def accepts_valid_value?
|
37
|
+
model = @klass.new(@attribute => @valid_value)
|
38
|
+
model.send(@attribute) == @valid_value
|
39
|
+
end
|
40
|
+
|
41
|
+
def defaults_invalid_value?
|
42
|
+
model = @klass.new(@attribute => @invalid_value)
|
43
|
+
value = model.send(@attribute)
|
44
|
+
return true if value == @default_value
|
45
|
+
|
46
|
+
@failure_description << " (Expected #{ @invalid_value.inspect } to default to "\
|
47
|
+
"#{ @default_value.inspect }), but got #{ value.inspect }"
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
def have_nullable_string( attribute, valid_hash = {} )
|
4
|
+
HaveNullableStringMatcher.new( attribute, valid_hash )
|
5
|
+
end
|
6
|
+
|
7
|
+
class HaveNullableStringMatcher < AttributeMatcher
|
8
|
+
def initialize( attribute, valid_hash )
|
9
|
+
super( attribute, valid_hash, 'nullable string' )
|
10
|
+
end
|
11
|
+
|
12
|
+
def matches?( klass )
|
13
|
+
super
|
14
|
+
|
15
|
+
accepts_nil? && accepts_string? && rejects_non_string?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def accepts_nil?
|
21
|
+
model = @klass.new( @valid_hash.merge( @attribute => nil ) )
|
22
|
+
model.send(@attribute).nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def accepts_string?
|
26
|
+
valid_string = 'A string'
|
27
|
+
model = @klass.new( @valid_hash.merge( @attribute => valid_string ) )
|
28
|
+
model.send(@attribute) == 'A string'
|
29
|
+
end
|
30
|
+
|
31
|
+
def rejects_non_string?
|
32
|
+
non_string = 10.0
|
33
|
+
@klass.new( @valid_hash.merge( @attribute => non_string ) )
|
34
|
+
rescue Fortnox::API::InvalidAttributeValueError => error
|
35
|
+
expected_message = "#{ non_string.inspect } (#{ non_string.class }) "\
|
36
|
+
"has invalid type for #{ @attribute.inspect }"
|
37
|
+
if error.message.include?(expected_message)
|
38
|
+
return true
|
39
|
+
else
|
40
|
+
fail_message = "Expected error message to include #{ expected_message.inspect }, "\
|
41
|
+
"but was #{ error.message.inspect }"
|
42
|
+
fail(fail_message)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
def have_sized_string( attribute, max_size, valid_hash = {} )
|
4
|
+
HaveSizedStringMatcher.new( attribute, max_size, valid_hash )
|
5
|
+
end
|
6
|
+
|
7
|
+
class HaveSizedStringMatcher < AttributeMatcher
|
8
|
+
def initialize( attribute, max_size, valid_hash )
|
9
|
+
super( attribute, valid_hash, 'sized string' )
|
10
|
+
@max_size = max_size
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?( klass )
|
14
|
+
@klass = klass
|
15
|
+
|
16
|
+
accepts_max_size? && rejects_too_long_string?
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def accepts_max_size?
|
22
|
+
@klass.new( @valid_hash.merge( @attribute => 'a' * @max_size ) )
|
23
|
+
end
|
24
|
+
|
25
|
+
def rejects_too_long_string?
|
26
|
+
too_long = @max_size + 1
|
27
|
+
too_long_string = 'a' * too_long
|
28
|
+
expect_error("Exception missing for too long string (#{ too_long } characters)") do
|
29
|
+
@klass.new( @valid_hash.merge( @attribute => too_long_string ) )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
class NumericMatcher < AttributeMatcher
|
4
|
+
def initialize( attribute, valid_hash, attr_type, options )
|
5
|
+
super( attribute, valid_hash, attr_type )
|
6
|
+
|
7
|
+
@min_value = options[:min_value]
|
8
|
+
@max_value = options[:max_value]
|
9
|
+
@step = options[:step]
|
10
|
+
end
|
11
|
+
|
12
|
+
def matches?( klass )
|
13
|
+
super
|
14
|
+
|
15
|
+
rejects_too_small_value? &&
|
16
|
+
accepts_min_value? &&
|
17
|
+
accepts_max_value? &&
|
18
|
+
rejects_too_big_value?
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def rejects_too_small_value?
|
24
|
+
too_small_value = @min_value - @step
|
25
|
+
expected_error_message = "Exception missing for too small value (#{ too_small_value })"
|
26
|
+
rejects_value?(too_small_value, expected_error_message)
|
27
|
+
end
|
28
|
+
|
29
|
+
def accepts_min_value?
|
30
|
+
@klass.new( @valid_hash.merge( @attribute => @min_value ) )
|
31
|
+
end
|
32
|
+
|
33
|
+
def accepts_max_value?
|
34
|
+
@klass.new( @valid_hash.merge( @attribute => @max_value ) )
|
35
|
+
end
|
36
|
+
|
37
|
+
def rejects_too_big_value?
|
38
|
+
too_big_value = @max_value + @step
|
39
|
+
expected_error_message = "Exception missing for too big value (#{ too_big_value })"
|
40
|
+
rejects_value?(too_big_value, expected_error_message)
|
41
|
+
end
|
42
|
+
|
43
|
+
def rejects_value?(value, expected_error_message)
|
44
|
+
expect_error(expected_error_message) do
|
45
|
+
@klass.new( @valid_hash.merge( @attribute => value ) )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'fortnox/api'
|
2
|
+
|
3
|
+
module Matchers
|
4
|
+
module Type
|
5
|
+
def require_attribute(attribute, valid_hash = {})
|
6
|
+
RequireAttributeMatcher.new(attribute, valid_hash)
|
7
|
+
end
|
8
|
+
|
9
|
+
class RequireAttributeMatcher
|
10
|
+
EXCEPTION = Fortnox::API::MissingAttributeError
|
11
|
+
|
12
|
+
def initialize( attribute, valid_hash )
|
13
|
+
@attribute = attribute
|
14
|
+
@invalid_hash = valid_hash.dup.tap{ |hash| hash.delete( attribute ) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches?( klass )
|
18
|
+
@klass = klass
|
19
|
+
|
20
|
+
raise_error && includes_error_message
|
21
|
+
end
|
22
|
+
|
23
|
+
def failure_message
|
24
|
+
return no_exception_failure_message unless raise_error
|
25
|
+
return wrong_error_message unless includes_error_message
|
26
|
+
end
|
27
|
+
|
28
|
+
def description
|
29
|
+
"require attribute #{ @attribute.inspect }"
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def raise_error
|
35
|
+
@klass.new(@invalid_hash)
|
36
|
+
|
37
|
+
false # Fail test since expected error is not thrown
|
38
|
+
|
39
|
+
rescue EXCEPTION
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def includes_error_message
|
44
|
+
@klass.new(@invalid_hash)
|
45
|
+
rescue EXCEPTION => error
|
46
|
+
if error.message.include? expected_error_message
|
47
|
+
return true
|
48
|
+
else
|
49
|
+
@wrong_error_message = error.message
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def expected_error_message
|
55
|
+
@attribute.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
def no_exception_failure_message
|
59
|
+
"Expected class to raise #{ EXCEPTION } "\
|
60
|
+
"when attribute #{ @attribute.inspect } is missing."
|
61
|
+
end
|
62
|
+
|
63
|
+
def wrong_error_message
|
64
|
+
"Expected exception to equal #{ expected_error_message.inspect }. "\
|
65
|
+
"Message was #{ @wrong_error_message.inspect }."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Matchers
|
2
|
+
module Type
|
3
|
+
class TypeMatcher < AttributeMatcher
|
4
|
+
def initialize( attr, valid_hash, attr_name, valid_value, invalid_value )
|
5
|
+
super( attr, valid_hash, attr_name )
|
6
|
+
|
7
|
+
@valid_value = valid_value
|
8
|
+
@invalid_value = invalid_value
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches?( klass )
|
12
|
+
super
|
13
|
+
|
14
|
+
correct_type? && rejects_invalid_value? && accepts_valid_value?
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def correct_type?
|
20
|
+
return true if expected_type?
|
21
|
+
|
22
|
+
@errors << "Attribute #{ @attribute.inspect } was expected to be of type #{ @attribute_type }, but was #{ @actual_type }"
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
def accepts_valid_value?
|
27
|
+
@klass.new( @valid_hash.merge( @attribute => @valid_value ) )
|
28
|
+
end
|
29
|
+
|
30
|
+
def rejects_invalid_value?
|
31
|
+
expect_error(@expected_error) do
|
32
|
+
@klass.new( @valid_hash.merge( @attribute => @invalid_value ) )
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|