lurch 0.1.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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +2 -0
- data/LICENSE.md +9 -0
- data/README.md +229 -0
- data/Rakefile +12 -0
- data/TODO.md +22 -0
- data/lib/lurch/changeset.rb +32 -0
- data/lib/lurch/client.rb +92 -0
- data/lib/lurch/collection.rb +111 -0
- data/lib/lurch/configuration.rb +14 -0
- data/lib/lurch/error.rb +13 -0
- data/lib/lurch/errors/bad_request.rb +6 -0
- data/lib/lurch/errors/conflict.rb +6 -0
- data/lib/lurch/errors/forbidden.rb +6 -0
- data/lib/lurch/errors/json_api_error.rb +29 -0
- data/lib/lurch/errors/not_found.rb +6 -0
- data/lib/lurch/errors/not_loaded.rb +13 -0
- data/lib/lurch/errors/relationship_not_loaded.rb +9 -0
- data/lib/lurch/errors/resource_not_loaded.rb +9 -0
- data/lib/lurch/errors/server_error.rb +6 -0
- data/lib/lurch/errors/unauthorized.rb +6 -0
- data/lib/lurch/errors/unprocessable_entity.rb +6 -0
- data/lib/lurch/inflector.rb +60 -0
- data/lib/lurch/logger.rb +7 -0
- data/lib/lurch/middleware/json_api_request.rb +22 -0
- data/lib/lurch/middleware/json_api_response.rb +24 -0
- data/lib/lurch/paginator.rb +71 -0
- data/lib/lurch/payload_builder.rb +43 -0
- data/lib/lurch/query.rb +143 -0
- data/lib/lurch/query_builder.rb +26 -0
- data/lib/lurch/railtie.rb +9 -0
- data/lib/lurch/relationship/has_many.rb +17 -0
- data/lib/lurch/relationship/has_one.rb +21 -0
- data/lib/lurch/relationship/linked.rb +40 -0
- data/lib/lurch/relationship.rb +26 -0
- data/lib/lurch/resource.rb +82 -0
- data/lib/lurch/store.rb +149 -0
- data/lib/lurch/store_configuration.rb +27 -0
- data/lib/lurch/stored_resource.rb +63 -0
- data/lib/lurch/uri_builder.rb +32 -0
- data/lib/lurch/version.rb +3 -0
- data/lib/lurch.rb +65 -0
- data/lurch.gemspec +26 -0
- data/lurch.gif +0 -0
- data/test/helpers/lurch_test.rb +40 -0
- data/test/helpers/response_factory.rb +193 -0
- data/test/lurch/test_configuration.rb +20 -0
- data/test/lurch/test_create_resources.rb +55 -0
- data/test/lurch/test_delete_resources.rb +27 -0
- data/test/lurch/test_errors.rb +29 -0
- data/test/lurch/test_fetch_relationships.rb +50 -0
- data/test/lurch/test_fetch_resources.rb +77 -0
- data/test/lurch/test_inflector.rb +13 -0
- data/test/lurch/test_paginated_collections.rb +125 -0
- data/test/lurch/test_queries.rb +104 -0
- data/test/lurch/test_relationship.rb +17 -0
- data/test/lurch/test_resource.rb +34 -0
- data/test/lurch/test_update_relationships.rb +53 -0
- data/test/lurch/test_update_resources.rb +56 -0
- data/test/test_helper.rb +15 -0
- metadata +235 -0
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestDeleteResources < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_delete_existing_resource_from_server_using_store
         | 
| 7 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 8 | 
            +
                delete_stub = stub_delete("#{person_type}/1", @response_factory.no_content_response)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                person = @store.from(:people).find("1")
         | 
| 11 | 
            +
                response = @store.delete(person)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                assert_requested delete_stub
         | 
| 14 | 
            +
                assert response
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def test_delete_existing_resource_from_server_using_query
         | 
| 18 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 19 | 
            +
                delete_stub = stub_delete("#{person_type}/1", @response_factory.no_content_response)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                person = @store.from(:people).find("1")
         | 
| 22 | 
            +
                response = @store.from(:people).delete(person)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                assert_requested delete_stub
         | 
| 25 | 
            +
                assert response
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestErrors < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_401
         | 
| 7 | 
            +
                stub_get("#{person_type}/1", @response_factory.unauthorized_response)
         | 
| 8 | 
            +
                err = assert_raises(Lurch::Errors::Unauthorized) { @store.from(:people).find("1") }
         | 
| 9 | 
            +
                assert_equal "401: Unauthorized", err.message
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def test_403
         | 
| 13 | 
            +
                stub_get("#{person_type}/1", @response_factory.forbidden_response)
         | 
| 14 | 
            +
                err = assert_raises(Lurch::Errors::Forbidden) { @store.from(:people).find("1") }
         | 
| 15 | 
            +
                assert_equal "403: Forbidden", err.message
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def test_404
         | 
| 19 | 
            +
                stub_get("#{person_type}/999", @response_factory.not_found_response)
         | 
| 20 | 
            +
                err = assert_raises(Lurch::Errors::NotFound) { @store.from(:people).find("999") }
         | 
| 21 | 
            +
                assert_equal "404: Not Found", err.message
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def test_500
         | 
| 25 | 
            +
                stub_get("#{person_type}/1", @response_factory.server_error_response)
         | 
| 26 | 
            +
                err = assert_raises(Lurch::Errors::ServerError) { @store.from(:people).find("1") }
         | 
| 27 | 
            +
                assert_equal "500: Internal Server Error", err.message
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestFetchRelationships < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_fetch_linked_has_one_relationship_from_server
         | 
| 7 | 
            +
                stub_get("#{phone_number_type}/1", @response_factory.phone_number_response("1", "Cell", "111-222-3344"))
         | 
| 8 | 
            +
                stub_get("#{phone_number_type}/1/contact", @response_factory.person_response("1", "Alice"))
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                phone_number = @store.from(:phone_numbers).find("1")
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                assert_kind_of Lurch::Relationship::Linked, phone_number.contact
         | 
| 13 | 
            +
                assert phone_number.contact.inspect
         | 
| 14 | 
            +
                assert_raises(Lurch::Errors::RelationshipNotLoaded) { phone_number.contact.name }
         | 
| 15 | 
            +
                err = assert_raises(Lurch::Errors::RelationshipNotLoaded) { phone_number.contact.respond_to?(:name) }
         | 
| 16 | 
            +
                assert_equal "Relationship (contact) not loaded, try calling #fetch first.", err.message
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                phone_number.contact.fetch
         | 
| 19 | 
            +
                person = phone_number.contact
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                assert_kind_of Lurch::Resource, person
         | 
| 22 | 
            +
                assert_kind_of Lurch::Relationship::Linked, phone_number.relationships[:contact]
         | 
| 23 | 
            +
                assert_raises(NoMethodError) { phone_number.relationships[:contact].name }
         | 
| 24 | 
            +
                refute phone_number.relationships[:contact].respond_to?(:name)
         | 
| 25 | 
            +
                assert_equal "Alice", person.name
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def test_fetch_linked_has_many_relationship_from_server
         | 
| 29 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 30 | 
            +
                stub_get(
         | 
| 31 | 
            +
                  "#{person_type}/1/#{@inflector.encode_key(:phone_numbers)}",
         | 
| 32 | 
            +
                  @response_factory.phone_numbers_response(["1", "Cell", "111-222-3344"], ["2", "Home", "222-111-3344"])
         | 
| 33 | 
            +
                )
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                person = @store.from(:people).find("1")
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                assert_kind_of Lurch::Relationship::Linked, person.phone_numbers
         | 
| 38 | 
            +
                assert_equal false, person.phone_numbers.loaded?
         | 
| 39 | 
            +
                assert person.phone_numbers.inspect
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                person.phone_numbers.fetch
         | 
| 42 | 
            +
                phone_numbers = person.phone_numbers
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                assert_kind_of Lurch::Collection, phone_numbers
         | 
| 45 | 
            +
                assert_equal true, person.phone_numbers.loaded?
         | 
| 46 | 
            +
                assert_kind_of Lurch::Relationship::Linked, person.relationships[:phone_numbers]
         | 
| 47 | 
            +
                assert_equal 2, phone_numbers.size
         | 
| 48 | 
            +
                assert_equal "Cell", phone_numbers.first.name
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| @@ -0,0 +1,77 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestFetchResources < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_fetch_resource_from_server
         | 
| 7 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                person = @store.from(:people).find("1")
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                assert_equal "Alice", person.name
         | 
| 12 | 
            +
                assert person.inspect
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def test_fetch_resource_collection_from_server
         | 
| 16 | 
            +
                stub_get(person_type, @response_factory.people_response(["1", "Alice"], ["2", "Bob"]))
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                people = @store.from(:people).all
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                assert_kind_of Lurch::Collection, people
         | 
| 21 | 
            +
                assert_equal 2, people.size
         | 
| 22 | 
            +
                assert_equal ["Alice", "Bob"], people.map(&:name)
         | 
| 23 | 
            +
                assert people.inspect
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def test_fetch_already_fetched_resource_from_store
         | 
| 27 | 
            +
                stub = stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                @store.from(:people).find("1")
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                remove_request_stub(stub)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                assert @store.from(:people).find("1")
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def test_fetch_resource_from_server_that_includes_has_one_relationship
         | 
| 37 | 
            +
                stub_get("#{phone_number_type}/1", @response_factory.phone_number_response("1", "Cell", "111-222-3344", ["1", "Alice"]))
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                phone_number = @store.from(:phone_numbers).find("1")
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                assert_kind_of Lurch::Relationship::HasOne, phone_number.relationships[:contact]
         | 
| 42 | 
            +
                assert phone_number.relationships[:contact].inspect
         | 
| 43 | 
            +
                assert_kind_of Lurch::Resource, phone_number.contact
         | 
| 44 | 
            +
                assert_equal "Alice", phone_number.contact.name
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              def test_fetch_resource_from_server_that_includes_has_many_relationship
         | 
| 48 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice", [["1", "Cell", "1112223344"], ["2", "Home", "2221113344"]]))
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                person = @store.from(:people).find("1")
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                assert_kind_of Lurch::Relationship::HasMany, person.relationships[:phone_numbers]
         | 
| 53 | 
            +
                assert person.relationships[:phone_numbers].inspect
         | 
| 54 | 
            +
                assert_kind_of Array, person.phone_numbers
         | 
| 55 | 
            +
                assert_equal "Cell", person.phone_numbers.first.name
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              def test_fetch_resource_that_includes_resource_identifiers_only
         | 
| 59 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice", [["1"]], include_phone_numbers: false))
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                person = @store.from(:people).find("1")
         | 
| 62 | 
            +
                phone_number = person.phone_numbers.first
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                assert_equal "1", phone_number.id
         | 
| 65 | 
            +
                refute phone_number.loaded?
         | 
| 66 | 
            +
                assert phone_number.inspect
         | 
| 67 | 
            +
                err = assert_raises(Lurch::Errors::ResourceNotLoaded) { phone_number.name }
         | 
| 68 | 
            +
                assert_equal "Resource (PhoneNumber) not loaded, try calling #fetch first.", err.message
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                stub_get("#{phone_number_type}/1", @response_factory.phone_number_response("1", "Cell", "111-222-3344"))
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                phone_number.fetch
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                assert phone_number.loaded?
         | 
| 75 | 
            +
                assert_equal "Cell", phone_number.name
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
            end
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestInflector < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_bad_inflector
         | 
| 7 | 
            +
                err = assert_raises(ArgumentError) { Lurch::Inflector.new(:foo, :pluralize) }
         | 
| 8 | 
            +
                assert_equal "Invalid inflection mode: foo", err.message
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                err = assert_raises(ArgumentError) { Lurch::Inflector.new(:dasherize, :bar) }
         | 
| 11 | 
            +
                assert_equal "Invalid types mode: bar", err.message
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
            end
         | 
| @@ -0,0 +1,125 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestPaginatedCollections < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_fetch_paginated_resource_collection_from_server
         | 
| 7 | 
            +
                stub_get(person_type, @response_factory.paginated_people_response(10, 1, 2))
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                people = @store.from(:people).all
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                assert_kind_of Lurch::Collection, people
         | 
| 12 | 
            +
                assert_equal 20, people.size
         | 
| 13 | 
            +
                assert_equal 10, people.page_size
         | 
| 14 | 
            +
                assert_equal 2, people.page_count
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def test_fetch_next_page_of_paginated_resource_collection_from_server
         | 
| 18 | 
            +
                stub_get(person_type, @response_factory.paginated_people_response(10, 1, 2))
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                people = @store.from(:people).all
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                assert people.next?
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                page2_stub = stub_get("#{person_type}?page[number]=2&page[size]=10", @response_factory.paginated_people_response(10, 2, 2))
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                people.next_collection
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                assert_requested page2_stub
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              def test_fetch_previous_page_of_paginated_resource_collection_from_server
         | 
| 32 | 
            +
                stub_get("#{person_type}?page[number]=2&page[size]=10", @response_factory.paginated_people_response(10, 2, 2))
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                people = @store.from(:people).page(number: 2, size: 10).all
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                assert people.prev?
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                page1_stub = stub_get("#{person_type}?page[number]=1&page[size]=10", @response_factory.paginated_people_response(10, 1, 2))
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                people.prev_collection
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                assert_requested page1_stub
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def test_fetch_first_page_of_paginated_resource_collection_from_server
         | 
| 46 | 
            +
                stub_get("#{person_type}?page[number]=2&page[size]=10", @response_factory.paginated_people_response(10, 2, 2))
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                people = @store.from(:people).page(number: 2, size: 10).all
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                assert people.first?
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                page1_stub = stub_get("#{person_type}?page[number]=1&page[size]=10", @response_factory.paginated_people_response(10, 1, 2))
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                people.first_collection
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                assert_requested page1_stub
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              def test_fetch_last_page_of_paginated_resource_collection_from_server
         | 
| 60 | 
            +
                stub_get(person_type, @response_factory.paginated_people_response(10, 1, 2))
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                people = @store.from(:people).all
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                assert people.last?
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                page2_stub = stub_get("#{person_type}?page[number]=2&page[size]=10", @response_factory.paginated_people_response(10, 2, 2))
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                people.last_collection
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                assert_requested page2_stub
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              def test_enumerate_paginated_collection_by_resource
         | 
| 74 | 
            +
                page1_stub = stub_get(person_type, @response_factory.paginated_people_response(10, 1, 3))
         | 
| 75 | 
            +
                page2_stub = stub_get("#{person_type}?page[number]=2&page[size]=10", @response_factory.paginated_people_response(10, 2, 3))
         | 
| 76 | 
            +
                page3_stub = stub_get("#{person_type}?page[number]=3&page[size]=10", @response_factory.paginated_people_response(10, 3, 3))
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                people = @store.from(:people).all
         | 
| 79 | 
            +
                names = people.map(&:name)
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                assert_kind_of Array, names
         | 
| 82 | 
            +
                assert names.size == 30
         | 
| 83 | 
            +
                assert names.first == "Person1"
         | 
| 84 | 
            +
                assert names.last == "Person30"
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                assert_requested page1_stub
         | 
| 87 | 
            +
                assert_requested page2_stub
         | 
| 88 | 
            +
                assert_requested page3_stub
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              def test_enumerate_paginated_collection_by_page
         | 
| 92 | 
            +
                page1_stub = stub_get(person_type, @response_factory.paginated_people_response(10, 1, 3))
         | 
| 93 | 
            +
                page2_stub = stub_get("#{person_type}?page[number]=2&page[size]=10", @response_factory.paginated_people_response(10, 2, 3))
         | 
| 94 | 
            +
                page3_stub = stub_get("#{person_type}?page[number]=3&page[size]=10", @response_factory.paginated_people_response(10, 3, 3))
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                people = @store.from(:people).all
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                people.each_page do |page|
         | 
| 99 | 
            +
                  assert_kind_of Array, page
         | 
| 100 | 
            +
                  assert page.size == 10
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                assert_requested page1_stub
         | 
| 104 | 
            +
                assert_requested page2_stub
         | 
| 105 | 
            +
                assert_requested page3_stub
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              def test_lazy_enumeration
         | 
| 109 | 
            +
                page1_stub = stub_get(person_type, @response_factory.paginated_people_response(10, 1, 3))
         | 
| 110 | 
            +
                page2_stub = stub_get("#{person_type}?page[number]=2&page[size]=10", @response_factory.paginated_people_response(10, 2, 3))
         | 
| 111 | 
            +
                page3_stub = stub_get("#{person_type}?page[number]=3&page[size]=10", @response_factory.paginated_people_response(10, 3, 3))
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                people = @store.from(:people).all
         | 
| 114 | 
            +
                names = people.lazy.map(&:name).first(20)
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                assert_kind_of Array, names
         | 
| 117 | 
            +
                assert names.size == 20
         | 
| 118 | 
            +
                assert names.first == "Person1"
         | 
| 119 | 
            +
                assert names.last == "Person20"
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                assert_requested page1_stub
         | 
| 122 | 
            +
                assert_requested page2_stub
         | 
| 123 | 
            +
                assert_not_requested page3_stub
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
            end
         | 
| @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestQueries < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_filter
         | 
| 7 | 
            +
                stub = stub_get(
         | 
| 8 | 
            +
                  "#{person_type}?filter[name]=Alice&filter[foo][]=bar&filter[foo][]=baz",
         | 
| 9 | 
            +
                  @response_factory.no_content_response
         | 
| 10 | 
            +
                )
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                @store
         | 
| 13 | 
            +
                  .from(:people)
         | 
| 14 | 
            +
                  .filter(name: "Alice", foo: ["bar", "baz"])
         | 
| 15 | 
            +
                  .all
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                assert_requested(stub)
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def test_include
         | 
| 21 | 
            +
                stub = stub_get(
         | 
| 22 | 
            +
                  "#{person_type}?include=#{@inflector.encode_key(:phone_numbers)},friends,friends.#{@inflector.encode_key(:phone_numbers)}",
         | 
| 23 | 
            +
                  @response_factory.no_content_response
         | 
| 24 | 
            +
                )
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                @store
         | 
| 27 | 
            +
                  .from(:people)
         | 
| 28 | 
            +
                  .include(:phone_numbers, :friends, "friends.phone_numbers")
         | 
| 29 | 
            +
                  .all
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                assert_requested(stub)
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def test_fields
         | 
| 35 | 
            +
                stub = stub_get(
         | 
| 36 | 
            +
                  "#{person_type}?fields[#{person_type}]=name&fields[#{phone_number_type}]=name,number",
         | 
| 37 | 
            +
                  @response_factory.no_content_response
         | 
| 38 | 
            +
                )
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                @store
         | 
| 41 | 
            +
                  .from(:people)
         | 
| 42 | 
            +
                  .fields([:name])
         | 
| 43 | 
            +
                  .fields(:phone_number, [:name, :number])
         | 
| 44 | 
            +
                  .all
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                assert_requested(stub)
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def test_sort
         | 
| 50 | 
            +
                stub = stub_get(
         | 
| 51 | 
            +
                  "#{person_type}?sort=name,-foo,bar",
         | 
| 52 | 
            +
                  @response_factory.no_content_response
         | 
| 53 | 
            +
                )
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                @store
         | 
| 56 | 
            +
                  .from(:people)
         | 
| 57 | 
            +
                  .sort(:name, {foo: :desc}, {bar: :asc})
         | 
| 58 | 
            +
                  .all
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                assert_requested(stub)
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              def test_bad_sort
         | 
| 64 | 
            +
                assert_raises ArgumentError do
         | 
| 65 | 
            +
                  @store.from(:people).sort(foo: :bar).all
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              def test_page
         | 
| 70 | 
            +
                stub = stub_get(
         | 
| 71 | 
            +
                  "#{person_type}?page[number]=12&page[size]=50",
         | 
| 72 | 
            +
                  @response_factory.no_content_response
         | 
| 73 | 
            +
                )
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                @store
         | 
| 76 | 
            +
                  .from(:people)
         | 
| 77 | 
            +
                  .page(number: 12, size: 50)
         | 
| 78 | 
            +
                  .all
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                assert_requested(stub)
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              def test_all
         | 
| 84 | 
            +
                stub = stub_get(
         | 
| 85 | 
            +
                  "#{person_type}?filter[name]=Alice&filter[foo][]=bar&filter[foo][]=baz&include=#{@inflector.encode_key(:phone_numbers)},friends,friends.#{@inflector.encode_key(:phone_numbers)}&fields[#{person_type}]=name&fields[#{phone_number_type}]=name,number&sort=name,-foo,bar&page[number]=12&page[size]=50",
         | 
| 86 | 
            +
                  @response_factory.no_content_response
         | 
| 87 | 
            +
                )
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                query = @store
         | 
| 90 | 
            +
                  .from(:people)
         | 
| 91 | 
            +
                  .filter(name: "Alice", foo: ["bar", "baz"])
         | 
| 92 | 
            +
                  .include(:phone_numbers, :friends, "friends.phone_numbers")
         | 
| 93 | 
            +
                  .fields([:name])
         | 
| 94 | 
            +
                  .fields(:phone_number, [:name, :number])
         | 
| 95 | 
            +
                  .sort(:name, {foo: :desc}, {bar: :asc})
         | 
| 96 | 
            +
                  .page(number: 12, size: 50)
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                assert query.inspect
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                query.all
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                assert_requested(stub)
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
            end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestRelationship < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_bad_relationship_document
         | 
| 7 | 
            +
                err = assert_raises(ArgumentError) { Lurch::Relationship.from_document(nil, nil, {}) }
         | 
| 8 | 
            +
                assert_equal "Invalid relationship document", err.message
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              def test_nil_has_one_relationship
         | 
| 12 | 
            +
                rel = Lurch::Relationship::HasOne.new(nil, nil, {data: nil})
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                assert rel.loaded?
         | 
| 15 | 
            +
                assert_nil rel.data
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestResource < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_resource_equality
         | 
| 7 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 8 | 
            +
                stub_get("#{person_type}/2", @response_factory.person_response("2", "Bob"))
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                person1 = @store.from(:people).find("1")
         | 
| 11 | 
            +
                person1_again = @store.from(:people).find("1")
         | 
| 12 | 
            +
                person2 = @store.from(:people).find("2")
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                assert person1 == person1_again
         | 
| 15 | 
            +
                assert person1.eql? person1_again
         | 
| 16 | 
            +
                refute person1.equal? person1_again
         | 
| 17 | 
            +
                refute person1 == person2
         | 
| 18 | 
            +
                refute person1.eql? person2
         | 
| 19 | 
            +
                refute person1.equal? person2
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              def test_resource_attribute_getters
         | 
| 23 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                person = @store.from(:people).find("1")
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                assert person.name == "Alice"
         | 
| 28 | 
            +
                assert person[:name] == "Alice"
         | 
| 29 | 
            +
                assert person.respond_to?(:name)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                refute person.respond_to?(:foo)
         | 
| 32 | 
            +
                assert_raises(NoMethodError) { person.foo }
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestUpdateRelationships < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_add_resources_to_has_many_relationship
         | 
| 7 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 8 | 
            +
                stub_get("#{phone_number_type}/1", @response_factory.phone_number_response("1", "Cell", "111-222-3344"))
         | 
| 9 | 
            +
                stub_post("#{person_type}/1/relationships/#{@inflector.encode_key(:phone_numbers)}", @response_factory.no_content_response)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                person = @store.from(:people).find("1")
         | 
| 12 | 
            +
                phone_number = @store.from(:phone_numbers).find("1")
         | 
| 13 | 
            +
                response = @store.add_related(person, :phone_numbers, [phone_number])
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                assert_requested :post, "#{@url}/#{person_type}/1/relationships/#{@inflector.encode_key(:phone_numbers)}", body: "{\"data\":[{\"id\":\"1\",\"type\":\"#{phone_number_type}\"}]}"
         | 
| 16 | 
            +
                assert response
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              def test_remove_resources_from_has_many_relationship
         | 
| 20 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 21 | 
            +
                stub_get("#{person_type}/1/#{@inflector.encode_key(:phone_numbers)}", @response_factory.phone_numbers_response(["1", "Cell", "111-222-3344"]))
         | 
| 22 | 
            +
                stub_delete("#{person_type}/1/relationships/#{@inflector.encode_key(:phone_numbers)}", @response_factory.no_content_response)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                person = @store.from(:people).find("1")
         | 
| 25 | 
            +
                phone_number = person.phone_numbers.fetch.first
         | 
| 26 | 
            +
                response = @store.remove_related(person, :phone_numbers, [phone_number])
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                assert_requested :delete, "#{@url}/#{person_type}/1/relationships/#{@inflector.encode_key(:phone_numbers)}", body: "{\"data\":[{\"id\":\"1\",\"type\":\"#{phone_number_type}\"}]}"
         | 
| 29 | 
            +
                assert response
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def test_replace_resources_for_has_many_relationship
         | 
| 33 | 
            +
                stub_get("#{person_type}/1", @response_factory.person_response("1", "Alice"))
         | 
| 34 | 
            +
                stub_patch("#{person_type}/1/relationships/#{@inflector.encode_key(:phone_numbers)}", @response_factory.no_content_response)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                person = @store.from(:people).find("1")
         | 
| 37 | 
            +
                response = @store.update_related(person, :phone_numbers, [])
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                assert_requested :patch, "#{@url}/#{person_type}/1/relationships/#{@inflector.encode_key(:phone_numbers)}", body: '{"data":[]}'
         | 
| 40 | 
            +
                assert response
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def test_replace_resource_for_has_one_relationship
         | 
| 44 | 
            +
                stub_get("#{phone_number_type}/1", @response_factory.phone_number_response("1", "Cell", "111-222-3344"))
         | 
| 45 | 
            +
                stub_patch("#{phone_number_type}/1/relationships/contact", @response_factory.no_content_response)
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                phone_number = @store.from(:phone_numbers).find("1")
         | 
| 48 | 
            +
                response = @store.update_related(phone_number, :contact, nil)
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                assert_requested :patch, "#{@url}/#{phone_number_type}/1/relationships/contact", body: '{"data":null}'
         | 
| 51 | 
            +
                assert response
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            require_relative "../test_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestUpdateResources < Minitest::Test
         | 
| 4 | 
            +
              include LurchTest
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def test_update_existing_resource_on_server_using_store
         | 
| 7 | 
            +
                stub_get("#{person_type}/2", @response_factory.person_response("2", "Bob"))
         | 
| 8 | 
            +
                stub_patch("#{person_type}/2", @response_factory.person_response("2", "Robert"))
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                person = @store.from(:people).find("2")
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                assert_equal "Bob", person.name
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                changeset = Lurch::Changeset.new(person, name: "Robert")
         | 
| 15 | 
            +
                @store.save(changeset)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                assert changeset.inspect
         | 
| 18 | 
            +
                assert_requested :patch, "#{@url}/#{person_type}/2", body: "{\"data\":{\"id\":\"2\",\"type\":\"#{person_type}\",\"attributes\":{\"name\":\"Robert\"}}}"
         | 
| 19 | 
            +
                assert_equal "Robert", person.name
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              def test_update_existing_resource_on_server_using_query
         | 
| 23 | 
            +
                stub_get("#{person_type}/2", @response_factory.person_response("2", "Bob"))
         | 
| 24 | 
            +
                stub_patch("#{person_type}/2", @response_factory.person_response("2", "Robert"))
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                person = @store.from(:people).find("2")
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                assert_equal "Bob", person.name
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                changeset = Lurch::Changeset.new(person)
         | 
| 31 | 
            +
                changeset.set(:name, "Robert")
         | 
| 32 | 
            +
                @store.to(:people).save(changeset)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                assert_requested :patch, "#{@url}/#{person_type}/2", body: "{\"data\":{\"id\":\"2\",\"type\":\"#{person_type}\",\"attributes\":{\"name\":\"Robert\"}}}"
         | 
| 35 | 
            +
                assert_equal "Robert", person.name
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def test_validation_errors_when_updating_existing_resource
         | 
| 39 | 
            +
                stub_get("#{person_type}/2", @response_factory.person_response("2", "Bob"))
         | 
| 40 | 
            +
                stub_patch("#{person_type}/2", @response_factory.unprocessable_entity_response("name - can't be blank"))
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                person = @store.from(:people).find("2")
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                assert_equal "Bob", person.name
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                changeset = Lurch::Changeset.new(person, name: "")
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                err = assert_raises(Lurch::Errors::UnprocessableEntity) { @store.save(changeset) }
         | 
| 49 | 
            +
                assert_equal "422: name - can't be blank", err.message
         | 
| 50 | 
            +
                assert_equal 422, changeset.errors.first.status
         | 
| 51 | 
            +
                assert_equal "name - can't be blank", changeset.errors.first.detail
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                assert_requested :patch, "#{@url}/#{person_type}/2", body: "{\"data\":{\"id\":\"2\",\"type\":\"#{person_type}\",\"attributes\":{\"name\":\"\"}}}"
         | 
| 54 | 
            +
                assert_equal "Bob", person.name
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
    
        data/test/test_helper.rb
    ADDED
    
    | @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            require "pry"
         | 
| 2 | 
            +
            require "simplecov"
         | 
| 3 | 
            +
            require "codecov"
         | 
| 4 | 
            +
            require "webmock/minitest"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            require_relative "helpers/lurch_test"
         | 
| 7 | 
            +
            require_relative "helpers/response_factory"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            SimpleCov.formatter = SimpleCov::Formatter::Codecov
         | 
| 10 | 
            +
            SimpleCov.start do
         | 
| 11 | 
            +
              add_filter "/test/"
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            require "minitest/autorun"
         | 
| 15 | 
            +
            require "lurch"
         |