Skip to content

Commit

Permalink
refactor: improve login test reuse
Browse files Browse the repository at this point in the history
  • Loading branch information
aeneasr committed Aug 27, 2020
1 parent 5242c55 commit b4184e5
Show file tree
Hide file tree
Showing 6 changed files with 406 additions and 509 deletions.
15 changes: 15 additions & 0 deletions internal/testhelpers/http.go
Expand Up @@ -3,6 +3,7 @@ package testhelpers
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"net/url"
Expand All @@ -15,6 +16,20 @@ func NewDebugClient(t *testing.T) *http.Client {
return &http.Client{Transport: NewTransportWithLogger(http.DefaultTransport, t)}
}

func NewRequest(t *testing.T, isAPI bool, method string, url string, payload io.Reader) *http.Request {
req, err := http.NewRequest("POST", url,payload)
require.NoError(t, err)

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "text/html")
if isAPI {
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
}

return req
}

func NewHTTPGetJSONRequest(t *testing.T, url string) *http.Request {
req, err := http.NewRequest("GET", url, nil)
require.NoError(t, err)
Expand Down
120 changes: 94 additions & 26 deletions internal/testhelpers/selfservice_login.go
@@ -1,19 +1,27 @@
package testhelpers

import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"

"github.com/ory/x/pointerx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/ory/viper"

"github.com/ory/kratos/driver"
"github.com/ory/kratos/driver/configuration"
"github.com/ory/kratos/identity"
"github.com/ory/kratos/internal/httpclient/client/common"
"github.com/ory/kratos/internal/httpclient/models"
"github.com/ory/kratos/selfservice/flow/login"
"github.com/ory/kratos/selfservice/strategy/password"
"github.com/ory/kratos/x"
)

Expand All @@ -28,32 +36,15 @@ func NewLoginUIFlowEchoServer(t *testing.T, reg driver.Registry) *httptest.Serve
return ts
}

func NewRegistrationUIFlowEchoServer(t *testing.T, reg driver.Registry) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
e, err := reg.RegistrationFlowPersister().GetRegistrationFlow(r.Context(), x.ParseUUID(r.URL.Query().Get("flow")))
require.NoError(t, err)
reg.Writer().Write(w, r, e)
}))
viper.Set(configuration.ViperKeySelfServiceRegistrationUI, ts.URL+"/registration-ts")
t.Cleanup(ts.Close)
return ts
}

func NewSettingsUIFlowEchoServer(t *testing.T, reg driver.Registry) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
e, err := reg.SettingsFlowPersister().GetSettingsFlow(r.Context(), x.ParseUUID(r.URL.Query().Get("flow")))
require.NoError(t, err)
reg.Writer().Write(w, r, e)
}))
viper.Set(configuration.ViperKeySelfServiceSettingsURL, ts.URL+"/settings-ts")
t.Cleanup(ts.Close)
return ts
}

func InitializeLoginFlowViaBrowser(t *testing.T, client *http.Client, ts *httptest.Server) *common.GetSelfServiceLoginFlowOK {
func InitializeLoginFlowViaBrowser(t *testing.T, client *http.Client, ts *httptest.Server, forced bool) *common.GetSelfServiceLoginFlowOK {
publicClient := NewSDKClient(ts)

res, err := client.Get(ts.URL + login.RouteInitBrowserFlow)
q := ""
if forced {
q = "?refresh=true"
}

res, err := client.Get(ts.URL + login.RouteInitBrowserFlow + q)
require.NoError(t, err)
require.NoError(t, res.Body.Close())

Expand All @@ -67,13 +58,90 @@ func InitializeLoginFlowViaBrowser(t *testing.T, client *http.Client, ts *httpte
return rs
}

func InitializeLoginFlowViaAPI(t *testing.T, client *http.Client, ts *httptest.Server) *common.InitializeSelfServiceLoginViaAPIFlowOK {
func InitializeLoginFlowViaAPI(t *testing.T, client *http.Client, ts *httptest.Server, forced bool) *common.InitializeSelfServiceLoginViaAPIFlowOK {
publicClient := NewSDKClient(ts)

rs, err := publicClient.Common.InitializeSelfServiceLoginViaAPIFlow(common.
NewInitializeSelfServiceLoginViaAPIFlowParams().WithHTTPClient(client))
NewInitializeSelfServiceLoginViaAPIFlowParams().WithHTTPClient(client).WithRefresh(pointerx.Bool(forced)))
require.NoError(t, err)
assert.Empty(t, rs.Payload.Active)

return rs
}

func GetLoginFlowMethodConfig(t *testing.T, rs *models.LoginFlow, id string) *models.LoginFlowMethodConfig {
require.NotEmpty(t, rs.Methods[id])
require.NotEmpty(t, rs.Methods[id].Config)
require.NotEmpty(t, rs.Methods[id].Config.Action)
return rs.Methods[id].Config
}

func LoginMakeRequest(
t *testing.T,
isAPI bool,
f *models.LoginFlowMethodConfig,
hc *http.Client,
values string,
) (string, *http.Response) {
require.NotEmpty(t, f.Action)

res, err := hc.Do(NewRequest(t, isAPI, "POST", pointerx.StringR(f.Action), bytes.NewBufferString(values)))
require.NoError(t, err)
defer res.Body.Close()

return string(x.MustReadAll(res.Body)), res
}

// SubmitLoginFormAndExpectValidationError initiates a login flow (for Browser and API!), fills out the form and modifies
// the form values with `withValues`, and submits the form. If completed, it will return the flow as JSON.
func SubmitLoginFormAndExpectValidationError(
t *testing.T,
isAPI bool,
hc *http.Client,
publicTS *httptest.Server,
withValues func(v url.Values) url.Values,
method identity.CredentialsType,
forced bool,
expectedStatusCode int,
) string {
hc.Transport = NewTransportWithLogger(hc.Transport, t)
var payload *models.LoginFlow
if isAPI {
payload = InitializeLoginFlowViaAPI(t, hc, publicTS,forced).Payload
} else {
payload = InitializeLoginFlowViaBrowser(t, hc, publicTS,forced).Payload
}

time.Sleep(time.Millisecond) // add a bit of delay to allow `1ns` to time out.

config := GetLoginFlowMethodConfig(t, payload, method.String())

b, res := LoginMakeRequest(t, isAPI, config, hc, EncodeFormAsJSON(t, isAPI,
withValues(SDKFormFieldsToURLValues(config.Fields))))
assert.EqualValues(t, expectedStatusCode, res.StatusCode, "%s", b)

expectURL := viper.GetString(configuration.ViperKeySelfServiceLoginUI)
if isAPI {
switch method {
case identity.CredentialsTypePassword:
expectURL = password.RouteLogin
default:
t.Logf("Expected method to be profile ior password but got: %s", method)
t.FailNow()
}
}

assert.Contains(t, res.Request.URL.String(), expectURL, "%+v\n\t%s", res.Request, b)

if isAPI {
return b
}

rs, err := NewSDKClientFromURL(viper.GetString(configuration.ViperKeyPublicBaseURL)).Common.GetSelfServiceLoginFlow(
common.NewGetSelfServiceLoginFlowParams().WithHTTPClient(hc).WithID(res.Request.URL.Query().Get("flow")))
require.NoError(t, err)

body, err := json.Marshal(rs.Payload)
require.NoError(t, err)
return string(body)
}
24 changes: 13 additions & 11 deletions internal/testhelpers/selfservice_registration.go
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/ory/viper"
"github.com/ory/x/pointerx"

"github.com/ory/kratos/driver"
"github.com/ory/kratos/driver/configuration"
"github.com/ory/kratos/identity"
"github.com/ory/kratos/internal/httpclient/client/common"
Expand All @@ -24,6 +25,17 @@ import (
"github.com/ory/kratos/x"
)

func NewRegistrationUIFlowEchoServer(t *testing.T, reg driver.Registry) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
e, err := reg.RegistrationFlowPersister().GetRegistrationFlow(r.Context(), x.ParseUUID(r.URL.Query().Get("flow")))
require.NoError(t, err)
reg.Writer().Write(w, r, e)
}))
viper.Set(configuration.ViperKeySelfServiceRegistrationUI, ts.URL+"/registration-ts")
t.Cleanup(ts.Close)
return ts
}

func InitializeRegistrationFlowViaBrowser(t *testing.T, client *http.Client, ts *httptest.Server) *common.GetSelfServiceRegistrationFlowOK {
res, err := client.Get(ts.URL + registration.RouteInitBrowserFlow)
require.NoError(t, err)
Expand Down Expand Up @@ -63,17 +75,7 @@ func RegistrationMakeRequest(
) (string, *http.Response) {
require.NotEmpty(t, f.Action)

req, err := http.NewRequest("POST", pointerx.StringR(f.Action), bytes.NewBufferString(values))
require.NoError(t, err)

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "text/html")
if isAPI {
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
}

res, err := hc.Do(req)
res, err := hc.Do(NewRequest(t,isAPI,"POST", pointerx.StringR(f.Action), bytes.NewBufferString(values)))
require.NoError(t, err)
defer res.Body.Close()

Expand Down
23 changes: 12 additions & 11 deletions internal/testhelpers/selfservice_settings.go
Expand Up @@ -35,6 +35,17 @@ import (
"github.com/ory/kratos/x"
)

func NewSettingsUIFlowEchoServer(t *testing.T, reg driver.Registry) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
e, err := reg.SettingsFlowPersister().GetSettingsFlow(r.Context(), x.ParseUUID(r.URL.Query().Get("flow")))
require.NoError(t, err)
reg.Writer().Write(w, r, e)
}))
viper.Set(configuration.ViperKeySelfServiceSettingsURL, ts.URL+"/settings-ts")
t.Cleanup(ts.Close)
return ts
}

func InitializeSettingsFlowViaBrowser(t *testing.T, client *http.Client, ts *httptest.Server) *common.GetSelfServiceSettingsFlowOK {
publicClient := NewSDKClient(ts)

Expand Down Expand Up @@ -219,17 +230,7 @@ func SettingsMakeRequest(
) (string, *http.Response) {
require.NotEmpty(t, f.Action)

req, err := http.NewRequest("POST", pointerx.StringR(f.Action), bytes.NewBufferString(values))
require.NoError(t, err)

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "text/html")
if isAPI {
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
}

res, err := hc.Do(req)
res, err := hc.Do(NewRequest(t,isAPI,"POST", pointerx.StringR(f.Action), bytes.NewBufferString(values)))
require.NoError(t, err)
defer res.Body.Close()

Expand Down

0 comments on commit b4184e5

Please sign in to comment.