test_helpers.rb (5123B)
1 # frozen_string_literal: true 2 3 require 'fileutils' 4 require 'json' 5 require 'stringio' 6 require 'tmpdir' 7 require 'yaml' 8 9 module TestHelpers 10 TEST_BRIDGE_UUID = 'bc6be180-4c57-0130-8d8f-0018de9ecdd0' 11 TEST_BRIDGE_URI = 'http://localhost/api' 12 TEST_APPLICATION_UUID = 'application_uuid' 13 14 TEST_UDP_BRIDGE_UUID = 'aa0be180-4c57-0130-8d8f-0018de9ecdd0' 15 TEST_UDP_BRIDGE_IP = '10.0.0.42' 16 TEST_UDP_BRIDGE_URI = "http://#{TEST_UDP_BRIDGE_IP}/api".freeze 17 18 FIXTURE_DIR = File.expand_path('config', __dir__) 19 JSON_FIXTURE_DIR = File.expand_path('json', __dir__) 20 EMPTY_CONFIG_FILE = File.join(FIXTURE_DIR, 'empty.yml') 21 22 TEST_TMP_DIR = File.join(Dir.tmpdir, 'hue-spec') 23 TEST_CONFIG_APPLICATION_PATH = File.join(TEST_TMP_DIR, 'applications.yml') 24 TEST_CONFIG_BRIDGE_PATH = File.join(TEST_TMP_DIR, 'bridges.yml') 25 26 TEST_CONFIG_APPLICATION = YAML.load_file(File.join(FIXTURE_DIR, 'applications.yml')) 27 TEST_CONFIG_BRIDGE = YAML.load_file(File.join(FIXTURE_DIR, 'bridges.yml')) 28 29 def mock_application_config_path 30 FileUtils.mkdir_p(TEST_TMP_DIR) 31 create_test_application_config 32 allow(Hue::Config::Application).to receive(:file_path).and_return(TEST_CONFIG_APPLICATION_PATH) 33 end 34 35 def mock_bridge_config_path 36 FileUtils.mkdir_p(TEST_TMP_DIR) 37 create_test_bridge_config 38 allow(Hue::Config::Bridge).to receive(:file_path).and_return(TEST_CONFIG_BRIDGE_PATH) 39 end 40 41 def create_test_application_config 42 FileUtils.mkdir_p(TEST_TMP_DIR) 43 File.write(TEST_CONFIG_APPLICATION_PATH, YAML.dump(TEST_CONFIG_APPLICATION)) 44 end 45 46 def create_test_bridge_config 47 FileUtils.mkdir_p(TEST_TMP_DIR) 48 File.write(TEST_CONFIG_BRIDGE_PATH, YAML.dump(TEST_CONFIG_BRIDGE)) 49 end 50 51 def mock_udp_replies(uuid = TEST_UDP_BRIDGE_UUID, ip = TEST_UDP_BRIDGE_IP) 52 fake_socket = instance_double(UDPSocket, send: 0) 53 payload = "HTTP/1.1 200 OK\r\nLOCATION: http://#{ip}/description.xml\r\n" \ 54 "ST: urn:schemas-upnp-org:device:Basic:1\r\nUSN: uuid:#{uuid}::IpBridge\r\n\r\n" 55 delivered = false 56 allow(fake_socket).to receive(:recvfrom) do 57 raise Hue::Error, 'simulated timeout' if delivered 58 59 delivered = true 60 [payload, [nil, 1900, 'fake.local', ip]] 61 end 62 allow(UDPSocket).to receive(:new).and_return(fake_socket) 63 end 64 65 def mock_udp_no_reply 66 fake_socket = instance_double(UDPSocket, send: 0) 67 allow(fake_socket).to receive(:recvfrom) { raise Hue::Error, 'simulated timeout' } 68 allow(UDPSocket).to receive(:new).and_return(fake_socket) 69 end 70 71 def mock_nupnp_empty_reply 72 stub_request(:get, 'https://www.meethue.com/api/nupnp').to_return(body: '[]', status: 200) 73 end 74 75 def mock_socket_hostname 76 allow(Socket).to receive(:gethostname).and_return('hostname') 77 end 78 79 def with_fake_request(path = nil, kind = :get_success) 80 fixture = kind == :get_success ? (path || :get_success) : kind 81 stub_request(:get, bridge_request_url(TEST_BRIDGE_URI, path)) 82 .to_return(body: read_json_fixture(fixture), status: 200, 83 headers: { 'Content-Type' => 'application/json' }) 84 end 85 86 def with_fake_post(path = nil, body = nil, fixture = 'post_success', host = TEST_BRIDGE_URI) 87 stub = stub_request(:post, raw_request_url(host, path)) 88 stub = stub.with(body: body) if body 89 stub.to_return(body: read_json_fixture(fixture), status: 200, 90 headers: { 'Content-Type' => 'application/json' }) 91 end 92 93 def with_fake_delete(path = nil, fixture = 'put_success') 94 stub_request(:delete, bridge_request_url(TEST_BRIDGE_URI, path)) 95 .to_return(body: read_json_fixture(fixture), status: 200, 96 headers: { 'Content-Type' => 'application/json' }) 97 end 98 99 def with_fake_update(path = nil, body = nil, fixture = 'put_success') 100 stub = stub_request(:put, bridge_request_url(TEST_BRIDGE_URI, path)) 101 stub = stub.with(body: body) if body 102 stub.to_return(body: read_json_fixture(fixture), status: 200, 103 headers: { 'Content-Type' => 'application/json' }) 104 end 105 106 def api_reply(name) 107 JSON.parse(read_json_fixture(name)) 108 end 109 110 def with_temp_config_path(with_default = false) 111 File.write(TEST_CONFIG_APPLICATION_PATH, YAML.dump(with_default ? TEST_CONFIG_APPLICATION : {})) 112 yield 113 ensure 114 create_test_application_config 115 end 116 117 def with_stdout(matcher = nil) 118 original = $stdout 119 $stdout = StringIO.new 120 yield 121 output = $stdout.string 122 expect(output).to match(matcher) if matcher 123 output 124 ensure 125 $stdout = original 126 end 127 128 def test_bridge 129 Hue::Bridge.new(TEST_APPLICATION_UUID, TEST_BRIDGE_URI) 130 end 131 132 private 133 134 def read_json_fixture(name) 135 File.read(File.join(JSON_FIXTURE_DIR, "#{name}.json")) 136 end 137 138 def bridge_request_url(host, path) 139 base = host.sub(%r{/$}, '') 140 segments = [base] 141 segments << TEST_APPLICATION_UUID unless path.to_s.start_with?(TEST_APPLICATION_UUID) 142 segments << path.to_s if path && !path.to_s.empty? 143 segments.reject { |s| s.to_s.empty? }.join('/') 144 end 145 146 def raw_request_url(host, path) 147 base = host.sub(%r{/$}, '') 148 path && !path.to_s.empty? ? "#{base}/#{path}" : base 149 end 150 end