Add more portal tests (#237)

* Initial plan

* Initial plan for increasing test coverage in pkg/portal

Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>

* Add smoke tests for org.go, org_enterprise.go, property.go, settings.go and audit.go handlers

Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>

* Fix code review feedback: use t.Context() consistently

Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>

* Fix failing tests: correct paths and use admin plan for org limits

Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
Taras
2026-01-07 09:54:27 +02:00
committed by GitHub
parent 8a03c3eb17
commit 55d9612fa5
5 changed files with 1202 additions and 0 deletions

1
.gitignore vendored
View File

@@ -39,6 +39,7 @@ fullcode.txt
.DS_Store
coverage_*.out
coverage_*.cov
coverage_integration/
*.keys

View File

@@ -3,6 +3,8 @@ package portal
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
@@ -10,6 +12,9 @@ import (
"github.com/PrivateCaptcha/PrivateCaptcha/pkg/common"
"github.com/PrivateCaptcha/PrivateCaptcha/pkg/db"
dbgen "github.com/PrivateCaptcha/PrivateCaptcha/pkg/db/generated"
db_tests "github.com/PrivateCaptcha/PrivateCaptcha/pkg/db/tests"
"github.com/PrivateCaptcha/PrivateCaptcha/pkg/email"
portal_tests "github.com/PrivateCaptcha/PrivateCaptcha/pkg/portal/tests"
)
func TestUserAuditLogInitFromUser(t *testing.T) {
@@ -484,3 +489,74 @@ func mustMarshalJSON(v interface{}) []byte {
}
return data
}
func TestGetAuditLogs(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", "/events", nil)
req.AddCookie(cookie)
w := httptest.NewRecorder()
viewModel, err := server.getAuditLogs(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != auditLogsTemplate {
t.Errorf("Expected view to be %s, got %s", auditLogsTemplate, viewModel.View)
}
if viewModel.AuditEvent == nil {
t.Error("Expected AuditEvent to be populated")
}
}
func TestCreateAuditLogsContext(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
renderCtx, err := server.CreateAuditLogsContext(ctx, user, 14, 0)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if renderCtx == nil {
t.Fatal("Expected render context to be populated, got nil")
}
if renderCtx.Days != 14 {
t.Errorf("Expected Days to be 14, got %d", renderCtx.Days)
}
if renderCtx.AuditLogs == nil {
t.Error("Expected AuditLogs to be initialized")
}
}

View File

@@ -187,3 +187,572 @@ func TestDeleteUserFromOrgPermissions(t *testing.T) {
t.Errorf("Unexpected length of members: %v", len(members))
}
}
func TestGetNewOrg(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", "/org/new", nil)
req.AddCookie(cookie)
w := httptest.NewRecorder()
viewModel, err := server.getNewOrg(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != orgWizardTemplate {
t.Errorf("Expected view to be %s, got %s", orgWizardTemplate, viewModel.View)
}
renderCtx, ok := viewModel.Model.(*orgWizardRenderContext)
if !ok {
t.Fatalf("Expected Model to be *orgWizardRenderContext, got %T", viewModel.Model)
}
if len(renderCtx.Token) == 0 {
t.Error("Expected CSRF token to be populated")
}
}
func TestGetOrgDashboard(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/tab/dashboard", server.IDHasher.Encrypt(int(org.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getOrgDashboard(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != orgDashboardTemplate {
t.Errorf("Expected view to be %s, got %s", orgDashboardTemplate, viewModel.View)
}
renderCtx, ok := viewModel.Model.(*orgPropertiesRenderContext)
if !ok {
t.Fatalf("Expected Model to be *orgPropertiesRenderContext, got %T", viewModel.Model)
}
if renderCtx.CurrentOrg == nil {
t.Fatal("Expected CurrentOrg to be populated, got nil")
}
if renderCtx.CurrentOrg.Name != org.Name {
t.Errorf("Expected org name to be %s, got %s", org.Name, renderCtx.CurrentOrg.Name)
}
}
func TestGetOrgProperties(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
if _, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org); err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/tab/properties", server.IDHasher.Encrypt(int(org.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getOrgProperties(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != orgPropertiesTemplate {
t.Errorf("Expected view to be %s, got %s", orgPropertiesTemplate, viewModel.View)
}
renderCtx, ok := viewModel.Model.(*orgPropertiesRenderContext)
if !ok {
t.Fatalf("Expected Model to be *orgPropertiesRenderContext, got %T", viewModel.Model)
}
if len(renderCtx.Properties) != 1 {
t.Errorf("Expected 1 property, got %d", len(renderCtx.Properties))
}
}
func TestGetOrgMembers(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/tab/members", server.IDHasher.Encrypt(int(org.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getOrgMembers(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != orgMembersTemplate {
t.Errorf("Expected view to be %s, got %s", orgMembersTemplate, viewModel.View)
}
renderCtx, ok := viewModel.Model.(*orgMemberRenderContext)
if !ok {
t.Fatalf("Expected Model to be *orgMemberRenderContext, got %T", viewModel.Model)
}
if !renderCtx.CanEdit {
t.Error("Expected CanEdit to be true for org owner")
}
}
func TestGetOrgSettings(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/tab/settings", server.IDHasher.Encrypt(int(org.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getOrgSettings(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != orgSettingsTemplate {
t.Errorf("Expected view to be %s, got %s", orgSettingsTemplate, viewModel.View)
}
renderCtx, ok := viewModel.Model.(*orgSettingsRenderContext)
if !ok {
t.Fatalf("Expected Model to be *orgSettingsRenderContext, got %T", viewModel.Model)
}
if !renderCtx.CanEdit {
t.Error("Expected CanEdit to be true for org owner")
}
if viewModel.AuditEvent == nil {
t.Error("Expected AuditEvent to be populated")
}
}
func TestGetOrgAuditLogs(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/tab/events", server.IDHasher.Encrypt(int(org.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getOrgAuditLogs(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != orgAuditLogsTemplate {
t.Errorf("Expected view to be %s, got %s", orgAuditLogsTemplate, viewModel.View)
}
renderCtx, ok := viewModel.Model.(*orgAuditLogsRenderContext)
if !ok {
t.Fatalf("Expected Model to be *orgAuditLogsRenderContext, got %T", viewModel.Model)
}
if !renderCtx.CanView {
t.Error("Expected CanView to be true for org owner")
}
}
func TestPutOrg(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
newName := t.Name() + "-updated"
form := url.Values{}
form.Set(common.ParamCSRFToken, server.XSRF.Token(strconv.Itoa(int(user.ID))))
form.Set(common.ParamName, newName)
req := httptest.NewRequest("PUT", fmt.Sprintf("/org/%s/edit", server.IDHasher.Encrypt(int(org.ID))), strings.NewReader(form.Encode()))
req.AddCookie(cookie)
req.Header.Set(common.HeaderContentType, common.ContentTypeURLEncoded)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
w := httptest.NewRecorder()
viewModel, err := server.putOrg(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != orgSettingsTemplate {
t.Errorf("Expected view to be %s, got %s", orgSettingsTemplate, viewModel.View)
}
renderCtx, ok := viewModel.Model.(*orgSettingsRenderContext)
if !ok {
t.Fatalf("Expected Model to be *orgSettingsRenderContext, got %T", viewModel.Model)
}
if renderCtx.CurrentOrg.Name != newName {
t.Errorf("Expected org name to be %s, got %s", newName, renderCtx.CurrentOrg.Name)
}
if viewModel.AuditEvent == nil {
t.Error("Expected AuditEvent to be populated")
}
}
func TestPostNewOrg(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
// Use admin plan with higher org limits to allow creating additional orgs
adminPlan := server.PlanService.GetInternalAdminPlan()
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), adminPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
orgName := t.Name() + "-new-org"
form := url.Values{}
form.Set(common.ParamCSRFToken, server.XSRF.Token(strconv.Itoa(int(user.ID))))
form.Set(common.ParamName, orgName)
req := httptest.NewRequest("POST", "/org/new", strings.NewReader(form.Encode()))
req.AddCookie(cookie)
req.Header.Set(common.HeaderContentType, common.ContentTypeURLEncoded)
w := httptest.NewRecorder()
srv.ServeHTTP(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusSeeOther {
t.Errorf("Unexpected status code %v", resp.StatusCode)
}
location, err := resp.Location()
if err != nil {
t.Fatalf("Expected redirect response but got error: %v", err)
}
if !strings.HasPrefix(location.String(), "/org/") {
t.Errorf("Unexpected redirect path: %s", location.String())
}
}
func TestJoinOrg(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
owner, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name()+"_1", testPlan)
if err != nil {
t.Fatalf("Failed to create owner account: %v", err)
}
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name()+"_2", testPlan)
if err != nil {
t.Fatalf("Failed to create user account: %v", err)
}
if _, err := store.Impl().InviteUserToOrg(ctx, owner, org, user); err != nil {
t.Fatal(err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("PUT", fmt.Sprintf("/org/%s/members", server.IDHasher.Encrypt(int(org.ID))), nil)
req.AddCookie(cookie)
req.Header.Set(common.HeaderCSRFToken, server.XSRF.Token(strconv.Itoa(int(user.ID))))
w := httptest.NewRecorder()
srv.ServeHTTP(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusSeeOther {
t.Errorf("Unexpected status code %v", resp.StatusCode)
}
members, err := store.Impl().RetrieveOrganizationUsers(ctx, org.ID)
if err != nil {
t.Fatal(err)
}
hasUser := false
for _, m := range members {
if m.User.ID == user.ID && m.Level == dbgen.AccessLevelMember {
hasUser = true
break
}
}
if !hasUser {
t.Error("User should be a member of the org after joining")
}
}
func TestLeaveOrg(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
owner, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name()+"_1", testPlan)
if err != nil {
t.Fatalf("Failed to create owner account: %v", err)
}
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name()+"_2", testPlan)
if err != nil {
t.Fatalf("Failed to create user account: %v", err)
}
if _, err := store.Impl().InviteUserToOrg(ctx, owner, org, user); err != nil {
t.Fatal(err)
}
if _, err := store.Impl().JoinOrg(ctx, org.ID, user); err != nil {
t.Fatal(err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("DELETE", fmt.Sprintf("/org/%s/members", server.IDHasher.Encrypt(int(org.ID))), nil)
req.AddCookie(cookie)
req.Header.Set(common.HeaderCSRFToken, server.XSRF.Token(strconv.Itoa(int(user.ID))))
w := httptest.NewRecorder()
srv.ServeHTTP(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusSeeOther {
t.Errorf("Unexpected status code %v", resp.StatusCode)
}
members, err := store.Impl().RetrieveOrganizationUsers(ctx, org.ID)
if err != nil {
t.Fatal(err)
}
for _, m := range members {
if m.User.ID == user.ID && m.Level == dbgen.AccessLevelMember {
t.Error("User should have left the org (level should change from member to invited)")
}
}
}
func TestDeleteOrg(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
// Use admin plan to allow creating extra org
adminPlan := server.PlanService.GetInternalAdminPlan()
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), adminPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
org, _, err := store.Impl().CreateNewOrganization(ctx, t.Name()+"-delete-org", user.ID)
if err != nil {
t.Fatalf("Failed to create extra org: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("DELETE", fmt.Sprintf("/org/%s/delete", server.IDHasher.Encrypt(int(org.ID))), nil)
req.AddCookie(cookie)
req.Header.Set(common.HeaderCSRFToken, server.XSRF.Token(strconv.Itoa(int(user.ID))))
w := httptest.NewRecorder()
srv.ServeHTTP(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusSeeOther {
t.Errorf("Unexpected status code %v", resp.StatusCode)
}
orgs, err := store.Impl().RetrieveUserOrganizations(ctx, user.ID)
if err != nil {
t.Fatal(err)
}
for _, o := range orgs {
if o.Organization.ID == org.ID {
t.Error("Org should have been deleted")
}
}
}

View File

@@ -413,3 +413,384 @@ func TestGetPropertyStats(t *testing.T) {
t.Errorf("Expected 2 total verified, got %d", totalVerified)
}
}
func TestGetOrgProperty(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
property, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org)
if err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/property/%s", server.IDHasher.Encrypt(int(org.ID)), server.IDHasher.Encrypt(int(property.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
req.SetPathValue(common.ParamProperty, server.IDHasher.Encrypt(int(property.ID)))
w := httptest.NewRecorder()
renderCtx, dbProperty, err := server.getOrgProperty(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if renderCtx == nil {
t.Fatal("Expected render context to be populated, got nil")
}
if dbProperty == nil {
t.Fatal("Expected property to be populated, got nil")
}
if dbProperty.ID != property.ID {
t.Errorf("Expected property ID to be %d, got %d", property.ID, dbProperty.ID)
}
if renderCtx.Property == nil {
t.Fatal("Expected Property in render context to be populated, got nil")
}
if !renderCtx.CanEdit {
t.Error("Expected CanEdit to be true for property creator")
}
}
func TestGetOrgPropertySettings(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
property, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org)
if err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/property/%s/tab/settings", server.IDHasher.Encrypt(int(org.ID)), server.IDHasher.Encrypt(int(property.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
req.SetPathValue(common.ParamProperty, server.IDHasher.Encrypt(int(property.ID)))
w := httptest.NewRecorder()
renderCtx, auditEvent, err := server.getOrgPropertySettings(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if renderCtx == nil {
t.Fatal("Expected render context to be populated, got nil")
}
if renderCtx.Tab != propertySettingsTabIndex {
t.Errorf("Expected tab to be %d, got %d", propertySettingsTabIndex, renderCtx.Tab)
}
if auditEvent == nil {
t.Error("Expected audit event to be populated")
}
}
func TestGetPropertyDashboard(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
property, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org)
if err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/property/%s", server.IDHasher.Encrypt(int(org.ID)), server.IDHasher.Encrypt(int(property.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
req.SetPathValue(common.ParamProperty, server.IDHasher.Encrypt(int(property.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getPropertyDashboard(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != propertyDashboardTemplate {
t.Errorf("Expected view to be %s, got %s", propertyDashboardTemplate, viewModel.View)
}
}
func TestGetPropertyReportsTab(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
property, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org)
if err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/property/%s/tab/reports", server.IDHasher.Encrypt(int(org.ID)), server.IDHasher.Encrypt(int(property.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
req.SetPathValue(common.ParamProperty, server.IDHasher.Encrypt(int(property.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getPropertyReportsTab(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != propertyDashboardReportsTemplate {
t.Errorf("Expected view to be %s, got %s", propertyDashboardReportsTemplate, viewModel.View)
}
}
func TestGetPropertySettingsTab(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
property, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org)
if err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/property/%s/tab/settings", server.IDHasher.Encrypt(int(org.ID)), server.IDHasher.Encrypt(int(property.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
req.SetPathValue(common.ParamProperty, server.IDHasher.Encrypt(int(property.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getPropertySettingsTab(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != propertyDashboardSettingsTemplate {
t.Errorf("Expected view to be %s, got %s", propertyDashboardSettingsTemplate, viewModel.View)
}
if viewModel.AuditEvent == nil {
t.Error("Expected AuditEvent to be populated")
}
}
func TestGetPropertyIntegrationsTab(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
property, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org)
if err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/property/%s/tab/integrations", server.IDHasher.Encrypt(int(org.ID)), server.IDHasher.Encrypt(int(property.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
req.SetPathValue(common.ParamProperty, server.IDHasher.Encrypt(int(property.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getPropertyIntegrationsTab(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != propertyDashboardIntegrationsTemplate {
t.Errorf("Expected view to be %s, got %s", propertyDashboardIntegrationsTemplate, viewModel.View)
}
}
func TestGetPropertyAuditLogsTab(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
property, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org)
if err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", fmt.Sprintf("/org/%s/property/%s/tab/events", server.IDHasher.Encrypt(int(org.ID)), server.IDHasher.Encrypt(int(property.ID))), nil)
req.AddCookie(cookie)
req.SetPathValue(common.ParamOrg, server.IDHasher.Encrypt(int(org.ID)))
req.SetPathValue(common.ParamProperty, server.IDHasher.Encrypt(int(property.ID)))
w := httptest.NewRecorder()
viewModel, err := server.getPropertyAuditLogsTab(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if viewModel.View != propertyDashboardAuditLogsTemplate {
t.Errorf("Expected view to be %s, got %s", propertyDashboardAuditLogsTemplate, viewModel.View)
}
}
func TestDeleteProperty(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := t.Context()
user, org, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
property, _, err := server.Store.Impl().CreateNewProperty(ctx, db_tests.CreateNewPropertyParams(user.ID, "example.com"), org)
if err != nil {
t.Fatalf("Failed to create new property: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("DELETE", fmt.Sprintf("/org/%s/property/%s/delete", server.IDHasher.Encrypt(int(org.ID)), server.IDHasher.Encrypt(int(property.ID))), nil)
req.AddCookie(cookie)
req.Header.Set(common.HeaderCSRFToken, server.XSRF.Token(strconv.Itoa(int(user.ID))))
w := httptest.NewRecorder()
srv.ServeHTTP(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusSeeOther {
t.Errorf("Unexpected status code %v", resp.StatusCode)
}
properties, _, err := store.Impl().RetrieveOrgProperties(ctx, org, 0, db.MaxOrgPropertiesPageSize)
if err != nil {
t.Fatal(err)
}
if len(properties) != 0 {
t.Error("Property should have been deleted")
}
}

View File

@@ -181,3 +181,178 @@ func TestRotateAPIKey(t *testing.T) {
t.Error("Key external ID was not rotated")
}
}
func TestGetSettings(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := common.TraceContext(t.Context(), t.Name())
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", "/settings", nil)
req.AddCookie(cookie)
w := httptest.NewRecorder()
viewModel, err := server.getSettings(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
if !strings.HasSuffix(viewModel.View, "page.html") {
t.Errorf("Expected view to end with page.html, got %s", viewModel.View)
}
}
func TestGetGeneralSettings(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := common.TraceContext(t.Context(), t.Name())
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", "/settings/tab/general", nil)
req.AddCookie(cookie)
w := httptest.NewRecorder()
viewModel, err := server.getGeneralSettings(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
renderCtx, ok := viewModel.Model.(*settingsGeneralRenderContext)
if !ok {
t.Fatalf("Expected Model to be *settingsGeneralRenderContext, got %T", viewModel.Model)
}
if renderCtx.Name != user.Name {
t.Errorf("Expected Name to be %s, got %s", user.Name, renderCtx.Name)
}
if viewModel.AuditEvent == nil {
t.Error("Expected AuditEvent to be populated")
}
}
func TestGetAPIKeysSettings(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := common.TraceContext(t.Context(), t.Name())
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", "/settings/tab/apikeys", nil)
req.AddCookie(cookie)
w := httptest.NewRecorder()
viewModel, err := server.getAPIKeysSettings(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
renderCtx, ok := viewModel.Model.(*settingsAPIKeysRenderContext)
if !ok {
t.Fatalf("Expected Model to be *settingsAPIKeysRenderContext, got %T", viewModel.Model)
}
if renderCtx.Keys == nil {
t.Error("Expected Keys to be initialized (even if empty)")
}
if viewModel.AuditEvent == nil {
t.Error("Expected AuditEvent to be populated")
}
}
func TestGetUsageSettings(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := common.TraceContext(t.Context(), t.Name())
user, _, err := db_tests.CreateNewAccountForTest(ctx, store, t.Name(), testPlan)
if err != nil {
t.Fatalf("Failed to create account: %v", err)
}
srv := http.NewServeMux()
server.Setup(portalDomain(), common.NoopMiddleware).Register(srv)
cookie, err := portal_tests.AuthenticateSuite(ctx, user.Email, srv, server.XSRF, server.Sessions.CookieName, server.Mailer.(*email.StubMailer))
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", "/settings/tab/usage", nil)
req.AddCookie(cookie)
w := httptest.NewRecorder()
viewModel, err := server.getUsageSettings(w, req)
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
if viewModel == nil {
t.Fatal("Expected ViewModel to be populated, got nil")
}
renderCtx, ok := viewModel.Model.(*settingsUsageRenderContext)
if !ok {
t.Fatalf("Expected Model to be *settingsUsageRenderContext, got %T", viewModel.Model)
}
if renderCtx.OrgsCount == 0 {
t.Error("Expected OrgsCount to be at least 1")
}
}