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

package wrouter
import (
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"git.aiterp.net/gisle/wrouter/generate"
"git.aiterp.net/gisle/wrouter/response"
"git.aiterp.net/gisle/wrouter/auth"
)
var pages = []Page{
Page{generate.ID(), "Test Page", "Blurg blurg"},
Page{generate.ID(), "Test Page 2", "Blurg blurg 2"},
Page{generate.ID(), "Stuff", "And things"},
}
type Page struct {
ID string `json:"id"`
Title string `json:"title"`
Text string `json:"text"`
}
type Header struct {
ID string `json:"id"`
Title string `json:"title"`
}
type PageForm struct {
Title string `json:"title"`
Text string `json:"text"`
}
func listPage(w http.ResponseWriter, req *http.Request, user *auth.User) {
headers := make([]Header, len(pages))
for i, page := range pages {
headers[i] = Header{page.ID, page.Title}
}
response.JSON(w, 200, headers)
}
func createPage(w http.ResponseWriter, req *http.Request, user *auth.User) {
title := req.Form.Get("title")
text := req.Form.Get("text")
if title == "" {
response.Text(w, 400, "No title")
return
}
for _, page := range pages {
if page.Title == title {
response.Text(w, 400, "Title already exists")
return
}
}
page := Page{generate.ID(), title, text}
pages = append(pages, page)
response.JSON(w, 200, page)
}
func getPage(w http.ResponseWriter, req *http.Request, id string, user *auth.User) {
for _, page := range pages {
if page.ID == id {
response.JSON(w, 200, page)
return
}
}
response.Text(w, 404, "Page not found")
}
func updatePage(w http.ResponseWriter, req *http.Request, id string, user *auth.User) {
for _, page := range pages {
if page.ID == id {
title := req.Form.Get("title")
text := req.Form.Get("text")
if title != "" {
page.Title = title
}
page.Text = text
response.JSON(w, 200, page)
return
}
}
response.Text(w, 404, "Page not found")
}
func deletePage(w http.ResponseWriter, req *http.Request, id string, user *auth.User) {
for i, page := range pages {
if page.ID == id {
pages = append(pages[:i], pages[i+1:]...)
response.Empty(w)
return
}
}
response.Text(w, 404, "Page not found")
}
var resource = Resource{listPage, createPage, getPage, updatePage, deletePage}
type handlerStruct struct{}
func (hs *handlerStruct) ServeHTTP(w http.ResponseWriter, req *http.Request) {
req.ParseForm() // Router does this in non-tests
if strings.HasPrefix(req.URL.Path, "/page") {
resource.Handle("/page", w, req, nil)
return
}
}
func runForm(method, url string, data url.Values) (*http.Response, error) {
body := strings.NewReader(data.Encode())
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
return http.DefaultClient.Do(req)
}
func TestResource(t *testing.T) {
server := httptest.NewServer(&handlerStruct{})
t.Run("List", func(t *testing.T) {
resp, err := http.Get(server.URL + "/page/")
if err != nil {
t.Error(err)
t.Fail()
}
if resp.StatusCode != 200 {
t.Error("Expected status 200, got", resp.StatusCode, resp.Status)
t.Fail()
}
headers := []Header{}
err = json.NewDecoder(resp.Body).Decode(&headers)
if err != nil {
t.Error(err)
t.Fail()
}
if len(headers) < 3 {
t.Error("Expected 3 headers, got", len(headers))
t.Fail()
}
for i, header := range headers {
page := pages[i]
if header.ID != page.ID {
t.Error(header.ID, "!=", page.ID)
t.Fail()
}
if header.Title != page.Title {
t.Error(header.Title, "!=", page.Title)
t.Fail()
}
}
})
t.Run("Get", func(t *testing.T) {
page := pages[1]
resp, err := http.Get(server.URL + "/page/" + page.ID)
if err != nil {
t.Error(err)
t.Fail()
}
if resp.StatusCode != 200 {
t.Error("Expected status 200, got", resp.StatusCode, resp.Status)
t.Fail()
}
respPage := Page{}
err = json.NewDecoder(resp.Body).Decode(&respPage)
if err != nil {
t.Error(err)
t.Fail()
}
if respPage.ID == "" {
t.Error("No ID in response page")
t.Fail()
}
if respPage.ID != page.ID {
t.Errorf("ID %s != %s", respPage.ID, page.ID)
t.Fail()
}
if respPage.Title != page.Title {
t.Errorf("Title %s != %s", respPage.Title, page.Title)
t.Fail()
}
if respPage.Text != page.Text {
t.Errorf("Text %s != %s", respPage.Text, page.Text)
t.Fail()
}
})
t.Run("Get_Fail", func(t *testing.T) {
resp, err := http.Get(server.URL + "/page/" + generate.ID())
if err != nil {
t.Error(err)
t.Fail()
}
if resp.StatusCode != 404 {
t.Error("Expected status 404, got", resp.StatusCode, resp.Status)
t.Fail()
}
respPage := Page{}
err = json.NewDecoder(resp.Body).Decode(&respPage)
if err == nil {
t.Error("Expected encoder error, got:", respPage)
t.Fail()
}
if respPage.ID != "" {
t.Error("Ad ID in response page", respPage.ID)
t.Fail()
}
})
t.Run("Create", func(t *testing.T) {
form := url.Values{}
form.Set("title", "Hello World")
form.Set("text", "Sei Gegrüßt, Erde")
resp, err := http.PostForm(server.URL+"/page/", form)
if err != nil {
t.Error(err)
t.Fail()
}
if resp.StatusCode != 200 {
t.Error("Expected status 200, got", resp.StatusCode, resp.Status)
t.Fail()
}
respPage := Page{}
err = json.NewDecoder(resp.Body).Decode(&respPage)
if err != nil {
t.Error(err)
t.Fail()
}
if respPage.ID == "" {
t.Error("No ID in response page")
t.Fail()
}
if respPage.Title != form.Get("title") {
t.Errorf("Title %s != %s", respPage.Title, form.Get("title"))
t.Fail()
}
if respPage.Text != form.Get("text") {
t.Errorf("Text %s != %s", respPage.Text, form.Get("text"))
t.Fail()
}
if len(pages) != 4 {
t.Errorf("Page was not added")
t.Fail()
}
})
t.Run("Update", func(t *testing.T) {
page := pages[0]
form := url.Values{}
form.Set("text", "Edits and stuff")
resp, err := runForm("PUT", server.URL+"/page/"+page.ID, form)
if err != nil {
t.Error("Request:", err)
t.Fail()
}
if resp.StatusCode != 200 {
t.Error("Expected status 200, got", resp.StatusCode, resp.Status)
t.Fail()
}
respPage := Page{}
err = json.NewDecoder(resp.Body).Decode(&respPage)
if err != nil {
t.Error("Decode:", err)
t.Fail()
}
if respPage.ID == "" {
t.Error("No ID in response page")
t.Fail()
}
if respPage.Title != page.Title {
t.Errorf("Title %s != %s", respPage.Title, form.Get("title"))
t.Fail()
}
if respPage.Text != form.Get("text") {
t.Errorf("Text %s != %s", respPage.Text, form.Get("text"))
t.Fail()
}
})
t.Run("Update_Fail", func(t *testing.T) {
form := url.Values{}
form.Set("text", "Edits and stuff")
resp, err := runForm("PUT", server.URL+"/page/NONEXISTENT-ID-GOES-HERE", form)
if err != nil {
t.Error("Request:", err)
t.Fail()
}
if resp.StatusCode != 404 {
t.Error("Expected status 404, got", resp.StatusCode, resp.Status)
t.Fail()
}
respPage := Page{}
err = json.NewDecoder(resp.Body).Decode(&respPage)
if err == nil {
t.Error("A page was returned:", respPage)
t.Fail()
}
if respPage.ID != "" {
t.Error("ID in response page", respPage.ID)
t.Fail()
}
})
t.Run("Delete", func(t *testing.T) {
page := pages[3]
resp, err := runForm("DELETE", server.URL+"/page/"+page.ID, url.Values{})
if err != nil {
t.Error("Request:", err)
t.Fail()
}
if resp.StatusCode != 204 {
t.Error("Expected status 204, got", resp.Status)
t.Fail()
}
if len(pages) != 3 {
t.Error("Page was not deleted")
t.Fail()
}
})
t.Run("Delete_Fail", func(t *testing.T) {
resp, err := runForm("DELETE", server.URL+"/page/NONEXISTENT-ID-GOES-HERE", url.Values{})
if err != nil {
t.Error("Request:", err)
t.Fail()
}
if resp.StatusCode != 404 {
t.Error("Expected status 404, got", resp.Status)
t.Fail()
}
if len(pages) != 3 {
t.Error("A page was deleted despite the non-existent ID")
t.Fail()
}
})
}