package main import ( "bytes" "encoding/json" "fmt" "github.com/stretchr/testify/assert" "go-nkode/internal/api" "go-nkode/internal/models" "go-nkode/internal/security" "io" "net/http" "strings" "testing" ) func TestApi(t *testing.T) { base := "http://localhost:8080" newCustomerBody := models.NewCustomerPost{ NKodePolicy: models.NewDefaultNKodePolicy(), } kp := models.KeypadDimension{ AttrsPerKey: 14, NumbOfKeys: 10, } var customerResp models.CreateNewCustomerResp testApiPost(t, base+api.CreateNewCustomer, newCustomerBody, &customerResp) userEmail := "test_username" + security.GenerateRandomString(12) + "@example.com" signupInterfaceBody := models.GenerateSignupRestInterfacePost{ CustomerId: customerResp.CustomerId, AttrsPerKey: kp.AttrsPerKey, NumbOfKeys: kp.NumbOfKeys, UserEmail: strings.ToUpper(userEmail), // should be case-insensitive Reset: false, } var signupInterfaceResp models.GenerateSignupResetInterfaceResp testApiPost(t, base+api.GenerateSignupResetInterface, signupInterfaceBody, &signupInterfaceResp) assert.Len(t, signupInterfaceResp.SvgInterface, kp.TotalAttrs()) passcodeLen := 4 setInterface := signupInterfaceResp.UserIdxInterface userPasscode := setInterface[:passcodeLen] kpSet := models.KeypadDimension{NumbOfKeys: kp.NumbOfKeys, AttrsPerKey: kp.NumbOfKeys} setKeySelection, err := models.SelectKeyByAttrIdx(setInterface, userPasscode, kpSet) assert.NoError(t, err) setNKodeBody := models.SetNKodePost{ CustomerId: customerResp.CustomerId, SessionId: signupInterfaceResp.SessionId, KeySelection: setKeySelection, } var setNKodeResp models.SetNKodeResp testApiPost(t, base+api.SetNKode, setNKodeBody, &setNKodeResp) confirmInterface := setNKodeResp.UserInterface confirmKeySelection, err := models.SelectKeyByAttrIdx(confirmInterface, userPasscode, kpSet) assert.NoError(t, err) confirmNKodeBody := models.ConfirmNKodePost{ CustomerId: customerResp.CustomerId, KeySelection: confirmKeySelection, SessionId: signupInterfaceResp.SessionId, } testApiPost(t, base+api.ConfirmNKode, confirmNKodeBody, nil) loginInterfaceBody := models.GetLoginInterfacePost{ CustomerId: customerResp.CustomerId, UserEmail: userEmail, } var loginInterfaceResp models.GetLoginInterfaceResp testApiPost(t, base+api.GetLoginInterface, loginInterfaceBody, &loginInterfaceResp) assert.Equal(t, loginInterfaceResp.AttrsPerKey, kp.AttrsPerKey) assert.Equal(t, loginInterfaceResp.NumbOfKeys, kp.NumbOfKeys) loginKeySelection, err := models.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp) assert.NoError(t, err) loginBody := models.LoginPost{ CustomerId: customerResp.CustomerId, UserEmail: userEmail, KeySelection: loginKeySelection, } var jwtTokens security.AuthenticationTokens testApiPost(t, base+api.Login, loginBody, &jwtTokens) refreshClaims, err := security.ParseRegisteredClaimToken(jwtTokens.RefreshToken) assert.Equal(t, refreshClaims.Subject, userEmail) accessClaims, err := security.ParseRegisteredClaimToken(jwtTokens.AccessToken) assert.Equal(t, accessClaims.Subject, userEmail) renewBody := models.RenewAttributesPost{CustomerId: customerResp.CustomerId} testApiPost(t, base+api.RenewAttributes, renewBody, nil) loginKeySelection, err = models.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp) assert.NoError(t, err) loginBody = models.LoginPost{ CustomerId: customerResp.CustomerId, UserEmail: userEmail, KeySelection: loginKeySelection, } testApiPost(t, base+api.Login, loginBody, &jwtTokens) var randomSvgInterfaceResp models.RandomSvgInterfaceResp testApiGet(t, base+api.RandomSvgInterface, &randomSvgInterfaceResp, "") assert.Equal(t, models.KeypadMax.TotalAttrs(), len(randomSvgInterfaceResp.Svgs)) var refreshTokenResp models.RefreshTokenResp testApiGet(t, base+api.RefreshToken, &refreshTokenResp, jwtTokens.RefreshToken) accessClaims, err = security.ParseRegisteredClaimToken(refreshTokenResp.AccessToken) assert.NoError(t, err) assert.Equal(t, accessClaims.Subject, userEmail) } func Unmarshal(t *testing.T, resp *http.Response, data any) { responseBody, err := io.ReadAll(resp.Body) assert.NoError(t, err) err = json.Unmarshal(responseBody, data) assert.NoError(t, err) } func Marshal(t *testing.T, data any) *bytes.Reader { jsonBytes, err := json.Marshal(data) assert.NoError(t, err) reader := bytes.NewReader(jsonBytes) return reader } func testApiPost(t *testing.T, endpointStr string, postBody any, respBody any) { reader := Marshal(t, postBody) resp, err := http.Post(endpointStr, "application/json", reader) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) if respBody != nil { Unmarshal(t, resp, respBody) } } func testApiGet(t *testing.T, endpointStr string, respBody any, bearerToken string) { req, err := http.NewRequest("GET", endpointStr, nil) if err != nil { fmt.Println("Error creating request:", err) return } // Add the Bearer token to the Authorization header if bearerToken != "" { req.Header.Set("Authorization", "Bearer "+bearerToken) } // Make the HTTP request client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Error making request:", err) return } defer resp.Body.Close() assert.NoError(t, err) assert.Equal(t, resp.StatusCode, http.StatusOK) if respBody != nil { Unmarshal(t, resp, respBody) } }