package console
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/cookiejar"
"net/url"
"os"
"strings"
"testing"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"golang.org/x/net/html"
"gitcode.com/openFuyao/e2e-auto-test/e2e/framework/env"
)
var (
baseURL string
client *http.Client
)
var _ = BeforeSuite(func() {
err := env.LoadEnv(".env")
if err != nil {
Fail("Error loading .env file: " + err.Error())
}
baseURL = os.Getenv("TEST_NODE2_IP")
if baseURL == "" {
Fail("TEST_NODE2_IP is not set")
}
baseURL = "https://" + baseURL + ":31616"
jar, err := cookiejar.New(nil)
if err != nil {
Fail("Error creating cookie jar: " + err.Error())
}
client = &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
Timeout: 30 * time.Second,
Jar: jar,
}
testConfig = &ConsoleTestConfig{
BaseURL: baseURL,
Client: client,
}
performLogin()
})
var _ = AfterSuite(func() {
performLogout()
})
func performLogout() {
if client == nil {
return
}
logoutURLStr := baseURL + "/rest/auth/logout"
resp, err := client.Post(logoutURLStr, "application/json", nil)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))
}
func extractLoginFormData(htmlContent string) (csrfToken, thenValue string, err error) {
doc, err := html.Parse(strings.NewReader(htmlContent))
Expect(err).NotTo(HaveOccurred())
var findInputs func(*html.Node)
findInputs = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "input" {
var name, value string
for _, attr := range n.Attr {
switch attr.Key {
case "name":
name = attr.Val
case "value":
value = attr.Val
}
}
switch name {
case "gorilla.csrf.Token":
csrfToken = value
case "then":
thenValue = value
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
findInputs(c)
}
}
findInputs(doc)
if csrfToken == "" {
return "", "", fmt.Errorf("CSRF token not found in HTML")
}
if thenValue == "" {
return "", "", fmt.Errorf("then parameter not found in HTML")
}
return csrfToken, thenValue, nil
}
func performLogin() {
loginPageURLStr := baseURL + "/rest/auth/login"
resp, err := client.Get(loginPageURLStr)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusFound))
location := resp.Header.Get("Location")
Expect(location).To(HavePrefix("/oauth2/oauth/authorize"))
resp, err = client.Get(baseURL + location)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusFound))
location = resp.Header.Get("Location")
Expect(location).To(HavePrefix("/oauth2/auth/login/fuyaoPasswordProvider"))
resp, err = client.Get(baseURL + location)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
resp.Body.Close()
htmlContent := string(body)
csrfToken, thenValue, err := extractLoginFormData(htmlContent)
Expect(err).NotTo(HaveOccurred(), "failed to extract login form data: %v", err)
passwordStr := os.Getenv("TEST_PASSWORD")
passwordInts := make([]int, len(passwordStr))
for i, char := range passwordStr {
passwordInts[i] = int(char)
}
jsonData, err := json.Marshal(map[string]interface{}{
"username": os.Getenv("TEST_USERNAME"),
"password": passwordInts,
"then": thenValue,
})
Expect(err).NotTo(HaveOccurred(), "failed to marshal login data: %v", err)
loginURLStr := baseURL + "/oauth2/auth/login/fuyaoPasswordProvider"
loginURL, err := url.Parse(loginURLStr)
Expect(err).NotTo(HaveOccurred(), "failed to parse login URL: %v", err)
loginReq := &http.Request{
Method: "POST",
URL: loginURL,
Header: http.Header{
"Content-Type": {"application/json"},
"X-CSRF-Token": {csrfToken},
"Referer": {location},
},
Body: io.NopCloser(bytes.NewReader(jsonData)),
}
resp, err = client.Do(loginReq)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusFound))
location = resp.Header.Get("Location")
Expect(location).To(HavePrefix("/oauth2/oauth/authorize"))
resp, err = client.Get(baseURL + location)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusFound))
location = resp.Header.Get("Location")
Expect(location).To(HavePrefix("/rest/auth/callback"))
resp, err = client.Get(baseURL + location)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusFound))
location = resp.Header.Get("Location")
Expect(location).To(Equal("/"))
resp, err = client.Get(baseURL + location)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
body, err = io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(string(body)).To(ContainSubstring("<div id=\"root\"></div>"))
resp.Body.Close()
}
func TestConsoleTest(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "ConsoleTest Suite")
}