Core functionality for new aiterp.net servers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
7.9 KiB

7 years ago
  1. package wrouter
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "net/http/httptest"
  6. "net/url"
  7. "strings"
  8. "testing"
  9. "git.aiterp.net/gisle/wrouter/generate"
  10. "git.aiterp.net/gisle/wrouter/response"
  11. "git.aiterp.net/gisle/wrouter/auth"
  12. )
  13. var pages = []Page{
  14. Page{generate.ID(), "Test Page", "Blurg blurg"},
  15. Page{generate.ID(), "Test Page 2", "Blurg blurg 2"},
  16. Page{generate.ID(), "Stuff", "And things"},
  17. }
  18. type Page struct {
  19. ID string `json:"id"`
  20. Title string `json:"title"`
  21. Text string `json:"text"`
  22. }
  23. type Header struct {
  24. ID string `json:"id"`
  25. Title string `json:"title"`
  26. }
  27. type PageForm struct {
  28. Title string `json:"title"`
  29. Text string `json:"text"`
  30. }
  31. func listPage(w http.ResponseWriter, req *http.Request, user *auth.User) {
  32. headers := make([]Header, len(pages))
  33. for i, page := range pages {
  34. headers[i] = Header{page.ID, page.Title}
  35. }
  36. response.JSON(w, 200, headers)
  37. }
  38. func createPage(w http.ResponseWriter, req *http.Request, user *auth.User) {
  39. title := req.Form.Get("title")
  40. text := req.Form.Get("text")
  41. if title == "" {
  42. response.Text(w, 400, "No title")
  43. return
  44. }
  45. for _, page := range pages {
  46. if page.Title == title {
  47. response.Text(w, 400, "Title already exists")
  48. return
  49. }
  50. }
  51. page := Page{generate.ID(), title, text}
  52. pages = append(pages, page)
  53. response.JSON(w, 200, page)
  54. }
  55. func getPage(w http.ResponseWriter, req *http.Request, id string, user *auth.User) {
  56. for _, page := range pages {
  57. if page.ID == id {
  58. response.JSON(w, 200, page)
  59. return
  60. }
  61. }
  62. response.Text(w, 404, "Page not found")
  63. }
  64. func updatePage(w http.ResponseWriter, req *http.Request, id string, user *auth.User) {
  65. for _, page := range pages {
  66. if page.ID == id {
  67. title := req.Form.Get("title")
  68. text := req.Form.Get("text")
  69. if title != "" {
  70. page.Title = title
  71. }
  72. page.Text = text
  73. response.JSON(w, 200, page)
  74. return
  75. }
  76. }
  77. response.Text(w, 404, "Page not found")
  78. }
  79. func deletePage(w http.ResponseWriter, req *http.Request, id string, user *auth.User) {
  80. for i, page := range pages {
  81. if page.ID == id {
  82. pages = append(pages[:i], pages[i+1:]...)
  83. response.Empty(w)
  84. return
  85. }
  86. }
  87. response.Text(w, 404, "Page not found")
  88. }
  89. var resource = Resource{listPage, createPage, getPage, updatePage, deletePage}
  90. type handlerStruct struct{}
  91. func (hs *handlerStruct) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  92. req.ParseForm() // Router does this in non-tests
  93. if strings.HasPrefix(req.URL.Path, "/page") {
  94. resource.Handle("/page", w, req, nil)
  95. return
  96. }
  97. }
  98. func runForm(method, url string, data url.Values) (*http.Response, error) {
  99. body := strings.NewReader(data.Encode())
  100. req, err := http.NewRequest(method, url, body)
  101. if err != nil {
  102. return nil, err
  103. }
  104. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  105. return http.DefaultClient.Do(req)
  106. }
  107. func TestResource(t *testing.T) {
  108. server := httptest.NewServer(&handlerStruct{})
  109. t.Run("List", func(t *testing.T) {
  110. resp, err := http.Get(server.URL + "/page/")
  111. if err != nil {
  112. t.Error(err)
  113. t.Fail()
  114. }
  115. if resp.StatusCode != 200 {
  116. t.Error("Expected status 200, got", resp.StatusCode, resp.Status)
  117. t.Fail()
  118. }
  119. headers := []Header{}
  120. err = json.NewDecoder(resp.Body).Decode(&headers)
  121. if err != nil {
  122. t.Error(err)
  123. t.Fail()
  124. }
  125. if len(headers) < 3 {
  126. t.Error("Expected 3 headers, got", len(headers))
  127. t.Fail()
  128. }
  129. for i, header := range headers {
  130. page := pages[i]
  131. if header.ID != page.ID {
  132. t.Error(header.ID, "!=", page.ID)
  133. t.Fail()
  134. }
  135. if header.Title != page.Title {
  136. t.Error(header.Title, "!=", page.Title)
  137. t.Fail()
  138. }
  139. }
  140. })
  141. t.Run("Get", func(t *testing.T) {
  142. page := pages[1]
  143. resp, err := http.Get(server.URL + "/page/" + page.ID)
  144. if err != nil {
  145. t.Error(err)
  146. t.Fail()
  147. }
  148. if resp.StatusCode != 200 {
  149. t.Error("Expected status 200, got", resp.StatusCode, resp.Status)
  150. t.Fail()
  151. }
  152. respPage := Page{}
  153. err = json.NewDecoder(resp.Body).Decode(&respPage)
  154. if err != nil {
  155. t.Error(err)
  156. t.Fail()
  157. }
  158. if respPage.ID == "" {
  159. t.Error("No ID in response page")
  160. t.Fail()
  161. }
  162. if respPage.ID != page.ID {
  163. t.Errorf("ID %s != %s", respPage.ID, page.ID)
  164. t.Fail()
  165. }
  166. if respPage.Title != page.Title {
  167. t.Errorf("Title %s != %s", respPage.Title, page.Title)
  168. t.Fail()
  169. }
  170. if respPage.Text != page.Text {
  171. t.Errorf("Text %s != %s", respPage.Text, page.Text)
  172. t.Fail()
  173. }
  174. })
  175. t.Run("Get_Fail", func(t *testing.T) {
  176. resp, err := http.Get(server.URL + "/page/" + generate.ID())
  177. if err != nil {
  178. t.Error(err)
  179. t.Fail()
  180. }
  181. if resp.StatusCode != 404 {
  182. t.Error("Expected status 404, got", resp.StatusCode, resp.Status)
  183. t.Fail()
  184. }
  185. respPage := Page{}
  186. err = json.NewDecoder(resp.Body).Decode(&respPage)
  187. if err == nil {
  188. t.Error("Expected encoder error, got:", respPage)
  189. t.Fail()
  190. }
  191. if respPage.ID != "" {
  192. t.Error("Ad ID in response page", respPage.ID)
  193. t.Fail()
  194. }
  195. })
  196. t.Run("Create", func(t *testing.T) {
  197. form := url.Values{}
  198. form.Set("title", "Hello World")
  199. form.Set("text", "Sei Gegrüßt, Erde")
  200. resp, err := http.PostForm(server.URL+"/page/", form)
  201. if err != nil {
  202. t.Error(err)
  203. t.Fail()
  204. }
  205. if resp.StatusCode != 200 {
  206. t.Error("Expected status 200, got", resp.StatusCode, resp.Status)
  207. t.Fail()
  208. }
  209. respPage := Page{}
  210. err = json.NewDecoder(resp.Body).Decode(&respPage)
  211. if err != nil {
  212. t.Error(err)
  213. t.Fail()
  214. }
  215. if respPage.ID == "" {
  216. t.Error("No ID in response page")
  217. t.Fail()
  218. }
  219. if respPage.Title != form.Get("title") {
  220. t.Errorf("Title %s != %s", respPage.Title, form.Get("title"))
  221. t.Fail()
  222. }
  223. if respPage.Text != form.Get("text") {
  224. t.Errorf("Text %s != %s", respPage.Text, form.Get("text"))
  225. t.Fail()
  226. }
  227. if len(pages) != 4 {
  228. t.Errorf("Page was not added")
  229. t.Fail()
  230. }
  231. })
  232. t.Run("Update", func(t *testing.T) {
  233. page := pages[0]
  234. form := url.Values{}
  235. form.Set("text", "Edits and stuff")
  236. resp, err := runForm("PUT", server.URL+"/page/"+page.ID, form)
  237. if err != nil {
  238. t.Error("Request:", err)
  239. t.Fail()
  240. }
  241. if resp.StatusCode != 200 {
  242. t.Error("Expected status 200, got", resp.StatusCode, resp.Status)
  243. t.Fail()
  244. }
  245. respPage := Page{}
  246. err = json.NewDecoder(resp.Body).Decode(&respPage)
  247. if err != nil {
  248. t.Error("Decode:", err)
  249. t.Fail()
  250. }
  251. if respPage.ID == "" {
  252. t.Error("No ID in response page")
  253. t.Fail()
  254. }
  255. if respPage.Title != page.Title {
  256. t.Errorf("Title %s != %s", respPage.Title, form.Get("title"))
  257. t.Fail()
  258. }
  259. if respPage.Text != form.Get("text") {
  260. t.Errorf("Text %s != %s", respPage.Text, form.Get("text"))
  261. t.Fail()
  262. }
  263. })
  264. t.Run("Update_Fail", func(t *testing.T) {
  265. form := url.Values{}
  266. form.Set("text", "Edits and stuff")
  267. resp, err := runForm("PUT", server.URL+"/page/NONEXISTENT-ID-GOES-HERE", form)
  268. if err != nil {
  269. t.Error("Request:", err)
  270. t.Fail()
  271. }
  272. if resp.StatusCode != 404 {
  273. t.Error("Expected status 404, got", resp.StatusCode, resp.Status)
  274. t.Fail()
  275. }
  276. respPage := Page{}
  277. err = json.NewDecoder(resp.Body).Decode(&respPage)
  278. if err == nil {
  279. t.Error("A page was returned:", respPage)
  280. t.Fail()
  281. }
  282. if respPage.ID != "" {
  283. t.Error("ID in response page", respPage.ID)
  284. t.Fail()
  285. }
  286. })
  287. t.Run("Delete", func(t *testing.T) {
  288. page := pages[3]
  289. resp, err := runForm("DELETE", server.URL+"/page/"+page.ID, url.Values{})
  290. if err != nil {
  291. t.Error("Request:", err)
  292. t.Fail()
  293. }
  294. if resp.StatusCode != 204 {
  295. t.Error("Expected status 204, got", resp.Status)
  296. t.Fail()
  297. }
  298. if len(pages) != 3 {
  299. t.Error("Page was not deleted")
  300. t.Fail()
  301. }
  302. })
  303. t.Run("Delete_Fail", func(t *testing.T) {
  304. resp, err := runForm("DELETE", server.URL+"/page/NONEXISTENT-ID-GOES-HERE", url.Values{})
  305. if err != nil {
  306. t.Error("Request:", err)
  307. t.Fail()
  308. }
  309. if resp.StatusCode != 404 {
  310. t.Error("Expected status 404, got", resp.Status)
  311. t.Fail()
  312. }
  313. if len(pages) != 3 {
  314. t.Error("A page was deleted despite the non-existent ID")
  315. t.Fail()
  316. }
  317. })
  318. }