actions_test.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. package server
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/require"
  5. )
  6. func TestParseActions(t *testing.T) {
  7. actions, err := parseActions("[]")
  8. require.Nil(t, err)
  9. require.Empty(t, actions)
  10. // Basic test
  11. actions, err = parseActions("action=http, label=Open door, url=https://door.lan/open; view, Show portal, https://door.lan")
  12. require.Nil(t, err)
  13. require.Equal(t, 2, len(actions))
  14. require.Equal(t, "http", actions[0].Action)
  15. require.Equal(t, "Open door", actions[0].Label)
  16. require.Equal(t, "https://door.lan/open", actions[0].URL)
  17. require.Equal(t, "view", actions[1].Action)
  18. require.Equal(t, "Show portal", actions[1].Label)
  19. require.Equal(t, "https://door.lan", actions[1].URL)
  20. // JSON
  21. actions, err = parseActions(`[{"action":"http","label":"Open door","url":"https://door.lan/open"}, {"action":"view","label":"Show portal","url":"https://door.lan"}]`)
  22. require.Nil(t, err)
  23. require.Equal(t, 2, len(actions))
  24. require.Equal(t, "http", actions[0].Action)
  25. require.Equal(t, "Open door", actions[0].Label)
  26. require.Equal(t, "https://door.lan/open", actions[0].URL)
  27. require.Equal(t, "view", actions[1].Action)
  28. require.Equal(t, "Show portal", actions[1].Label)
  29. require.Equal(t, "https://door.lan", actions[1].URL)
  30. // Other params
  31. actions, err = parseActions("action=http, label=Open door, url=https://door.lan/open, body=this is a body, method=PUT")
  32. require.Nil(t, err)
  33. require.Equal(t, 1, len(actions))
  34. require.Equal(t, "http", actions[0].Action)
  35. require.Equal(t, "Open door", actions[0].Label)
  36. require.Equal(t, "https://door.lan/open", actions[0].URL)
  37. require.Equal(t, "PUT", actions[0].Method)
  38. require.Equal(t, "this is a body", actions[0].Body)
  39. // Extras with underscores
  40. actions, err = parseActions("action=broadcast, label=Do a thing, extras.command=some command, extras.some_param=a parameter")
  41. require.Nil(t, err)
  42. require.Equal(t, 1, len(actions))
  43. require.Equal(t, "broadcast", actions[0].Action)
  44. require.Equal(t, "Do a thing", actions[0].Label)
  45. require.Equal(t, 2, len(actions[0].Extras))
  46. require.Equal(t, "some command", actions[0].Extras["command"])
  47. require.Equal(t, "a parameter", actions[0].Extras["some_param"])
  48. // Broadcast action with intent
  49. actions, err = parseActions("action=broadcast, label=Do a thing, intent=io.heckel.ntfy.TEST_INTENT")
  50. require.Nil(t, err)
  51. require.Equal(t, 1, len(actions))
  52. require.Equal(t, "broadcast", actions[0].Action)
  53. require.Equal(t, "Do a thing", actions[0].Label)
  54. require.Equal(t, "io.heckel.ntfy.TEST_INTENT", actions[0].Intent)
  55. // Headers with dashes
  56. actions, err = parseActions("action=http, label=Send request, url=http://example.com, method=GET, headers.Content-Type=application/json, headers.Authorization=Basic sdasffsf")
  57. require.Nil(t, err)
  58. require.Equal(t, 1, len(actions))
  59. require.Equal(t, "http", actions[0].Action)
  60. require.Equal(t, "Send request", actions[0].Label)
  61. require.Equal(t, 2, len(actions[0].Headers))
  62. require.Equal(t, "application/json", actions[0].Headers["Content-Type"])
  63. require.Equal(t, "Basic sdasffsf", actions[0].Headers["Authorization"])
  64. // Quotes
  65. actions, err = parseActions(`action=http, "Look ma, \"quotes\"; and semicolons", url=http://example.com`)
  66. require.Nil(t, err)
  67. require.Equal(t, 1, len(actions))
  68. require.Equal(t, "http", actions[0].Action)
  69. require.Equal(t, `Look ma, "quotes"; and semicolons`, actions[0].Label)
  70. require.Equal(t, `http://example.com`, actions[0].URL)
  71. // Single quotes
  72. actions, err = parseActions(`action=http, '"quotes" and \'single quotes\'', url=http://example.com`)
  73. require.Nil(t, err)
  74. require.Equal(t, 1, len(actions))
  75. require.Equal(t, "http", actions[0].Action)
  76. require.Equal(t, `"quotes" and 'single quotes'`, actions[0].Label)
  77. require.Equal(t, `http://example.com`, actions[0].URL)
  78. // Single quotes (JSON)
  79. actions, err = parseActions(`action=http, Post it, url=http://example.com, body='{"temperature": 65}'`)
  80. require.Nil(t, err)
  81. require.Equal(t, 1, len(actions))
  82. require.Equal(t, "http", actions[0].Action)
  83. require.Equal(t, "Post it", actions[0].Label)
  84. require.Equal(t, `http://example.com`, actions[0].URL)
  85. require.Equal(t, `{"temperature": 65}`, actions[0].Body)
  86. // Out of order
  87. actions, err = parseActions(`label="Out of order!" , action="http", url=http://example.com`)
  88. require.Nil(t, err)
  89. require.Equal(t, 1, len(actions))
  90. require.Equal(t, "http", actions[0].Action)
  91. require.Equal(t, `Out of order!`, actions[0].Label)
  92. require.Equal(t, `http://example.com`, actions[0].URL)
  93. // Spaces
  94. actions, err = parseActions(`action = http, label = 'this is a label', url = "http://google.com"`)
  95. require.Nil(t, err)
  96. require.Equal(t, 1, len(actions))
  97. require.Equal(t, "http", actions[0].Action)
  98. require.Equal(t, `this is a label`, actions[0].Label)
  99. require.Equal(t, `http://google.com`, actions[0].URL)
  100. // Non-ASCII
  101. actions, err = parseActions(`action = http, 'Кохайтеся а не воюйте, 💙🫤', url = "http://google.com"`)
  102. require.Nil(t, err)
  103. require.Equal(t, 1, len(actions))
  104. require.Equal(t, "http", actions[0].Action)
  105. require.Equal(t, `Кохайтеся а не воюйте, 💙🫤`, actions[0].Label)
  106. require.Equal(t, `http://google.com`, actions[0].URL)
  107. // Multiple actions, awkward spacing
  108. actions, err = parseActions(`http , 'Make love, not war 💙🫤' , https://ntfy.sh ; view, " yo ", https://x.org, clear=true`)
  109. require.Nil(t, err)
  110. require.Equal(t, 2, len(actions))
  111. require.Equal(t, "http", actions[0].Action)
  112. require.Equal(t, `Make love, not war 💙🫤`, actions[0].Label)
  113. require.Equal(t, `https://ntfy.sh`, actions[0].URL)
  114. require.Equal(t, false, actions[0].Clear)
  115. require.Equal(t, "view", actions[1].Action)
  116. require.Equal(t, " yo ", actions[1].Label)
  117. require.Equal(t, `https://x.org`, actions[1].URL)
  118. require.Equal(t, true, actions[1].Clear)
  119. // Copy action (simple format)
  120. actions, err = parseActions("copy, Copy code, 1234")
  121. require.Nil(t, err)
  122. require.Equal(t, 1, len(actions))
  123. require.Equal(t, "copy", actions[0].Action)
  124. require.Equal(t, "Copy code", actions[0].Label)
  125. require.Equal(t, "1234", actions[0].Value)
  126. // Copy action (JSON)
  127. actions, err = parseActions(`[{"action":"copy","label":"Copy OTP","value":"567890"}]`)
  128. require.Nil(t, err)
  129. require.Equal(t, 1, len(actions))
  130. require.Equal(t, "copy", actions[0].Action)
  131. require.Equal(t, "Copy OTP", actions[0].Label)
  132. require.Equal(t, "567890", actions[0].Value)
  133. // Copy action with clear
  134. actions, err = parseActions("copy, Copy code, 1234, clear=true")
  135. require.Nil(t, err)
  136. require.Equal(t, 1, len(actions))
  137. require.Equal(t, "copy", actions[0].Action)
  138. require.Equal(t, "Copy code", actions[0].Label)
  139. require.Equal(t, "1234", actions[0].Value)
  140. require.Equal(t, true, actions[0].Clear)
  141. // Copy action with explicit value key
  142. actions, err = parseActions("action=copy, label=Copy token, clear=true, value=abc-123-def")
  143. require.Nil(t, err)
  144. require.Equal(t, 1, len(actions))
  145. require.Equal(t, "copy", actions[0].Action)
  146. require.Equal(t, "Copy token", actions[0].Label)
  147. require.Equal(t, "abc-123-def", actions[0].Value)
  148. require.True(t, actions[0].Clear)
  149. // Copy action without value (error)
  150. _, err = parseActions("copy, Copy code")
  151. require.EqualError(t, err, "parameter 'value' is required for action 'copy'")
  152. // Invalid syntax
  153. _, err = parseActions(`label="Out of order!" x, action="http", url=http://example.com`)
  154. require.EqualError(t, err, "unexpected character 'x' at position 22")
  155. _, err = parseActions(`label="", action="http", url=http://example.com`)
  156. require.EqualError(t, err, "parameter 'label' is required")
  157. _, err = parseActions(`label=, action="http", url=http://example.com`)
  158. require.EqualError(t, err, "parameter 'label' is required")
  159. _, err = parseActions(`label="xx", action="http", url=http://example.com, what is this anyway`)
  160. require.EqualError(t, err, "term 'what is this anyway' unknown")
  161. _, err = parseActions(`fdsfdsf`)
  162. require.EqualError(t, err, "parameter 'action' cannot be 'fdsfdsf', valid values are 'view', 'broadcast', 'http' and 'copy'")
  163. _, err = parseActions(`aaa=a, "bbb, 'ccc, ddd, eee "`)
  164. require.EqualError(t, err, "key 'aaa' unknown")
  165. _, err = parseActions(`action=http, label="omg the end quote is missing`)
  166. require.EqualError(t, err, "unexpected end of input, quote started at position 20")
  167. _, err = parseActions(`;;;;`)
  168. require.EqualError(t, err, "only 3 actions allowed")
  169. _, err = parseActions(`,,,,,,;;`)
  170. require.EqualError(t, err, "term '' unknown")
  171. _, err = parseActions(`''";,;"`)
  172. require.EqualError(t, err, "unexpected character '\"' at position 2")
  173. _, err = parseActions(`action=http, label=a label, body=somebody`)
  174. require.EqualError(t, err, "parameter 'url' is required for action 'http'")
  175. _, err = parseActions(`action=http, label=a label, url=http://ntfy.sh, method=HEAD, body=somebody`)
  176. require.EqualError(t, err, "parameter 'body' cannot be set if method is HEAD")
  177. _, err = parseActions(`[ invalid json ]`)
  178. require.EqualError(t, err, "JSON error: invalid character 'i' looking for beginning of value")
  179. _, err = parseActions(`[ { "some": "object" } ]`)
  180. require.EqualError(t, err, "parameter 'action' cannot be '', valid values are 'view', 'broadcast', 'http' and 'copy'")
  181. _, err = parseActions("\x00\x01\xFFx\xFE")
  182. require.EqualError(t, err, "invalid utf-8 string")
  183. _, err = parseActions(`http, label, http://x.org, clear=x`)
  184. require.EqualError(t, err, "parameter 'clear' cannot be 'x', only boolean values are allowed (true/yes/1/false/no/0)")
  185. }