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"
|