diff options
Diffstat (limited to 'test/e2e_test.go')
| -rw-r--r-- | test/e2e_test.go | 95 |
1 files changed, 79 insertions, 16 deletions
diff --git a/test/e2e_test.go b/test/e2e_test.go index f14410a0..e4ef0a08 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -1,25 +1,23 @@ package main import ( + "bytes" + "context" "net/http" + "net/url" "strings" "testing" + "time" "github.com/playwright-community/playwright-go" "github.com/stretchr/testify/assert" "github.com/xlgmokha/x/pkg/env" "github.com/xlgmokha/x/pkg/serde" "github.com/xlgmokha/x/pkg/x" + "golang.org/x/oauth2" ) -type OAuthTokens struct { - AccessToken string `json:"access_token"` - TokenType string `json:"token_type"` - ExpiresIn uint64 `json:"expires_in"` - RefreshToken string `json:"refresh_token"` -} - -func TestHelloWorld(t *testing.T) { +func TestAuthx(t *testing.T) { _ = playwright.Install() pw := x.Must(playwright.Run()) @@ -29,6 +27,8 @@ func TestHelloWorld(t *testing.T) { })) page := x.Must(browser.NewPage()) + client := &http.Client{Timeout: 2 * time.Second} + defer func() { x.Check(browser.Close()) x.Check(pw.Stop()) @@ -36,19 +36,19 @@ func TestHelloWorld(t *testing.T) { t.Run("SAML", func(t *testing.T) { t.Run("IdP", func(t *testing.T) { - t.Run("provides metadata", func(t *testing.T) { + t.Run("metadata.xml", func(t *testing.T) { response := x.Must(http.Get("http://idp.example.com:8080/saml/metadata.xml")) assert.Equal(t, http.StatusOK, response.StatusCode) }) }) - t.Run("Service provider", func(t *testing.T) { - t.Run("provides metadata", func(t *testing.T) { + t.Run("SP", func(t *testing.T) { + t.Run("metadata.xml", func(t *testing.T) { response := x.Must(http.Get("http://ui.example.com:8080/saml/metadata.xml")) assert.Equal(t, http.StatusOK, response.StatusCode) }) - t.Run("starts a new session with the IdP", func(t *testing.T) { + t.Run("ACS", func(t *testing.T) { x.Must(page.Goto("http://ui.example.com:8080/saml/new")) action := x.Must(page.Locator("#idp-form").GetAttribute("action")) assert.Equal(t, "http://idp.example.com:8080/saml/new", action) @@ -63,19 +63,82 @@ func TestHelloWorld(t *testing.T) { }) t.Run("OIDC", func(t *testing.T) { - t.Run("Performs an OIDC login", func(t *testing.T) { + t.Run("login", func(t *testing.T) { x.Must(page.Goto("http://ui.example.com:8080/oidc/new")) assert.Contains(t, page.URL(), "http://idp.example.com:8080/oauth/authorize") assert.NoError(t, page.Locator("#submit-button").Click()) assert.Contains(t, page.URL(), "http://ui.example.com:8080/oauth/callback") content := x.Must(page.Locator("pre").First().InnerText()) - item := x.Must(serde.FromJSON[OAuthTokens](strings.NewReader(content))) + item := x.Must(serde.FromJSON[oauth2.Token](strings.NewReader(content))) assert.NotEmpty(t, item.AccessToken) assert.Equal(t, "Bearer", item.TokenType) assert.NotEmpty(t, item.RefreshToken) - // header = { 'Authorization' => "Bearer #{token}" } - // http.Get("http://api.example.com:8080/projects.json") + + response := x.Must(http.Get("http://api.example.com:8080/projects.json")) + assert.Equal(t, http.StatusOK, response.StatusCode) + projects := x.Must(serde.FromJSON[[]map[string]string](response.Body)) + assert.NotNil(t, projects) + + io := bytes.NewBuffer(nil) + assert.NoError(t, serde.ToJSON(io, map[string]string{"name": "example"})) + request := x.Must(http.NewRequestWithContext(t.Context(), "POST", "http://api.example.com:8080/projects", io)) + request.Header.Add("Authorization", "Bearer "+item.AccessToken) + response = x.Must(client.Do(request)) + assert.Equal(t, http.StatusCreated, response.StatusCode) + project := x.Must(serde.FromJSON[map[string]string](response.Body)) + assert.Equal(t, "example", project["name"]) + }) + }) + + t.Run("OAuth", func(t *testing.T) { + conf := &oauth2.Config{ + ClientID: "client_id", + ClientSecret: "client_secret", + Scopes: []string{"openid"}, + Endpoint: oauth2.Endpoint{ + TokenURL: "http://idp.example.com:8080/oauth/token", + AuthURL: "http://idp.example.com:8080/oauth/authorize", + }, + } + + t.Run("authorization code grant", func(t *testing.T) { + authURL := conf.AuthCodeURL( + "state", + oauth2.SetAuthURLParam("client_id", "client_id"), + oauth2.SetAuthURLParam("scope", "openid"), + oauth2.SetAuthURLParam("redirect_uri", "http://example.org/oauth/callback"), + oauth2.SetAuthURLParam("response_type", "code"), + oauth2.SetAuthURLParam("response_mode", "fragment"), + ) + x.Must(page.Goto(authURL)) + assert.NoError(t, page.Locator("#submit-button").Click()) + + uri := x.Must(url.Parse(page.URL())) + values := x.Must(url.ParseQuery(uri.Fragment)) + code := values.Get("code") + + ctx := t.Context() + ctx = context.WithValue(ctx, oauth2.HTTPClient, client) + credentials := x.Must(conf.Exchange(ctx, code)) + assert.NotEmpty(t, credentials.AccessToken) + assert.Equal(t, "Bearer", credentials.TokenType) + assert.NotEmpty(t, credentials.RefreshToken) + + t.Run("token is usable against REST API", func(t *testing.T) { + client := conf.Client(ctx, credentials) + response := x.Must(client.Get("http://api.example.com:8080/projects.json")) + assert.Equal(t, http.StatusOK, response.StatusCode) + projects := x.Must(serde.FromJSON[[]map[string]string](response.Body)) + assert.NotNil(t, projects) + + io := bytes.NewBuffer(nil) + assert.NoError(t, serde.ToJSON(io, map[string]string{"name": "foo"})) + response = x.Must(client.Post("http://api.example.com:8080/projects", "application/json", io)) + assert.Equal(t, http.StatusCreated, response.StatusCode) + project := x.Must(serde.FromJSON[map[string]string](response.Body)) + assert.Equal(t, "foo", project["name"]) + }) }) }) } |
