fortnox-api 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|