add test for visibility of notice edit buttons

This commit is contained in:
Henry 2021-03-09 13:39:43 +01:00 committed by cblgh
parent 3db514fd66
commit ae44a878b8
6 changed files with 150 additions and 16 deletions

View File

@ -19,6 +19,9 @@ import (
// AuthFallbackService might be helpful for scenarios where one lost access to his ssb device or key
type AuthFallbackService interface {
// Check receives the username and password (in clear) and checks them accordingly.
// If it's a valid combination it returns the user ID, or an error if they are not.
auth.Auther
Create(ctx context.Context, user string, password []byte) (int64, error)

View File

@ -24,6 +24,8 @@ type AuthFallback struct {
db *sql.DB
}
// Check receives the username and password (in clear) and checks them accordingly.
// If it's a valid combination it returns the user ID, or an error if they are not.
func (af AuthFallback) Check(name, password string) (interface{}, error) {
ctx := context.Background()
found, err := models.AuthFallbacks(qm.Where("name = ?", name)).One(ctx, af.db)

View File

@ -78,7 +78,8 @@ func newSession(t *testing.T) *testSession {
testFuncs["current_page_is"] = func(routeName string) bool {
return true
}
testFuncs["is_logged_in"] = func() *roomdb.User { return nil }
testFuncs["is_logged_in"] = func() *roomdb.User { return ts.User }
testFuncs["urlToNotice"] = func(name string) string { return "" }
r, err := render.New(web.Templates,

View File

@ -5,6 +5,7 @@ import (
"net/http"
"testing"
"github.com/ssb-ngi-pointer/go-ssb-room/web"
"github.com/ssb-ngi-pointer/go-ssb-room/web/router"
"github.com/stretchr/testify/assert"
)
@ -14,35 +15,37 @@ func TestNoticeEditFormIncludesAllFields(t *testing.T) {
ts := newSession(t)
a := assert.New(t)
// Construct notice url to edit
// Construct notice url to edit
baseurl, err := ts.Router.Get(router.AdminNoticeEdit).URL()
a.Nil(err)
url := fmt.Sprintf("%s?id=%d", baseurl.String(), 1)
url := fmt.Sprintf("%s?id=%d", baseurl.String(), 1)
_, resp := ts.Client.GetHTML(url)
/* TODO: continue test by checking for 1) forms, and 2) their required input fields */
/* TODO: continue test by checking for 1) forms, and 2) their required input fields */
a.Equal(http.StatusOK, resp.Code, "Wrong HTTP status code")
}
/* TODO: use this test as an example for pair programming 2021-03-09 */
// Assumption: I can use all the exported routes for my tests
// Reality: I can only use the routes associated with the 'correct' testing setup function
// Reality: I can only use the routes associated with the 'correct' testing setup function
// (setup for all, newSession for admin)
// TestEditButtonVisibleForAdmin specifically tests if the regular notice view at /notice/show?id=<x>
// displays an edit button for admin users
func TestNoticeEditButtonVisibleForAdmin(t *testing.T) {
ts := newSession(t)
a := assert.New(t)
// a := assert.New(t)
// Construct notice url to edit
baseurl, err := ts.Router.Get(router.CompleteNoticeShow).URL() // MARK
fmt.Println(baseurl.String())
a.Nil(err)
// url := fmt.Sprintf("%s?id=%d", baseurl.String(), 1)
//
// html, resp := ts.Client.GetHTML(url)
// fmt.Println(html.Html())
// a.Equal(http.StatusOK, resp.Code, "Wrong HTTP status code")
urlTo := web.NewURLTo(ts.Router)
// Construct notice url to edit
baseurl := urlTo(router.CompleteNoticeShow, "id", 3)
t.Log(baseurl.String())
// url := fmt.Sprintf("%s?id=%d", baseurl.String(), 1)
//
// html, resp := ts.Client.GetHTML(url)
// fmt.Println(html.Html())
// a.Equal(http.StatusOK, resp.Code, "Wrong HTTP status code")
}

View File

@ -2,10 +2,15 @@ package handlers
import (
"net/http"
"net/http/cookiejar"
"net/url"
"testing"
"github.com/ssb-ngi-pointer/go-ssb-room/admindb"
"github.com/ssb-ngi-pointer/go-ssb-room/web"
"github.com/ssb-ngi-pointer/go-ssb-room/web/router"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestNoticeSmokeTest ensures the most basic notice serving is working
@ -47,3 +52,122 @@ Hello world!
a.Equal("Welcome!", html.Find("title").Text())
a.Equal("The loveliest of rooms is here", html.Find("h2").Text())
}
// First we get the notices page (to see the buttons are NOT there)
// then we log in as an admin and see that the edit links are there.
func TestNoticesEditButtonVisible(t *testing.T) {
ts := setup(t)
a, r := assert.New(t), require.New(t)
urlTo := web.NewURLTo(ts.Router)
noticeData := admindb.Notice{
ID: 42,
Title: "Welcome!",
Content: `super simple conent`,
}
ts.NoticeDB.GetByIDReturns(noticeData, nil)
// first check the button isn't there when not logged in
noticeURL := urlTo(router.CompleteNoticeShow, "id", 42)
noticeURL.Host = "localhost"
noticeURL.Scheme = "https"
editButtonSelector := `#edit-notice`
doc, resp := ts.Client.GetHTML(noticeURL.String())
a.Equal(http.StatusOK, resp.Code)
// empty election == no link
a.EqualValues(0, doc.Find(editButtonSelector).Length())
// start prepareing login dance
// very cheap client session
// TODO: refactor login dance for re-use in testing
jar, err := cookiejar.New(nil)
r.NoError(err)
// when dealing with cookies we also need to have an Host and URL-Scheme
// for the jar to save and load them correctly
formEndpoint := urlTo(router.AuthFallbackSignInForm)
r.NotNil(formEndpoint)
formEndpoint.Host = "localhost"
formEndpoint.Scheme = "https"
doc, resp = ts.Client.GetHTML(formEndpoint.String())
a.Equal(http.StatusOK, resp.Code)
csrfCookie := resp.Result().Cookies()
a.Len(csrfCookie, 1, "should have one cookie for CSRF protection validation")
t.Log(csrfCookie)
jar.SetCookies(formEndpoint, csrfCookie)
csrfTokenElem := doc.Find("input[type=hidden]")
a.Equal(1, csrfTokenElem.Length())
csrfName, has := csrfTokenElem.Attr("name")
a.True(has, "should have a name attribute")
csrfValue, has := csrfTokenElem.Attr("value")
a.True(has, "should have value attribute")
loginVals := url.Values{
"user": []string{"test"},
"pass": []string{"test"},
csrfName: []string{csrfValue},
}
// have the database return okay for any user
testUser := &admindb.User{
ID: 23,
Name: "test admin",
}
ts.AuthFallbackDB.CheckReturns(testUser.ID, nil)
ts.AuthFallbackDB.GetByIDReturns(testUser, nil)
postEndpoint, err := ts.Router.Get(router.AuthFallbackSignIn).URL()
r.Nil(err)
postEndpoint.Host = "localhost"
postEndpoint.Scheme = "https"
// construct HTTP Header with Referer and Cookie
var csrfCookieHeader = http.Header(map[string][]string{})
csrfCookieHeader.Set("Referer", "https://localhost")
cs := jar.Cookies(postEndpoint)
r.Len(cs, 1, "expecting one cookie for csrf")
theCookie := cs[0].String()
a.NotEqual("", theCookie, "should have a new cookie")
csrfCookieHeader.Set("Cookie", theCookie)
ts.Client.SetHeaders(csrfCookieHeader)
resp = ts.Client.PostForm(postEndpoint.String(), loginVals)
a.Equal(http.StatusSeeOther, resp.Code, "wrong HTTP status code for sign in")
sessionCookie := resp.Result().Cookies()
jar.SetCookies(postEndpoint, sessionCookie)
var sessionHeader = http.Header(map[string][]string{})
cs = jar.Cookies(noticeURL)
// TODO: why doesnt this return the csrf cookie?!
r.NotEqual(len(cs), 0, "expecting a cookie!")
for _, c := range cs {
theCookie := c.String()
a.NotEqual("", theCookie, "should have a new cookie")
sessionHeader.Add("Cookie", theCookie)
}
// update headers
ts.Client.ClearHeaders()
ts.Client.SetHeaders(sessionHeader)
// now we are logged in, anchor tag should be there
doc, resp = ts.Client.GetHTML(noticeURL.String())
a.Equal(http.StatusOK, resp.Code)
// html, err := doc.Html()
// r.NoError(err)
// t.Log(html)
a.EqualValues(1, doc.Find(editButtonSelector).Length())
}

View File

@ -11,6 +11,7 @@
<div class="h-10"></div>
{{if is_logged_in}}
<a
id="edit-notice"
href="{{urlTo "admin:notice:edit" "id" .ID}}"
class="self-start shadow rounded px-4 h-8 flex flex-row justify-center items-center text-gray-100 bg-pink-600 hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-pink-600 focus:ring-opacity-50"
>{{i18n "NoticeEditTitle"}}</a>