rest_spec.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. require 'api_client'
  2. RSpec.describe 'REST Server' do
  3. before(:all) do
  4. @client = ApiClient.new(ENV.fetch('ESPMH_HOSTNAME'), ENV.fetch('ESPMH_TEST_DEVICE_ID_BASE'))
  5. @client.upload_json('/settings', 'settings.json')
  6. @username = 'a'
  7. @password = 'a'
  8. end
  9. context 'authentication' do
  10. after(:all) do
  11. @client.set_auth!(@username, @password)
  12. @client.put('/settings', admin_username: '', admin_password: '')
  13. end
  14. it 'should not require auth unless both username and password are set' do
  15. @client.put('/settings', admin_username: 'abc', admin_password: '')
  16. expect { @client.get('/settings') }.not_to raise_error
  17. @client.put('/settings', admin_username: '', admin_password: 'abc')
  18. expect { @client.get('/settings') }.not_to raise_error
  19. @client.put('/settings', admin_username: '', admin_password: '')
  20. expect { @client.get('/settings') }.not_to raise_error
  21. end
  22. it 'should require auth for all routes when password is set' do
  23. @client.put('/settings', admin_username: @username, admin_password: @password)
  24. # Try no auth
  25. expect { @client.get('/settings') }.to raise_error(Net::HTTPServerException)
  26. # Try wrong username
  27. @client.set_auth!("#{@username}wronguser", @password)
  28. expect { @client.get('/settings') }.to raise_error(Net::HTTPServerException)
  29. # Try wrong password
  30. @client.set_auth!(@username, "wrong#{@password}")
  31. expect { @client.get('/settings') }.to raise_error(Net::HTTPServerException)
  32. # Try right username
  33. @client.set_auth!(@username, @password)
  34. expect { @client.get('/settings') }.not_to raise_error
  35. # Make sure all routes are protected
  36. @client.clear_auth!
  37. [
  38. '/about',
  39. '/gateways/0/rgb_cct/1',
  40. '/remote_configs',
  41. '/'
  42. ].each do |page|
  43. expect { @client.get(page) }.to raise_error(Net::HTTPServerException), "No auth required for page: #{page}"
  44. end
  45. expect { @client.post('/system', {}) }.to raise_error(Net::HTTPServerException)
  46. expect { @client.post('/firmware', {}) }.to raise_error(Net::HTTPServerException)
  47. # Clear auth
  48. @client.set_auth!(@username, @password)
  49. @client.put('/settings', admin_username: '', admin_password: '')
  50. @client.clear_auth!
  51. expect { @client.get('/settings') }.not_to raise_error
  52. end
  53. end
  54. context 'misc routes' do
  55. it 'should respond to /about' do
  56. result = @client.get('/about')
  57. expect(result['firmware']).to eq('milight-hub')
  58. end
  59. it 'should respond to /system' do
  60. expect { @client.post('/system', {}) }.to raise_error('400 "Bad Request"')
  61. end
  62. it 'should respond to /remote_configs' do
  63. result = @client.get('/remote_configs')
  64. expect(result).to be_a(Array)
  65. expect(result).to include('rgb_cct')
  66. end
  67. end
  68. context 'sending raw packets' do
  69. it 'should support sending a raw packet' do
  70. id = {
  71. id: 0x2222,
  72. type: 'rgb_cct',
  73. group_id: 1
  74. }
  75. @client.delete_state(id)
  76. # Hard-coded packet which should turn the bulb on
  77. result = @client.post(
  78. '/raw_commands/rgb_cct',
  79. packet: '00 DB BF 01 66 D1 BB 66 F7',
  80. num_repeats: 1
  81. )
  82. expect(result['success']).to be_truthy
  83. sleep(1)
  84. state = @client.get_state(id)
  85. expect(state['status']).to eq('ON')
  86. end
  87. end
  88. context 'device aliases' do
  89. before(:all) do
  90. @device_id = {
  91. id: @client.generate_id,
  92. type: 'rgb_cct',
  93. group_id: 1
  94. }
  95. @alias = 'test'
  96. @client.patch_settings(
  97. group_id_aliases: {
  98. @alias => [
  99. @device_id[:type],
  100. @device_id[:id],
  101. @device_id[:group_id]
  102. ]
  103. }
  104. )
  105. @client.delete_state(@device_id)
  106. end
  107. it 'should respond with a 404 for an alias that doesn\'t exist' do
  108. expect {
  109. @client.put("/gateways/__#{@alias}", status: 'on')
  110. }.to raise_error(Net::HTTPServerException)
  111. end
  112. it 'should update state for known alias' do
  113. path = "/gateways/#{@alias}"
  114. @client.put(path, status: 'ON', hue: 100)
  115. state = @client.get(path)
  116. expect(state['status']).to eq('ON')
  117. expect(state['hue']).to eq(100)
  118. # ensure state for the non-aliased ID is the same
  119. state = @client.get_state(@device_id)
  120. expect(state['status']).to eq('ON')
  121. expect(state['hue']).to eq(100)
  122. end
  123. it 'should handle saving bad input gracefully' do
  124. values_to_try = [
  125. 'string',
  126. 123,
  127. [ ],
  128. { 'test' => [ 'rgb_cct' ] },
  129. { 'test' => [ 'rgb_cct', 1 ] },
  130. { 'test' => [ 'rgb_cct', '1', 2 ] },
  131. { 'test' => [ 'abc' ] }
  132. ]
  133. values_to_try.each do |v|
  134. expect {
  135. @client.patch_settings(group_id_aliases: v)
  136. }.to_not raise_error
  137. end
  138. end
  139. end
  140. end