fortnox-api 0.5.2 → 0.6.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/.gitignore +3 -0
- data/.rubocop.yml +9 -1104
- data/.travis.yml +22 -2
- data/Gemfile +3 -1
- data/Guardfile +4 -2
- data/README.md +2 -2
- data/Rakefile +3 -1
- data/bin/console +17 -3
- data/fortnox-api.gemspec +32 -27
- data/lib/fortnox/api.rb +17 -16
- data/lib/fortnox/api/circular_queue.rb +13 -7
- data/lib/fortnox/api/mappers.rb +29 -25
- data/lib/fortnox/api/mappers/article.rb +7 -6
- data/lib/fortnox/api/mappers/base.rb +18 -16
- data/lib/fortnox/api/mappers/base/from_json.rb +37 -30
- data/lib/fortnox/api/mappers/base/to_json.rb +39 -37
- data/lib/fortnox/api/mappers/customer.rb +7 -7
- data/lib/fortnox/api/mappers/default_delivery_types.rb +4 -2
- data/lib/fortnox/api/mappers/default_templates.rb +5 -4
- data/lib/fortnox/api/mappers/edi_information.rb +5 -4
- data/lib/fortnox/api/mappers/email_information.rb +5 -4
- data/lib/fortnox/api/mappers/invoice.rb +10 -8
- data/lib/fortnox/api/mappers/invoice_row.rb +12 -7
- data/lib/fortnox/api/mappers/order.rb +10 -7
- data/lib/fortnox/api/mappers/order_row.rb +13 -6
- data/lib/fortnox/api/mappers/project.rb +6 -4
- data/lib/fortnox/api/mappers/terms_of_payments.rb +17 -0
- data/lib/fortnox/api/mappers/unit.rb +17 -0
- data/lib/fortnox/api/models.rb +9 -5
- data/lib/fortnox/api/models/article.rb +68 -67
- data/lib/fortnox/api/models/base.rb +52 -36
- data/lib/fortnox/api/models/customer.rb +95 -94
- data/lib/fortnox/api/models/document.rb +186 -0
- data/lib/fortnox/api/models/invoice.rb +44 -44
- data/lib/fortnox/api/models/label.rb +5 -3
- data/lib/fortnox/api/models/order.rb +8 -8
- data/lib/fortnox/api/models/project.rb +10 -8
- data/lib/fortnox/api/models/terms_of_payments.rb +28 -0
- data/lib/fortnox/api/models/unit.rb +24 -0
- data/lib/fortnox/api/repositories.rb +9 -5
- data/lib/fortnox/api/repositories/article.rb +6 -4
- data/lib/fortnox/api/repositories/base.rb +49 -46
- data/lib/fortnox/api/repositories/base/loaders.rb +32 -36
- data/lib/fortnox/api/repositories/base/savers.rb +23 -21
- data/lib/fortnox/api/repositories/customer.rb +6 -4
- data/lib/fortnox/api/repositories/invoice.rb +6 -4
- data/lib/fortnox/api/repositories/order.rb +6 -4
- data/lib/fortnox/api/repositories/project.rb +6 -4
- data/lib/fortnox/api/repositories/terms_of_payments.rb +17 -0
- data/lib/fortnox/api/repositories/unit.rb +17 -0
- data/lib/fortnox/api/request_handling.rb +12 -12
- data/lib/fortnox/api/types.rb +62 -11
- data/lib/fortnox/api/types/default_delivery_types.rb +5 -3
- data/lib/fortnox/api/types/default_templates.rb +3 -1
- data/lib/fortnox/api/types/defaulted.rb +2 -2
- data/lib/fortnox/api/types/document_row.rb +41 -42
- data/lib/fortnox/api/types/edi_information.rb +10 -8
- data/lib/fortnox/api/types/email_information.rb +10 -8
- data/lib/fortnox/api/types/enums.rb +60 -47
- data/lib/fortnox/api/types/invoice_row.rb +8 -8
- data/lib/fortnox/api/types/model.rb +14 -10
- data/lib/fortnox/api/types/nullable.rb +7 -7
- data/lib/fortnox/api/types/order_row.rb +5 -5
- data/lib/fortnox/api/types/required.rb +5 -5
- data/lib/fortnox/api/types/sized.rb +14 -6
- data/lib/fortnox/api/version.rb +3 -1
- data/spec/fortnox/api/mappers/article_spec.rb +3 -1
- data/spec/fortnox/api/mappers/base/from_json_spec.rb +15 -13
- data/spec/fortnox/api/mappers/base/to_json_spec.rb +4 -3
- data/spec/fortnox/api/mappers/base_spec.rb +40 -35
- data/spec/fortnox/api/mappers/contexts/json_conversion.rb +12 -11
- data/spec/fortnox/api/mappers/customer_spec.rb +3 -1
- data/spec/fortnox/api/mappers/default_delivery_types_spec.rb +3 -1
- data/spec/fortnox/api/mappers/edi_information_spec.rb +4 -2
- data/spec/fortnox/api/mappers/email_information_spec.rb +4 -2
- data/spec/fortnox/api/mappers/examples/mapper.rb +17 -9
- data/spec/fortnox/api/mappers/invoice_row_spec.rb +8 -3
- data/spec/fortnox/api/mappers/invoice_spec.rb +4 -1
- data/spec/fortnox/api/mappers/order_row_spec.rb +9 -2
- data/spec/fortnox/api/mappers/order_spec.rb +4 -1
- data/spec/fortnox/api/mappers/project_spec.rb +3 -1
- data/spec/fortnox/api/mappers/terms_of_payments_spec.rb +16 -0
- data/spec/fortnox/api/mappers/unit_spec.rb +57 -0
- data/spec/fortnox/api/models/article_spec.rb +2 -0
- data/spec/fortnox/api/models/base_spec.rb +46 -38
- data/spec/fortnox/api/models/customer_spec.rb +2 -0
- data/spec/fortnox/api/models/examples/document_base.rb +5 -3
- data/spec/fortnox/api/models/examples/model.rb +12 -9
- data/spec/fortnox/api/models/invoice_spec.rb +2 -0
- data/spec/fortnox/api/models/order_spec.rb +2 -0
- data/spec/fortnox/api/models/project_spec.rb +2 -0
- data/spec/fortnox/api/models/terms_of_payments_spec.rb +9 -0
- data/spec/fortnox/api/models/unit_spec.rb +31 -0
- data/spec/fortnox/api/repositories/article_spec.rb +7 -5
- data/spec/fortnox/api/repositories/base_spec.rb +121 -100
- data/spec/fortnox/api/repositories/customer_spec.rb +7 -5
- data/spec/fortnox/api/repositories/examples/all.rb +5 -4
- data/spec/fortnox/api/repositories/examples/find.rb +50 -41
- data/spec/fortnox/api/repositories/examples/only.rb +14 -13
- data/spec/fortnox/api/repositories/examples/save.rb +23 -29
- data/spec/fortnox/api/repositories/examples/save_with_nested_model.rb +11 -11
- data/spec/fortnox/api/repositories/examples/save_with_specially_named_attribute.rb +11 -10
- data/spec/fortnox/api/repositories/examples/search.rb +15 -15
- data/spec/fortnox/api/repositories/invoice_spec.rb +8 -6
- data/spec/fortnox/api/repositories/order_spec.rb +8 -6
- data/spec/fortnox/api/repositories/project_spec.rb +7 -5
- data/spec/fortnox/api/repositories/terms_of_payments_spec.rb +30 -0
- data/spec/fortnox/api/repositories/unit_spec.rb +34 -0
- data/spec/fortnox/api/types/account_number_spec.rb +12 -9
- data/spec/fortnox/api/types/default_delivery_types_spec.rb +6 -4
- data/spec/fortnox/api/types/edi_information_spec.rb +9 -7
- data/spec/fortnox/api/types/email_information_spec.rb +8 -6
- data/spec/fortnox/api/types/email_spec.rb +27 -14
- data/spec/fortnox/api/types/enums_spec.rb +3 -1
- data/spec/fortnox/api/types/examples/document_row.rb +10 -8
- data/spec/fortnox/api/types/examples/enum.rb +29 -22
- data/spec/fortnox/api/types/examples/types.rb +8 -4
- data/spec/fortnox/api/types/housework_types_spec.rb +68 -0
- data/spec/fortnox/api/types/invoice_row_spec.rb +3 -1
- data/spec/fortnox/api/types/model_spec.rb +12 -9
- data/spec/fortnox/api/types/nullable_spec.rb +8 -6
- data/spec/fortnox/api/types/order_row_spec.rb +4 -2
- data/spec/fortnox/api/types/required_spec.rb +4 -2
- data/spec/fortnox/api/types/sized_spec.rb +18 -16
- data/spec/fortnox/api_spec.rb +45 -43
- data/spec/spec_helper.rb +9 -6
- data/spec/support/helpers.rb +3 -1
- data/spec/support/helpers/configuration_helper.rb +2 -0
- data/spec/support/helpers/dummy_class_helper.rb +7 -8
- data/spec/support/helpers/repository_helper.rb +2 -0
- data/spec/support/helpers/when_performing_helper.rb +3 -1
- data/spec/support/matchers.rb +2 -0
- data/spec/support/matchers/type.rb +3 -1
- data/spec/support/matchers/type/attribute_matcher.rb +15 -14
- data/spec/support/matchers/type/enum_matcher.rb +9 -7
- data/spec/support/matchers/type/have_account_number_matcher.rb +11 -9
- data/spec/support/matchers/type/have_country_code_matcher.rb +6 -4
- data/spec/support/matchers/type/have_currency_matcher.rb +4 -2
- data/spec/support/matchers/type/have_customer_type_matcher.rb +6 -4
- data/spec/support/matchers/type/have_default_delivery_type_matcher.rb +4 -2
- data/spec/support/matchers/type/have_discount_type_matcher.rb +4 -2
- data/spec/support/matchers/type/have_email_matcher.rb +11 -9
- data/spec/support/matchers/type/have_housework_type_matcher.rb +9 -0
- data/spec/support/matchers/type/have_nullable_date_matcher.rb +29 -29
- data/spec/support/matchers/type/have_nullable_matcher.rb +23 -21
- data/spec/support/matchers/type/have_nullable_string_matcher.rb +30 -32
- data/spec/support/matchers/type/have_sized_float_matcher.rb +4 -2
- data/spec/support/matchers/type/have_sized_integer_matcher.rb +4 -2
- data/spec/support/matchers/type/have_sized_string_matcher.rb +16 -15
- data/spec/support/matchers/type/have_vat_type_matcher.rb +4 -2
- data/spec/support/matchers/type/numeric_matcher.rb +25 -23
- data/spec/support/matchers/type/require_attribute_matcher.rb +36 -37
- data/spec/support/matchers/type/type_matcher.rb +18 -16
- data/spec/support/vcr_setup.rb +2 -0
- data/spec/vcr_cassettes/orders/{house_work_type_babysitting.yml → housework_type_babysitting.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_cleaning.yml → housework_type_cleaning.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_construction.yml → housework_type_construction.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_cooking.yml → housework_type_cooking.yml} +7 -7
- data/spec/vcr_cassettes/orders/{house_work_type_electricity.yml → housework_type_electricity.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_gardening.yml → housework_type_gardening.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_glassmetalwork.yml → housework_type_glassmetalwork.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_grounddrainagework.yml → housework_type_grounddrainagework.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_hvac.yml → housework_type_hvac.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_masonry.yml → housework_type_masonry.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_othercare.yml → housework_type_othercare.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_othercosts.yml → housework_type_othercosts.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_paintingwallpapering.yml → housework_type_paintingwallpapering.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_snowplowing.yml → housework_type_snowplowing.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_textileclothing.yml → housework_type_textileclothing.yml} +9 -10
- data/spec/vcr_cassettes/orders/{house_work_type_tutoring.yml → housework_type_tutoring.yml} +7 -7
- data/spec/vcr_cassettes/termsofpayments/all.yml +51 -0
- data/spec/vcr_cassettes/termsofpayments/find_failure.yml +45 -0
- data/spec/vcr_cassettes/termsofpayments/find_id_1.yml +46 -0
- data/spec/vcr_cassettes/termsofpayments/find_new.yml +46 -0
- data/spec/vcr_cassettes/termsofpayments/save_new.yml +45 -0
- data/spec/vcr_cassettes/termsofpayments/save_old.yml +46 -0
- data/spec/vcr_cassettes/units/all.yml +48 -0
- data/spec/vcr_cassettes/units/find_failure.yml +45 -0
- data/spec/vcr_cassettes/units/find_id_1.yml +46 -0
- data/spec/vcr_cassettes/units/find_new.yml +48 -0
- data/spec/vcr_cassettes/units/save_new.yml +47 -0
- data/spec/vcr_cassettes/units/save_old.yml +48 -0
- data/spec/vcr_cassettes/units/save_with_specially_named_attribute.yml +47 -0
- metadata +127 -88
- data/docs/account.rb +0 -59
- data/docs/extraction_script.js +0 -23
- data/docs/generation_script.rb +0 -43
- data/docs/json/account.json +0 -77
- data/lib/fortnox/api/models/document_base.rb +0 -189
- data/spec/fortnox/api/types/house_work_types_spec.rb +0 -64
- data/spec/support/matchers/type/have_house_work_type_matcher.rb +0 -7
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require 'spec_helper'
         | 
| 2 4 | 
             
            require 'fortnox/api'
         | 
| 3 5 | 
             
            require 'fortnox/api/mappers'
         | 
| @@ -11,9 +13,9 @@ require 'fortnox/api/repositories/examples/search' | |
| 11 13 | 
             
            describe Fortnox::API::Repository::Customer, order: :defined, integration: true do
         | 
| 12 14 | 
             
              include Helpers::Configuration
         | 
| 13 15 |  | 
| 14 | 
            -
              before{ set_api_test_configuration }
         | 
| 16 | 
            +
              before { set_api_test_configuration }
         | 
| 15 17 |  | 
| 16 | 
            -
              subject(:repository){ described_class.new }
         | 
| 18 | 
            +
              subject(:repository) { described_class.new }
         | 
| 17 19 |  | 
| 18 20 | 
             
              include_examples '.save', :name
         | 
| 19 21 |  | 
| @@ -28,10 +30,10 @@ describe Fortnox::API::Repository::Customer, order: :defined, integration: true | |
| 28 30 | 
             
              include_examples '.all', 100
         | 
| 29 31 |  | 
| 30 32 | 
             
              include_examples '.find', '1' do
         | 
| 31 | 
            -
                let( | 
| 32 | 
            -
                let( | 
| 33 | 
            +
                let(:find_by_hash_failure) { { city: 'Not Found' } }
         | 
| 34 | 
            +
                let(:single_param_find_by_hash) { { find_hash: { city: 'New York' }, matches: 2 } }
         | 
| 33 35 |  | 
| 34 | 
            -
                let( | 
| 36 | 
            +
                let(:multi_param_find_by_hash) do
         | 
| 35 37 | 
             
                  { find_hash: { city: 'New York', zipcode: '10001' }, matches: 1 }
         | 
| 36 38 | 
             
                end
         | 
| 37 39 | 
             
              end
         | 
| @@ -1,16 +1,17 @@ | |
| 1 | 
            -
            #  | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 2 3 | 
             
            RSpec.shared_examples_for '.all' do |count|
         | 
| 3 4 | 
             
              describe '.all' do
         | 
| 4 5 | 
             
                let(:response) do
         | 
| 5 | 
            -
                  VCR.use_cassette( | 
| 6 | 
            +
                  VCR.use_cassette("#{vcr_dir}/all") { subject.all }
         | 
| 6 7 | 
             
                end
         | 
| 7 8 |  | 
| 8 9 | 
             
                specify 'returns correct number of records' do
         | 
| 9 | 
            -
                  expect( | 
| 10 | 
            +
                  expect(response.size).to be count
         | 
| 10 11 | 
             
                end
         | 
| 11 12 |  | 
| 12 13 | 
             
                specify 'returns correct class' do
         | 
| 13 | 
            -
                  expect( | 
| 14 | 
            +
                  expect(response.first.class).to be described_class::MODEL
         | 
| 14 15 | 
             
                end
         | 
| 15 16 | 
             
              end
         | 
| 16 17 | 
             
            end
         | 
| @@ -1,78 +1,87 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            shared_examples_for '.find' do |searched_entity_id, find_by_hash: true|
         | 
| 2 4 | 
             
              describe '.find by id' do
         | 
| 3 | 
            -
                let( | 
| 4 | 
            -
                  VCR.use_cassette( | 
| 5 | 
            +
                let(:returned_object) do
         | 
| 6 | 
            +
                  VCR.use_cassette("#{vcr_dir}/find_id_1") { repository.find(searched_entity_id) }
         | 
| 5 7 | 
             
                end
         | 
| 6 8 |  | 
| 7 9 | 
             
                context 'when found' do
         | 
| 8 10 | 
             
                  describe 'returned object' do
         | 
| 9 | 
            -
                    subject{ returned_object }
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                    it{ is_expected. | 
| 11 | 
            +
                    subject { returned_object }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    it { is_expected.to be_saved }
         | 
| 14 | 
            +
                    it { is_expected.not_to be_new }
         | 
| 12 15 | 
             
                  end
         | 
| 13 16 |  | 
| 14 17 | 
             
                  describe 'class' do
         | 
| 15 | 
            -
                    subject{ returned_object.class }
         | 
| 16 | 
            -
             | 
| 18 | 
            +
                    subject { returned_object.class }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    it { is_expected.to be described_class::MODEL }
         | 
| 17 21 | 
             
                  end
         | 
| 18 22 |  | 
| 19 23 | 
             
                  describe 'unique id' do
         | 
| 20 | 
            -
                    subject{ returned_object.unique_id }
         | 
| 21 | 
            -
             | 
| 24 | 
            +
                    subject { returned_object.unique_id }
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    it { is_expected.to eq searched_entity_id }
         | 
| 22 27 | 
             
                  end
         | 
| 23 28 | 
             
                end
         | 
| 24 29 |  | 
| 25 30 | 
             
                context 'when not found' do
         | 
| 26 | 
            -
                  subject{ find_failure }
         | 
| 31 | 
            +
                  subject { find_failure }
         | 
| 27 32 |  | 
| 28 | 
            -
                  let( | 
| 29 | 
            -
                  let( | 
| 33 | 
            +
                  let(:not_found_id) { '123456789' }
         | 
| 34 | 
            +
                  let(:find_failure) do
         | 
| 30 35 | 
             
                    when_performing do
         | 
| 31 | 
            -
                      VCR.use_cassette( | 
| 36 | 
            +
                      VCR.use_cassette("#{vcr_dir}/find_failure") { repository.find(not_found_id) }
         | 
| 32 37 | 
             
                    end
         | 
| 33 38 | 
             
                  end
         | 
| 34 39 |  | 
| 35 | 
            -
                  it{ is_expected.to raise_error( | 
| 40 | 
            +
                  it { is_expected.to raise_error(Fortnox::API::RemoteServerError, /Kan inte hitta /) }
         | 
| 36 41 | 
             
                end
         | 
| 37 42 | 
             
              end
         | 
| 38 43 |  | 
| 39 | 
            -
               | 
| 40 | 
            -
                 | 
| 41 | 
            -
                   | 
| 42 | 
            -
                     | 
| 43 | 
            -
             | 
| 44 | 
            +
              if find_by_hash
         | 
| 45 | 
            +
                describe '.find by hash' do
         | 
| 46 | 
            +
                  context 'when found' do
         | 
| 47 | 
            +
                    let(:returned_array) do
         | 
| 48 | 
            +
                      VCR.use_cassette("#{vcr_dir}/#{cassette}") { repository.find(find_hash) }
         | 
| 49 | 
            +
                    end
         | 
| 44 50 |  | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 51 | 
            +
                    context 'with single parameter' do
         | 
| 52 | 
            +
                      let(:cassette) { 'single_param_find_by_hash' }
         | 
| 53 | 
            +
                      let(:find_hash) { single_param_find_by_hash[:find_hash] }
         | 
| 48 54 |  | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 55 | 
            +
                      describe 'returned array size' do
         | 
| 56 | 
            +
                        subject { returned_array.size }
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                        it { is_expected.to eq single_param_find_by_hash[:matches] }
         | 
| 59 | 
            +
                      end
         | 
| 52 60 | 
             
                    end
         | 
| 53 | 
            -
                  end
         | 
| 54 61 |  | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 62 | 
            +
                    context 'with multiple parameters' do
         | 
| 63 | 
            +
                      let(:cassette) { 'multi_param_find_by_hash' }
         | 
| 64 | 
            +
                      let(:find_hash) { multi_param_find_by_hash[:find_hash] }
         | 
| 58 65 |  | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 66 | 
            +
                      describe 'returned array size' do
         | 
| 67 | 
            +
                        subject { returned_array.size }
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                        it { is_expected.to eq multi_param_find_by_hash[:matches] }
         | 
| 70 | 
            +
                      end
         | 
| 62 71 | 
             
                    end
         | 
| 63 72 | 
             
                  end
         | 
| 64 | 
            -
                end
         | 
| 65 73 |  | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 74 | 
            +
                  context 'when not found' do
         | 
| 75 | 
            +
                    subject { find_failure }
         | 
| 68 76 |  | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 77 | 
            +
                    let(:find_failure) do
         | 
| 78 | 
            +
                      VCR.use_cassette("#{vcr_dir}/find_by_hash_failure") do
         | 
| 79 | 
            +
                        repository.find(find_by_hash_failure)
         | 
| 80 | 
            +
                      end
         | 
| 72 81 | 
             
                    end
         | 
| 73 | 
            -
                  end
         | 
| 74 82 |  | 
| 75 | 
            -
             | 
| 83 | 
            +
                    it { is_expected.to eq [] }
         | 
| 84 | 
            +
                  end
         | 
| 76 85 | 
             
                end
         | 
| 77 86 | 
             
              end
         | 
| 78 87 | 
             
            end
         | 
| @@ -1,41 +1,42 @@ | |
| 1 | 
            -
            #  | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 2 3 | 
             
            shared_examples_for '.only' do |matching_filter, expected_matches, missing_filter: nil|
         | 
| 3 4 | 
             
              describe '.only' do
         | 
| 4 5 | 
             
                def repository_only(repository, vcr_cassette, filter)
         | 
| 5 | 
            -
                  VCR.use_cassette( | 
| 6 | 
            -
                    repository.only( | 
| 6 | 
            +
                  VCR.use_cassette("#{vcr_dir}/#{vcr_cassette}") do
         | 
| 7 | 
            +
                    repository.only(filter)
         | 
| 7 8 | 
             
                  end
         | 
| 8 9 | 
             
                end
         | 
| 9 10 |  | 
| 10 11 | 
             
                shared_examples '.only response' do |vcr_cassette, expected_entries|
         | 
| 11 | 
            -
                  subject{ repository_only( | 
| 12 | 
            +
                  subject { repository_only(repository, vcr_cassette, filter) }
         | 
| 12 13 |  | 
| 13 | 
            -
                  it{ is_expected.to be_instance_of( | 
| 14 | 
            -
                  it{ is_expected.to have(expected_entries).entries }
         | 
| 14 | 
            +
                  it { is_expected.to be_instance_of(Array) }
         | 
| 15 | 
            +
                  it { is_expected.to have(expected_entries).entries }
         | 
| 15 16 | 
             
                end
         | 
| 16 17 |  | 
| 17 18 | 
             
                unless missing_filter.nil?
         | 
| 18 | 
            -
                  context  | 
| 19 | 
            +
                  context 'with no matches' do
         | 
| 19 20 | 
             
                    include_examples '.only response', 'filter_miss', 0 do
         | 
| 20 | 
            -
                      let(:filter){ missing_filter }
         | 
| 21 | 
            +
                      let(:filter) { missing_filter }
         | 
| 21 22 | 
             
                    end
         | 
| 22 23 | 
             
                  end
         | 
| 23 24 | 
             
                end
         | 
| 24 25 |  | 
| 25 | 
            -
                context  | 
| 26 | 
            +
                context 'with matches' do
         | 
| 26 27 | 
             
                  include_examples '.only response', 'filter_hit', expected_matches do
         | 
| 27 | 
            -
                    let(:filter){ matching_filter }
         | 
| 28 | 
            +
                    let(:filter) { matching_filter }
         | 
| 28 29 | 
             
                  end
         | 
| 29 30 | 
             
                end
         | 
| 30 31 |  | 
| 31 | 
            -
                context  | 
| 32 | 
            +
                context 'with invalid filter' do
         | 
| 32 33 | 
             
                  subject do
         | 
| 33 34 | 
             
                    when_performing do
         | 
| 34 | 
            -
                      repository_only( | 
| 35 | 
            +
                      repository_only(repository, 'filter_invalid', 'doesntexist')
         | 
| 35 36 | 
             
                    end
         | 
| 36 37 | 
             
                  end
         | 
| 37 38 |  | 
| 38 | 
            -
                  it{ is_expected.to raise_error( | 
| 39 | 
            +
                  it { is_expected.to raise_error(Fortnox::API::RemoteServerError, /ogiltigt filter/) }
         | 
| 39 40 | 
             
                end
         | 
| 40 41 | 
             
              end
         | 
| 41 42 | 
             
            end
         | 
| @@ -1,65 +1,59 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            #######################################
         | 
| 2 4 | 
             
            # SPEC IS DEPENDENT ON DEFINED ORDER!
         | 
| 3 5 | 
             
            #######################################
         | 
| 4 6 | 
             
            #
         | 
| 5 7 | 
             
            # Assumes that attribute is a string attribute without restrictions.
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            # rubocop:disable RSpec/DescribeClass
         | 
| 8 8 | 
             
            shared_examples_for '.save' do |attribute, additional_attrs: {}|
         | 
| 9 9 | 
             
              describe '.save' do
         | 
| 10 | 
            -
                let( | 
| 11 | 
            -
                let( | 
| 12 | 
            -
                let( | 
| 13 | 
            -
                let( | 
| 14 | 
            -
                let( | 
| 10 | 
            +
                let(:new_hash) { additional_attrs.merge(attribute => value) }
         | 
| 11 | 
            +
                let(:new_model) { described_class::MODEL.new(new_hash) }
         | 
| 12 | 
            +
                let(:save_new) { VCR.use_cassette("#{vcr_dir}/save_new") { repository.save(new_model) } }
         | 
| 13 | 
            +
                let(:entity_wrapper) { repository.mapper.class::JSON_ENTITY_WRAPPER }
         | 
| 14 | 
            +
                let(:value) { 'A value' }
         | 
| 15 15 |  | 
| 16 16 | 
             
                shared_examples_for 'save' do
         | 
| 17 17 | 
             
                  before do
         | 
| 18 18 | 
             
                    if model.saved?
         | 
| 19 19 | 
             
                      message = 'Test trying to save model, but already marked as saved!'
         | 
| 20 | 
            -
                      message << " Model: #{ | 
| 21 | 
            -
                       | 
| 20 | 
            +
                      message << " Model: #{model.inspect}"
         | 
| 21 | 
            +
                      raise(message)
         | 
| 22 22 | 
             
                    end
         | 
| 23 23 | 
             
                  end
         | 
| 24 24 |  | 
| 25 | 
            -
                  specify "includes correct #{ | 
| 25 | 
            +
                  specify "includes correct #{attribute.inspect}" do
         | 
| 26 26 | 
             
                    saved_entity = send_request
         | 
| 27 | 
            -
                    expect( | 
| 27 | 
            +
                    expect(saved_entity.send(attribute)).to eql(value)
         | 
| 28 28 | 
             
                  end
         | 
| 29 29 | 
             
                end
         | 
| 30 30 |  | 
| 31 31 | 
             
                describe 'new' do
         | 
| 32 32 | 
             
                  context 'when not saved' do
         | 
| 33 33 | 
             
                    include_examples 'save' do
         | 
| 34 | 
            -
                      let( | 
| 35 | 
            -
                      let( | 
| 34 | 
            +
                      let(:model) { new_model }
         | 
| 35 | 
            +
                      let(:send_request) { save_new }
         | 
| 36 36 | 
             
                    end
         | 
| 37 37 | 
             
                  end
         | 
| 38 38 |  | 
| 39 | 
            -
                  context "saved #{ | 
| 40 | 
            -
                    let( | 
| 41 | 
            -
                    let( | 
| 42 | 
            -
             | 
| 43 | 
            -
                    before do
         | 
| 44 | 
            -
                      # Should not make an API request in test!
         | 
| 45 | 
            -
                      expect( repository ).not_to receive( :save_new )
         | 
| 46 | 
            -
                      expect( repository ).not_to receive( :update_existing )
         | 
| 47 | 
            -
                    end
         | 
| 39 | 
            +
                  context "saved #{described_class::MODEL}" do
         | 
| 40 | 
            +
                    let(:hash) { { unsaved: false }.merge(new_hash) }
         | 
| 41 | 
            +
                    let(:model) { described_class::MODEL.new(hash) }
         | 
| 48 42 |  | 
| 49 | 
            -
                    specify{ expect( | 
| 43 | 
            +
                    specify { expect(repository.save(model)).to be(true) }
         | 
| 50 44 | 
             
                  end
         | 
| 51 45 | 
             
                end
         | 
| 52 46 |  | 
| 53 47 | 
             
                describe 'old (update existing)' do
         | 
| 54 48 | 
             
                  include_examples 'save' do
         | 
| 55 | 
            -
                    let( | 
| 56 | 
            -
                    let( | 
| 49 | 
            +
                    let(:value) { "Updated #{attribute}" }
         | 
| 50 | 
            +
                    let(:model) do
         | 
| 57 51 | 
             
                      new_id = save_new.unique_id
         | 
| 58 | 
            -
                      new_record = VCR.use_cassette( | 
| 59 | 
            -
                      new_record.update( | 
| 52 | 
            +
                      new_record = VCR.use_cassette("#{vcr_dir}/find_new") { repository.find(new_id) }
         | 
| 53 | 
            +
                      new_record.update(attribute => value)
         | 
| 60 54 | 
             
                    end
         | 
| 61 | 
            -
                    let( | 
| 62 | 
            -
                      VCR.use_cassette( | 
| 55 | 
            +
                    let(:send_request) do
         | 
| 56 | 
            +
                      VCR.use_cassette("#{vcr_dir}/save_old") { repository.save(model) }
         | 
| 63 57 | 
             
                    end
         | 
| 64 58 | 
             
                  end
         | 
| 65 59 | 
             
                end
         | 
| @@ -1,26 +1,26 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            # TODO: This will not work until we solve issue #62.
         | 
| 2 4 | 
             
            # Until then, these tests are pending.
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            # rubocop:disable RSpec/DescribeClass
         | 
| 5 5 | 
             
            shared_examples_for '.save with nested model' do |required_hash, nested_model_key, nested_model_hash, nested_entity|
         | 
| 6 6 | 
             
              describe '.save with nested model' do
         | 
| 7 | 
            -
                let( | 
| 8 | 
            -
                let( | 
| 9 | 
            -
                  required_hash.merge( | 
| 7 | 
            +
                let(:repository) { described_class.new }
         | 
| 8 | 
            +
                let(:new_hash) do
         | 
| 9 | 
            +
                  required_hash.merge(nested_model_key => nested_entity)
         | 
| 10 10 | 
             
                end
         | 
| 11 | 
            -
                let( | 
| 12 | 
            -
                  VCR.use_cassette( | 
| 13 | 
            -
                    model = described_class::MODEL.new( | 
| 14 | 
            -
                    repository.save( | 
| 11 | 
            +
                let(:response) do
         | 
| 12 | 
            +
                  VCR.use_cassette("#{vcr_dir}/save_with_nested_model") do
         | 
| 13 | 
            +
                    model = described_class::MODEL.new(new_hash)
         | 
| 14 | 
            +
                    repository.save(model)
         | 
| 15 15 | 
             
                  end
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 18 | 
             
                it 'does not raise any errors' do
         | 
| 19 | 
            -
                  expect{ response }.not_to raise_error
         | 
| 19 | 
            +
                  expect { response }.not_to raise_error
         | 
| 20 20 | 
             
                end
         | 
| 21 21 |  | 
| 22 22 | 
             
                describe 'returned entity\'s nested model' do
         | 
| 23 | 
            -
                  subject(:returned_nested_model){ response.send(nested_model_key).first }
         | 
| 23 | 
            +
                  subject(:returned_nested_model) { response.send(nested_model_key).first }
         | 
| 24 24 |  | 
| 25 25 | 
             
                  it 'has the wanted attributes' do
         | 
| 26 26 | 
             
                    nested_model_hash.each do |attribute, value|
         | 
| @@ -1,26 +1,27 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            # Test saving model with attributes that has specially names that needs to be mapped.
         | 
| 2 4 | 
             
            #
         | 
| 3 5 | 
             
            # NOTE: VCR cassette must be discarded when repositories are updated to reflect
         | 
| 4 6 | 
             
            # the changes!
         | 
| 5 | 
            -
             | 
| 6 | 
            -
            # rubocop:disable RSpec/DescribeClass
         | 
| 7 7 | 
             
            shared_examples_for '.save with specially named attribute' do |required_hash, attribute, value|
         | 
| 8 8 | 
             
              describe '.save' do
         | 
| 9 9 | 
             
                context 'with specially named attribute' do
         | 
| 10 | 
            -
                  subject{ ->{ save_model } }
         | 
| 10 | 
            +
                  subject { -> { save_model } }
         | 
| 11 11 |  | 
| 12 | 
            -
                  let( | 
| 13 | 
            -
                  let( | 
| 14 | 
            -
                    VCR.use_cassette( | 
| 15 | 
            -
             | 
| 12 | 
            +
                  let(:new_model) { described_class::MODEL.new(required_hash.merge(attribute => value)) }
         | 
| 13 | 
            +
                  let(:save_model) do
         | 
| 14 | 
            +
                    VCR.use_cassette("#{vcr_dir}/save_with_specially_named_attribute") do
         | 
| 15 | 
            +
                      repository.save(new_model)
         | 
| 16 16 | 
             
                    end
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 | 
            -
                  it{ is_expected.not_to raise_error }
         | 
| 19 | 
            +
                  it { is_expected.not_to raise_error }
         | 
| 20 20 |  | 
| 21 21 | 
             
                  describe 'response' do
         | 
| 22 | 
            -
                    subject{ save_model.send(attribute) }
         | 
| 23 | 
            -
             | 
| 22 | 
            +
                    subject { save_model.send(attribute) }
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    it { is_expected.to eq(value) }
         | 
| 24 25 | 
             
                  end
         | 
| 25 26 | 
             
                end
         | 
| 26 27 | 
             
              end
         | 
| @@ -1,40 +1,40 @@ | |
| 1 | 
            -
            #  | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 2 3 | 
             
            shared_examples_for '.search' do |attribute_hash_key_name, value, matches|
         | 
| 3 4 | 
             
              describe '.search' do
         | 
| 4 | 
            -
             | 
| 5 5 | 
             
                describe 'search' do
         | 
| 6 | 
            -
                  context  | 
| 6 | 
            +
                  context 'with no matches' do
         | 
| 7 7 | 
             
                    subject do
         | 
| 8 | 
            -
                      VCR.use_cassette( | 
| 9 | 
            -
                        repository.search( | 
| 8 | 
            +
                      VCR.use_cassette("#{vcr_dir}/search_miss") do
         | 
| 9 | 
            +
                        repository.search(attribute_hash_key_name => 'nothing')
         | 
| 10 10 | 
             
                      end
         | 
| 11 11 | 
             
                    end
         | 
| 12 12 |  | 
| 13 | 
            -
                    it{ is_expected.to be_instance_of( | 
| 14 | 
            -
                    it{ is_expected.to have(0).entries }
         | 
| 13 | 
            +
                    it { is_expected.to be_instance_of(Array) }
         | 
| 14 | 
            +
                    it { is_expected.to have(0).entries }
         | 
| 15 15 | 
             
                  end
         | 
| 16 16 |  | 
| 17 | 
            -
                  context "with #{ | 
| 17 | 
            +
                  context "with #{matches} match(es)" do
         | 
| 18 18 | 
             
                    subject do
         | 
| 19 | 
            -
                      VCR.use_cassette( | 
| 20 | 
            -
                        repository.search( | 
| 19 | 
            +
                      VCR.use_cassette("#{vcr_dir}/search_by_name") do
         | 
| 20 | 
            +
                        repository.search(attribute_hash_key_name => value)
         | 
| 21 21 | 
             
                      end
         | 
| 22 22 | 
             
                    end
         | 
| 23 23 |  | 
| 24 | 
            -
                    it{ is_expected.to be_instance_of( | 
| 25 | 
            -
                    it{ is_expected.to have(matches).entries }
         | 
| 24 | 
            +
                    it { is_expected.to be_instance_of(Array) }
         | 
| 25 | 
            +
                    it { is_expected.to have(matches).entries }
         | 
| 26 26 | 
             
                  end
         | 
| 27 27 |  | 
| 28 28 | 
             
                  context 'with special characters' do
         | 
| 29 29 | 
             
                    subject do
         | 
| 30 30 | 
             
                      when_performing do
         | 
| 31 | 
            -
                        VCR.use_cassette( | 
| 32 | 
            -
                          repository.search( | 
| 31 | 
            +
                        VCR.use_cassette("#{vcr_dir}/search_with_special_char") do
         | 
| 32 | 
            +
                          repository.search(attribute_hash_key_name => 'special char å')
         | 
| 33 33 | 
             
                        end
         | 
| 34 34 | 
             
                      end
         | 
| 35 35 | 
             
                    end
         | 
| 36 36 |  | 
| 37 | 
            -
                    it{ is_expected.not_to raise_error }
         | 
| 37 | 
            +
                    it { is_expected.not_to raise_error }
         | 
| 38 38 | 
             
                  end
         | 
| 39 39 | 
             
                end
         | 
| 40 40 | 
             
              end
         |