uploadcare-api_struct 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +25 -0
  3. data/.gitignore +18 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +15 -0
  6. data/CHANGELOG.md +15 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +123 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +211 -0
  11. data/Rakefile +6 -0
  12. data/api_struct.gemspec +36 -0
  13. data/api_struct.svg +1 -0
  14. data/bin/console +14 -0
  15. data/bin/setup +8 -0
  16. data/lib/api_struct/client.rb +88 -0
  17. data/lib/api_struct/collection.rb +19 -0
  18. data/lib/api_struct/concerns/underscore.rb +7 -0
  19. data/lib/api_struct/entity.rb +93 -0
  20. data/lib/api_struct/errors/client.rb +43 -0
  21. data/lib/api_struct/errors/entity.rb +7 -0
  22. data/lib/api_struct/extensions/api_client.rb +43 -0
  23. data/lib/api_struct/extensions/dry_monads.rb +22 -0
  24. data/lib/api_struct/settings.rb +7 -0
  25. data/lib/api_struct/version.rb +3 -0
  26. data/lib/api_struct.rb +20 -0
  27. data/spec/api_struct/client_spec.rb +156 -0
  28. data/spec/api_struct/entity_spec.rb +188 -0
  29. data/spec/fixtures/cassettes/posts/1.yml +73 -0
  30. data/spec/fixtures/cassettes/posts/index_success.yml +1335 -0
  31. data/spec/fixtures/cassettes/posts/show_failure.yml +67 -0
  32. data/spec/fixtures/cassettes/posts/show_failure_html.yml +67 -0
  33. data/spec/fixtures/cassettes/posts/show_success.yml +74 -0
  34. data/spec/fixtures/cassettes/posts/suffix.yml +73 -0
  35. data/spec/fixtures/cassettes/posts/update_success.yml +71 -0
  36. data/spec/fixtures/cassettes/todos.yml +143 -0
  37. data/spec/fixtures/cassettes/user_todos.yml +189 -0
  38. data/spec/fixtures/cassettes/users/1/posts/1.yml +797 -0
  39. data/spec/fixtures/cassettes/users/1/posts.yml +1049 -0
  40. data/spec/spec_helper.rb +26 -0
  41. data/spec/support/stub.rb +9 -0
  42. metadata +283 -0
@@ -0,0 +1,188 @@
1
+ describe ApiStruct::Entity do
2
+ extend Support::Stub
3
+
4
+ stub_api('https://jsonplaceholder.typicode.com')
5
+
6
+ # rubocop:disable Lint/ConstantDefinitionInBlock
7
+ class StubClient < ApiStruct::Client
8
+ stub_api 'posts'
9
+
10
+ def show(id)
11
+ get(id)
12
+ end
13
+
14
+ def index(params = {})
15
+ get(json: params)
16
+ end
17
+ end
18
+
19
+ class StubNestedEntity < ApiStruct::Entity
20
+ attr_entity :name
21
+ end
22
+
23
+ class StubEntity < ApiStruct::Entity
24
+ client_service StubClient
25
+ client_service StubClient, prefix: true
26
+ client_service StubClient, prefix: :custom
27
+ client_service StubClient, prefix: :only, only: :index
28
+ client_service StubClient, prefix: :except, except: :show
29
+
30
+ attr_entity :id, :title, :camel_case
31
+
32
+ has_entity :nested_entity, as: StubNestedEntity
33
+ has_entities :another_nested_entities, as: StubNestedEntity
34
+ end
35
+ # rubocop:enable Lint/ConstantDefinitionInBlock
36
+
37
+ let(:response) { { title: FFaker::Name.name, 'id' => rand(1..100), another_attributes: FFaker::Name.name } }
38
+ let(:nested_response) { { name: FFaker::Name.name } }
39
+
40
+ it '.new' do
41
+ entity = StubEntity.new(response)
42
+
43
+ expect(entity).to be_success
44
+ expect(entity.id).to eq(response['id'])
45
+ expect(entity.title).to eq(response[:title])
46
+ expect { entity.another_attributes }.to raise_error(NoMethodError)
47
+ end
48
+
49
+ it '.collection' do
50
+ entities = StubEntity.collection([response, response])
51
+
52
+ expect(entities.count).to eq(2)
53
+ expect(entities.success?).to eq(true)
54
+ expect(entities.failure?).to eq(false)
55
+ expect(entities.class).to eq(ApiStruct::Collection)
56
+ expect(entities.first.title).to eq(response[:title])
57
+ end
58
+
59
+ context 'Nested entity' do
60
+ it 'when response is valid' do
61
+ response[:nested_entity] = nested_response
62
+ entity = StubEntity.new(response)
63
+ nested_entity = entity.nested_entity
64
+
65
+ expect(nested_entity.class).to eq(StubNestedEntity)
66
+ expect(nested_entity.name).to eq(nested_response[:name])
67
+ end
68
+
69
+ it 'when response is invalid' do
70
+ response[:nested_entity] = [nested_response]
71
+ entity = StubEntity.new(response)
72
+
73
+ expect { entity.nested_entity }.to raise_error(ApiStruct::EntityError)
74
+ end
75
+ end
76
+
77
+ context 'Nested entities' do
78
+ it 'when response is valid' do
79
+ response[:another_nested_entities] = [nested_response]
80
+ entity = StubEntity.new(response)
81
+ nested_entity = entity.another_nested_entities.first
82
+
83
+ expect(nested_entity.class).to eq(StubNestedEntity)
84
+ expect(nested_entity.name).to eq(nested_response[:name])
85
+ end
86
+
87
+ it 'when response is invalid' do
88
+ response[:another_nested_entities] = nested_response
89
+ entity = StubEntity.new(response)
90
+
91
+ expect { entity.another_nested_entities }.to raise_error(ApiStruct::EntityError)
92
+ end
93
+ end
94
+
95
+ context 'From monad' do
96
+ it 'convert to entity', type: :webmock do
97
+ VCR.use_cassette('posts/show_success') do
98
+ entity = StubEntity.from_monad(StubClient.new.show(1))
99
+
100
+ expect(entity).to be_success
101
+ expect(entity.id).to eq(1)
102
+ expect(entity.title).not_to be_empty
103
+ end
104
+ end
105
+
106
+ it 'convert to collection of entities', type: :webmock do
107
+ VCR.use_cassette('posts/index_success') do
108
+ entities = StubEntity.from_monad(StubClient.new.index)
109
+
110
+ expect(entities.class).to eq(ApiStruct::Collection)
111
+ expect(entities.first.id).to eq(1)
112
+ end
113
+ end
114
+ end
115
+
116
+ context 'From client service' do
117
+ it 'convert to entity', type: :webmock do
118
+ VCR.use_cassette('posts/show_success') do
119
+ entity = StubEntity.show(1)
120
+
121
+ expect(entity).to be_success
122
+ expect(entity.id).to eq(1)
123
+ expect(entity.title).not_to be_empty
124
+ expect(entity.camel_case).not_to be_empty
125
+ end
126
+ end
127
+
128
+ it 'convert to collection of entities', type: :webmock do
129
+ VCR.use_cassette('posts/index_success') do
130
+ entities = StubEntity.index
131
+
132
+ expect(entities.class).to eq(ApiStruct::Collection)
133
+ expect(entities.first.id).to eq(1)
134
+ end
135
+ end
136
+ end
137
+
138
+ describe '.client_service' do
139
+ context 'prefix' do
140
+ context 'empty' do
141
+ it 'should register client as base' do
142
+ expect(StubEntity.clients[:base]).to eq StubClient
143
+ end
144
+
145
+ it 'should define client methods without prefix' do
146
+ expect(StubEntity).to be_respond_to(:show)
147
+ expect(StubEntity).to be_respond_to(:index)
148
+ end
149
+ end
150
+
151
+ context 'eq true' do
152
+ it 'should register client as stubclient' do
153
+ expect(StubEntity.clients[:stub_client]).to eq StubClient
154
+ end
155
+
156
+ it 'should define client methods' do
157
+ expect(StubEntity).to be_respond_to(:stub_client_show)
158
+ expect(StubEntity).to be_respond_to(:stub_client_index)
159
+ end
160
+ end
161
+
162
+ context 'eq string' do
163
+ it 'should register client as custom' do
164
+ expect(StubEntity.clients[:custom]).to eq StubClient
165
+ end
166
+
167
+ it 'should define client methods' do
168
+ expect(StubEntity).to be_respond_to(:custom_show)
169
+ expect(StubEntity).to be_respond_to(:custom_index)
170
+ end
171
+ end
172
+ end
173
+
174
+ context 'only' do
175
+ it 'should define methods from options[:only]' do
176
+ expect(StubEntity).to be_respond_to(:only_index)
177
+ expect(StubEntity).not_to be_respond_to(:only_show)
178
+ end
179
+ end
180
+
181
+ context 'except' do
182
+ it 'should define all methods except options[:except]' do
183
+ expect(StubEntity).to be_respond_to(:except_index)
184
+ expect(StubEntity).not_to be_respond_to(:except_show)
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,73 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://jsonplaceholder.typicode.com/posts/1
6
+ body:
7
+ encoding: UTF-8
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Content-Type:
13
+ - application/json
14
+ Connection:
15
+ - close
16
+ Host:
17
+ - jsonplaceholder.typicode.com
18
+ User-Agent:
19
+ - http.rb/3.0.0
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Tue, 06 Mar 2018 08:02:15 GMT
27
+ Content-Type:
28
+ - application/json; charset=utf-8
29
+ Content-Length:
30
+ - '292'
31
+ Connection:
32
+ - close
33
+ Set-Cookie:
34
+ - __cfduid=db9bcdebf92e32fd92ce9630387d2e0761520323335; expires=Wed, 06-Mar-19
35
+ 08:02:15 GMT; path=/; domain=.typicode.com; HttpOnly
36
+ X-Powered-By:
37
+ - Express
38
+ Vary:
39
+ - Origin, Accept-Encoding
40
+ Access-Control-Allow-Credentials:
41
+ - 'true'
42
+ Cache-Control:
43
+ - public, max-age=14400
44
+ Pragma:
45
+ - no-cache
46
+ Expires:
47
+ - Tue, 06 Mar 2018 12:02:15 GMT
48
+ X-Content-Type-Options:
49
+ - nosniff
50
+ Etag:
51
+ - W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU"
52
+ Via:
53
+ - 1.1 vegur
54
+ Cf-Cache-Status:
55
+ - HIT
56
+ Expect-Ct:
57
+ - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
58
+ Server:
59
+ - cloudflare
60
+ Cf-Ray:
61
+ - 3f734c8d68fb8d7d-DME
62
+ body:
63
+ encoding: UTF-8
64
+ string: |-
65
+ {
66
+ "userId": 1,
67
+ "id": 1,
68
+ "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
69
+ "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
70
+ }
71
+ http_version:
72
+ recorded_at: Tue, 06 Mar 2018 08:09:11 GMT
73
+ recorded_with: VCR 3.0.3