blest 0.0.2 → 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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -99
  3. data/lib/blest.rb +811 -143
  4. data/spec/blest_spec.rb +220 -0
  5. metadata +10 -9
@@ -0,0 +1,220 @@
1
+ require 'rspec'
2
+ require 'securerandom'
3
+ require_relative '../lib/blest'
4
+
5
+ RSpec.describe Router do
6
+
7
+ benchmarks = []
8
+
9
+ router = Router.new(timeout: 1000)
10
+ router2 = Router.new(timeout: 10)
11
+ router3 = Router.new
12
+
13
+ testId1 = nil
14
+ testValue1 = nil
15
+ result1 = nil
16
+ error1 = nil
17
+ testId2 = nil
18
+ testValue2 = nil
19
+ result2 = nil
20
+ error2 = nil
21
+ testId3 = nil
22
+ testValue3 = nil
23
+ result3 = nil
24
+ error3 = nil
25
+ testId4 = nil
26
+ testValue4 = nil
27
+ result4 = nil
28
+ error4 = nil
29
+ testId5 = nil
30
+ testValue5 = nil
31
+ result5 = nil
32
+ error5 = nil
33
+ testId6 = nil
34
+ testValue6 = nil
35
+ result6 = nil
36
+ error6 = nil
37
+
38
+ before(:all) do
39
+ router.route('basicRoute') do |body, context|
40
+ { 'route'=> 'basicRoute', 'body' => body, 'context' => context }
41
+ end
42
+
43
+ router.before do |body, context|
44
+ context['test'] = { 'value' => body['testValue'] }
45
+ context['requestTime'] = Time.now
46
+ nil
47
+ end
48
+
49
+ router.after do |_, context|
50
+ complete_time = Time.now
51
+ difference = (complete_time - context['requestTime'])
52
+ benchmarks.push(difference)
53
+ nil
54
+ end
55
+
56
+ router2.route('mergedRoute') do |body, context|
57
+ { 'route' => 'mergedRoute', 'body' => body, 'context' => context }
58
+ end
59
+
60
+ router2.route('timeoutRoute') do |body|
61
+ sleep(0.2)
62
+ { 'testValue' => body['testValue'] }
63
+ end
64
+
65
+ router.merge(router2)
66
+
67
+ router3.route('errorRoute') do |body|
68
+ error = BlestError.new(body['testValue'])
69
+ error.code = "ERROR_#{(body['testValue'].to_f * 10).round}"
70
+ raise error
71
+ end
72
+
73
+ router.namespace('subRoutes', router3)
74
+
75
+ # puts router.routes
76
+
77
+ # Basic route
78
+ testId1 = SecureRandom.uuid
79
+ testValue1 = rand
80
+ result1, error1 = router.handle([[testId1, 'basicRoute', { 'testValue' => testValue1 }]], { 'testValue' => testValue1 })
81
+
82
+ # Merged route
83
+ testId2 = SecureRandom.uuid
84
+ testValue2 = rand
85
+ result2, error2 = router.handle([[testId2, 'mergedRoute', { 'testValue' => testValue2 }]], { 'testValue' => testValue2 })
86
+
87
+ # Error route
88
+ testId3 = SecureRandom.uuid
89
+ testValue3 = rand
90
+ result3, error3 = router.handle([[testId3, 'subRoutes/errorRoute', { 'testValue' => testValue3 }]], { 'testValue' => testValue3 })
91
+
92
+ # Missing route
93
+ testId4 = SecureRandom.uuid
94
+ testValue4 = rand
95
+ result4, error4 = router.handle([[testId4, 'missingRoute', { 'testValue' => testValue4 }]], { 'testValue' => testValue4 })
96
+
97
+ # Timeout route
98
+ testId5 = SecureRandom.uuid
99
+ testValue5 = rand
100
+ result5, error5 = router.handle([[testId5, 'timeoutRoute', { 'testValue' => testValue5 }]], { 'testValue' => testValue5 })
101
+
102
+ # Malformed request
103
+ testId6 = SecureRandom.uuid
104
+ result6, error6 = router.handle([[testId6], {}, [true, 1.25]])
105
+
106
+ end
107
+
108
+ it 'should have class properties' do
109
+ expect(router.is_a?(Router)).to be_truthy
110
+ expect(router.routes.keys.length).to eq(4)
111
+ expect(router).to respond_to(:handle)
112
+ end
113
+
114
+ it 'should have class properties' do
115
+ expect(router).to be_a(Router)
116
+ expect(router.routes.keys.length).to eq(4)
117
+ expect(router).to respond_to(:handle)
118
+ end
119
+
120
+ it 'should process all valid requests' do
121
+ expect(error1).to be_nil
122
+ expect(error2).to be_nil
123
+ expect(error3).to be_nil
124
+ expect(error4).to be_nil
125
+ expect(error5).to be_nil
126
+ end
127
+
128
+ it 'should return matching IDs' do
129
+ expect(result1[0][0]).to eq(testId1)
130
+ expect(result2[0][0]).to eq(testId2)
131
+ expect(result3[0][0]).to eq(testId3)
132
+ expect(result4[0][0]).to eq(testId4)
133
+ expect(result5[0][0]).to eq(testId5)
134
+ end
135
+
136
+ it 'should return matching routes' do
137
+ expect(result1[0][1]).to eq('basicRoute')
138
+ expect(result2[0][1]).to eq('mergedRoute')
139
+ expect(result3[0][1]).to eq('subRoutes/errorRoute')
140
+ expect(result4[0][1]).to eq('missingRoute')
141
+ expect(result5[0][1]).to eq('timeoutRoute')
142
+ end
143
+
144
+ it 'should accept body' do
145
+ expect(result1[0][2]['body']['testValue']).to eq(testValue1)
146
+ expect(result2[0][2]['body']['testValue']).to eq(testValue2)
147
+ end
148
+
149
+ it 'should respect context' do
150
+ expect(result1[0][2]['context']['testValue']).to eq(testValue1)
151
+ expect(result2[0][2]['context']['testValue']).to eq(testValue2)
152
+ end
153
+
154
+ it 'should support middleware' do
155
+ expect(result1[0][2]['context']['test']).to be_nil
156
+ expect(result2[0][2]['context']['test']['value']).to eq(testValue2)
157
+ end
158
+
159
+ it 'should handle errors correctly' do
160
+ expect(result1[0][3]).to be_nil
161
+ expect(result2[0][3]).to be_nil
162
+ expect(result3[0][3]['message']).to eq(testValue3.to_s)
163
+ expect(result3[0][3]['status']).to eq(500)
164
+ expect(result3[0][3]['code']).to eq("ERROR_#{(testValue3 * 10).round}")
165
+ expect(result4[0][3]['message']).to eq('Not Found')
166
+ expect(result4[0][3]['status']).to eq(404)
167
+ end
168
+
169
+ it 'should support timeout setting' do
170
+ expect(result5[0][2]).to be_nil
171
+ expect(result5[0][3]['message']).to eq('Internal Server Error')
172
+ expect(result5[0][3]['status']).to eq(500)
173
+ end
174
+
175
+ it 'should reject malformed requests' do
176
+ expect(error6['message']).not_to be_nil
177
+ end
178
+
179
+ it 'should allow trailing middleware' do
180
+ expect(benchmarks.length).to eq(1)
181
+ end
182
+
183
+ it 'should throw an error for invalid routes' do
184
+ handler = proc {}
185
+ expect { router.route('a', &handler) }.to raise_error(ArgumentError)
186
+ expect { router.route('0abc', &handler) }.to raise_error(ArgumentError)
187
+ expect { router.route('_abc', &handler) }.to raise_error(ArgumentError)
188
+ expect { router.route('-abc', &handler) }.to raise_error(ArgumentError)
189
+ expect { router.route('abc_', &handler) }.to raise_error(ArgumentError)
190
+ expect { router.route('abc-', &handler) }.to raise_error(ArgumentError)
191
+ expect { router.route('abc/0abc', &handler) }.to raise_error(ArgumentError)
192
+ expect { router.route('abc/_abc', &handler) }.to raise_error(ArgumentError)
193
+ expect { router.route('abc/-abc', &handler) }.to raise_error(ArgumentError)
194
+ expect { router.route('abc/', &handler) }.to raise_error(ArgumentError)
195
+ expect { router.route('/abc', &handler) }.to raise_error(ArgumentError)
196
+ expect { router.route('abc//abc', &handler) }.to raise_error(ArgumentError)
197
+ expect { router.route('abc/a/abc', &handler) }.to raise_error(ArgumentError)
198
+ expect { router.route('abc/0abc/abc', &handler) }.to raise_error(ArgumentError)
199
+ expect { router.route('abc/_abc/abc', &handler) }.to raise_error(ArgumentError)
200
+ expect { router.route('abc/-abc/abc', &handler) }.to raise_error(ArgumentError)
201
+ expect { router.route('abc/abc_/abc', &handler) }.to raise_error(ArgumentError)
202
+ expect { router.route('abc/abc-/abc', &handler) }.to raise_error(ArgumentError)
203
+ end
204
+
205
+ end
206
+
207
+
208
+
209
+ RSpec.describe HttpClient do
210
+ client = HttpClient.new('http://localhost:8080', max_batch_size = 25, buffer_delay = 10)
211
+
212
+ it 'should have class properties' do
213
+ expect(client.is_a?(HttpClient)).to be_truthy
214
+ expect(client.url).to eq('http://localhost:8080')
215
+ expect(client.max_batch_size).to eq(25)
216
+ expect(client.buffer_delay).to eq(10)
217
+ expect(client).to respond_to(:request)
218
+ end
219
+
220
+ end
metadata CHANGED
@@ -1,21 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JHunt
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-10 00:00:00.000000000 Z
11
+ date: 2024-10-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: The Ruby reference implementation of BLEST (Batch-able, Lightweight,
14
14
  Encrypted State Transfer), an improved communication protocol for web APIs which
15
- leverages JSON, supports request batching and selective returns, and provides a
16
- modern alternative to REST.
15
+ leverages JSON, supports request batching by default, and provides a modern alternative
16
+ to REST.
17
17
  email:
18
- - blest@jhunt.dev
18
+ - hello@jhunt.dev
19
19
  executables: []
20
20
  extensions: []
21
21
  extra_rdoc_files: []
@@ -23,11 +23,12 @@ files:
23
23
  - LICENSE
24
24
  - README.md
25
25
  - lib/blest.rb
26
+ - spec/blest_spec.rb
26
27
  homepage: https://blest.jhunt.dev
27
28
  licenses:
28
29
  - MIT
29
30
  metadata: {}
30
- post_install_message:
31
+ post_install_message:
31
32
  rdoc_options: []
32
33
  require_paths:
33
34
  - lib
@@ -42,8 +43,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
42
43
  - !ruby/object:Gem::Version
43
44
  version: '0'
44
45
  requirements: []
45
- rubygems_version: 3.0.3
46
- signing_key:
46
+ rubygems_version: 3.5.16
47
+ signing_key:
47
48
  specification_version: 4
48
49
  summary: The Ruby reference implementation of BLEST
49
50
  test_files: []