spyke 1.0.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.
@@ -0,0 +1,102 @@
1
+ require 'test_helper'
2
+
3
+ module Spyke
4
+ class AttributesTest < MiniTest::Test
5
+ def test_predicate_methods
6
+ stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(data: { id: 1, title: 'Sushi' })
7
+
8
+ recipe = Recipe.find(1)
9
+
10
+ assert_equal true, recipe.title?
11
+ assert_equal false, recipe.description?
12
+ end
13
+
14
+ def test_respond_to
15
+ stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(data: { id: 1, serves: 3 })
16
+
17
+ recipe = Recipe.find(1)
18
+
19
+ assert_equal true, recipe.respond_to?(:serves)
20
+ assert_equal false, recipe.respond_to?(:story)
21
+ end
22
+
23
+ def test_assigning_attributes
24
+ recipe = Recipe.new(id: 2)
25
+ recipe.attributes = { title: 'Pasta' }
26
+
27
+ assert_equal 'Pasta', recipe.title
28
+ assert_equal 2, recipe.id
29
+ end
30
+
31
+ def test_removing_id_if_blank_string
32
+ recipe = Recipe.new
33
+
34
+ assert_nil recipe.id
35
+ assert_equal({ 'recipe' => {} }, recipe.to_params)
36
+
37
+ recipe.id = ''
38
+ assert_nil recipe.id
39
+ assert_equal({ 'recipe' => {} }, recipe.to_params)
40
+ end
41
+
42
+ def test_setters
43
+ recipe = Recipe.new
44
+ recipe.title = 'Sushi'
45
+ assert_equal 'Sushi', recipe.title
46
+ end
47
+
48
+ def test_equality
49
+ assert_equal Recipe.new(id: 2, title: 'Fish'), Recipe.new(id: 2, title: 'Fish')
50
+ refute_equal Recipe.new(id: 2, title: 'Fish'), Recipe.new(id: 1, title: 'Fish')
51
+ refute_equal Recipe.new(id: 2, title: 'Fish'), 'not_a_spyke_object'
52
+ end
53
+
54
+ def test_explicit_attributes
55
+ recipe = Recipe.new
56
+ assert_equal nil, recipe.title
57
+ assert_raises NoMethodError do
58
+ recipe.description
59
+ end
60
+
61
+ recipe = Recipe.new(title: 'Fish')
62
+ assert_equal 'Fish', recipe.title
63
+ end
64
+
65
+ def test_converting_files_to_faraday_io
66
+ Faraday::UploadIO.stubs(:new).with('/photo.jpg', 'image/jpeg').returns('UploadIO')
67
+ file = mock
68
+ file.stubs(:path).returns('/photo.jpg')
69
+ file.stubs(:content_type).returns('image/jpeg')
70
+
71
+ recipe = Recipe.new(image: Image.new(file: file))
72
+
73
+ assert_equal 'UploadIO', recipe.image.to_params['image']['file']
74
+ assert_equal 'UploadIO', recipe.to_params['recipe']['image']['file']
75
+
76
+ recipe = Recipe.new(image_attributes: { file: file })
77
+
78
+ assert_equal 'UploadIO', recipe.image.to_params['image']['file']
79
+ assert_equal 'UploadIO', recipe.to_params['recipe']['image']['file']
80
+ end
81
+
82
+ def test_inspect
83
+ recipe = Recipe.new(id: 2, title: 'Pizza', description: 'Delicious')
84
+ assert_equal '#<Recipe(/recipes/2) id: 2 title: "Pizza" description: "Delicious">', recipe.inspect
85
+ end
86
+
87
+ def test_rejecting_wrong_number_of_args
88
+ skip 'wishlisted'
89
+ stub_request(:any, /.*/)
90
+ recipe = Recipe.new(description: 'Delicious')
91
+ assert_raises ArgumentError do
92
+ recipe.description(2)
93
+ end
94
+ assert_raises ArgumentError do
95
+ recipe.description?(2)
96
+ end
97
+ assert_raises ArgumentError do
98
+ recipe.image(2)
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ module Spyke
4
+ class CallbacksTest < MiniTest::Test
5
+ def setup
6
+ stub_request(:any, /.*/)
7
+ end
8
+
9
+ def test_before_save
10
+ Recipe.any_instance.expects(:before_save_callback)
11
+ Recipe.create
12
+ end
13
+
14
+ def test_before_create
15
+ Recipe.any_instance.expects(:before_create_callback)
16
+ Recipe.create
17
+ end
18
+
19
+ def test_before_update
20
+ Recipe.any_instance.expects(:before_update_callback)
21
+ Recipe.new(id: 1).save
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ module Spyke
4
+ class CustomRequestTest < MiniTest::Test
5
+ def test_custom_get_request_from_class
6
+ endpoint = stub_request(:get, 'http://sushi.com/recipes/recent').to_return_json(data: [{ id: 1, title: 'Bread' }])
7
+ assert_equal %w{ Bread }, Recipe.get('/recipes/recent').map(&:title)
8
+ assert_requested endpoint
9
+ end
10
+
11
+ def test_get_request_with_prepended_scope
12
+ skip 'wishlisted'
13
+ endpoint = stub_request(:get, 'http://sushi.com/recipes/recent?status=published')
14
+ Recipe.published.get('/recipes/recent')
15
+ assert_requested endpoint
16
+ end
17
+
18
+ def test_get_request_with_appended_scope
19
+ skip 'wishlisted'
20
+ endpoint = stub_request(:get, 'http://sushi.com/recipes/recent?status=published')
21
+ Recipe.get('/recipes/recent').published.fetch
22
+ assert_requested endpoint
23
+ end
24
+
25
+ def test_custom_get_request_from_class
26
+ endpoint = stub_request(:get, 'http://sushi.com/recipes/recent').to_return_json(data: [{ id: 1, title: 'Bread' }])
27
+ assert_equal %w{ Bread }, Recipe.get('/recipes/recent').map(&:title)
28
+ assert_requested endpoint
29
+ end
30
+
31
+ def test_custom_put_request_from_class
32
+ endpoint = stub_request(:put, 'http://sushi.com/recipes/1/publish')
33
+ Recipe.put('/recipes/1/publish')
34
+ assert_requested endpoint
35
+ end
36
+
37
+ def test_custom_put_request_from_instance
38
+ endpoint = stub_request(:put, 'http://sushi.com/recipes/1/publish').to_return_json(data: { id: 1, status: 'published' })
39
+ recipe = Recipe.new(id: 1, status: 'unpublished')
40
+ recipe.put('/recipes/:id/publish')
41
+
42
+ assert_equal 'published', recipe.status
43
+ assert_requested endpoint
44
+ end
45
+
46
+ def test_custom_put_request_from_instance_with_symbol
47
+ endpoint = stub_request(:put, 'http://sushi.com/recipes/1/draft')
48
+ recipe = Recipe.new(id: 1)
49
+ recipe.put(:draft)
50
+ assert_requested endpoint
51
+ end
52
+ end
53
+ end
data/test/orm_test.rb ADDED
@@ -0,0 +1,136 @@
1
+ require 'test_helper'
2
+
3
+ module Spyke
4
+ class OrmTest < MiniTest::Test
5
+ def test_find
6
+ stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(data: { id: 1, title: 'Sushi' })
7
+ stub_request(:get, 'http://sushi.com/users/1').to_return_json(data: { id: 1, name: 'Bob' })
8
+
9
+ recipe = Recipe.find(1)
10
+ user = User.find(1)
11
+
12
+ assert_equal 1, recipe.id
13
+ assert_equal 'Sushi', recipe.title
14
+ assert_equal 'Bob', user.name
15
+ end
16
+
17
+ def test_reload
18
+ stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(data: { id: 1, title: 'Sushi' })
19
+
20
+ recipe = Recipe.find(1)
21
+ assert_equal 'Sushi', recipe.title
22
+
23
+ stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(data: { id: 1, title: 'Sashimi' })
24
+ recipe.reload
25
+ assert_equal 'Sashimi', recipe.title
26
+ end
27
+
28
+ def test_find_with_slug
29
+ endpoint = stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(data: { id: 1 })
30
+ Recipe.find('1-delicious-soup')
31
+ assert_requested endpoint
32
+ end
33
+
34
+ def test_404
35
+ stub_request(:get, 'http://sushi.com/recipes/1').to_return(status: 404, body: { message: 'Not found' }.to_json)
36
+
37
+ assert_raises ResourceNotFound do
38
+ Recipe.find(1)
39
+ end
40
+ end
41
+
42
+ def test_save_new_record
43
+ endpoint = stub_request(:post, 'http://sushi.com/recipes').with(body: { recipe: { title: 'Sushi' } }).to_return_json(data: { id: 1, title: 'Sushi (created)' })
44
+
45
+ recipe = Recipe.new(title: 'Sushi')
46
+ recipe.save
47
+
48
+ assert_equal 'Sushi (created)', recipe.title
49
+ assert_requested endpoint
50
+ end
51
+
52
+ def test_save_persisted_record
53
+ stub_request(:put, /.*/)
54
+ endpoint = stub_request(:put, 'http://sushi.com/recipes/1').with(body: { recipe: { title: 'Sushi' } }).to_return_json(data: { id: 1, title: 'Sushi (saved)' })
55
+
56
+ recipe = Recipe.new(id: 1, title: 'Sashimi')
57
+ recipe.title = 'Sushi'
58
+ recipe.save
59
+
60
+ assert_equal 'Sushi (saved)', recipe.title
61
+ assert_requested endpoint
62
+ end
63
+
64
+ def test_create
65
+ endpoint = stub_request(:post, 'http://sushi.com/recipes').with(body: { recipe: { title: 'Sushi' } }).to_return_json(data: { id: 1, title: 'Sushi' })
66
+
67
+ recipe = Recipe.create(title: 'Sushi')
68
+
69
+ assert_equal 'Sushi', recipe.title
70
+ assert_requested endpoint
71
+ end
72
+
73
+ def test_find_using_custom_uri_template
74
+ endpoint = stub_request(:get, 'http://sushi.com/images/photos/1').to_return_json(data: { id: 1 })
75
+ Photo.find(1)
76
+ assert_requested endpoint
77
+ end
78
+
79
+ def test_create_using_custom_uri_template
80
+ endpoint = stub_request(:post, 'http://sushi.com/images/photos')
81
+ Photo.create
82
+ assert_requested endpoint
83
+ end
84
+
85
+ def test_create_using_nested_custom_uri_template
86
+ endpoint = stub_request(:post, 'http://sushi.com/recipes/1/ingredients')
87
+ Ingredient.new(recipe_id: 1).save
88
+ assert_requested endpoint
89
+ end
90
+
91
+ def test_create_using_custom_method
92
+ endpoint = stub_request(:put, 'http://sushi.com/images')
93
+ Image.create
94
+ assert_requested endpoint
95
+ end
96
+
97
+ def test_inheritance_using_custom_method
98
+ endpoint = stub_request(:put, 'http://sushi.com/step_images')
99
+ StepImage.create
100
+ assert_requested endpoint
101
+ end
102
+
103
+ def test_non_nested_params
104
+ assert_equal({ 'url' => 'bob.jpg' }, RecipeImage.new(url: 'bob.jpg').to_params)
105
+ end
106
+
107
+ def test_destroy
108
+ endpoint = stub_request(:delete, 'http://sushi.com/recipes/1')
109
+ Recipe.new(id: 1).destroy
110
+ assert_requested endpoint
111
+ end
112
+
113
+ def test_destroy_class_method
114
+ endpoint = stub_request(:delete, 'http://sushi.com/recipes/1')
115
+ Recipe.destroy(1)
116
+ assert_requested endpoint
117
+ end
118
+
119
+ def test_scoped_destroy_class_method
120
+ endpoint = stub_request(:delete, 'http://sushi.com/recipes/1/ingredients/2')
121
+ Ingredient.where(recipe_id: 1).destroy(2)
122
+ assert_requested endpoint
123
+ end
124
+
125
+ def test_scoped_destroy_class_method_without_param
126
+ endpoint = stub_request(:delete, 'http://sushi.com/recipes/1/image')
127
+ RecipeImage.where(recipe_id: 1).destroy
128
+ assert_requested endpoint
129
+ end
130
+
131
+ def test_validations
132
+ assert_equal false, RecipeImage.new.valid?
133
+ assert_equal true, RecipeImage.new(url: 'bob.jpg').valid?
134
+ end
135
+ end
136
+ end
data/test/path_test.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ module Spyke
4
+ class PathTest < MiniTest::Test
5
+ def test_collection_path
6
+ assert_equal '/recipes', Path.new('/recipes/:id').to_s
7
+ end
8
+
9
+ def test_resource_path
10
+ assert_equal '/recipes/2', Path.new('/recipes/:id', id: 2).to_s
11
+ end
12
+
13
+ def test_nested_collection_path
14
+ path = Path.new('/users/:user_id/recipes/:id', user_id: 1, status: 'published')
15
+ assert_equal [:user_id, :id], path.variables
16
+ assert_equal '/users/1/recipes', path.to_s
17
+ end
18
+
19
+ def test_nested_resource_path
20
+ assert_equal '/users/1/recipes/2', Path.new('/users/:user_id/recipes/:id', user_id: 1, id: 2).to_s
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,76 @@
1
+ require 'test_helper'
2
+
3
+ module Spyke
4
+ class RelationTest < MiniTest::Test
5
+ def test_all
6
+ stub_request(:get, 'http://sushi.com/recipes').to_return_json(data: [{ id: 1, title: 'Sushi' }, { id: 2, title: 'Nigiri' }], metadata: 'meta')
7
+
8
+ recipes = Recipe.all
9
+
10
+ assert_equal %w{ Sushi Nigiri }, recipes.map(&:title)
11
+ assert_equal [1, 2], recipes.map(&:id)
12
+ assert_equal 'meta', recipes.metadata
13
+ end
14
+
15
+ def test_chainable_where
16
+ endpoint = stub_request(:get, 'http://sushi.com/recipes?status=published&per_page=3')
17
+
18
+ Recipe.where(status: 'published').where(per_page: 3).to_a
19
+
20
+ assert_requested endpoint
21
+ end
22
+
23
+ def test_chainable_class_method
24
+ endpoint = stub_request(:get, 'http://sushi.com/recipes?status=published&per_page=3')
25
+
26
+ Recipe.where(per_page: 3).published.to_a
27
+
28
+ assert_requested endpoint
29
+ end
30
+
31
+ def test_prepended_chainable_class_method
32
+ endpoint = stub_request(:get, 'http://sushi.com/recipes?status=published&per_page=3')
33
+
34
+ Recipe.published.where(per_page: 3).to_a
35
+
36
+ assert_requested endpoint
37
+ end
38
+
39
+ def test_scope_class_method
40
+ endpoint = stub_request(:get, 'http://sushi.com/recipes?status=published&page=3')
41
+
42
+ Recipe.published.page(3).to_a
43
+ assert_requested endpoint
44
+ end
45
+
46
+ def test_scope_doesnt_get_stuck
47
+ endpoint_1 = stub_request(:get, 'http://sushi.com/recipes?per_page=3&status=published')
48
+ endpoint_2 = stub_request(:get, 'http://sushi.com/recipes?status=published')
49
+
50
+ Recipe.where(status: 'published').where(per_page: 3).to_a
51
+ Recipe.where(status: 'published').to_a
52
+ assert_requested endpoint_1
53
+ assert_requested endpoint_2
54
+ end
55
+
56
+ def test_create_scoped
57
+ endpoint = stub_request(:post, 'http://sushi.com/recipes').with(body: { recipe: { title: 'Sushi', status: 'published' } })
58
+
59
+ Recipe.published.create(title: 'Sushi')
60
+
61
+ assert_requested endpoint
62
+ end
63
+
64
+ def test_cached_result
65
+ endpoint_1 = stub_request(:get, 'http://sushi.com/recipes?status=published&per_page=3')
66
+ endpoint_2 = stub_request(:get, 'http://sushi.com/recipes?status=published')
67
+
68
+ recipes = Recipe.published.where(per_page: 3)
69
+ recipes.any?
70
+ recipes.to_a
71
+ assert_requested endpoint_1, times: 1
72
+ Recipe.published.to_a
73
+ assert_requested endpoint_2, times: 1
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,6 @@
1
+ # Set up dummy api
2
+ Spyke::Config.connection = Faraday.new(url: 'http://sushi.com') do |faraday|
3
+ faraday.request :json
4
+ faraday.response :json
5
+ faraday.adapter Faraday.default_adapter
6
+ end
@@ -0,0 +1,65 @@
1
+ class Recipe < Spyke::Base
2
+ has_many :groups
3
+ has_one :image
4
+ has_one :background_image, class_name: 'Image', uri: nil
5
+ has_one :alternate, class_name: 'Recipe', uri: '/recipes/:recipe_id/alternates/recipe'
6
+ belongs_to :user
7
+
8
+ scope :published, -> { where(status: 'published') }
9
+ attributes :title
10
+
11
+ before_save :before_save_callback
12
+ before_create :before_create_callback
13
+ before_update :before_update_callback
14
+
15
+ accepts_nested_attributes_for :image, :user, :groups
16
+
17
+ def self.page(number)
18
+ if number.present?
19
+ where(page: number)
20
+ else
21
+ all
22
+ end
23
+ end
24
+
25
+ def ingredients
26
+ groups.first.ingredients
27
+ end
28
+
29
+ private
30
+
31
+ def before_create_callback; end
32
+ def before_update_callback; end
33
+ def before_save_callback; end
34
+ end
35
+
36
+ class Image < Spyke::Base
37
+ method_for :create, :put
38
+ end
39
+
40
+ class StepImage < Image
41
+ end
42
+
43
+ class RecipeImage < Image
44
+ uri '/recipes/:recipe_id/image'
45
+ validates :url, presence: true
46
+ attributes :url
47
+ include_root_in_json false
48
+ end
49
+
50
+ class Group < Spyke::Base
51
+ has_many :ingredients, uri: nil
52
+ accepts_nested_attributes_for :ingredients
53
+ end
54
+
55
+ class Ingredient < Spyke::Base
56
+ uri '/recipes/:recipe_id/ingredients/:id'
57
+ end
58
+
59
+ class User < Spyke::Base
60
+ has_many :recipes
61
+ end
62
+
63
+ class Photo < Spyke::Base
64
+ uri '/images/photos/:id'
65
+ end