1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
package webui
import (
"net/http"
"net/url"
"testing"
"git.adyxax.org/adyxax/trains/pkg/database"
"git.adyxax.org/adyxax/trains/pkg/model"
"github.com/stretchr/testify/require"
)
func TestLoginHandler(t *testing.T) {
// test environment setup
dbEnv, err := database.InitDB("sqlite3", "file::memory:?_foreign_keys=on")
require.Nil(t, err)
err = dbEnv.Migrate()
require.Nil(t, err)
user1, err := dbEnv.CreateUser(&model.UserRegistration{Username: "user1", Password: "password1", Email: "julien@adyxax.org"})
require.Nil(t, err)
_, err = dbEnv.Login(&model.UserLogin{Username: "user1", Password: "password1"})
require.Nil(t, err)
token1, err := dbEnv.CreateSession(user1)
require.Nil(t, err)
e := &env{dbEnv: dbEnv}
// test GET requests
runHttpTest(t, e, loginHandler, &httpTestCase{
name: "a simple get should display the login page",
input: httpTestInput{
method: http.MethodGet,
path: "/login",
},
expect: httpTestExpect{
code: http.StatusOK,
bodyString: "<form action=\"/login\"",
},
})
runHttpTest(t, e, loginHandler, &httpTestCase{
name: "an invalid or expired token should also just display the login page",
input: httpTestInput{
method: http.MethodGet,
path: "/login",
cookie: &http.Cookie{Name: sessionCookieName, Value: "graou"},
},
expect: httpTestExpect{
code: http.StatusOK,
bodyString: "<form action=\"/login\"",
},
})
runHttpTest(t, e, loginHandler, &httpTestCase{
name: "if already logged in we should be redirected to /",
input: httpTestInput{
method: http.MethodGet,
path: "/login",
cookie: &http.Cookie{Name: sessionCookieName, Value: *token1},
},
expect: httpTestExpect{
code: http.StatusFound,
location: "/",
},
})
runHttpTest(t, e, loginHandler, &httpTestCase{
name: "an invalid path should get a 404",
input: httpTestInput{
method: http.MethodGet,
path: "/login/non_existent",
},
expect: httpTestExpect{
code: http.StatusNotFound,
err: &statusError{http.StatusNotFound, simpleErrorMessage},
},
})
runHttpTest(t, e, loginHandler, &httpTestCase{
name: "an invalid path should get a 404 even if we are already logged in",
input: httpTestInput{
method: http.MethodGet,
path: "/login/non_existent",
cookie: &http.Cookie{Name: sessionCookieName, Value: *token1},
},
expect: httpTestExpect{
code: http.StatusNotFound,
err: &statusError{http.StatusNotFound, simpleErrorMessage},
},
})
// Test POST requests
runHttpTest(t, e, loginHandler, &httpTestCase{
name: "a valid login attempt should succeed and redirect to /",
input: httpTestInput{
method: http.MethodPost,
path: "/login",
data: url.Values{
"username": []string{"user1"},
"password": []string{"password1"},
},
},
expect: httpTestExpect{
code: http.StatusFound,
location: "/",
setsCookie: true,
},
})
//errorNoUsername := newTestRequest(t, http.MethodPost, "/login", nil)
//// too many username fields
//dataWtfUsername := url.Values{"username": []string{"user1", "user2"}}
//errorWtfUsername, err := http.NewRequest(http.MethodPost, "/login", strings.NewReader(dataWtfUsername.Encode()))
//require.Nil(t, err)
//errorWtfUsername.Header.Add("Content-Type", "application/x-www-form-urlencoded")
//// Invalid username
//dataInvalidUsername := url.Values{"username": []string{"%"}}
//errorInvalidUsername, err := http.NewRequest(http.MethodPost, "/login", strings.NewReader(dataInvalidUsername.Encode()))
//require.Nil(t, err)
//errorInvalidUsername.Header.Add("Content-Type", "application/x-www-form-urlencoded")
//// no password field
//dataNoPassword := url.Values{"username": []string{"user1"}}
//errorNoPassword, err := http.NewRequest(http.MethodPost, "/login", strings.NewReader(dataNoPassword.Encode()))
//require.Nil(t, err)
//errorNoPassword.Header.Add("Content-Type", "application/x-www-form-urlencoded")
//// too many password fields
//dataWtfPassword := url.Values{"username": []string{"user1"}, "password": []string{"user1", "user2"}}
//errorWtfPassword, err := http.NewRequest(http.MethodPost, "/login", strings.NewReader(dataWtfPassword.Encode()))
//require.Nil(t, err)
//errorWtfPassword.Header.Add("Content-Type", "application/x-www-form-urlencoded")
//// Invalid password
//dataInvalidPassword := url.Values{"username": []string{"user1"}, "password": []string{""}}
//errorInvalidPassword, err := http.NewRequest(http.MethodPost, "/login", strings.NewReader(dataInvalidPassword.Encode()))
//require.Nil(t, err)
//errorInvalidPassword.Header.Add("Content-Type", "application/x-www-form-urlencoded")
//// run the tests
//// {"error no username", &env{dbEnv: dbEnv}, errorNoUsername, &expected{err: &statusError{code: 500, err: simpleError}}},
//// {"error wtf username", &env{dbEnv: dbEnv}, errorWtfUsername, &expected{err: &statusError{code: 500, err: simpleError}}},
//// {"error invalid username", &env{dbEnv: dbEnv}, errorInvalidUsername, &expected{err: &statusError{code: 500, err: simpleError}}},
//// {"error no password", &env{dbEnv: dbEnv}, errorNoPassword, &expected{err: &statusError{code: 500, err: simpleError}}},
//// {"error wtf password", &env{dbEnv: dbEnv}, errorWtfPassword, &expected{err: &statusError{code: 500, err: simpleError}}},
//// {"error invalid password", &env{dbEnv: dbEnv}, errorInvalidPassword, &expected{err: &statusError{code: 500, err: simpleError}}},
////}
}
|