MrMurano 1.11.3 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +2 -0
  4. data/README.markdown +12 -14
  5. data/Rakefile +2 -2
  6. data/TODO.taskpaper +8 -6
  7. data/docs/demo.md +109 -0
  8. data/lib/MrMurano/Account.rb +6 -3
  9. data/lib/MrMurano/Config.rb +13 -37
  10. data/lib/MrMurano/Product-1P-Device.rb +2 -0
  11. data/lib/MrMurano/Product-Resources.rb +5 -4
  12. data/lib/MrMurano/Product.rb +3 -3
  13. data/lib/MrMurano/Solution-File.rb +1 -2
  14. data/lib/MrMurano/Solution-ServiceConfig.rb +11 -1
  15. data/lib/MrMurano/Solution-Services.rb +24 -7
  16. data/lib/MrMurano/Solution-Users.rb +6 -4
  17. data/lib/MrMurano/SyncUpDown.rb +67 -28
  18. data/lib/MrMurano/commands/config.rb +4 -1
  19. data/lib/MrMurano/commands/exportImport.rb +3 -0
  20. data/lib/MrMurano/hash.rb +2 -0
  21. data/lib/MrMurano/http.rb +3 -3
  22. data/lib/MrMurano/verbosing.rb +9 -3
  23. data/lib/MrMurano/version.rb +1 -1
  24. data/spec/Account_spec.rb +104 -0
  25. data/spec/Config_spec.rb +202 -57
  26. data/spec/Http_spec.rb +204 -0
  27. data/spec/MakePretties_spec.rb +35 -0
  28. data/spec/Mock_spec.rb +13 -20
  29. data/spec/ProductBase_spec.rb +2 -0
  30. data/spec/ProductContent_spec.rb +77 -12
  31. data/spec/ProductResources_spec.rb +235 -0
  32. data/spec/Product_1P_Device_spec.rb +62 -0
  33. data/spec/Product_1P_RPC_spec.rb +2 -0
  34. data/spec/Product_spec.rb +18 -8
  35. data/spec/Solution-Cors_spec.rb +28 -1
  36. data/spec/Solution-Endpoint_spec.rb +250 -33
  37. data/spec/Solution-File_spec.rb +210 -0
  38. data/spec/Solution-ServiceConfig_spec.rb +2 -0
  39. data/spec/Solution-ServiceDevice_spec.rb +174 -0
  40. data/spec/Solution-ServiceEventHandler_spec.rb +134 -1
  41. data/spec/Solution-ServiceModules_spec.rb +317 -64
  42. data/spec/Solution-UsersRoles_spec.rb +207 -0
  43. data/spec/Solution_spec.rb +90 -0
  44. data/spec/SyncRoot_spec.rb +52 -46
  45. data/spec/SyncUpDown_spec.rb +364 -0
  46. data/spec/Verbosing_spec.rb +279 -0
  47. data/spec/_workspace.rb +27 -0
  48. data/spec/fixtures/dumped_config +47 -0
  49. data/spec/fixtures/product_spec_files/lightbulb-no-state.yaml +11 -0
  50. data/spec/fixtures/product_spec_files/lightbulb.yaml +2 -0
  51. data/spec/fixtures/roles-three.yaml +11 -0
  52. data/spec/spec_helper.rb +9 -0
  53. metadata +26 -2
@@ -1,8 +1,10 @@
1
1
  require 'MrMurano/version'
2
2
  require 'MrMurano/Solution-Services'
3
3
  require 'tempfile'
4
+ require '_workspace'
4
5
 
5
6
  RSpec.describe MrMurano::Library do
7
+ include_context "WORKSPACE"
6
8
  before(:example) do
7
9
  $cfg = MrMurano::Config.new
8
10
  $cfg.load
@@ -57,6 +59,29 @@ RSpec.describe MrMurano::Library do
57
59
  expect(ret).to eq(body[:script])
58
60
  end
59
61
 
62
+ it "fetches with block" do
63
+ body = {:id=>"9K0",
64
+ :name=>"debug",
65
+ :alias=>"XYZ_debug",
66
+ :solution_id=>"XYZ",
67
+ :created_at=>"2016-07-07T19:16:19.479Z",
68
+ :updated_at=>"2016-09-12T13:26:55.868Z",
69
+ :script=>%{-- lua code is here
70
+ function foo(bar)
71
+ return bar + 1
72
+ end
73
+ }
74
+ }
75
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/9K0").
76
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
77
+ 'Content-Type'=>'application/json'}).
78
+ to_return(body: body.to_json)
79
+
80
+ ret = nil
81
+ @srv.fetch('9K0') {|sc| ret = sc}
82
+ expect(ret).to eq(body[:script])
83
+ end
84
+
60
85
  it "removes" do
61
86
  stub_request(:delete, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/9K0").
62
87
  with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
@@ -67,55 +92,134 @@ RSpec.describe MrMurano::Library do
67
92
  expect(ret).to eq({})
68
93
  end
69
94
 
70
- it "uploads over old version" do
71
- stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
72
- with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
73
- 'Content-Type'=>'application/json'}).
74
- to_return(body: "")
95
+ context "uploads" do
96
+ it "over old version" do
97
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
98
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
99
+ 'Content-Type'=>'application/json'}).
100
+ to_return(body: "")
75
101
 
76
- Tempfile.open('foo') do |tio|
77
- tio << %{-- lua code is here
78
- function foo(bar)
79
- return bar + 1
102
+ Tempfile.open('foo') do |tio|
103
+ tio << %{-- lua code is here
104
+ function foo(bar)
105
+ return bar + 1
106
+ end
107
+ }
108
+ tio.close
109
+
110
+ ret = @srv.upload(tio.path, {:id=>"9K0",
111
+ :name=>"debug",
112
+ :alias=>"XYZ_debug",
113
+ :solution_id=>"XYZ",
114
+ })
115
+ expect(ret)
116
+ end
80
117
  end
81
- }
82
- tio.close
83
118
 
84
- ret = @srv.upload(tio.path, {:id=>"9K0",
85
- :name=>"debug",
86
- :alias=>"XYZ_debug",
87
- :solution_id=>"XYZ",
88
- })
89
- expect(ret)
119
+ it "when nothing is there" do
120
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
121
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
122
+ 'Content-Type'=>'application/json'}).
123
+ to_return(status: 404)
124
+ stub_request(:post, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/").
125
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
126
+ 'Content-Type'=>'application/json'}).
127
+ to_return(body: "")
128
+
129
+ Tempfile.open('foo') do |tio|
130
+ tio << %{-- lua code is here
131
+ function foo(bar)
132
+ return bar + 1
133
+ end
134
+ }
135
+ tio.close
136
+
137
+ ret = @srv.upload(tio.path, {:id=>"9K0",
138
+ :name=>"debug",
139
+ :alias=>"XYZ_debug",
140
+ :solution_id=>"XYZ",
141
+ })
142
+ expect(ret)
143
+ end
90
144
  end
91
- end
92
145
 
93
- it "uploads when nothing is there" do
94
- stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
95
- with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
96
- 'Content-Type'=>'application/json'}).
97
- to_return(status: 404)
98
- stub_request(:post, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/").
99
- with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
100
- 'Content-Type'=>'application/json'}).
101
- to_return(body: "")
146
+ it "shows other errors" do
147
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
148
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
149
+ 'Content-Type'=>'application/json'}).
150
+ to_return(status: 418, body: %{{"teapot":true}})
102
151
 
103
- Tempfile.open('foo') do |tio|
104
- tio << %{-- lua code is here
105
- function foo(bar)
106
- return bar + 1
152
+ Tempfile.open('foo') do |tio|
153
+ tio << %{-- lua code is here
154
+ function foo(bar)
155
+ return bar + 1
156
+ end
157
+ }
158
+ tio.close
159
+
160
+ expect(@srv).to receive(:error).and_return(nil)
161
+ ret = @srv.upload(tio.path, {:id=>"9K0",
162
+ :name=>"debug",
163
+ :alias=>"XYZ_debug",
164
+ :solution_id=>"XYZ",
165
+ })
166
+ expect(ret)
167
+ end
107
168
  end
108
- }
109
- tio.close
110
169
 
111
- ret = @srv.upload(tio.path, {:id=>"9K0",
112
- :name=>"debug",
113
- :alias=>"XYZ_debug",
114
- :solution_id=>"XYZ",
115
- })
116
- expect(ret)
170
+ it "over old version; replacing cache miss" do
171
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
172
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
173
+ 'Content-Type'=>'application/json'}).
174
+ to_return(body: "")
175
+
176
+ Tempfile.open('foo') do |tio|
177
+ tio << %{-- lua code is here
178
+ function foo(bar)
179
+ return bar + 1
180
+ end
181
+ }
182
+ tio.close
183
+
184
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
185
+ FileUtils.touch(cacheFile.to_path)
186
+ ret = @srv.upload(tio.path, {:id=>"9K0",
187
+ :name=>"debug",
188
+ :alias=>"XYZ_debug",
189
+ :solution_id=>"XYZ",
190
+ })
191
+ expect(ret)
192
+ end
117
193
  end
118
194
 
195
+ it "over old version; replacing cache hit" do
196
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
197
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
198
+ 'Content-Type'=>'application/json'}).
199
+ to_return(body: "")
200
+
201
+ Tempfile.open('foo') do |tio|
202
+ tio << %{-- lua code is here
203
+ function foo(bar)
204
+ return bar + 1
205
+ end
206
+ }
207
+ tio.close
208
+
209
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
210
+ cacheFile.open('w') do |cfio|
211
+ cfio << {tio.path=>{:sha1=>"6",
212
+ :updated_at=>Time.now.getutc.to_datetime.iso8601(3)}
213
+ }.to_yaml
214
+ end
215
+ ret = @srv.upload(tio.path, {:id=>"9K0",
216
+ :name=>"debug",
217
+ :alias=>"XYZ_debug",
218
+ :solution_id=>"XYZ",
219
+ })
220
+ expect(ret)
221
+ end
222
+ end
119
223
  end
120
224
 
121
225
  context "compares" do
@@ -138,40 +242,189 @@ RSpec.describe MrMurano::Library do
138
242
  expect(ret).to eq(false)
139
243
  end
140
244
 
141
- it "iA is a local file" do
142
- Tempfile.open('foo') do |tio|
143
- tio << "something"
144
- tio.close
145
- iA = @iA.reject{|k,v| k == :updated_at}.merge({
146
- :local_path => Pathname.new(tio.path)
147
- })
148
- ret = @srv.docmp(iA, @iB)
149
- expect(ret).to eq(true)
245
+ context "iA is a local file" do
246
+ it "no cacheFile" do
247
+ Tempfile.open('foo') do |tio|
248
+ tio << "something"
249
+ tio.close
250
+ iA = @iA.reject{|k,v| k == :updated_at}.merge({
251
+ :local_path => Pathname.new(tio.path)
252
+ })
253
+ ret = @srv.docmp(iA, @iB)
254
+ expect(ret).to eq(true)
255
+
256
+ iB = @iB.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
257
+ ret = @srv.docmp(iA, iB)
258
+ expect(ret).to eq(false)
259
+ end
260
+ end
261
+
262
+ it "cache miss" do
263
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
264
+ FileUtils.touch(cacheFile.to_path)
265
+ Tempfile.open('foo') do |tio|
266
+ tio << "something"
267
+ tio.close
268
+ iA = @iA.reject{|k,v| k == :updated_at}.merge({
269
+ :local_path => Pathname.new(tio.path)
270
+ })
271
+ ret = @srv.docmp(iA, @iB)
272
+ expect(ret).to eq(true)
273
+
274
+ iB = @iB.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
275
+ ret = @srv.docmp(iA, iB)
276
+ expect(ret).to eq(false)
277
+ end
278
+ end
279
+
280
+ it "cache hit" do
281
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
282
+ Tempfile.open('foo') do |tio|
283
+ tio << "something"
284
+ tio.close
285
+ tio_mtime = Pathname.new(tio.path).mtime.getutc
286
+ entry = {
287
+ :sha1=>Digest::SHA1.file(tio.path).hexdigest,
288
+ :updated_at=>tio_mtime.to_datetime.iso8601(3)
289
+ }
290
+ cacheFile.open('w') do |io|
291
+ cache = {}
292
+ cache[tio.path] = entry
293
+ io << cache.to_yaml
294
+ end
295
+
296
+ iA = @iA.reject{|k,v| k == :updated_at}.merge({
297
+ :local_path => Pathname.new(tio.path)
298
+ })
299
+ ret = @srv.docmp(iA, @iB)
300
+ expect(ret).to eq(true)
150
301
 
151
- iB = @iB.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
152
- ret = @srv.docmp(iA, iB)
153
- expect(ret).to eq(false)
302
+ iB = @iB.merge({:updated_at=>tio_mtime})
303
+ ret = @srv.docmp(iA, iB)
304
+ expect(ret).to eq(false)
305
+ end
154
306
  end
155
307
  end
156
308
 
157
- it "iB is a local file" do
158
- Tempfile.open('foo') do |tio|
159
- tio << "something"
160
- tio.close
161
- iB = @iB.reject{|k,v| k == :updated_at}.merge({
162
- :local_path => Pathname.new(tio.path)
163
- })
164
- ret = @srv.docmp(@iA, iB)
165
- expect(ret).to eq(true)
309
+ context "iB is a local file" do
310
+ it "no cacheFile" do
311
+ Tempfile.open('foo') do |tio|
312
+ tio << "something"
313
+ tio.close
314
+ iB = @iB.reject{|k,v| k == :updated_at}.merge({
315
+ :local_path => Pathname.new(tio.path)
316
+ })
317
+ ret = @srv.docmp(@iA, iB)
318
+ expect(ret).to eq(true)
166
319
 
167
- iA = @iA.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
168
- ret = @srv.docmp(iA, iB)
169
- expect(ret).to eq(false)
320
+ iA = @iA.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
321
+ ret = @srv.docmp(iA, iB)
322
+ expect(ret).to eq(false)
323
+ end
324
+ end
325
+
326
+ it "cache miss" do
327
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
328
+ FileUtils.touch(cacheFile.to_path)
329
+ Tempfile.open('foo') do |tio|
330
+ tio << "something"
331
+ tio.close
332
+ iB = @iB.reject{|k,v| k == :updated_at}.merge({
333
+ :local_path => Pathname.new(tio.path)
334
+ })
335
+ ret = @srv.docmp(@iA, iB)
336
+ expect(ret).to eq(true)
337
+
338
+ iA = @iA.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
339
+ ret = @srv.docmp(iA, iB)
340
+ expect(ret).to eq(false)
341
+ end
342
+ end
343
+
344
+ it "cache hit" do
345
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
346
+ Tempfile.open('foo') do |tio|
347
+ tio << "something"
348
+ tio.close
349
+ tio_mtime = Pathname.new(tio.path).mtime.getutc
350
+ entry = {
351
+ :sha1=>Digest::SHA1.file(tio.path).hexdigest,
352
+ :updated_at=>tio_mtime.to_datetime.iso8601(3)
353
+ }
354
+ cacheFile.open('w') do |io|
355
+ cache = {}
356
+ cache[tio.path] = entry
357
+ io << cache.to_yaml
358
+ end
359
+
360
+ iB = @iB.reject{|k,v| k == :updated_at}.merge({
361
+ :local_path => Pathname.new(tio.path)
362
+ })
363
+ ret = @srv.docmp(@iA, iB)
364
+ expect(ret).to eq(true)
365
+
366
+ iA = @iA.merge({:updated_at=>tio_mtime})
367
+ ret = @srv.docmp(iA, iB)
368
+ expect(ret).to eq(false)
369
+ end
170
370
  end
171
371
  end
172
372
  end
173
373
 
174
- # TODO: status tests
374
+ context "Lookup functions" do
375
+ it "gets local name" do
376
+ ret = @srv.tolocalname({ :name=>"bob" }, nil)
377
+ expect(ret).to eq('bob.lua')
378
+ end
379
+
380
+ it "gets synckey" do
381
+ ret = @srv.synckey({ :name=>'device' })
382
+ expect(ret).to eq("device")
383
+ end
175
384
 
385
+ it "gets searchfor" do
386
+ $cfg['modules.searchFor'] = %{a b c/**/d/*.bob}
387
+ ret = @srv.searchFor
388
+ expect(ret).to eq(["a", "b", "c/**/d/*.bob"])
389
+ end
390
+
391
+ it "gets ignoring" do
392
+ $cfg['modules.ignoring'] = %{a b c/**/d/*.bob}
393
+ ret = @srv.ignoring
394
+ expect(ret).to eq(["a", "b", "c/**/d/*.bob"])
395
+ end
396
+
397
+ it "raises on alias without service" do
398
+ expect {
399
+ @srv.mkname( {:event=>'bob'} )
400
+ }.to raise_error %{Missing parts! {"event":"bob"}}
401
+ end
402
+
403
+ it "raises on alias without event" do
404
+ expect {
405
+ @srv.mkalias( {:service=>'bob'} )
406
+ }.to raise_error %{Missing parts! {"service":"bob"}}
407
+ end
408
+
409
+ it "raises on name without service" do
410
+ expect {
411
+ @srv.mkalias( {:event=>'bob'} )
412
+ }.to raise_error %{Missing parts! {"event":"bob"}}
413
+ end
414
+
415
+ it "raises on name without event" do
416
+ expect {
417
+ @srv.mkname( {:service=>'bob'} )
418
+ }.to raise_error %{Missing parts! {"service":"bob"}}
419
+ end
420
+ end
421
+
422
+ context "toRemoteItem" do
423
+ it "reads one" do
424
+ path = Pathname.new(@projectDir) + 'test.lua'
425
+ ret = @srv.toRemoteItem(nil, path)
426
+ expect(ret).to eq({:name=>'test'})
427
+ end
428
+ end
176
429
  end
177
430
  # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,207 @@
1
+ require 'MrMurano/version'
2
+ require 'MrMurano/Solution-Users'
3
+ require 'MrMurano/hash'
4
+ require 'tempfile'
5
+ require '_workspace'
6
+
7
+ RSpec.describe MrMurano::Role do
8
+ include_context "WORKSPACE"
9
+ before(:example) do
10
+ $cfg = MrMurano::Config.new
11
+ $cfg.load
12
+ $cfg['net.host'] = 'bizapi.hosted.exosite.io'
13
+ $cfg['solution.id'] = 'XYZ'
14
+
15
+ @srv = MrMurano::Role.new
16
+ allow(@srv).to receive(:token).and_return("TTTTTTTTTT")
17
+ end
18
+
19
+ it "initializes" do
20
+ uri = @srv.endPoint('/')
21
+ expect(uri.to_s).to eq("https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/")
22
+ end
23
+
24
+ it "lists" do
25
+ body = [{:role_id=>"guest", :parameter=>[{:name=>"did"}]},
26
+ {:role_id=>"admin", :parameter=>[{:name=>"enabled"}]},
27
+ {:role_id=>"owns", :parameter=>[{:name=>"did"}]}]
28
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role").
29
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
30
+ 'Content-Type'=>'application/json'}).
31
+ to_return(body: body.to_json)
32
+ ret = @srv.list
33
+ expect(ret).to eq(body)
34
+ end
35
+
36
+ it "fetches" do
37
+ body = {:role_id=>"guest", :parameter=>[{:name=>"did"}]}
38
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/guest").
39
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
40
+ 'Content-Type'=>'application/json'}).
41
+ to_return(body: body.to_json)
42
+ ret = @srv.fetch('guest')
43
+ expect(ret).to eq(body)
44
+ end
45
+
46
+ it "removes" do
47
+ stub_request(:delete, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/guest").
48
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
49
+ 'Content-Type'=>'application/json'}).
50
+ to_return(status: 200, body: "")
51
+ ret = @srv.remove('guest')
52
+ expect(ret).to eq({})
53
+ end
54
+
55
+ context "uploads" do
56
+ it "updating" do
57
+ body = {:role_id=>"guest", :parameter=>[{:name=>"did"}]}
58
+ stub_request(:delete, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/guest").
59
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
60
+ 'Content-Type'=>'application/json'}).
61
+ to_return(status: 200, body: "")
62
+ stub_request(:post, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/").
63
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
64
+ 'Content-Type'=>'application/json'},
65
+ :body=>body.to_json
66
+ ).
67
+ to_return(status: 205, body: "")
68
+
69
+
70
+ @srv.upload(nil, body, true)
71
+ end
72
+
73
+ it "creating" do
74
+ body = {:role_id=>"guest", :parameter=>[{:name=>"did"}]}
75
+ stub_request(:delete, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/guest").
76
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
77
+ 'Content-Type'=>'application/json'}).
78
+ to_return(status: 404, body: "")
79
+ stub_request(:post, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/").
80
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
81
+ 'Content-Type'=>'application/json'},
82
+ :body=>body.to_json
83
+ ).
84
+ to_return(status: 205, body: "")
85
+
86
+
87
+ @srv.upload(nil, body, false)
88
+ end
89
+
90
+ it "with delete error" do
91
+ body = {:role_id=>"guest", :parameter=>[{:name=>"did"}]}
92
+ stub_request(:delete, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/guest").
93
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
94
+ 'Content-Type'=>'application/json'}).
95
+ to_return(status: 418, body: "I'm a teapot!")
96
+ stub_request(:post, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/role/").
97
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
98
+ 'Content-Type'=>'application/json'},
99
+ :body=>body.to_json
100
+ ).
101
+ to_return(status: 205, body: "")
102
+
103
+ saved = $stderr
104
+ $stderr = StringIO.new
105
+ @srv.upload(nil, body, false)
106
+ expect($stderr.string).to match(/Request Failed: 418: I'm a teapot/)
107
+ $stderr = saved
108
+ end
109
+ end
110
+
111
+ context "downloads" do
112
+ before(:example) do
113
+ @lry = Pathname.new(@projectDir) + 'roles.yaml'
114
+ @grl = {:role_id=>"guest", :parameter=>[{:name=>"could"}]}
115
+ end
116
+
117
+ it "creates" do
118
+ @srv.download(@lry, @grl)
119
+
120
+ expect(@lry.exist?).to be true
121
+ got = YAML.load(@lry.read)
122
+ expect(got).to include(Hash.transform_keys_to_strings(@grl))
123
+ end
124
+
125
+ it "updates" do
126
+ FileUtils.copy(File.join(@testdir, 'spec/fixtures/roles-three.yaml'), @lry.to_path)
127
+
128
+ @srv.download(@lry, @grl)
129
+ got = YAML.load(@lry.read)
130
+ expect(got).to include(Hash.transform_keys_to_strings(@grl))
131
+ end
132
+ end
133
+
134
+ context "removing local roles" do
135
+ before(:example) do
136
+ @lry = Pathname.new(@projectDir) + 'roles.yaml'
137
+ @grl = {:role_id=>"guest", :parameter=>[{:name=>"could"}]}
138
+ end
139
+
140
+ it "when file missing" do
141
+ @srv.removelocal(@lry, @grl)
142
+ expect(@lry.exist?).to be true
143
+ got = YAML.load(@lry.read)
144
+ expect(got).to eq([])
145
+ end
146
+
147
+ it "when not there" do
148
+ FileUtils.copy(File.join(@testdir, 'spec/fixtures/roles-three.yaml'), @lry.to_path)
149
+ @srv.removelocal(@lry, {:role_id=>"undertow"})
150
+ got = YAML.load(@lry.read)
151
+ rty = Pathname.new(@testdir) + 'spec/fixtures/roles-three.yaml'
152
+ want = YAML.load(rty.read)
153
+ expect(got).to eq(want)
154
+ end
155
+
156
+ it "with matching role" do
157
+ FileUtils.copy(File.join(@testdir, 'spec/fixtures/roles-three.yaml'), @lry.to_path)
158
+ @srv.removelocal(@lry, @grl)
159
+ got = YAML.load(@lry.read)
160
+ expect(got.count).to eq(2)
161
+ expect(got).to contain_exactly(
162
+ a_hash_including('role_id' => 'admin'),
163
+ a_hash_including('role_id' => 'owns')
164
+ )
165
+ end
166
+ end
167
+
168
+ it "tolocalpath is into" do
169
+ lry = Pathname.new(@projectDir) + 'roles.yaml'
170
+ ret = @srv.tolocalpath(lry, {:role_id=>"guest", :parameter=>[{:name=>"could"}]})
171
+ expect(ret).to eq(lry)
172
+ end
173
+
174
+ context "list local items" do
175
+ before(:example) do
176
+ @lry = Pathname.new(@projectDir) + 'roles.yaml'
177
+ end
178
+
179
+ it "when missing" do
180
+ expect(@srv).to receive(:warning).with(/^Skipping missing/)
181
+ ret = @srv.localitems(@lry)
182
+ expect(ret).to eq([])
183
+ end
184
+
185
+ it "when not a file" do
186
+ FileUtils.mkpath(@lry.to_path)
187
+ expect(@srv).to receive(:warning).with(/^Cannot read from/)
188
+ ret = @srv.localitems(@lry)
189
+ expect(ret).to eq([])
190
+ end
191
+
192
+ it "when empty" do
193
+ FileUtils.touch(@lry.to_path)
194
+ ret = @srv.localitems(@lry)
195
+ expect(ret).to eq([])
196
+ end
197
+
198
+ it "with roles" do
199
+ FileUtils.copy(File.join(@testdir, 'spec/fixtures/roles-three.yaml'), @lry.to_path)
200
+ ret = @srv.localitems(@lry)
201
+ expect(ret).to eq([{:role_id=>"guest", :parameter=>[{:name=>"did"}]},
202
+ {:role_id=>"admin", :parameter=>[{:name=>"enabled"}]},
203
+ {:role_id=>"owns", :parameter=>[{:name=>"did"}]}])
204
+ end
205
+ end
206
+ end
207
+ # vim: set ai et sw=2 ts=2 :