PageRenderTime 35ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/components/test_alexa.py

https://gitlab.com/mkerfoot/home-assistant
Python | 323 lines | 302 code | 12 blank | 9 comment | 1 complexity | c7d0da5e1705f717b6a8e2485eb15fd6 MD5 | raw file
  1. """
  2. tests.components.test_alexa
  3. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. Tests Home Assistant Alexa component does what it should do.
  5. """
  6. # pylint: disable=protected-access,too-many-public-methods
  7. import unittest
  8. import json
  9. import requests
  10. from homeassistant import bootstrap, const
  11. from homeassistant.components import alexa, http
  12. from tests.common import get_test_instance_port, get_test_home_assistant
  13. API_PASSWORD = "test1234"
  14. SERVER_PORT = get_test_instance_port()
  15. API_URL = "http://127.0.0.1:{}{}".format(SERVER_PORT, alexa.API_ENDPOINT)
  16. HA_HEADERS = {const.HTTP_HEADER_HA_AUTH: API_PASSWORD}
  17. SESSION_ID = 'amzn1.echo-api.session.0000000-0000-0000-0000-00000000000'
  18. APPLICATION_ID = 'amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe'
  19. REQUEST_ID = 'amzn1.echo-api.request.0000000-0000-0000-0000-00000000000'
  20. hass = None
  21. calls = []
  22. def setUpModule(): # pylint: disable=invalid-name
  23. """ Initalize a Home Assistant server for testing this module. """
  24. global hass
  25. hass = get_test_home_assistant()
  26. bootstrap.setup_component(
  27. hass, http.DOMAIN,
  28. {http.DOMAIN: {http.CONF_API_PASSWORD: API_PASSWORD,
  29. http.CONF_SERVER_PORT: SERVER_PORT}})
  30. hass.services.register('test', 'alexa', lambda call: calls.append(call))
  31. bootstrap.setup_component(hass, alexa.DOMAIN, {
  32. 'alexa': {
  33. 'intents': {
  34. 'WhereAreWeIntent': {
  35. 'speech': {
  36. 'type': 'plaintext',
  37. 'text':
  38. """
  39. {%- if is_state('device_tracker.paulus', 'home')
  40. and is_state('device_tracker.anne_therese',
  41. 'home') -%}
  42. You are both home, you silly
  43. {%- else -%}
  44. Anne Therese is at {{
  45. states("device_tracker.anne_therese")
  46. }} and Paulus is at {{
  47. states("device_tracker.paulus")
  48. }}
  49. {% endif %}
  50. """,
  51. }
  52. },
  53. 'GetZodiacHoroscopeIntent': {
  54. 'speech': {
  55. 'type': 'plaintext',
  56. 'text': 'You told us your sign is {{ ZodiacSign }}.',
  57. }
  58. },
  59. 'CallServiceIntent': {
  60. 'speech': {
  61. 'type': 'plaintext',
  62. 'text': 'Service called',
  63. },
  64. 'action': {
  65. 'service': 'test.alexa',
  66. 'data': {
  67. 'hello': 1
  68. },
  69. 'entity_id': 'switch.test',
  70. }
  71. }
  72. }
  73. }
  74. })
  75. hass.start()
  76. def tearDownModule(): # pylint: disable=invalid-name
  77. """ Stops the Home Assistant server. """
  78. hass.stop()
  79. def _req(data={}):
  80. return requests.post(API_URL, data=json.dumps(data), timeout=5,
  81. headers=HA_HEADERS)
  82. class TestAlexa(unittest.TestCase):
  83. """ Test Alexa. """
  84. def tearDown(self):
  85. hass.pool.block_till_done()
  86. def test_launch_request(self):
  87. data = {
  88. 'version': '1.0',
  89. 'session': {
  90. 'new': True,
  91. 'sessionId': SESSION_ID,
  92. 'application': {
  93. 'applicationId': APPLICATION_ID
  94. },
  95. 'attributes': {},
  96. 'user': {
  97. 'userId': 'amzn1.account.AM3B00000000000000000000000'
  98. }
  99. },
  100. 'request': {
  101. 'type': 'LaunchRequest',
  102. 'requestId': REQUEST_ID,
  103. 'timestamp': '2015-05-13T12:34:56Z'
  104. }
  105. }
  106. req = _req(data)
  107. self.assertEqual(200, req.status_code)
  108. resp = req.json()
  109. self.assertIn('outputSpeech', resp['response'])
  110. def test_intent_request_with_slots(self):
  111. data = {
  112. 'version': '1.0',
  113. 'session': {
  114. 'new': False,
  115. 'sessionId': SESSION_ID,
  116. 'application': {
  117. 'applicationId': APPLICATION_ID
  118. },
  119. 'attributes': {
  120. 'supportedHoroscopePeriods': {
  121. 'daily': True,
  122. 'weekly': False,
  123. 'monthly': False
  124. }
  125. },
  126. 'user': {
  127. 'userId': 'amzn1.account.AM3B00000000000000000000000'
  128. }
  129. },
  130. 'request': {
  131. 'type': 'IntentRequest',
  132. 'requestId': REQUEST_ID,
  133. 'timestamp': '2015-05-13T12:34:56Z',
  134. 'intent': {
  135. 'name': 'GetZodiacHoroscopeIntent',
  136. 'slots': {
  137. 'ZodiacSign': {
  138. 'name': 'ZodiacSign',
  139. 'value': 'virgo'
  140. }
  141. }
  142. }
  143. }
  144. }
  145. req = _req(data)
  146. self.assertEqual(200, req.status_code)
  147. text = req.json().get('response', {}).get('outputSpeech',
  148. {}).get('text')
  149. self.assertEqual('You told us your sign is virgo.', text)
  150. def test_intent_request_with_slots_but_no_value(self):
  151. data = {
  152. 'version': '1.0',
  153. 'session': {
  154. 'new': False,
  155. 'sessionId': SESSION_ID,
  156. 'application': {
  157. 'applicationId': APPLICATION_ID
  158. },
  159. 'attributes': {
  160. 'supportedHoroscopePeriods': {
  161. 'daily': True,
  162. 'weekly': False,
  163. 'monthly': False
  164. }
  165. },
  166. 'user': {
  167. 'userId': 'amzn1.account.AM3B00000000000000000000000'
  168. }
  169. },
  170. 'request': {
  171. 'type': 'IntentRequest',
  172. 'requestId': REQUEST_ID,
  173. 'timestamp': '2015-05-13T12:34:56Z',
  174. 'intent': {
  175. 'name': 'GetZodiacHoroscopeIntent',
  176. 'slots': {
  177. 'ZodiacSign': {
  178. 'name': 'ZodiacSign',
  179. }
  180. }
  181. }
  182. }
  183. }
  184. req = _req(data)
  185. self.assertEqual(200, req.status_code)
  186. text = req.json().get('response', {}).get('outputSpeech',
  187. {}).get('text')
  188. self.assertEqual('You told us your sign is .', text)
  189. def test_intent_request_without_slots(self):
  190. data = {
  191. 'version': '1.0',
  192. 'session': {
  193. 'new': False,
  194. 'sessionId': SESSION_ID,
  195. 'application': {
  196. 'applicationId': APPLICATION_ID
  197. },
  198. 'attributes': {
  199. 'supportedHoroscopePeriods': {
  200. 'daily': True,
  201. 'weekly': False,
  202. 'monthly': False
  203. }
  204. },
  205. 'user': {
  206. 'userId': 'amzn1.account.AM3B00000000000000000000000'
  207. }
  208. },
  209. 'request': {
  210. 'type': 'IntentRequest',
  211. 'requestId': REQUEST_ID,
  212. 'timestamp': '2015-05-13T12:34:56Z',
  213. 'intent': {
  214. 'name': 'WhereAreWeIntent',
  215. }
  216. }
  217. }
  218. req = _req(data)
  219. self.assertEqual(200, req.status_code)
  220. text = req.json().get('response', {}).get('outputSpeech',
  221. {}).get('text')
  222. self.assertEqual('Anne Therese is at unknown and Paulus is at unknown',
  223. text)
  224. hass.states.set('device_tracker.paulus', 'home')
  225. hass.states.set('device_tracker.anne_therese', 'home')
  226. req = _req(data)
  227. self.assertEqual(200, req.status_code)
  228. text = req.json().get('response', {}).get('outputSpeech',
  229. {}).get('text')
  230. self.assertEqual('You are both home, you silly', text)
  231. def test_intent_request_calling_service(self):
  232. data = {
  233. 'version': '1.0',
  234. 'session': {
  235. 'new': False,
  236. 'sessionId': SESSION_ID,
  237. 'application': {
  238. 'applicationId': APPLICATION_ID
  239. },
  240. 'attributes': {},
  241. 'user': {
  242. 'userId': 'amzn1.account.AM3B00000000000000000000000'
  243. }
  244. },
  245. 'request': {
  246. 'type': 'IntentRequest',
  247. 'requestId': REQUEST_ID,
  248. 'timestamp': '2015-05-13T12:34:56Z',
  249. 'intent': {
  250. 'name': 'CallServiceIntent',
  251. }
  252. }
  253. }
  254. call_count = len(calls)
  255. req = _req(data)
  256. self.assertEqual(200, req.status_code)
  257. self.assertEqual(call_count + 1, len(calls))
  258. call = calls[-1]
  259. self.assertEqual('test', call.domain)
  260. self.assertEqual('alexa', call.service)
  261. self.assertEqual(['switch.test'], call.data.get('entity_id'))
  262. self.assertEqual(1, call.data.get('hello'))
  263. def test_session_ended_request(self):
  264. data = {
  265. 'version': '1.0',
  266. 'session': {
  267. 'new': False,
  268. 'sessionId': SESSION_ID,
  269. 'application': {
  270. 'applicationId': APPLICATION_ID
  271. },
  272. 'attributes': {
  273. 'supportedHoroscopePeriods': {
  274. 'daily': True,
  275. 'weekly': False,
  276. 'monthly': False
  277. }
  278. },
  279. 'user': {
  280. 'userId': 'amzn1.account.AM3B00000000000000000000000'
  281. }
  282. },
  283. 'request': {
  284. 'type': 'SessionEndedRequest',
  285. 'requestId': REQUEST_ID,
  286. 'timestamp': '2015-05-13T12:34:56Z',
  287. 'reason': 'USER_INITIATED'
  288. }
  289. }
  290. req = _req(data)
  291. self.assertEqual(200, req.status_code)
  292. self.assertEqual('', req.text)