Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
203 lines
6.5 KiB
Go
203 lines
6.5 KiB
Go
// Copyright © 2023 Ory Corp
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package testhelpers
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ory/kratos/selfservice/flow/registration"
|
|
|
|
"github.com/tidwall/gjson"
|
|
|
|
"github.com/ory/x/assertx"
|
|
|
|
kratos "github.com/ory/kratos/pkg/httpclient"
|
|
|
|
"github.com/ory/x/ioutilx"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/ory/kratos/driver"
|
|
"github.com/ory/kratos/driver/config"
|
|
"github.com/ory/kratos/x"
|
|
)
|
|
|
|
func NewRegistrationUIFlowEchoServer(t *testing.T, reg driver.Registry) *httptest.Server {
|
|
ctx := context.Background()
|
|
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)
|
|
}))
|
|
reg.Config().MustSet(ctx, config.ViperKeySelfServiceRegistrationUI, ts.URL+"/registration-ts")
|
|
t.Cleanup(ts.Close)
|
|
return ts
|
|
}
|
|
|
|
// Deprecated: Use context-based InitializeRegistrationFlowViaBrowserCtx instead
|
|
func InitializeRegistrationFlowViaBrowser(t *testing.T, client *http.Client, ts *httptest.Server, isSPA bool, expectInitError bool, expectGetError bool, opts ...InitFlowWithOption) *kratos.RegistrationFlow {
|
|
return InitializeRegistrationFlowViaBrowserCtx(t.Context(), t, client, ts, isSPA, expectInitError, expectGetError, opts...)
|
|
}
|
|
|
|
func InitializeRegistrationFlowViaBrowserCtx(ctx context.Context, t *testing.T, client *http.Client, ts *httptest.Server, isSPA bool, expectInitError bool, expectGetError bool, opts ...InitFlowWithOption) *kratos.RegistrationFlow {
|
|
req, err := http.NewRequest("GET", getURLFromInitOptions(ts, registration.RouteInitBrowserFlow, false, opts...), nil)
|
|
require.NoError(t, err)
|
|
req = req.WithContext(ctx)
|
|
|
|
if isSPA {
|
|
req.Header.Set("Accept", "application/json")
|
|
}
|
|
|
|
res, err := client.Do(req)
|
|
require.NoError(t, err)
|
|
body := x.MustReadAll(res.Body)
|
|
if isSPA {
|
|
require.True(t, gjson.ValidBytes(body), "body is not valid JSON: %s", string(body))
|
|
}
|
|
require.NoError(t, res.Body.Close())
|
|
if expectInitError {
|
|
require.Equal(t, 200, res.StatusCode)
|
|
require.NotNil(t, res.Request.URL)
|
|
require.Contains(t, res.Request.URL.String(), "error-ts")
|
|
}
|
|
|
|
flowID := res.Request.URL.Query().Get("flow")
|
|
if isSPA {
|
|
flowID = gjson.GetBytes(body, "id").String()
|
|
}
|
|
|
|
rs, _, err := NewSDKCustomClient(ts, client).FrontendAPI.GetRegistrationFlow(ctx).Id(flowID).Execute()
|
|
if expectGetError {
|
|
require.Error(t, err)
|
|
require.Nil(t, rs)
|
|
} else {
|
|
require.NoError(t, err)
|
|
assert.Empty(t, rs.Active)
|
|
}
|
|
return rs
|
|
}
|
|
|
|
func InitializeRegistrationFlowViaAPIExpectError(t *testing.T, client *http.Client, ts *httptest.Server, opts ...InitFlowWithOption) {
|
|
o := new(initFlowOptions).apply(opts)
|
|
|
|
_, _, err := NewSDKCustomClient(ts, client).FrontendAPI.CreateNativeRegistrationFlow(context.Background()).IdentitySchema(o.identitySchema).Execute()
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// Deprecated: Use context-based InitializeRegistrationFlowViaAPICtx instead
|
|
func InitializeRegistrationFlowViaAPI(t *testing.T, client *http.Client, ts *httptest.Server, opts ...InitFlowWithOption) *kratos.RegistrationFlow {
|
|
return InitializeRegistrationFlowViaAPICtx(context.Background(), t, client, ts, opts...)
|
|
}
|
|
|
|
func InitializeRegistrationFlowViaAPICtx(ctx context.Context, t *testing.T, client *http.Client, ts *httptest.Server, opts ...InitFlowWithOption) *kratos.RegistrationFlow {
|
|
o := new(initFlowOptions).apply(opts)
|
|
|
|
rs, _, err := NewSDKCustomClient(ts, client).FrontendAPI.CreateNativeRegistrationFlow(ctx).IdentitySchema(o.identitySchema).Execute()
|
|
require.NoError(t, err)
|
|
assert.Empty(t, rs.Active)
|
|
return rs
|
|
}
|
|
|
|
func GetRegistrationFlow(t *testing.T, client *http.Client, ts *httptest.Server, flowID string) *kratos.RegistrationFlow {
|
|
rs, _, err := NewSDKCustomClient(ts, client).FrontendAPI.GetRegistrationFlow(context.Background()).Id(flowID).Execute()
|
|
require.NoError(t, err)
|
|
assert.Empty(t, rs.Active)
|
|
return rs
|
|
}
|
|
|
|
func RegistrationMakeRequest(
|
|
t *testing.T,
|
|
isAPI bool,
|
|
isSPA bool,
|
|
f *kratos.RegistrationFlow,
|
|
hc *http.Client,
|
|
values string,
|
|
) (string, *http.Response) {
|
|
return RegistrationMakeRequestCtx(t.Context(), t, isAPI, isSPA, f, hc, values)
|
|
}
|
|
|
|
func RegistrationMakeRequestCtx(
|
|
ctx context.Context,
|
|
t *testing.T,
|
|
isAPI bool,
|
|
isSPA bool,
|
|
f *kratos.RegistrationFlow,
|
|
hc *http.Client,
|
|
values string,
|
|
) (string, *http.Response) {
|
|
require.NotEmpty(t, f.Ui.Action)
|
|
|
|
req := NewPostRequest(t, isAPI, f.Ui.Action, bytes.NewBufferString(values))
|
|
if isSPA {
|
|
req.Header.Set("Accept", "application/json")
|
|
req.Header.Set("Sec-Fetch-Mode", "cors")
|
|
}
|
|
req = req.WithContext(ctx)
|
|
|
|
res, err := hc.Do(req)
|
|
require.NoError(t, err)
|
|
defer func() { _ = res.Body.Close() }()
|
|
|
|
return string(ioutilx.MustReadAll(res.Body)), res
|
|
}
|
|
|
|
// Deprecated: Use context-based SubmitRegistrationFormCtx instead
|
|
func SubmitRegistrationForm(
|
|
t *testing.T,
|
|
isAPI bool,
|
|
hc *http.Client,
|
|
publicTS *httptest.Server,
|
|
withValues func(v url.Values),
|
|
isSPA bool,
|
|
expectedStatusCode int,
|
|
expectedURL string,
|
|
opts ...InitFlowWithOption,
|
|
) string {
|
|
return SubmitRegistrationFormCtx(context.Background(), t, isAPI, hc, publicTS, withValues, isSPA, expectedStatusCode, expectedURL, opts...)
|
|
}
|
|
|
|
// SubmitRegistrationFormCtx (for Browser and API!), fills out the form and modifies
|
|
// the form values with `withValues`, and submits the form. Returns the body and checks for expectedStatusCode and
|
|
// expectedURL on completion
|
|
func SubmitRegistrationFormCtx(
|
|
ctx context.Context,
|
|
t *testing.T,
|
|
isAPI bool,
|
|
hc *http.Client,
|
|
publicTS *httptest.Server,
|
|
withValues func(v url.Values),
|
|
isSPA bool,
|
|
expectedStatusCode int,
|
|
expectedURL string,
|
|
opts ...InitFlowWithOption,
|
|
) string {
|
|
if hc == nil {
|
|
hc = NewTestClient(t)
|
|
}
|
|
|
|
hc.Transport = NewTransportWithLogger(hc.Transport, t)
|
|
var payload *kratos.RegistrationFlow
|
|
if isAPI {
|
|
payload = InitializeRegistrationFlowViaAPICtx(ctx, t, hc, publicTS, opts...)
|
|
} else {
|
|
payload = InitializeRegistrationFlowViaBrowserCtx(ctx, t, hc, publicTS, isSPA, false, false, opts...)
|
|
}
|
|
|
|
time.Sleep(time.Millisecond) // add a bit of delay to allow `1ns` to time out.
|
|
|
|
values := SDKFormFieldsToURLValues(payload.Ui.Nodes)
|
|
withValues(values)
|
|
b, res := RegistrationMakeRequest(t, isAPI, isSPA, payload, hc, EncodeFormAsJSON(t, isAPI, values))
|
|
assert.EqualValues(t, expectedStatusCode, res.StatusCode, assertx.PrettifyJSONPayload(t, b))
|
|
assert.Containsf(t, res.Request.URL.String(), expectedURL, "%+v\n\t%s", res.Request, assertx.PrettifyJSONPayload(t, b))
|
|
return b
|
|
}
|