snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
1
server/store/tests/.gitignore
vendored
Normal file
1
server/store/tests/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.env
|
||||
129
server/store/tests/actionlog_test.go
Normal file
129
server/store/tests/actionlog_test.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/actionlog"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testActionlogs(t *testing.T, s store.Actionlogs) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(id uint64) *actionlog.Action {
|
||||
// minimum data set for new user
|
||||
return &actionlog.Action{
|
||||
ID: id,
|
||||
Timestamp: *now(),
|
||||
Action: "test-action",
|
||||
Resource: "test-resource",
|
||||
}
|
||||
}
|
||||
|
||||
stringifySetRange = func(set actionlog.ActionSet) string {
|
||||
if len(set) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var out = strconv.FormatUint(set[0].ID, 10)
|
||||
|
||||
if len(set) > 1 {
|
||||
out += ".." + strconv.FormatUint(set[len(set)-1].ID, 10)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, actionlog.ActionSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateActionlogs(ctx))
|
||||
|
||||
set := make([]*actionlog.Action, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew(uint64(i))
|
||||
}
|
||||
|
||||
req.NoError(s.CreateActionlog(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateActionlogs(ctx))
|
||||
action := &actionlog.Action{
|
||||
ID: 42,
|
||||
Timestamp: time.Now(),
|
||||
Resource: "resource",
|
||||
Action: "action",
|
||||
}
|
||||
req.NoError(s.CreateActionlog(ctx, action))
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Run("by resource", func(t *testing.T) {
|
||||
req, set := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchActionlogs(ctx, actionlog.Filter{Resource: "test-resource"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
})
|
||||
|
||||
t.Run("by action", func(t *testing.T) {
|
||||
req, set := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchActionlogs(ctx, actionlog.Filter{Action: "test-action"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
})
|
||||
|
||||
t.Run("with paging", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateActionlogs(ctx))
|
||||
|
||||
set := []*actionlog.Action{
|
||||
makeNew(1),
|
||||
makeNew(2),
|
||||
makeNew(3),
|
||||
makeNew(4),
|
||||
makeNew(5),
|
||||
makeNew(6),
|
||||
makeNew(7),
|
||||
makeNew(8),
|
||||
makeNew(9),
|
||||
}
|
||||
|
||||
req.NoError(s.CreateActionlog(ctx, set...))
|
||||
f := actionlog.Filter{}
|
||||
|
||||
// Fetch first page
|
||||
f.Limit = 1
|
||||
set, f, err := store.SearchActionlogs(ctx, s, f)
|
||||
req.NoError(err)
|
||||
req.Len(set, int(f.Limit))
|
||||
req.Equal("9", stringifySetRange(set))
|
||||
|
||||
f.Limit = 3
|
||||
f.BeforeActionID = set[0].ID
|
||||
set, f, err = store.SearchActionlogs(ctx, s, f)
|
||||
req.NoError(err)
|
||||
req.Len(set, int(f.Limit))
|
||||
req.Equal("8..6", stringifySetRange(set))
|
||||
|
||||
f.Limit = 9
|
||||
f.BeforeActionID = set[2].ID
|
||||
set, f, err = store.SearchActionlogs(ctx, s, f)
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
req.Equal("5..1", stringifySetRange(set))
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
155
server/store/tests/all_test.go
Normal file
155
server/store/tests/all_test.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package tests
|
||||
|
||||
// This file is auto-generated.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
//
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func testAllGenerated(t *testing.T, s store.Storer) {
|
||||
|
||||
t.Run("actionlog", func(t *testing.T) {
|
||||
testActionlogs(t, s)
|
||||
})
|
||||
t.Run("apigwFilter", func(t *testing.T) {
|
||||
testApigwFilters(t, s)
|
||||
})
|
||||
t.Run("apigwRoute", func(t *testing.T) {
|
||||
testApigwRoutes(t, s)
|
||||
})
|
||||
t.Run("application", func(t *testing.T) {
|
||||
testApplications(t, s)
|
||||
})
|
||||
t.Run("attachment", func(t *testing.T) {
|
||||
testAttachments(t, s)
|
||||
})
|
||||
t.Run("authClient", func(t *testing.T) {
|
||||
testAuthClients(t, s)
|
||||
})
|
||||
t.Run("authConfirmedClient", func(t *testing.T) {
|
||||
testAuthConfirmedClients(t, s)
|
||||
})
|
||||
t.Run("authOa2token", func(t *testing.T) {
|
||||
testAuthOa2tokens(t, s)
|
||||
})
|
||||
t.Run("authSession", func(t *testing.T) {
|
||||
testAuthSessions(t, s)
|
||||
})
|
||||
t.Run("automationSession", func(t *testing.T) {
|
||||
testAutomationSessions(t, s)
|
||||
})
|
||||
t.Run("automationTrigger", func(t *testing.T) {
|
||||
testAutomationTriggers(t, s)
|
||||
})
|
||||
t.Run("automationWorkflow", func(t *testing.T) {
|
||||
testAutomationWorkflows(t, s)
|
||||
})
|
||||
t.Run("composeAttachment", func(t *testing.T) {
|
||||
testComposeAttachments(t, s)
|
||||
})
|
||||
t.Run("composeChart", func(t *testing.T) {
|
||||
testComposeCharts(t, s)
|
||||
})
|
||||
t.Run("composeModule", func(t *testing.T) {
|
||||
testComposeModules(t, s)
|
||||
})
|
||||
t.Run("composeModuleField", func(t *testing.T) {
|
||||
testComposeModuleFields(t, s)
|
||||
})
|
||||
t.Run("composeNamespace", func(t *testing.T) {
|
||||
testComposeNamespaces(t, s)
|
||||
})
|
||||
t.Run("composePage", func(t *testing.T) {
|
||||
testComposePages(t, s)
|
||||
})
|
||||
t.Run("composePageLayout", func(t *testing.T) {
|
||||
testComposePageLayouts(t, s)
|
||||
})
|
||||
t.Run("credential", func(t *testing.T) {
|
||||
testCredentials(t, s)
|
||||
})
|
||||
t.Run("dalConnection", func(t *testing.T) {
|
||||
testDalConnections(t, s)
|
||||
})
|
||||
t.Run("dalSchemaAlteration", func(t *testing.T) {
|
||||
testDalSchemaAlterations(t, s)
|
||||
})
|
||||
t.Run("dalSensitivityLevel", func(t *testing.T) {
|
||||
testDalSensitivityLevels(t, s)
|
||||
})
|
||||
t.Run("dataPrivacyRequest", func(t *testing.T) {
|
||||
testDataPrivacyRequests(t, s)
|
||||
})
|
||||
t.Run("dataPrivacyRequestComment", func(t *testing.T) {
|
||||
testDataPrivacyRequestComments(t, s)
|
||||
})
|
||||
t.Run("federationExposedModule", func(t *testing.T) {
|
||||
testFederationExposedModules(t, s)
|
||||
})
|
||||
t.Run("federationModuleMapping", func(t *testing.T) {
|
||||
testFederationModuleMappings(t, s)
|
||||
})
|
||||
t.Run("federationNode", func(t *testing.T) {
|
||||
testFederationNodes(t, s)
|
||||
})
|
||||
t.Run("federationNodeSync", func(t *testing.T) {
|
||||
testFederationNodeSyncs(t, s)
|
||||
})
|
||||
t.Run("federationSharedModule", func(t *testing.T) {
|
||||
testFederationSharedModules(t, s)
|
||||
})
|
||||
t.Run("flag", func(t *testing.T) {
|
||||
testFlags(t, s)
|
||||
})
|
||||
t.Run("label", func(t *testing.T) {
|
||||
testLabels(t, s)
|
||||
})
|
||||
t.Run("notification", func(t *testing.T) {
|
||||
testNotifications(t, s)
|
||||
})
|
||||
t.Run("queue", func(t *testing.T) {
|
||||
testQueues(t, s)
|
||||
})
|
||||
t.Run("queueMessage", func(t *testing.T) {
|
||||
testQueueMessages(t, s)
|
||||
})
|
||||
t.Run("rbacRule", func(t *testing.T) {
|
||||
testRbacRules(t, s)
|
||||
})
|
||||
t.Run("reminder", func(t *testing.T) {
|
||||
testReminders(t, s)
|
||||
})
|
||||
t.Run("report", func(t *testing.T) {
|
||||
testReports(t, s)
|
||||
})
|
||||
t.Run("resourceActivity", func(t *testing.T) {
|
||||
testResourceActivitys(t, s)
|
||||
})
|
||||
t.Run("resourceTranslation", func(t *testing.T) {
|
||||
testResourceTranslations(t, s)
|
||||
})
|
||||
t.Run("role", func(t *testing.T) {
|
||||
testRoles(t, s)
|
||||
})
|
||||
t.Run("roleMember", func(t *testing.T) {
|
||||
testRoleMembers(t, s)
|
||||
})
|
||||
t.Run("settingValue", func(t *testing.T) {
|
||||
testSettingValues(t, s)
|
||||
})
|
||||
t.Run("template", func(t *testing.T) {
|
||||
testTemplates(t, s)
|
||||
})
|
||||
t.Run("user", func(t *testing.T) {
|
||||
testUsers(t, s)
|
||||
})
|
||||
t.Run("userGroup", func(t *testing.T) {
|
||||
testUserGroups(t, s)
|
||||
})
|
||||
}
|
||||
85
server/store/tests/apigw_filter_test.go
Normal file
85
server/store/tests/apigw_filter_test.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testApigwFilters(t *testing.T, s store.ApigwFilters) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
new = &types.ApigwFilter{
|
||||
ID: 42,
|
||||
Enabled: true,
|
||||
CreatedAt: time.Now(),
|
||||
CreatedBy: 1}
|
||||
disabled = &types.ApigwFilter{
|
||||
ID: 4242,
|
||||
Enabled: false,
|
||||
CreatedAt: time.Now(),
|
||||
CreatedBy: 1}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwFilters(ctx))
|
||||
req.NoError(s.CreateApigwFilter(ctx, new))
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwFilters(ctx))
|
||||
req.NoError(s.UpdateApigwFilter(ctx, new))
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwFilters(ctx))
|
||||
req.NoError(s.CreateApigwFilter(ctx,
|
||||
new,
|
||||
))
|
||||
|
||||
set, _, err := s.SearchApigwFilters(ctx, types.ApigwFilterFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("search only disabled", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwFilters(ctx))
|
||||
req.NoError(s.CreateApigwFilter(ctx,
|
||||
disabled,
|
||||
))
|
||||
|
||||
set, _, err := s.SearchApigwFilters(ctx, types.ApigwFilterFilter{
|
||||
Disabled: filter.StateExclusive,
|
||||
})
|
||||
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.Equal(set[0].ID, disabled.ID)
|
||||
})
|
||||
|
||||
t.Run("search enabled and disabled", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwFilters(ctx))
|
||||
req.NoError(s.CreateApigwFilter(ctx,
|
||||
new,
|
||||
disabled,
|
||||
))
|
||||
|
||||
set, _, err := s.SearchApigwFilters(ctx, types.ApigwFilterFilter{
|
||||
Disabled: filter.StateInclusive,
|
||||
})
|
||||
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
})
|
||||
}
|
||||
113
server/store/tests/apigw_route_test.go
Normal file
113
server/store/tests/apigw_route_test.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testApigwRoutes(t *testing.T, s store.ApigwRoutes) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
new = &types.ApigwRoute{
|
||||
CreatedAt: *now(),
|
||||
ID: 42,
|
||||
Endpoint: "/foo",
|
||||
Enabled: true,
|
||||
CreatedBy: 1}
|
||||
|
||||
disabled = &types.ApigwRoute{
|
||||
CreatedAt: *now(),
|
||||
ID: 4242,
|
||||
Endpoint: "/foo_disabled",
|
||||
Enabled: false,
|
||||
CreatedBy: 1}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwRoutes(ctx))
|
||||
req.NoError(s.CreateApigwRoute(ctx, new))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwRoutes(ctx))
|
||||
req.NoError(s.CreateApigwRoute(ctx, new))
|
||||
fetched, err := s.LookupApigwRouteByID(ctx, new.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(new.ID, fetched.ID)
|
||||
req.Equal(new.Endpoint, fetched.Endpoint)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("lookup by endpoint", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwRoutes(ctx))
|
||||
req.NoError(s.CreateApigwRoute(ctx, new))
|
||||
fetched, err := s.LookupApigwRouteByEndpoint(ctx, new.Endpoint)
|
||||
req.NoError(err)
|
||||
req.Equal(new.ID, fetched.ID)
|
||||
req.Equal(new.Endpoint, fetched.Endpoint)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwRoutes(ctx))
|
||||
req.NoError(s.UpdateApigwRoute(ctx, new))
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwRoutes(ctx))
|
||||
req.NoError(s.CreateApigwRoute(ctx,
|
||||
new,
|
||||
))
|
||||
|
||||
set, _, err := s.SearchApigwRoutes(ctx, types.ApigwRouteFilter{Endpoint: "fo"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("search only disabled", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwRoutes(ctx))
|
||||
req.NoError(s.CreateApigwRoute(ctx,
|
||||
disabled,
|
||||
))
|
||||
|
||||
set, _, err := s.SearchApigwRoutes(ctx, types.ApigwRouteFilter{
|
||||
Disabled: filter.StateExclusive,
|
||||
})
|
||||
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.Equal(set[0].ID, disabled.ID)
|
||||
})
|
||||
|
||||
t.Run("search enabled and disabled", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApigwRoutes(ctx))
|
||||
req.NoError(s.CreateApigwRoute(ctx,
|
||||
new,
|
||||
disabled,
|
||||
))
|
||||
|
||||
set, _, err := s.SearchApigwRoutes(ctx, types.ApigwRouteFilter{
|
||||
Disabled: filter.StateInclusive,
|
||||
})
|
||||
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
})
|
||||
}
|
||||
172
server/store/tests/applications_test.go
Normal file
172
server/store/tests/applications_test.go
Normal file
@@ -0,0 +1,172 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testApplications(t *testing.T, s store.Applications) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(name string) *types.Application {
|
||||
// minimum data set for new application
|
||||
return &types.Application{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Name: name,
|
||||
Unify: &types.ApplicationUnify{},
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Application) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateApplications(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateApplication(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
application := makeNew("ApplicationCRUD")
|
||||
req.NoError(s.CreateApplication(ctx, application))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, application := truncAndCreate(t)
|
||||
fetched, err := s.LookupApplicationByID(ctx, application.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(application.Name, fetched.Name)
|
||||
req.Equal(application.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, application := truncAndCreate(t)
|
||||
application.Name = "ApplicationCRUD+2"
|
||||
|
||||
req.NoError(s.UpdateApplication(ctx, application))
|
||||
|
||||
updated, err := s.LookupApplicationByID(ctx, application.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(application.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, application := truncAndCreate(t)
|
||||
application.Name = "ApplicationCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertApplication(ctx, application))
|
||||
|
||||
updated, err := s.LookupApplicationByID(ctx, application.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(application.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
application := makeNew("upsert me")
|
||||
application.Name = "ComposeChartCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertApplication(ctx, application))
|
||||
|
||||
upserted, err := s.LookupApplicationByID(ctx, application.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(application.Name, upserted.Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Application", func(t *testing.T) {
|
||||
req, application := truncAndCreate(t)
|
||||
req.NoError(s.DeleteApplication(ctx, application))
|
||||
_, err := s.LookupApplicationByID(ctx, application.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, application := truncAndCreate(t)
|
||||
req.NoError(s.DeleteApplicationByID(ctx, application.ID))
|
||||
_, err := s.LookupApplicationByID(ctx, application.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Application{
|
||||
makeNew("/one-one"),
|
||||
makeNew("/one-two"),
|
||||
makeNew("/two-one"),
|
||||
makeNew("/two-two"),
|
||||
makeNew("/two-deleted"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateApplications(ctx))
|
||||
req.NoError(s.CreateApplication(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchApplications(ctx, types.ApplicationFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchApplications(ctx, types.ApplicationFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchApplications(ctx, types.ApplicationFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, f, err = s.SearchApplications(ctx, types.ApplicationFilter{Name: "/two-one"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchApplications(ctx, types.ApplicationFilter{Query: "/two"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
|
||||
t.Run("metrics", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
|
||||
e = &types.ApplicationMetrics{
|
||||
Total: 5,
|
||||
Valid: 2,
|
||||
Deleted: 3,
|
||||
}
|
||||
)
|
||||
|
||||
req.NoError(s.TruncateApplications(ctx))
|
||||
req.NoError(s.CreateApplication(ctx, &types.Application{ID: id.Next(), CreatedAt: *now(), UpdatedAt: now(), Unify: &types.ApplicationUnify{}}))
|
||||
req.NoError(s.CreateApplication(ctx, &types.Application{ID: id.Next(), CreatedAt: *now(), UpdatedAt: now(), Unify: &types.ApplicationUnify{}}))
|
||||
req.NoError(s.CreateApplication(ctx, &types.Application{ID: id.Next(), CreatedAt: *now(), DeletedAt: now(), Unify: &types.ApplicationUnify{}}))
|
||||
req.NoError(s.CreateApplication(ctx, &types.Application{ID: id.Next(), CreatedAt: *now(), DeletedAt: now(), Unify: &types.ApplicationUnify{}}))
|
||||
req.NoError(s.CreateApplication(ctx, &types.Application{ID: id.Next(), CreatedAt: *now(), DeletedAt: now(), Unify: &types.ApplicationUnify{}}))
|
||||
|
||||
m, err := store.ApplicationMetrics(ctx, s)
|
||||
req.NoError(err)
|
||||
req.Equal(e, m)
|
||||
})
|
||||
}
|
||||
147
server/store/tests/attachments_test.go
Normal file
147
server/store/tests/attachments_test.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testAttachments(t *testing.T, s store.Attachments) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(nn ...string) *types.Attachment {
|
||||
name := strings.Join(nn, "")
|
||||
return &types.Attachment{
|
||||
ID: id.Next(),
|
||||
Name: "handle_" + name,
|
||||
Kind: "test-kind" + name,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Attachment) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAttachments(ctx))
|
||||
attachment := makeNew()
|
||||
req.NoError(s.CreateAttachment(ctx, attachment))
|
||||
return req, attachment
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, types.AttachmentSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAttachments(ctx))
|
||||
|
||||
set := make([]*types.Attachment, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew(string(rand.Bytes(10)))
|
||||
}
|
||||
|
||||
req.NoError(s.CreateAttachment(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.CreateAttachment(ctx, makeNew()))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
fetched, err := s.LookupAttachmentByID(ctx, att.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(att.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
att.Url = "url"
|
||||
req.NoError(s.UpdateAttachment(ctx, att))
|
||||
fetched, err := s.LookupAttachmentByID(ctx, att.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(att.ID, fetched.ID)
|
||||
req.Equal("url", fetched.Url)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
att.Url = "url"
|
||||
|
||||
req.NoError(s.UpsertAttachment(ctx, att))
|
||||
|
||||
upserted, err := s.LookupAttachmentByID(ctx, att.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(att.Name, upserted.Name)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
att := makeNew("upsert me", "upsert-me")
|
||||
|
||||
req.NoError(s.UpsertAttachment(ctx, att))
|
||||
|
||||
upserted, err := s.LookupAttachmentByID(ctx, att.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(att.Name, upserted.Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Attachment", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAttachment(ctx, att))
|
||||
_, err := s.LookupAttachmentByID(ctx, att.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAttachmentByID(ctx, att.ID))
|
||||
_, err := s.LookupAttachmentByID(ctx, att.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Run("by kind", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchAttachments(ctx, types.AttachmentFilter{Kind: prefill[0].Kind})
|
||||
req.NoError(err)
|
||||
req.Equal(prefill[0].Kind, f.Kind)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("with check", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchAttachments(ctx, types.AttachmentFilter{
|
||||
Check: func(attachment *types.Attachment) (bool, error) {
|
||||
return attachment.Kind == prefill[0].Kind, nil
|
||||
},
|
||||
})
|
||||
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.Equal(prefill[0].Kind, set[0].Kind)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("ordered search", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
}
|
||||
145
server/store/tests/auth_clients.go
Normal file
145
server/store/tests/auth_clients.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testAuthClients(t *testing.T, s store.AuthClients) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(handle string) *types.AuthClient {
|
||||
// minimum data set for new authClient
|
||||
return &types.AuthClient{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.AuthClient) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAuthClients(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateAuthClient(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req.NoError(s.TruncateAuthClients(ctx))
|
||||
authClient := makeNew("AuthClientCRUD")
|
||||
req.NoError(s.CreateAuthClient(ctx, authClient))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, authClient := truncAndCreate(t)
|
||||
fetched, err := s.LookupAuthClientByID(ctx, authClient.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(authClient.Handle, fetched.Handle)
|
||||
req.Equal(authClient.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, authClient := truncAndCreate(t)
|
||||
authClient.Handle = "AuthClientCRUD-2"
|
||||
|
||||
req.NoError(s.UpdateAuthClient(ctx, authClient))
|
||||
|
||||
updated, err := s.LookupAuthClientByID(ctx, authClient.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(authClient.Handle, updated.Handle)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, authClient := truncAndCreate(t)
|
||||
authClient.Handle = "AuthClientCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertAuthClient(ctx, authClient))
|
||||
|
||||
updated, err := s.LookupAuthClientByID(ctx, authClient.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(authClient.Handle, updated.Handle)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
authClient := makeNew("upsert me")
|
||||
authClient.Handle = "ComposeChartCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertAuthClient(ctx, authClient))
|
||||
|
||||
upserted, err := s.LookupAuthClientByID(ctx, authClient.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(authClient.Handle, upserted.Handle)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by AuthClient", func(t *testing.T) {
|
||||
req, authClient := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAuthClient(ctx, authClient))
|
||||
_, err := s.LookupAuthClientByID(ctx, authClient.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, authClient := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAuthClientByID(ctx, authClient.ID))
|
||||
_, err := s.LookupAuthClientByID(ctx, authClient.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.AuthClient{
|
||||
makeNew("/one-one"),
|
||||
makeNew("/one-two"),
|
||||
makeNew("/two-one"),
|
||||
makeNew("/two-two"),
|
||||
makeNew("/two-deleted"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateAuthClients(ctx))
|
||||
req.NoError(s.CreateAuthClient(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchAuthClients(ctx, types.AuthClientFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchAuthClients(ctx, types.AuthClientFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchAuthClients(ctx, types.AuthClientFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, f, err = s.SearchAuthClients(ctx, types.AuthClientFilter{Handle: "/two-one"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
55
server/store/tests/auth_confirmed_clients.go
Normal file
55
server/store/tests/auth_confirmed_clients.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testAuthConfirmedClients(t *testing.T, s store.AuthConfirmedClients) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(c, u uint64) *types.AuthConfirmedClient {
|
||||
// minimum data set for new authConfirmedClient
|
||||
return &types.AuthConfirmedClient{
|
||||
ClientID: c,
|
||||
UserID: u,
|
||||
ConfirmedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.AuthConfirmedClient) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAuthConfirmedClients(ctx))
|
||||
res := makeNew(1, 2)
|
||||
req.NoError(s.CreateAuthConfirmedClient(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, acc := truncAndCreate(t)
|
||||
fetched, err := s.LookupAuthConfirmedClientByUserIDClientID(ctx, acc.UserID, acc.ClientID)
|
||||
req.NoError(err)
|
||||
req.NotNil(fetched)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, authConfirmedClient := truncAndCreate(t)
|
||||
req.NoError(s.UpsertAuthConfirmedClient(ctx, authConfirmedClient))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by client and user ID", func(t *testing.T) {
|
||||
req, acc := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAuthConfirmedClientByUserIDClientID(ctx, acc.UserID, acc.ClientID))
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
88
server/store/tests/auth_oa2tokens.go
Normal file
88
server/store/tests/auth_oa2tokens.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testAuthOa2tokens(t *testing.T, s store.AuthOa2tokens) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func() *types.AuthOa2token {
|
||||
// minimum data set for new authOa2token
|
||||
return &types.AuthOa2token{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
ExpiresAt: time.Now(),
|
||||
Access: string(rand.Bytes(5)),
|
||||
Code: string(rand.Bytes(5)),
|
||||
Refresh: string(rand.Bytes(5)),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.AuthOa2token) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAuthOa2tokens(ctx))
|
||||
res := makeNew()
|
||||
req.NoError(s.CreateAuthOa2token(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
authOa2token := makeNew()
|
||||
req.NoError(s.CreateAuthOa2token(ctx, authOa2token))
|
||||
})
|
||||
|
||||
t.Run("lookup by", func(t *testing.T) {
|
||||
t.Run("access", func(t *testing.T) {
|
||||
req, authOa2token := truncAndCreate(t)
|
||||
fetched, err := s.LookupAuthOa2tokenByAccess(ctx, authOa2token.Access)
|
||||
req.NoError(err)
|
||||
req.NotNil(fetched)
|
||||
})
|
||||
|
||||
t.Run("code", func(t *testing.T) {
|
||||
req, authOa2token := truncAndCreate(t)
|
||||
fetched, err := s.LookupAuthOa2tokenByCode(ctx, authOa2token.Code)
|
||||
req.NoError(err)
|
||||
req.NotNil(fetched)
|
||||
})
|
||||
|
||||
t.Run("refresh", func(t *testing.T) {
|
||||
req, authOa2token := truncAndCreate(t)
|
||||
fetched, err := s.LookupAuthOa2tokenByRefresh(ctx, authOa2token.Refresh)
|
||||
req.NoError(err)
|
||||
req.NotNil(fetched)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("access", func(t *testing.T) {
|
||||
req, authOa2token := truncAndCreate(t)
|
||||
err := s.DeleteAuthOA2TokenByRefresh(ctx, authOa2token.Access)
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
t.Run("code", func(t *testing.T) {
|
||||
req, authOa2token := truncAndCreate(t)
|
||||
err := s.DeleteAuthOA2TokenByRefresh(ctx, authOa2token.Code)
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
t.Run("refresh", func(t *testing.T) {
|
||||
req, authOa2token := truncAndCreate(t)
|
||||
err := s.DeleteAuthOA2TokenByRefresh(ctx, authOa2token.Refresh)
|
||||
req.NoError(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
65
server/store/tests/auth_sessions.go
Normal file
65
server/store/tests/auth_sessions.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testAuthSessions(t *testing.T, s store.AuthSessions) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(handle string) *types.AuthSession {
|
||||
// minimum data set for new authSession
|
||||
return &types.AuthSession{
|
||||
ID: handle,
|
||||
CreatedAt: time.Now(),
|
||||
ExpiresAt: time.Now(),
|
||||
Data: []byte("..."),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.AuthSession) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAuthSessions(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateAuthSession(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
authSession := makeNew("AuthSessionCRUD")
|
||||
req.NoError(s.CreateAuthSession(ctx, authSession))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, authSession := truncAndCreate(t)
|
||||
fetched, err := s.LookupAuthSessionByID(ctx, authSession.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(authSession.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
})
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by AuthSession", func(t *testing.T) {
|
||||
req, authSession := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAuthSession(ctx, authSession))
|
||||
_, err := s.LookupAuthSessionByID(ctx, authSession.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, authSession := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAuthSessionByID(ctx, authSession.ID))
|
||||
_, err := s.LookupAuthSessionByID(ctx, authSession.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
}
|
||||
124
server/store/tests/automation_sessions_test.go
Normal file
124
server/store/tests/automation_sessions_test.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/automation/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testAutomationSessions(t *testing.T, s store.AutomationSessions) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(wfID uint64, completed bool) *types.Session {
|
||||
ses := &types.Session{
|
||||
ID: id.Next(),
|
||||
WorkflowID: wfID,
|
||||
CreatedAt: *now(),
|
||||
}
|
||||
if completed {
|
||||
ses.CompletedAt = now()
|
||||
}
|
||||
return ses
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Session) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAutomationSessions(ctx))
|
||||
res := makeNew(0, false)
|
||||
req.NoError(s.CreateAutomationSession(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
wf := &types.Session{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
}
|
||||
req.NoError(s.CreateAutomationSession(ctx, wf))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, wf := truncAndCreate(t)
|
||||
|
||||
fetched, err := s.LookupAutomationSessionByID(ctx, wf.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(wf.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, wf := truncAndCreate(t)
|
||||
wf.Status = types.SessionCompleted
|
||||
req.NoError(s.UpdateAutomationSession(ctx, wf))
|
||||
fetched, err := s.LookupAutomationSessionByID(ctx, wf.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(wf.ID, fetched.ID)
|
||||
req.Equal(types.SessionCompleted, fetched.Status)
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Session", func(t *testing.T) {
|
||||
req, wf := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAutomationSession(ctx, wf))
|
||||
_, err := s.LookupAutomationSessionByID(ctx, wf.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, wf := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAutomationSessionByID(ctx, wf.ID))
|
||||
_, err := s.LookupAutomationSessionByID(ctx, wf.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Session{
|
||||
makeNew(1001, false),
|
||||
makeNew(1001, false),
|
||||
makeNew(1001, false),
|
||||
makeNew(1001, false),
|
||||
makeNew(1001, true),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].CompletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateAutomationSessions(ctx))
|
||||
req.NoError(s.CreateAutomationSession(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchAutomationSessions(ctx, types.SessionFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchAutomationSessions(ctx, types.SessionFilter{Completed: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchAutomationSessions(ctx, types.SessionFilter{Completed: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchAutomationSessions(ctx, types.SessionFilter{WorkflowID: id.Strings(1001)})
|
||||
req.NoError(err)
|
||||
req.Len(set, 4)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
149
server/store/tests/automation_triggers_test.go
Normal file
149
server/store/tests/automation_triggers_test.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/automation/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testAutomationTriggers(t *testing.T, s store.AutomationTriggers) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func() *types.Trigger {
|
||||
return &types.Trigger{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Trigger) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAutomationTriggers(ctx))
|
||||
res := makeNew()
|
||||
req.NoError(s.CreateAutomationTrigger(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
tr := &types.Trigger{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
}
|
||||
req.NoError(s.CreateAutomationTrigger(ctx, tr))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, tr := truncAndCreate(t)
|
||||
|
||||
fetched, err := s.LookupAutomationTriggerByID(ctx, tr.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(tr.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, tr := truncAndCreate(t)
|
||||
tr.Enabled = true
|
||||
req.NoError(s.UpdateAutomationTrigger(ctx, tr))
|
||||
fetched, err := s.LookupAutomationTriggerByID(ctx, tr.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(tr.ID, fetched.ID)
|
||||
req.True(fetched.Enabled)
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Trigger", func(t *testing.T) {
|
||||
req, tr := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAutomationTrigger(ctx, tr))
|
||||
_, err := s.LookupAutomationTriggerByID(ctx, tr.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, tr := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAutomationTriggerByID(ctx, tr.ID))
|
||||
_, err := s.LookupAutomationTriggerByID(ctx, tr.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
auxWf := id.Next()
|
||||
|
||||
// Create test triggers
|
||||
{
|
||||
req.NoError(s.CreateAutomationTrigger(ctx, &types.Trigger{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
Enabled: true,
|
||||
|
||||
WorkflowID: auxWf,
|
||||
}))
|
||||
req.NoError(s.CreateAutomationTrigger(ctx, &types.Trigger{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
Enabled: true,
|
||||
|
||||
EventType: "event.test",
|
||||
}))
|
||||
req.NoError(s.CreateAutomationTrigger(ctx, &types.Trigger{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
Enabled: true,
|
||||
|
||||
ResourceType: "resource:test",
|
||||
}))
|
||||
req.NoError(s.CreateAutomationTrigger(ctx, &types.Trigger{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
Enabled: true,
|
||||
|
||||
DeletedAt: now(),
|
||||
}))
|
||||
req.NoError(s.CreateAutomationTrigger(ctx, &types.Trigger{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
|
||||
Enabled: false,
|
||||
}))
|
||||
}
|
||||
|
||||
tt, _, err := store.SearchAutomationTriggers(ctx, s, types.TriggerFilter{
|
||||
WorkflowID: id.Strings(auxWf, 10),
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(tt, 1)
|
||||
tt, _, err = store.SearchAutomationTriggers(ctx, s, types.TriggerFilter{
|
||||
EventType: "event.test",
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(tt, 1)
|
||||
tt, _, err = store.SearchAutomationTriggers(ctx, s, types.TriggerFilter{
|
||||
ResourceType: "resource:test",
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(tt, 1)
|
||||
tt, _, err = store.SearchAutomationTriggers(ctx, s, types.TriggerFilter{
|
||||
Deleted: filter.StateExclusive,
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(tt, 1)
|
||||
tt, _, err = store.SearchAutomationTriggers(ctx, s, types.TriggerFilter{
|
||||
Disabled: filter.StateExclusive,
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(tt, 1)
|
||||
})
|
||||
}
|
||||
137
server/store/tests/automation_workflows_test.go
Normal file
137
server/store/tests/automation_workflows_test.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/automation/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testAutomationWorkflows(t *testing.T, s store.AutomationWorkflows) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(handle string) *types.Workflow {
|
||||
return &types.Workflow{
|
||||
ID: id.Next(),
|
||||
Handle: handle,
|
||||
CreatedAt: *now(),
|
||||
Enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Workflow) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateAutomationWorkflows(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateAutomationWorkflow(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
wf := &types.Workflow{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
}
|
||||
req.NoError(s.CreateAutomationWorkflow(ctx, wf))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, wf := truncAndCreate(t)
|
||||
|
||||
fetched, err := s.LookupAutomationWorkflowByID(ctx, wf.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(wf.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, wf := truncAndCreate(t)
|
||||
wf.Enabled = true
|
||||
req.NoError(s.UpdateAutomationWorkflow(ctx, wf))
|
||||
fetched, err := s.LookupAutomationWorkflowByID(ctx, wf.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(wf.ID, fetched.ID)
|
||||
req.True(fetched.Enabled)
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Workflow", func(t *testing.T) {
|
||||
req, wf := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAutomationWorkflow(ctx, wf))
|
||||
_, err := s.LookupAutomationWorkflowByID(ctx, wf.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, wf := truncAndCreate(t)
|
||||
req.NoError(s.DeleteAutomationWorkflowByID(ctx, wf.ID))
|
||||
_, err := s.LookupAutomationWorkflowByID(ctx, wf.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Workflow{
|
||||
makeNew("one-one"),
|
||||
makeNew("one-two"),
|
||||
makeNew("two-one"),
|
||||
makeNew("two-two"),
|
||||
makeNew("two-deleted"),
|
||||
func() *types.Workflow {
|
||||
wf := makeNew("subwf")
|
||||
wf.Meta = &types.WorkflowMeta{SubWorkflow: true}
|
||||
return wf
|
||||
}(),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 2
|
||||
|
||||
req.NoError(s.TruncateAutomationWorkflows(ctx))
|
||||
req.NoError(s.CreateAutomationWorkflow(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // all but deleted or workflows
|
||||
|
||||
// search for ALL, including deleted and sub-workflows
|
||||
set, f, err = s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{
|
||||
Deleted: filter.StateInclusive,
|
||||
SubWorkflow: filter.StateInclusive,
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, count)
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{Query: "two-"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
// find just sub-workflows (one)
|
||||
set, f, err = s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{SubWorkflow: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
94
server/store/tests/compose_attachments_test.go
Normal file
94
server/store/tests/compose_attachments_test.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testComposeAttachments(t *testing.T, s store.ComposeAttachments) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(nn ...string) *types.Attachment {
|
||||
// minimum data set for new attachment
|
||||
name := strings.Join(nn, "")
|
||||
return &types.Attachment{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
Name: "handle_" + name,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Attachment) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposeAttachments(ctx))
|
||||
res := makeNew()
|
||||
req.NoError(s.CreateComposeAttachment(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
attachment := &types.Attachment{
|
||||
ID: id.Next(),
|
||||
CreatedAt: *now(),
|
||||
}
|
||||
req.NoError(s.CreateComposeAttachment(ctx, attachment))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
|
||||
fetched, err := s.LookupComposeAttachmentByID(ctx, att.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(att.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
att.Url = "url"
|
||||
req.NoError(s.UpdateComposeAttachment(ctx, att))
|
||||
fetched, err := s.LookupComposeAttachmentByID(ctx, att.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(att.ID, fetched.ID)
|
||||
req.Equal("url", fetched.Url)
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Attachment", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeAttachment(ctx, att))
|
||||
_, err := s.LookupComposeAttachmentByID(ctx, att.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, att := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeAttachmentByID(ctx, att.ID))
|
||||
_, err := s.LookupComposeAttachmentByID(ctx, att.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("search by *", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("ordered search", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
}
|
||||
175
server/store/tests/compose_charts_test.go
Normal file
175
server/store/tests/compose_charts_test.go
Normal file
@@ -0,0 +1,175 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testComposeCharts(t *testing.T, s store.Storer) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
namespaceID = id.Next()
|
||||
|
||||
makeNew = func(name, handle string) *types.Chart {
|
||||
// minimum data set for new composeChart
|
||||
return &types.Chart{
|
||||
ID: id.Next(),
|
||||
NamespaceID: namespaceID,
|
||||
CreatedAt: time.Now(),
|
||||
Name: name,
|
||||
Handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Chart) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposeCharts(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)), string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateComposeChart(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
composeChart := makeNew("ComposeChartCRUD", "compose-chart-crud")
|
||||
req.NoError(s.CreateComposeChart(ctx, composeChart))
|
||||
})
|
||||
|
||||
t.Run("create with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("lookup", func(t *testing.T) {
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
composeChart := makeNew("look up by id", "look-up-by-id")
|
||||
req.NoError(s.CreateComposeChart(ctx, composeChart))
|
||||
fetched, err := s.LookupComposeChartByID(ctx, composeChart.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeChart.Name, fetched.Name)
|
||||
req.Equal(composeChart.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("by Namespace ID, Handle", func(t *testing.T) {
|
||||
composeChart := makeNew("look up by handle", "look-up-by-handle")
|
||||
req.NoError(s.CreateComposeChart(ctx, composeChart))
|
||||
fetched, err := s.LookupComposeChartByNamespaceIDHandle(ctx, composeChart.NamespaceID, composeChart.Handle)
|
||||
req.NoError(err)
|
||||
req.Equal(composeChart.Name, fetched.Name)
|
||||
req.Equal(composeChart.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, composeChart := truncAndCreate(t)
|
||||
composeChart.Name = "ComposeChartCRUD+2"
|
||||
|
||||
req.NoError(s.UpdateComposeChart(ctx, composeChart))
|
||||
|
||||
updated, err := s.LookupComposeChartByID(ctx, composeChart.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeChart.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("update with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, composeChart := truncAndCreate(t)
|
||||
composeChart.Name = "ComposeChartCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposeChart(ctx, composeChart))
|
||||
|
||||
upserted, err := s.LookupComposeChartByID(ctx, composeChart.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeChart.Name, upserted.Name)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
composeChart := makeNew("upsert me", "upsert-me")
|
||||
composeChart.Name = "ComposeChartCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposeChart(ctx, composeChart))
|
||||
|
||||
upserted, err := s.LookupComposeChartByID(ctx, composeChart.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeChart.Name, upserted.Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Chart", func(t *testing.T) {
|
||||
req, composeChart := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeChart(ctx, composeChart))
|
||||
_, err := s.LookupComposeChartByID(ctx, composeChart.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, composeChart := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeChartByID(ctx, composeChart.ID))
|
||||
_, err := s.LookupComposeChartByID(ctx, composeChart.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Chart{
|
||||
makeNew("/one-one", "chart-1-1"),
|
||||
makeNew("/one-two", "chart-1-2"),
|
||||
makeNew("/two-one", "chart-2-1"),
|
||||
makeNew("/two-two", "chart-2-2"),
|
||||
makeNew("/two-deleted", "chart-2-d"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateComposeCharts(ctx))
|
||||
req.NoError(s.CreateComposeChart(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchComposeCharts(ctx, types.ChartFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchComposeCharts(ctx, types.ChartFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchComposeCharts(ctx, types.ChartFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, f, err = s.SearchComposeCharts(ctx, types.ChartFilter{Handle: "chart-2-1"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchComposeCharts(ctx, types.ChartFilter{Query: "/two-"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
121
server/store/tests/compose_module_fields_test.go
Normal file
121
server/store/tests/compose_module_fields_test.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testComposeModuleFields(t *testing.T, s store.ComposeModuleFields) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
moduleID = id.Next()
|
||||
|
||||
makeNew = func(name, label string) *types.ModuleField {
|
||||
// minimum data set for new composeModuleField
|
||||
return &types.ModuleField{
|
||||
ID: id.Next(),
|
||||
ModuleID: moduleID,
|
||||
CreatedAt: time.Now(),
|
||||
Name: name,
|
||||
Label: label,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.ModuleField) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposeModuleFields(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)), string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateComposeModuleField(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposeModuleFields(ctx))
|
||||
composeModuleField := makeNew("ComposeModuleFieldCRUD", "compose-moduleField-crud")
|
||||
req.NoError(s.CreateComposeModuleField(ctx, composeModuleField))
|
||||
})
|
||||
|
||||
t.Run("create with duplicate name", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposeModuleFields(ctx))
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("lookup by Module ID, Name", func(t *testing.T) {
|
||||
req, composeModuleField := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposeModuleFieldByModuleIDName(ctx, composeModuleField.ModuleID, composeModuleField.Name)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModuleField.Name, fetched.Name)
|
||||
req.Equal(composeModuleField.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, composeModuleField := truncAndCreate(t)
|
||||
composeModuleField.Name = "ComposeModuleFieldCRUD+2"
|
||||
|
||||
req.NoError(s.UpdateComposeModuleField(ctx, composeModuleField))
|
||||
|
||||
updated, err := s.LookupComposeModuleFieldByModuleIDName(ctx, composeModuleField.ModuleID, composeModuleField.Name)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModuleField.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("update with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, composeModuleField := truncAndCreate(t)
|
||||
composeModuleField.Name = "ComposeModuleFieldCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposeModuleField(ctx, composeModuleField))
|
||||
|
||||
upserted, err := s.LookupComposeModuleFieldByModuleIDName(ctx, composeModuleField.ModuleID, composeModuleField.Name)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModuleField.Name, upserted.Name)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
composeModuleField := makeNew("upsert me", "upsert-me")
|
||||
composeModuleField.Name = "ComposeModuleFieldCRUD+3"
|
||||
|
||||
req.NoError(s.UpsertComposeModuleField(ctx, composeModuleField))
|
||||
|
||||
upserted, err := s.LookupComposeModuleFieldByModuleIDName(ctx, composeModuleField.ModuleID, composeModuleField.Name)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModuleField.Name, upserted.Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Field", func(t *testing.T) {
|
||||
req, fld := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeModuleField(ctx, fld))
|
||||
fetched, _, err := s.SearchComposeModuleFields(ctx, types.ModuleFieldFilter{ModuleID: []uint64{fld.ModuleID}})
|
||||
req.NoError(err)
|
||||
req.Empty(fetched)
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, fld := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeModuleFieldByID(ctx, fld.ID))
|
||||
fetched, _, err := s.SearchComposeModuleFields(ctx, types.ModuleFieldFilter{ModuleID: []uint64{fld.ModuleID}})
|
||||
req.NoError(err)
|
||||
req.Empty(fetched)
|
||||
})
|
||||
})
|
||||
}
|
||||
187
server/store/tests/compose_modules_test.go
Normal file
187
server/store/tests/compose_modules_test.go
Normal file
@@ -0,0 +1,187 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testComposeModules(t *testing.T, s store.ComposeModules) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
namespaceID = id.Next()
|
||||
|
||||
makeNew = func(name, handle string) *types.Module {
|
||||
// minimum data set for new composeModule
|
||||
return &types.Module{
|
||||
ID: id.Next(),
|
||||
NamespaceID: namespaceID,
|
||||
CreatedAt: time.Now(),
|
||||
Name: name,
|
||||
Handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Module) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposeModules(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)), string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateComposeModule(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
composeModule := makeNew("ComposeModuleCRUD", "compose-module-crud")
|
||||
req.NoError(s.CreateComposeModule(ctx, composeModule))
|
||||
})
|
||||
|
||||
t.Run("create with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("lookup", func(t *testing.T) {
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
composeModule := makeNew("look up by id", "look-up-by-id")
|
||||
req.NoError(s.CreateComposeModule(ctx, composeModule))
|
||||
fetched, err := s.LookupComposeModuleByID(ctx, composeModule.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModule.Name, fetched.Name)
|
||||
req.Equal(composeModule.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("by NamespaceID, Name", func(t *testing.T) {
|
||||
composeModule := makeNew("look up by namespaceIDName", "look-up-by-namespaceIDName")
|
||||
req.NoError(s.CreateComposeModule(ctx, composeModule))
|
||||
fetched, err := s.LookupComposeModuleByNamespaceIDName(ctx, composeModule.NamespaceID, composeModule.Name)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModule.Name, fetched.Name)
|
||||
req.Equal(composeModule.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("by Handle", func(t *testing.T) {
|
||||
composeModule := makeNew("look up by namespaceIDHandle", "look-up-by-namespaceIDHandle")
|
||||
req.NoError(s.CreateComposeModule(ctx, composeModule))
|
||||
fetched, err := s.LookupComposeModuleByNamespaceIDHandle(ctx, composeModule.NamespaceID, composeModule.Handle)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModule.Name, fetched.Name)
|
||||
req.Equal(composeModule.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, composeModule := truncAndCreate(t)
|
||||
composeModule.Name = "ComposeModuleCRUD+2"
|
||||
|
||||
req.NoError(s.UpdateComposeModule(ctx, composeModule))
|
||||
|
||||
updated, err := s.LookupComposeModuleByID(ctx, composeModule.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModule.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("update with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, composeModule := truncAndCreate(t)
|
||||
composeModule.Name = "ComposeModuleCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposeModule(ctx, composeModule))
|
||||
|
||||
updated, err := s.LookupComposeModuleByID(ctx, composeModule.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModule.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
composeModule := makeNew("upsert me", "upsert-me")
|
||||
composeModule.Name = "ComposeChartCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposeModule(ctx, composeModule))
|
||||
|
||||
upserted, err := s.LookupComposeModuleByID(ctx, composeModule.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeModule.Name, upserted.Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Module", func(t *testing.T) {
|
||||
req, composeModule := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeModule(ctx, composeModule))
|
||||
_, err := s.LookupComposeModuleByID(ctx, composeModule.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, composeModule := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeModuleByID(ctx, composeModule.ID))
|
||||
_, err := s.LookupComposeModuleByID(ctx, composeModule.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Module{
|
||||
makeNew("/one-one", "module-1-1"),
|
||||
makeNew("/one-two", "module-1-2"),
|
||||
makeNew("/two-one", "module-2-1"),
|
||||
makeNew("/two-two", "module-2-2"),
|
||||
makeNew("/two-deleted", "module-2-d"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateComposeModules(ctx))
|
||||
req.NoError(s.CreateComposeModule(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchComposeModules(ctx, types.ModuleFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchComposeModules(ctx, types.ModuleFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchComposeModules(ctx, types.ModuleFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, f, err = s.SearchComposeModules(ctx, types.ModuleFilter{Handle: "module-2-1"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchComposeModules(ctx, types.ModuleFilter{Query: "/two-"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
177
server/store/tests/compose_namespaces_test.go
Normal file
177
server/store/tests/compose_namespaces_test.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testComposeNamespaces(t *testing.T, s store.ComposeNamespaces) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(name, slug string) *types.Namespace {
|
||||
// minimum data set for new composeNamespace
|
||||
return &types.Namespace{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Name: name,
|
||||
Slug: slug,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Namespace) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposeNamespaces(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)), string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateComposeNamespace(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req.NoError(s.TruncateComposeNamespaces(ctx))
|
||||
composeNamespace := makeNew("ComposeNamespaceCRUD", "compose-namespace-crud")
|
||||
req.NoError(s.CreateComposeNamespace(ctx, composeNamespace))
|
||||
})
|
||||
|
||||
t.Run("create with duplicate slug", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("lookup", func(t *testing.T) {
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, composeNamespace := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposeNamespaceByID(ctx, composeNamespace.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeNamespace.Name, fetched.Name)
|
||||
req.Equal(composeNamespace.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("by Slug", func(t *testing.T) {
|
||||
req, composeNamespace := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposeNamespaceBySlug(ctx, composeNamespace.Slug)
|
||||
req.NoError(err)
|
||||
req.Equal(composeNamespace.Name, fetched.Name)
|
||||
req.Equal(composeNamespace.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
composeNamespace := makeNew("update me", "update-me")
|
||||
req.NoError(s.CreateComposeNamespace(ctx, composeNamespace))
|
||||
|
||||
composeNamespace = &types.Namespace{
|
||||
ID: composeNamespace.ID,
|
||||
CreatedAt: composeNamespace.CreatedAt,
|
||||
Name: "ComposeNamespaceCRUD+2",
|
||||
}
|
||||
req.NoError(s.UpdateComposeNamespace(ctx, composeNamespace))
|
||||
|
||||
updated, err := s.LookupComposeNamespaceByID(ctx, composeNamespace.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeNamespace.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("update with duplicate slug", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, composeNamespace := truncAndCreate(t)
|
||||
composeNamespace.Name = "ComposeNamespaceCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposeNamespace(ctx, composeNamespace))
|
||||
|
||||
upserted, err := s.LookupComposeNamespaceByID(ctx, composeNamespace.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeNamespace.Name, upserted.Name)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
composeNamespace := makeNew("upsert me", "upsert-me")
|
||||
composeNamespace.Name = "ComposeNamespaceCRUD+3"
|
||||
|
||||
req.NoError(s.UpsertComposeNamespace(ctx, composeNamespace))
|
||||
|
||||
upserted, err := s.LookupComposeNamespaceByID(ctx, composeNamespace.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composeNamespace.Name, upserted.Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Namespace", func(t *testing.T) {
|
||||
req, composeNamespace := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeNamespace(ctx, composeNamespace))
|
||||
_, err := s.LookupComposeNamespaceByID(ctx, composeNamespace.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, composeNamespace := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposeNamespaceByID(ctx, composeNamespace.ID))
|
||||
_, err := s.LookupComposeNamespaceByID(ctx, composeNamespace.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Namespace{
|
||||
makeNew("/one-one", "namespace-1-1"),
|
||||
makeNew("/one-two", "namespace-1-2"),
|
||||
makeNew("/two-one", "namespace-2-1"),
|
||||
makeNew("/two-two", "namespace-2-2"),
|
||||
makeNew("/two-deleted", "namespace-2-d"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateComposeNamespaces(ctx))
|
||||
req.NoError(s.CreateComposeNamespace(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchComposeNamespaces(ctx, types.NamespaceFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchComposeNamespaces(ctx, types.NamespaceFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchComposeNamespaces(ctx, types.NamespaceFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, f, err = s.SearchComposeNamespaces(ctx, types.NamespaceFilter{Slug: "namespace-2-1"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchComposeNamespaces(ctx, types.NamespaceFilter{Query: "/two-"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
194
server/store/tests/compose_page_layouts_test.go
Normal file
194
server/store/tests/compose_page_layouts_test.go
Normal file
@@ -0,0 +1,194 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testComposePageLayouts(t *testing.T, s store.ComposePageLayouts) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
namespaceID = id.Next()
|
||||
|
||||
makeNew = func(title, handle string) *types.PageLayout {
|
||||
// minimum data set for new composePageLayout
|
||||
return &types.PageLayout{
|
||||
ID: id.Next(),
|
||||
NamespaceID: namespaceID,
|
||||
CreatedAt: time.Now(),
|
||||
Meta: types.PageLayoutMeta{
|
||||
Title: title,
|
||||
},
|
||||
Handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.PageLayout) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposePageLayouts(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)), string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateComposePageLayout(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
composePageLayout := makeNew("ComposePageLayoutCRUD", "compose-page-crud")
|
||||
req.NoError(s.CreateComposePageLayout(ctx, composePageLayout))
|
||||
})
|
||||
|
||||
t.Run("create with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("lookup", func(t *testing.T) {
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, composePageLayout := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposePageLayoutByID(ctx, composePageLayout.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePageLayout.Meta.Title, fetched.Meta.Title)
|
||||
req.Equal(composePageLayout.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("lookup by NamespaceID, PageID, Handle", func(t *testing.T) {
|
||||
req, composePageLayout := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposePageLayoutByNamespaceIDPageIDHandle(ctx, composePageLayout.NamespaceID, composePageLayout.PageID, composePageLayout.Handle)
|
||||
req.NoError(err)
|
||||
req.Equal(composePageLayout.Meta.Title, fetched.Meta.Title)
|
||||
req.Equal(composePageLayout.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("lookup by NamespaceID, Handle", func(t *testing.T) {
|
||||
req, composePageLayout := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposePageLayoutByNamespaceIDHandle(ctx, composePageLayout.NamespaceID, composePageLayout.Handle)
|
||||
req.NoError(err)
|
||||
req.Equal(composePageLayout.Meta.Title, fetched.Meta.Title)
|
||||
req.Equal(composePageLayout.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
composePageLayout := makeNew("update me", "update-me")
|
||||
req.NoError(s.CreateComposePageLayout(ctx, composePageLayout))
|
||||
|
||||
composePageLayout = &types.PageLayout{
|
||||
ID: composePageLayout.ID,
|
||||
CreatedAt: composePageLayout.CreatedAt,
|
||||
Meta: types.PageLayoutMeta{
|
||||
Title: "ComposePageLayoutCRUD+2",
|
||||
},
|
||||
}
|
||||
req.NoError(s.UpdateComposePageLayout(ctx, composePageLayout))
|
||||
|
||||
updated, err := s.LookupComposePageLayoutByID(ctx, composePageLayout.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePageLayout.Meta.Title, updated.Meta.Title)
|
||||
})
|
||||
|
||||
t.Run("update with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, composePageLayout := truncAndCreate(t)
|
||||
composePageLayout.Meta.Title = "ComposePageLayoutCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposePageLayout(ctx, composePageLayout))
|
||||
|
||||
upserted, err := s.LookupComposePageLayoutByID(ctx, composePageLayout.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePageLayout.Meta.Title, upserted.Meta.Title)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
composePageLayout := makeNew("upsert me", "upsert-me")
|
||||
composePageLayout.Meta.Title = "ComposePageLayoutCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposePageLayout(ctx, composePageLayout))
|
||||
|
||||
upserted, err := s.LookupComposePageLayoutByID(ctx, composePageLayout.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePageLayout.Meta.Title, upserted.Meta.Title)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by PageLayout", func(t *testing.T) {
|
||||
req, composePageLayout := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposePageLayout(ctx, composePageLayout))
|
||||
_, err := s.LookupComposePageLayoutByID(ctx, composePageLayout.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, composePageLayout := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposePageLayoutByID(ctx, composePageLayout.ID))
|
||||
_, err := s.LookupComposePageLayoutByID(ctx, composePageLayout.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.PageLayout{
|
||||
makeNew("/one-one", "page-1-1"),
|
||||
makeNew("/one-two", "page-1-2"),
|
||||
makeNew("/two-one", "page-2-1"),
|
||||
makeNew("/two-two", "page-2-2"),
|
||||
makeNew("/two-deleted", "page-2-d"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateComposePageLayouts(ctx))
|
||||
req.NoError(s.CreateComposePageLayout(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchComposePageLayouts(ctx, types.PageLayoutFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchComposePageLayouts(ctx, types.PageLayoutFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchComposePageLayouts(ctx, types.PageLayoutFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, f, err = s.SearchComposePageLayouts(ctx, types.PageLayoutFilter{Handle: "page-2-1"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchComposePageLayouts(ctx, types.PageLayoutFilter{Query: "/two-"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
191
server/store/tests/compose_pages_test.go
Normal file
191
server/store/tests/compose_pages_test.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testComposePages(t *testing.T, s store.ComposePages) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
namespaceID = id.Next()
|
||||
moduleID = id.Next()
|
||||
|
||||
makeNew = func(title, handle string) *types.Page {
|
||||
// minimum data set for new composePage
|
||||
return &types.Page{
|
||||
ID: id.Next(),
|
||||
NamespaceID: namespaceID,
|
||||
ModuleID: moduleID,
|
||||
CreatedAt: time.Now(),
|
||||
Title: title,
|
||||
Handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Page) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateComposePages(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)), string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateComposePage(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
composePage := makeNew("ComposePageCRUD", "compose-page-crud")
|
||||
req.NoError(s.CreateComposePage(ctx, composePage))
|
||||
})
|
||||
|
||||
t.Run("create with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("lookup", func(t *testing.T) {
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, composePage := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposePageByID(ctx, composePage.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePage.Title, fetched.Title)
|
||||
req.Equal(composePage.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("lookup by NamespaceID, ModuleID", func(t *testing.T) {
|
||||
req, composePage := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposePageByNamespaceIDModuleID(ctx, composePage.NamespaceID, composePage.ModuleID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePage.Title, fetched.Title)
|
||||
req.Equal(composePage.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("lookup by NamespaceID, Handle", func(t *testing.T) {
|
||||
req, composePage := truncAndCreate(t)
|
||||
fetched, err := s.LookupComposePageByNamespaceIDHandle(ctx, composePage.NamespaceID, composePage.Handle)
|
||||
req.NoError(err)
|
||||
req.Equal(composePage.Title, fetched.Title)
|
||||
req.Equal(composePage.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
composePage := makeNew("update me", "update-me")
|
||||
req.NoError(s.CreateComposePage(ctx, composePage))
|
||||
|
||||
composePage = &types.Page{
|
||||
ID: composePage.ID,
|
||||
CreatedAt: composePage.CreatedAt,
|
||||
Title: "ComposePageCRUD+2",
|
||||
}
|
||||
req.NoError(s.UpdateComposePage(ctx, composePage))
|
||||
|
||||
updated, err := s.LookupComposePageByID(ctx, composePage.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePage.Title, updated.Title)
|
||||
})
|
||||
|
||||
t.Run("update with duplicate handle", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, composePage := truncAndCreate(t)
|
||||
composePage.Title = "ComposePageCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposePage(ctx, composePage))
|
||||
|
||||
upserted, err := s.LookupComposePageByID(ctx, composePage.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePage.Title, upserted.Title)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
composePage := makeNew("upsert me", "upsert-me")
|
||||
composePage.Title = "ComposePageCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertComposePage(ctx, composePage))
|
||||
|
||||
upserted, err := s.LookupComposePageByID(ctx, composePage.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(composePage.Title, upserted.Title)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Page", func(t *testing.T) {
|
||||
req, composePage := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposePage(ctx, composePage))
|
||||
_, err := s.LookupComposePageByID(ctx, composePage.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, composePage := truncAndCreate(t)
|
||||
req.NoError(s.DeleteComposePageByID(ctx, composePage.ID))
|
||||
_, err := s.LookupComposePageByID(ctx, composePage.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Page{
|
||||
makeNew("/one-one", "page-1-1"),
|
||||
makeNew("/one-two", "page-1-2"),
|
||||
makeNew("/two-one", "page-2-1"),
|
||||
makeNew("/two-two", "page-2-2"),
|
||||
makeNew("/two-deleted", "page-2-d"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateComposePages(ctx))
|
||||
req.NoError(s.CreateComposePage(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchComposePages(ctx, types.PageFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchComposePages(ctx, types.PageFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchComposePages(ctx, types.PageFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, f, err = s.SearchComposePages(ctx, types.PageFilter{Handle: "page-2-1"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchComposePages(ctx, types.PageFilter{Query: "/two-"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
148
server/store/tests/credentials_test.go
Normal file
148
server/store/tests/credentials_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
// "github.com/cortezaproject/corteza/server/pkg/rh"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testCredentials(t *testing.T, s store.Credentials) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(nn ...string) *types.Credential {
|
||||
name := strings.Join(nn, "")
|
||||
return &types.Credential{
|
||||
ID: id.Next(),
|
||||
OwnerID: id.Next(),
|
||||
Kind: "test-kind" + name,
|
||||
Credentials: name,
|
||||
Label: "CredentialsCRUD" + name,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Credential) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateCredentials(ctx))
|
||||
credentials := makeNew()
|
||||
req.NoError(s.CreateCredential(ctx, credentials))
|
||||
return req, credentials
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, types.CredentialSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateCredentials(ctx))
|
||||
|
||||
set := make([]*types.Credential, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew(string(rand.Bytes(10)))
|
||||
}
|
||||
|
||||
req.NoError(s.CreateCredential(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.CreateCredential(ctx, makeNew()))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, crd := truncAndCreate(t)
|
||||
|
||||
fetched, err := s.LookupCredentialByID(ctx, crd.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(crd.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, crd := truncAndCreate(t)
|
||||
crd.Credentials = "new-credentials"
|
||||
req.NoError(s.UpdateCredential(ctx, crd))
|
||||
fetched, err := s.LookupCredentialByID(ctx, crd.ID)
|
||||
req.NoError(err)
|
||||
req.Equal("new-credentials", fetched.Credentials)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, crd := truncAndCreate(t)
|
||||
crd.Credentials = "new-credentials"
|
||||
req.NoError(s.UpdateCredential(ctx, crd))
|
||||
fetched, err := s.LookupCredentialByID(ctx, crd.ID)
|
||||
req.NoError(err)
|
||||
req.Equal("new-credentials", fetched.Credentials)
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by credentials", func(t *testing.T) {
|
||||
req, crd := truncAndCreate(t)
|
||||
req.NoError(s.DeleteCredential(ctx, crd))
|
||||
set, _, err := s.SearchCredentials(ctx, types.CredentialFilter{OwnerID: crd.OwnerID})
|
||||
req.NoError(err)
|
||||
req.Len(set, 0)
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, crd := truncAndCreate(t)
|
||||
req.NoError(s.DeleteCredentialByID(ctx, crd.ID))
|
||||
set, _, err := s.SearchCredentials(ctx, types.CredentialFilter{OwnerID: crd.OwnerID})
|
||||
req.NoError(err)
|
||||
req.Len(set, 0)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Run("by owner", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchCredentials(ctx, types.CredentialFilter{OwnerID: prefill[0].OwnerID})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by kind", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchCredentials(ctx, types.CredentialFilter{Kind: prefill[0].Kind})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
// Not sure why this doesnt work
|
||||
// t.Run("by state", func(t *testing.T) {
|
||||
// t.Run("deleted", func(t *testing.T) {
|
||||
// req, prefill := truncAndFill(t, 5)
|
||||
// time := time.Now()
|
||||
// prefill[0].DeletedAt = &time
|
||||
// req.NoError(s.DeleteCredentialsByID(ctx, prefill[0].ID))
|
||||
|
||||
// set, _, err := s.SearchCredentials(ctx, types.CredentialFilter{Deleted: filter.StateExcluded})
|
||||
// req.NoError(err)
|
||||
// req.Len(set, 4)
|
||||
|
||||
// set, _, err = s.SearchCredentials(ctx, types.CredentialFilter{Deleted: filter.StateInclusive})
|
||||
// req.NoError(err)
|
||||
// req.Len(set, 5)
|
||||
|
||||
// set, _, err = s.SearchCredentials(ctx, types.CredentialFilter{Deleted: filter.StateExclusive})
|
||||
// req.NoError(err)
|
||||
// req.Len(set, 1)
|
||||
// })
|
||||
// })
|
||||
})
|
||||
}
|
||||
143
server/store/tests/dal_connections.go
Normal file
143
server/store/tests/dal_connections.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testDalConnections(t *testing.T, s store.DalConnections) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(handle string) *types.DalConnection {
|
||||
// minimum data set for new dalConnection
|
||||
return &types.DalConnection{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.DalConnection) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateDalConnections(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateDalConnection(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req.NoError(s.TruncateDalConnections(ctx))
|
||||
dalConnection := makeNew("DalConnectionCRUD")
|
||||
req.NoError(s.CreateDalConnection(ctx, dalConnection))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, dalConnection := truncAndCreate(t)
|
||||
fetched, err := s.LookupDalConnectionByID(ctx, dalConnection.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dalConnection.Handle, fetched.Handle)
|
||||
req.Equal(dalConnection.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, dalConnection := truncAndCreate(t)
|
||||
dalConnection.Handle = "DalConnectionCRUD-2"
|
||||
|
||||
req.NoError(s.UpdateDalConnection(ctx, dalConnection))
|
||||
|
||||
updated, err := s.LookupDalConnectionByID(ctx, dalConnection.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dalConnection.Handle, updated.Handle)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, dalConnection := truncAndCreate(t)
|
||||
dalConnection.Handle = "DalConnectionCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertDalConnection(ctx, dalConnection))
|
||||
|
||||
updated, err := s.LookupDalConnectionByID(ctx, dalConnection.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dalConnection.Handle, updated.Handle)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
dalConnection := makeNew("upsert me")
|
||||
dalConnection.Handle = "ComposeChartCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertDalConnection(ctx, dalConnection))
|
||||
|
||||
upserted, err := s.LookupDalConnectionByID(ctx, dalConnection.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dalConnection.Handle, upserted.Handle)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by DalConnection", func(t *testing.T) {
|
||||
req, dalConnection := truncAndCreate(t)
|
||||
req.NoError(s.DeleteDalConnection(ctx, dalConnection))
|
||||
_, err := s.LookupDalConnectionByID(ctx, dalConnection.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, dalConnection := truncAndCreate(t)
|
||||
req.NoError(s.DeleteDalConnectionByID(ctx, dalConnection.ID))
|
||||
_, err := s.LookupDalConnectionByID(ctx, dalConnection.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.DalConnection{
|
||||
makeNew("/one-one"),
|
||||
makeNew("/one-two"),
|
||||
makeNew("/two-one"),
|
||||
makeNew("/two-two"),
|
||||
makeNew("/two-deleted"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateDalConnections(ctx))
|
||||
req.NoError(s.CreateDalConnection(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, _, err := s.SearchDalConnections(ctx, types.DalConnectionFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, _, err = s.SearchDalConnections(ctx, types.DalConnectionFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, _, err = s.SearchDalConnections(ctx, types.DalConnectionFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, _, err = s.SearchDalConnections(ctx, types.DalConnectionFilter{Handle: "/two-one"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
}
|
||||
10
server/store/tests/dal_schema_alterations.go
Normal file
10
server/store/tests/dal_schema_alterations.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func testDalSchemaAlterations(t *testing.T, s store.DalSensitivityLevels) {
|
||||
}
|
||||
138
server/store/tests/dal_sensitivity_levels.go
Normal file
138
server/store/tests/dal_sensitivity_levels.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testDalSensitivityLevels(t *testing.T, s store.DalSensitivityLevels) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(handle string) *types.DalSensitivityLevel {
|
||||
// minimum data set for new dalSensitivityLevel
|
||||
return &types.DalSensitivityLevel{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.DalSensitivityLevel) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateDalSensitivityLevels(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateDalSensitivityLevel(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
dalSensitivityLevel := makeNew("DalSensitivityLevelCRUD")
|
||||
req.NoError(s.CreateDalSensitivityLevel(ctx, dalSensitivityLevel))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, dalSensitivityLevel := truncAndCreate(t)
|
||||
fetched, err := s.LookupDalSensitivityLevelByID(ctx, dalSensitivityLevel.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dalSensitivityLevel.Handle, fetched.Handle)
|
||||
req.Equal(dalSensitivityLevel.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, dalSensitivityLevel := truncAndCreate(t)
|
||||
dalSensitivityLevel.Handle = "DalSensitivityLevelCRUD-2"
|
||||
|
||||
req.NoError(s.UpdateDalSensitivityLevel(ctx, dalSensitivityLevel))
|
||||
|
||||
updated, err := s.LookupDalSensitivityLevelByID(ctx, dalSensitivityLevel.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dalSensitivityLevel.Handle, updated.Handle)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, dalSensitivityLevel := truncAndCreate(t)
|
||||
dalSensitivityLevel.Handle = "DalSensitivityLevelCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertDalSensitivityLevel(ctx, dalSensitivityLevel))
|
||||
|
||||
updated, err := s.LookupDalSensitivityLevelByID(ctx, dalSensitivityLevel.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dalSensitivityLevel.Handle, updated.Handle)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
dalSensitivityLevel := makeNew("upsert me")
|
||||
dalSensitivityLevel.Handle = "ComposeChartCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertDalSensitivityLevel(ctx, dalSensitivityLevel))
|
||||
|
||||
upserted, err := s.LookupDalSensitivityLevelByID(ctx, dalSensitivityLevel.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dalSensitivityLevel.Handle, upserted.Handle)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by DalSensitivityLevel", func(t *testing.T) {
|
||||
req, dalSensitivityLevel := truncAndCreate(t)
|
||||
req.NoError(s.DeleteDalSensitivityLevel(ctx, dalSensitivityLevel))
|
||||
_, err := s.LookupDalSensitivityLevelByID(ctx, dalSensitivityLevel.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, dalSensitivityLevel := truncAndCreate(t)
|
||||
req.NoError(s.DeleteDalSensitivityLevelByID(ctx, dalSensitivityLevel.ID))
|
||||
_, err := s.LookupDalSensitivityLevelByID(ctx, dalSensitivityLevel.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.DalSensitivityLevel{
|
||||
makeNew("/one-one"),
|
||||
makeNew("/one-two"),
|
||||
makeNew("/two-one"),
|
||||
makeNew("/two-two"),
|
||||
makeNew("/two-deleted"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateDalSensitivityLevels(ctx))
|
||||
req.NoError(s.CreateDalSensitivityLevel(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, _, err := s.SearchDalSensitivityLevels(ctx, types.DalSensitivityLevelFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, _, err = s.SearchDalSensitivityLevels(ctx, types.DalSensitivityLevelFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, _, err = s.SearchDalSensitivityLevels(ctx, types.DalSensitivityLevelFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
})
|
||||
}
|
||||
97
server/store/tests/data_privacy_request_comments.go
Normal file
97
server/store/tests/data_privacy_request_comments.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testDataPrivacyRequestComments(t *testing.T, s store.DataPrivacyRequestComments) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(handle string) *types.DataPrivacyRequestComment {
|
||||
// minimum data set for new dataPrivacyRequestComment
|
||||
return &types.DataPrivacyRequestComment{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.DataPrivacyRequestComment) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateDataPrivacyRequestComments(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateDataPrivacyRequestComment(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
dataPrivacyRequestComment := makeNew("DataPrivacyRequestCommentCRUD")
|
||||
req.NoError(s.CreateDataPrivacyRequestComment(ctx, dataPrivacyRequestComment))
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, dataPrivacyRequestComment := truncAndCreate(t)
|
||||
dataPrivacyRequestComment.Comment = "DataPrivacyRequestCommentCRUD-2"
|
||||
|
||||
req.NoError(s.UpdateDataPrivacyRequestComment(ctx, dataPrivacyRequestComment))
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, dataPrivacyRequestComment := truncAndCreate(t)
|
||||
dataPrivacyRequestComment.Comment = "DataPrivacyRequestCommentCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertDataPrivacyRequestComment(ctx, dataPrivacyRequestComment))
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
dataPrivacyRequestComment := makeNew("upsert me")
|
||||
dataPrivacyRequestComment.Comment = "ComposeChartCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertDataPrivacyRequestComment(ctx, dataPrivacyRequestComment))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by DataPrivacyRequestComment", func(t *testing.T) {
|
||||
req, dataPrivacyRequestComment := truncAndCreate(t)
|
||||
req.NoError(s.DeleteDataPrivacyRequestComment(ctx, dataPrivacyRequestComment))
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, dataPrivacyRequestComment := truncAndCreate(t)
|
||||
req.NoError(s.DeleteDataPrivacyRequestCommentByID(ctx, dataPrivacyRequestComment.ID))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.DataPrivacyRequestComment{
|
||||
makeNew("/one-one"),
|
||||
makeNew("/one-two"),
|
||||
makeNew("/two-one"),
|
||||
makeNew("/two-two"),
|
||||
makeNew("/two-yes"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
valid := count
|
||||
|
||||
req.NoError(s.TruncateDataPrivacyRequestComments(ctx))
|
||||
req.NoError(s.CreateDataPrivacyRequestComment(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, _, err := s.SearchDataPrivacyRequestComments(ctx, types.DataPrivacyRequestCommentFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
})
|
||||
}
|
||||
131
server/store/tests/data_privacy_requests.go
Normal file
131
server/store/tests/data_privacy_requests.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testDataPrivacyRequests(t *testing.T, s store.DataPrivacyRequests) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(handle string) *types.DataPrivacyRequest {
|
||||
// minimum data set for new dataPrivacyRequest
|
||||
return &types.DataPrivacyRequest{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
RequestedAt: time.Now(),
|
||||
Kind: types.RequestKindCorrect,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.DataPrivacyRequest) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateDataPrivacyRequests(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateDataPrivacyRequest(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
dataPrivacyRequest := makeNew("DataPrivacyRequestCRUD")
|
||||
req.NoError(s.CreateDataPrivacyRequest(ctx, dataPrivacyRequest))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, dataPrivacyRequest := truncAndCreate(t)
|
||||
fetched, err := s.LookupDataPrivacyRequestByID(ctx, dataPrivacyRequest.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dataPrivacyRequest.Kind, fetched.Kind)
|
||||
req.Equal(dataPrivacyRequest.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, dataPrivacyRequest := truncAndCreate(t)
|
||||
dataPrivacyRequest.Kind = types.RequestKindDelete
|
||||
|
||||
req.NoError(s.UpdateDataPrivacyRequest(ctx, dataPrivacyRequest))
|
||||
|
||||
updated, err := s.LookupDataPrivacyRequestByID(ctx, dataPrivacyRequest.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dataPrivacyRequest.Kind, updated.Kind)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, dataPrivacyRequest := truncAndCreate(t)
|
||||
dataPrivacyRequest.Kind = types.RequestKindDelete
|
||||
|
||||
req.NoError(s.UpsertDataPrivacyRequest(ctx, dataPrivacyRequest))
|
||||
|
||||
updated, err := s.LookupDataPrivacyRequestByID(ctx, dataPrivacyRequest.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dataPrivacyRequest.Kind, updated.Kind)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
dataPrivacyRequest := makeNew("upsert me")
|
||||
dataPrivacyRequest.Kind = "ComposeChartCRUD-2"
|
||||
|
||||
req.NoError(s.UpsertDataPrivacyRequest(ctx, dataPrivacyRequest))
|
||||
|
||||
upserted, err := s.LookupDataPrivacyRequestByID(ctx, dataPrivacyRequest.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(dataPrivacyRequest.Kind, upserted.Kind)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by DataPrivacyRequest", func(t *testing.T) {
|
||||
req, dataPrivacyRequest := truncAndCreate(t)
|
||||
req.NoError(s.DeleteDataPrivacyRequest(ctx, dataPrivacyRequest))
|
||||
_, err := s.LookupDataPrivacyRequestByID(ctx, dataPrivacyRequest.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, dataPrivacyRequest := truncAndCreate(t)
|
||||
req.NoError(s.DeleteDataPrivacyRequestByID(ctx, dataPrivacyRequest.ID))
|
||||
_, err := s.LookupDataPrivacyRequestByID(ctx, dataPrivacyRequest.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.DataPrivacyRequest{
|
||||
makeNew("/one-one"),
|
||||
makeNew("/one-two"),
|
||||
makeNew("/two-one"),
|
||||
makeNew("/two-two"),
|
||||
}
|
||||
|
||||
prefill[3].Kind = types.RequestKindDelete
|
||||
|
||||
count := len(prefill)
|
||||
valid := count
|
||||
|
||||
req.NoError(s.TruncateDataPrivacyRequests(ctx))
|
||||
req.NoError(s.CreateDataPrivacyRequest(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, _, err := s.SearchDataPrivacyRequests(ctx, types.DataPrivacyRequestFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
set, _, err = s.SearchDataPrivacyRequests(ctx, types.DataPrivacyRequestFilter{Kind: []string{"delete"}})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
}
|
||||
10
server/store/tests/federation_exposed_modules_test.go
Normal file
10
server/store/tests/federation_exposed_modules_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testFederationExposedModules(t *testing.T, s store.FederationExposedModules) {
|
||||
// @todo
|
||||
}
|
||||
10
server/store/tests/federation_module_mappings_test.go
Normal file
10
server/store/tests/federation_module_mappings_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testFederationModuleMappings(t *testing.T, s store.FederationModuleMappings) {
|
||||
// @todo
|
||||
}
|
||||
11
server/store/tests/federation_nodes_sync_test.go
Normal file
11
server/store/tests/federation_nodes_sync_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func testFederationNodeSyncs(t *testing.T, s store.FederationNodeSyncs) {
|
||||
t.Skip("@todo")
|
||||
}
|
||||
144
server/store/tests/federation_nodes_test.go
Normal file
144
server/store/tests/federation_nodes_test.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/federation/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testFederationNodes(t *testing.T, s store.FederationNodes) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(name string) *types.Node {
|
||||
// minimum data set for new FederationNode
|
||||
return &types.Node{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Node) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateFederationNodes(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateFederationNode(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
FederationNode := makeNew("FederationNodeCRUD")
|
||||
req.NoError(s.CreateFederationNode(ctx, FederationNode))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
fetched, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(FederationNode.Name, fetched.Name)
|
||||
req.Equal(FederationNode.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
FederationNode.Name = "FederationNodeCRUD+2"
|
||||
|
||||
req.NoError(s.UpdateFederationNode(ctx, FederationNode))
|
||||
|
||||
updated, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(FederationNode.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
FederationNode.Name = "FederationNodeCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertFederationNode(ctx, FederationNode))
|
||||
|
||||
updated, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(FederationNode.Name, updated.Name)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
FederationNode := makeNew("upsert me")
|
||||
FederationNode.Name = "ComposeChartCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertFederationNode(ctx, FederationNode))
|
||||
|
||||
upserted, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(FederationNode.Name, upserted.Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by FederationNode", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
req.NoError(s.DeleteFederationNode(ctx, FederationNode))
|
||||
_, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, FederationNode := truncAndCreate(t)
|
||||
req.NoError(s.DeleteFederationNodeByID(ctx, FederationNode.ID))
|
||||
_, err := s.LookupFederationNodeByID(ctx, FederationNode.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Node{
|
||||
makeNew("/one-one"),
|
||||
makeNew("/one-two"),
|
||||
makeNew("/two-one"),
|
||||
makeNew("/two-two"),
|
||||
makeNew("/two-deleted"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateFederationNodes(ctx))
|
||||
req.NoError(s.CreateFederationNode(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchFederationNodes(ctx, types.NodeFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchFederationNodes(ctx, types.NodeFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchFederationNodes(ctx, types.NodeFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
// find all prefixed
|
||||
set, f, err = s.SearchFederationNodes(ctx, types.NodeFilter{Query: "/two"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
10
server/store/tests/federation_shared_modules_test.go
Normal file
10
server/store/tests/federation_shared_modules_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testFederationSharedModules(t *testing.T, s store.FederationSharedModules) {
|
||||
// @todo
|
||||
}
|
||||
53
server/store/tests/flags_test.go
Normal file
53
server/store/tests/flags_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/flag/types"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testFlags(t *testing.T, s store.Flags) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateFlags(ctx))
|
||||
req.NoError(s.CreateFlag(ctx, &types.Flag{
|
||||
Kind: "kind",
|
||||
ResourceID: 1,
|
||||
OwnedBy: 2,
|
||||
Name: "fname",
|
||||
Active: true,
|
||||
}))
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateFlags(ctx))
|
||||
req.NoError(s.UpdateFlag(ctx, &types.Flag{
|
||||
Kind: "kind",
|
||||
ResourceID: 1,
|
||||
OwnedBy: 2,
|
||||
Name: "fname",
|
||||
Active: false,
|
||||
}))
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateFlags(ctx))
|
||||
req.NoError(s.UpsertFlag(ctx, &types.Flag{
|
||||
Kind: "kind",
|
||||
ResourceID: 1,
|
||||
OwnedBy: 2,
|
||||
Name: "fname",
|
||||
Active: true,
|
||||
}))
|
||||
})
|
||||
}
|
||||
53
server/store/tests/labels_test.go
Normal file
53
server/store/tests/labels_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/label/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/logger"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testLabels(t *testing.T, s store.Labels) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
ctx = logger.ContextWithValue(ctx, logger.MakeDebugLogger())
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateLabels(ctx))
|
||||
req.NoError(s.CreateLabel(ctx, &types.Label{
|
||||
Kind: "kind",
|
||||
ResourceID: 1,
|
||||
Name: "lname",
|
||||
Value: types.LabelValue{Val: "lvalue"},
|
||||
}))
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateLabels(ctx))
|
||||
req.NoError(s.UpdateLabel(ctx, &types.Label{
|
||||
Kind: "kind",
|
||||
ResourceID: 1,
|
||||
Name: "lname",
|
||||
Value: types.LabelValue{Val: "lvalue"},
|
||||
}))
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateLabels(ctx))
|
||||
req.NoError(s.UpsertLabel(ctx, &types.Label{
|
||||
Kind: "kind",
|
||||
ResourceID: 1,
|
||||
Name: "lname",
|
||||
Value: types.LabelValue{Val: "lvalue"},
|
||||
}))
|
||||
})
|
||||
}
|
||||
106
server/store/tests/main_test.go
Normal file
106
server/store/tests/main_test.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/cli"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/store/adapters/rdbms/drivers/mssql"
|
||||
"github.com/cortezaproject/corteza/server/store/adapters/rdbms/drivers/mysql"
|
||||
"github.com/cortezaproject/corteza/server/store/adapters/rdbms/drivers/postgres"
|
||||
"github.com/cortezaproject/corteza/server/store/adapters/rdbms/drivers/sqlite"
|
||||
"github.com/cortezaproject/corteza/server/tests/helpers"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
now = func() *time.Time {
|
||||
n := time.Now().Round(time.Second)
|
||||
return &n
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
helpers.RecursiveDotEnvLoad()
|
||||
id.Init(cli.Context())
|
||||
}
|
||||
|
||||
func Test_RDBMS_SQLITE(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, sqlite.Connect))
|
||||
}
|
||||
|
||||
func Test_RDBMS_MYSQL(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, mysql.Connect))
|
||||
}
|
||||
|
||||
func Test_RDBMS_SQLSERVER_2022(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, mssql.Connect))
|
||||
}
|
||||
|
||||
func Test_RDBMS_SQLSERVER_2019(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, mssql.Connect))
|
||||
}
|
||||
|
||||
func Test_RDBMS_SQLSERVER_2017(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, mssql.Connect))
|
||||
}
|
||||
|
||||
func Test_RDBMS_PGSQL(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, postgres.Connect))
|
||||
}
|
||||
|
||||
func Test_RDBMS_COCKROACHDB(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, nil))
|
||||
}
|
||||
|
||||
func Test_MEMORY(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, nil))
|
||||
}
|
||||
|
||||
func Test_MONGODB(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, nil))
|
||||
}
|
||||
|
||||
func Test_ELASTICSEARCH(t *testing.T) {
|
||||
testAllGenerated(t, setup(t, nil))
|
||||
}
|
||||
|
||||
func setup(t *testing.T, connect store.ConnectorFn) (s store.Storer) {
|
||||
t.Parallel()
|
||||
|
||||
if connect == nil {
|
||||
t.Skipf("connection function not set, skipping tests")
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
err error
|
||||
env = t.Name()[5:] + "_DSN"
|
||||
dsn, has = os.LookupEnv(env)
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
if !has || len(dsn) == 0 {
|
||||
t.Skipf("no %s found, skipping tests", env)
|
||||
return
|
||||
}
|
||||
|
||||
s, err = connect(ctx, dsn)
|
||||
if err != nil {
|
||||
t.Errorf("failed to initialize: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = store.Upgrade(ctx, zap.NewNop(), s)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to upgrade : %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
178
server/store/tests/notifications_test.go
Normal file
178
server/store/tests/notifications_test.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testNotifications(t *testing.T, s store.Notifications) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(nn ...string) *types.Notification {
|
||||
// minimum data set for new notification
|
||||
thisID := id.Next()
|
||||
return &types.Notification{
|
||||
ID: thisID,
|
||||
Kind: types.NotificationKindSimple,
|
||||
Config: types.NotificationConfig{
|
||||
Simple: types.SimpleNotificationConfig{
|
||||
Title: "Test Notification",
|
||||
Description: "This is a test notification",
|
||||
},
|
||||
},
|
||||
Recipient: thisID,
|
||||
CreatedAt: time.Now(),
|
||||
CreatedBy: thisID,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Notification) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateNotifications(ctx))
|
||||
notification := makeNew()
|
||||
req.NoError(s.CreateNotification(ctx, notification))
|
||||
return req, notification
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, types.NotificationSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateNotifications(ctx))
|
||||
|
||||
set := make([]*types.Notification, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew(string(rand.Bytes(10)))
|
||||
}
|
||||
|
||||
req.NoError(s.CreateNotification(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.CreateNotification(ctx, makeNew()))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, notification := truncAndCreate(t)
|
||||
fetched, err := s.LookupNotificationByID(ctx, notification.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(notification.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, notification := truncAndCreate(t)
|
||||
req.NoError(s.UpdateNotification(ctx, notification))
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchNotifications(ctx, types.NotificationFilter{NotificationID: []uint64{prefill[0].ID}})
|
||||
req.NoError(err)
|
||||
req.Equal([]uint64{prefill[0].ID}, f.NotificationID)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by kind", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchNotifications(ctx, types.NotificationFilter{Kind: []types.NotificationKind{prefill[0].Kind}})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5) // All have the same kind
|
||||
})
|
||||
|
||||
t.Run("by recipient", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, f, err := s.SearchNotifications(ctx, types.NotificationFilter{Recipient: prefill[0].Recipient})
|
||||
req.NoError(err)
|
||||
req.Equal(prefill[0].Recipient, f.Recipient)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("unread only", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
// Check that all notifications are initially unread
|
||||
filter := types.NotificationFilter{
|
||||
Read: filter.StateExcluded, // Only unread notifications
|
||||
}
|
||||
set, _, err := s.SearchNotifications(ctx, filter)
|
||||
req.NoError(err)
|
||||
req.Len(set, 5, "Expected all 5 notifications to be unread")
|
||||
|
||||
// Mark one notification as read
|
||||
now := time.Now()
|
||||
prefill[0].ReadAt = &now
|
||||
req.NoError(s.UpdateNotification(ctx, prefill[0]))
|
||||
|
||||
// Search for unread notifications again
|
||||
set, _, err = s.SearchNotifications(ctx, filter)
|
||||
req.NoError(err)
|
||||
|
||||
// We expect 4 unread notifications (5 total - 1 read)
|
||||
req.Len(set, 4, "Expected 4 unread notifications after marking one as read")
|
||||
})
|
||||
|
||||
t.Run("deleted only", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
// Check that no notifications are initially deleted
|
||||
filter := types.NotificationFilter{
|
||||
Deleted: filter.StateExclusive, // Only deleted notifications
|
||||
}
|
||||
set, _, err := s.SearchNotifications(ctx, filter)
|
||||
req.NoError(err)
|
||||
req.Len(set, 0, "Expected no deleted notifications")
|
||||
|
||||
// Mark one notification as deleted
|
||||
now := time.Now()
|
||||
prefill[0].DeletedAt = &now
|
||||
req.NoError(s.UpdateNotification(ctx, prefill[0]))
|
||||
|
||||
// Search for deleted notifications
|
||||
set, _, err = s.SearchNotifications(ctx, filter)
|
||||
req.NoError(err)
|
||||
|
||||
// We expect 1 deleted notification
|
||||
req.Len(set, 1, "Expected 1 deleted notification")
|
||||
})
|
||||
|
||||
t.Run("with check", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, _, err := s.SearchNotifications(ctx, types.NotificationFilter{
|
||||
Check: func(notification *types.Notification) (bool, error) {
|
||||
// simple check that matches with the first notification from prefill
|
||||
return notification.ID == prefill[0].ID, nil
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.Equal(prefill[0].ID, set[0].ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
req, notification := truncAndCreate(t)
|
||||
req.NoError(s.DeleteNotificationByID(ctx, notification.ID))
|
||||
|
||||
// Verify it can't be found
|
||||
_, err := s.LookupNotificationByID(ctx, notification.ID)
|
||||
req.Error(err)
|
||||
})
|
||||
}
|
||||
43
server/store/tests/queue_message_test.go
Normal file
43
server/store/tests/queue_message_test.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testQueueMessages(t *testing.T, s store.QueueMessages) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
foobarMessage = &types.QueueMessage{Payload: []byte(`foobar`), Created: now()}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateQueueMessages(ctx))
|
||||
req.NoError(s.CreateQueueMessage(ctx, foobarMessage))
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateQueueMessages(ctx))
|
||||
req.NoError(s.UpdateQueueMessage(ctx, foobarMessage))
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.CreateQueueMessage(ctx,
|
||||
&types.QueueMessage{ID: 1, Queue: "test", Payload: []byte{}, Created: now()},
|
||||
&types.QueueMessage{ID: 2, Queue: "test", Payload: []byte{}, Created: now()},
|
||||
&types.QueueMessage{ID: 3, Queue: "test", Payload: []byte{}, Created: now()},
|
||||
))
|
||||
|
||||
set, _, err := s.SearchQueueMessages(ctx, types.QueueMessageFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, 3)
|
||||
})
|
||||
}
|
||||
69
server/store/tests/queue_test.go
Normal file
69
server/store/tests/queue_test.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testQueues(t *testing.T, s store.Queues) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
new = &types.Queue{
|
||||
ID: 42,
|
||||
Consumer: "testConsumer",
|
||||
Queue: "testQueue",
|
||||
Meta: types.QueueMeta{},
|
||||
CreatedAt: time.Now(),
|
||||
CreatedBy: 1}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateQueues(ctx))
|
||||
req.NoError(s.CreateQueue(ctx, new))
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateQueues(ctx))
|
||||
req.NoError(s.UpdateQueue(ctx, new))
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateQueues(ctx))
|
||||
req.NoError(s.UpsertQueue(ctx, &types.Queue{ID: 42, Queue: "test", CreatedAt: *now()}))
|
||||
set, _, err := s.SearchQueues(ctx, types.QueueFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.True(set[0].Queue == "test")
|
||||
|
||||
req.NoError(s.UpsertQueue(ctx, &types.Queue{ID: 42, Queue: "foobar", CreatedAt: *now()}))
|
||||
set, _, err = s.SearchQueues(ctx, types.QueueFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.True(set[0].Queue == "foobar")
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateQueues(ctx))
|
||||
req.NoError(s.CreateQueue(ctx,
|
||||
new,
|
||||
))
|
||||
|
||||
set, _, err := s.SearchQueues(ctx, types.QueueFilter{Query: "EST"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
set, _, err = s.SearchQueues(ctx, types.QueueFilter{Query: "foo"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 0)
|
||||
})
|
||||
}
|
||||
57
server/store/tests/rbac_rules_test.go
Normal file
57
server/store/tests/rbac_rules_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testRbacRules(t *testing.T, s store.RbacRules) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateRbacRules(ctx))
|
||||
req.NoError(s.CreateRbacRule(ctx, rbac.AllowRule(42, "res1", "op1")))
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateRbacRules(ctx))
|
||||
req.NoError(s.UpdateRbacRule(ctx, rbac.AllowRule(42, "res1", "op1")))
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateRbacRules(ctx))
|
||||
req.NoError(s.UpsertRbacRule(ctx, rbac.AllowRule(42, "res1", "op1")))
|
||||
set, _, err := s.SearchRbacRules(ctx, rbac.RuleFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.True(set[0].Access == rbac.Allow)
|
||||
|
||||
req.NoError(s.UpsertRbacRule(ctx, rbac.DenyRule(42, "res1", "op1")))
|
||||
set, _, err = s.SearchRbacRules(ctx, rbac.RuleFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.True(set[0].Access == rbac.Deny)
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateRbacRules(ctx))
|
||||
req.NoError(s.CreateRbacRule(ctx,
|
||||
rbac.AllowRule(42, "res1", "op1"),
|
||||
rbac.AllowRule(42, "res2", "op2"),
|
||||
))
|
||||
|
||||
set, _, err := s.SearchRbacRules(ctx, rbac.RuleFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
})
|
||||
}
|
||||
311
server/store/tests/reminders_test.go
Normal file
311
server/store/tests/reminders_test.go
Normal file
@@ -0,0 +1,311 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func testReminders(t *testing.T, s store.Reminders) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(nn ...string) *types.Reminder {
|
||||
// minimum data set for new user
|
||||
name := strings.Join(nn, "")
|
||||
thisID := id.Next()
|
||||
return &types.Reminder{
|
||||
ID: thisID,
|
||||
Resource: "resource+" + name,
|
||||
AssignedTo: thisID,
|
||||
CreatedAt: time.Now(),
|
||||
AssignedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Reminder) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateReminders(ctx))
|
||||
reminder := makeNew()
|
||||
req.NoError(s.CreateReminder(ctx, reminder))
|
||||
return req, reminder
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, types.ReminderSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateReminders(ctx))
|
||||
|
||||
set := make([]*types.Reminder, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew(string(rand.Bytes(10)))
|
||||
}
|
||||
|
||||
req.NoError(s.CreateReminder(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.CreateReminder(ctx, makeNew()))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, reminder := truncAndCreate(t)
|
||||
fetched, err := s.LookupReminderByID(ctx, reminder.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(reminder.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, reminder := truncAndCreate(t)
|
||||
req.NoError(s.UpdateReminder(ctx, reminder))
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{ReminderID: []uint64{prefill[0].ID}})
|
||||
req.NoError(err)
|
||||
req.Equal([]uint64{prefill[0].ID}, f.ReminderID)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by resource", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchReminders(ctx, types.ReminderFilter{Resource: prefill[0].Resource})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by assigned to", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{AssignedTo: prefill[0].AssignedTo})
|
||||
req.NoError(err)
|
||||
req.Equal(prefill[0].AssignedTo, f.AssignedTo)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by dismissed", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
prefill[0].DismissedAt = &(prefill[0].CreatedAt)
|
||||
s.UpdateReminder(ctx, prefill[0])
|
||||
|
||||
set, _, err := s.SearchReminders(ctx, types.ReminderFilter{ExcludeDismissed: true})
|
||||
req.NoError(err)
|
||||
req.Len(set, 4)
|
||||
})
|
||||
|
||||
t.Run("by scheduled", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
prefill[0].RemindAt = &(prefill[0].CreatedAt)
|
||||
s.UpdateReminder(ctx, prefill[0])
|
||||
|
||||
set, _, err := s.SearchReminders(ctx, types.ReminderFilter{ScheduledOnly: true})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("with check", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, _, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Check: func(user *types.Reminder) (bool, error) {
|
||||
// simple check that matches with the first user from prefill
|
||||
return user.ID == prefill[0].ID, nil
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.Equal(prefill[0].ID, set[0].ID)
|
||||
})
|
||||
|
||||
t.Run("paging with check", func(t *testing.T) {
|
||||
// hide every third reminder from the check fn
|
||||
hide := func(prefill types.ReminderSet) (map[uint64]bool, int) {
|
||||
hidden, visible := make(map[uint64]bool), 0
|
||||
for i, r := range prefill {
|
||||
if i%3 == 0 {
|
||||
hidden[r.ID] = true
|
||||
} else {
|
||||
visible++
|
||||
}
|
||||
}
|
||||
return hidden, visible
|
||||
}
|
||||
|
||||
t.Run("page holds no more than the limit and no duplicates", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 20)
|
||||
hidden, _ := hide(prefill)
|
||||
|
||||
set, _, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 5},
|
||||
Check: func(r *types.Reminder) (bool, error) { return !hidden[r.ID], nil },
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
|
||||
seen := make(map[uint64]bool)
|
||||
for _, r := range set {
|
||||
req.False(seen[r.ID], "reminder %d returned twice", r.ID)
|
||||
seen[r.ID] = true
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("walking every page yields each visible item once", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 20)
|
||||
hidden, visible := hide(prefill)
|
||||
|
||||
var (
|
||||
cursor *filter.PagingCursor
|
||||
seen = make(map[uint64]int)
|
||||
)
|
||||
|
||||
for page := 0; page < 30; page++ {
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 3, PageCursor: cursor},
|
||||
Check: func(r *types.Reminder) (bool, error) { return !hidden[r.ID], nil },
|
||||
})
|
||||
req.NoError(err)
|
||||
|
||||
for _, r := range set {
|
||||
req.False(hidden[r.ID], "hidden reminder %d was returned", r.ID)
|
||||
seen[r.ID]++
|
||||
}
|
||||
|
||||
if f.NextPage == nil {
|
||||
break
|
||||
}
|
||||
cursor = f.NextPage
|
||||
}
|
||||
|
||||
req.Len(seen, visible)
|
||||
for id, times := range seen {
|
||||
req.Equal(1, times, "reminder %d returned %d times", id, times)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("fills a page past a long run of rejected items", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 200)
|
||||
|
||||
// hide everything but the last 5
|
||||
hidden := make(map[uint64]bool)
|
||||
for _, r := range prefill[:len(prefill)-5] {
|
||||
hidden[r.ID] = true
|
||||
}
|
||||
|
||||
set, _, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 3},
|
||||
Check: func(r *types.Reminder) (bool, error) { return !hidden[r.ID], nil },
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 3)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("total", func(t *testing.T) {
|
||||
t.Run("omitted when not requested", func(t *testing.T) {
|
||||
req, _ := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 2},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
req.Equal(uint(0), f.Total)
|
||||
})
|
||||
|
||||
t.Run("without limit", func(t *testing.T) {
|
||||
req, _ := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{IncTotal: true},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
req.Equal(uint(5), f.Total)
|
||||
})
|
||||
|
||||
t.Run("with limit above count", func(t *testing.T) {
|
||||
req, _ := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 10, IncTotal: true},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
req.Equal(uint(5), f.Total)
|
||||
})
|
||||
|
||||
t.Run("with limit equal to count", func(t *testing.T) {
|
||||
req, _ := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 5, IncTotal: true},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
req.Equal(uint(5), f.Total)
|
||||
})
|
||||
|
||||
t.Run("with limit below count", func(t *testing.T) {
|
||||
req, _ := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 2, IncTotal: true},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
req.Equal(uint(5), f.Total)
|
||||
})
|
||||
|
||||
t.Run("counts only what check keeps", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 2, IncTotal: true},
|
||||
Check: func(r *types.Reminder) (bool, error) {
|
||||
return r.ID != prefill[0].ID && r.ID != prefill[1].ID, nil
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 2)
|
||||
req.Equal(uint(3), f.Total)
|
||||
})
|
||||
|
||||
t.Run("refused with a page cursor", func(t *testing.T) {
|
||||
req, _ := truncAndFill(t, 5)
|
||||
|
||||
_, f, err := s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 2},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.NotNil(f.NextPage)
|
||||
|
||||
_, _, err = s.SearchReminders(ctx, types.ReminderFilter{
|
||||
Paging: filter.Paging{Limit: 2, IncTotal: true, PageCursor: f.NextPage},
|
||||
})
|
||||
req.Error(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("ordered search", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
}
|
||||
11
server/store/tests/reports_test.go
Normal file
11
server/store/tests/reports_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func testReports(t *testing.T, s store.Reports) {
|
||||
t.Skip("@todo")
|
||||
}
|
||||
11
server/store/tests/resource_activity_log_test.go
Normal file
11
server/store/tests/resource_activity_log_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func testResourceActivitys(t *testing.T, s store.ResourceActivitys) {
|
||||
t.Skip("@todo")
|
||||
}
|
||||
11
server/store/tests/resource_translations_test.go
Normal file
11
server/store/tests/resource_translations_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func testResourceTranslations(t *testing.T, s store.Reports) {
|
||||
t.Skip("@todo")
|
||||
}
|
||||
100
server/store/tests/role_members_test.go
Normal file
100
server/store/tests/role_members_test.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testRoleMembers(t *testing.T, s store.RoleMembers) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(nn ...string) *types.RoleMember {
|
||||
// minimum data set for new RoleMember
|
||||
return &types.RoleMember{
|
||||
RoleID: id.Next(),
|
||||
Resource: fmt.Sprintf("corteza::system:user/%d", id.Next()),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.RoleMember) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateRoleMembers(ctx))
|
||||
roleMember := makeNew()
|
||||
req.NoError(s.CreateRoleMember(ctx, roleMember))
|
||||
return req, roleMember
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, types.RoleMemberSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateRoleMembers(ctx))
|
||||
|
||||
set := make([]*types.RoleMember, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew()
|
||||
}
|
||||
|
||||
req.NoError(s.CreateRoleMember(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.CreateRoleMember(ctx, makeNew()))
|
||||
})
|
||||
|
||||
t.Run("create multiple", func(t *testing.T) {
|
||||
truncAndFill(t, 5)
|
||||
})
|
||||
|
||||
// t.Run("update", func(t *testing.T) {
|
||||
// req, roleMember := truncAndCreate(t)
|
||||
|
||||
// newID := id.Next()
|
||||
// roleMember = &types.RoleMember{
|
||||
// OwnerID: roleMember.OwnerID,
|
||||
// RoleID: newID,
|
||||
// }
|
||||
// req.NoError(s.UpdateRoleMember(ctx, roleMember))
|
||||
|
||||
// updated, f, err := s.SearchRoleMembers(ctx, types.RoleMemberFilter{OwnerID: roleMember.OwnerID})
|
||||
// req.NoError(err)
|
||||
// req.Equal(updated[0].OwnerID, f.OwnerID)
|
||||
// })
|
||||
|
||||
// t.Run("search", func(t *testing.T) {
|
||||
// t.Run("by RoleID", func(t *testing.T) {
|
||||
// req, prefill := truncAndFill(t, 5)
|
||||
|
||||
// set, f, err := s.SearchRoleMembers(ctx, types.RoleMemberFilter{RoleID: prefill[0].RoleID})
|
||||
// req.NoError(err)
|
||||
// req.Equal(prefill[0].RoleID, f.RoleID)
|
||||
// req.Len(set, 1)
|
||||
// })
|
||||
// })
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by role member", func(t *testing.T) {
|
||||
req, roleMember := truncAndCreate(t)
|
||||
req.NoError(s.DeleteRoleMember(ctx, roleMember))
|
||||
roleMembers, _, _ := s.SearchRoleMembers(ctx, types.RoleMemberFilter{Resource: roleMember.Resource, RoleID: roleMember.RoleID})
|
||||
req.Len(roleMembers, 0)
|
||||
})
|
||||
|
||||
t.Run("by RoleID and UserID", func(t *testing.T) {
|
||||
req, roleMember := truncAndCreate(t)
|
||||
req.NoError(s.DeleteRoleMemberByResourceRoleID(ctx, roleMember.Resource, roleMember.RoleID))
|
||||
roleMembers, _, _ := s.SearchRoleMembers(ctx, types.RoleMemberFilter{Resource: roleMember.Resource, RoleID: roleMember.RoleID})
|
||||
req.Len(roleMembers, 0)
|
||||
})
|
||||
})
|
||||
}
|
||||
205
server/store/tests/roles_test.go
Normal file
205
server/store/tests/roles_test.go
Normal file
@@ -0,0 +1,205 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testRoles(t *testing.T, s store.Roles) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(nn ...string) *types.Role {
|
||||
name := strings.Join(nn, "")
|
||||
return &types.Role{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Name: "RoleCRUD+" + name,
|
||||
Handle: "rolecrud+" + name,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Role) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateRoles(ctx))
|
||||
role := makeNew()
|
||||
req.NoError(s.CreateRole(ctx, role))
|
||||
return req, role
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, types.RoleSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateRoles(ctx))
|
||||
|
||||
set := make([]*types.Role, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew(string(rand.Bytes(10)))
|
||||
}
|
||||
|
||||
req.NoError(s.CreateRole(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.CreateRole(ctx, makeNew()))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, role := truncAndCreate(t)
|
||||
fetched, err := s.LookupRoleByID(ctx, role.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(role.Name, fetched.Name)
|
||||
req.Equal(role.Handle, fetched.Handle)
|
||||
req.Equal(role.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, role := truncAndCreate(t)
|
||||
req.NoError(s.UpdateRole(ctx, role))
|
||||
})
|
||||
|
||||
t.Run("create and update deleted with existing handle", func(t *testing.T) {
|
||||
req, role := truncAndCreate(t)
|
||||
deletedRole := makeNew("copy")
|
||||
deletedRole.DeletedAt = now()
|
||||
deletedRole.Handle = role.Handle
|
||||
req.NoError(store.CreateRole(ctx, s, deletedRole))
|
||||
req.NoError(store.UpdateRole(ctx, s, deletedRole))
|
||||
})
|
||||
|
||||
t.Run("lookup by handle", func(t *testing.T) {
|
||||
req, role := truncAndCreate(t)
|
||||
fetched, err := s.LookupRoleByHandle(ctx, role.Handle)
|
||||
req.NoError(err)
|
||||
req.Equal(role.ID, fetched.ID)
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchRoles(ctx, types.RoleFilter{RoleID: id.Strings(prefill[0].ID)})
|
||||
req.NoError(err)
|
||||
req.Equal(id.Strings(prefill[0].ID), f.RoleID)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by query", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchRoles(ctx, types.RoleFilter{Query: prefill[0].Handle})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by state", func(t *testing.T) {
|
||||
t.Run("deleted", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
prefill[0].DeletedAt = &(prefill[0].CreatedAt)
|
||||
s.UpdateRole(ctx, prefill[0])
|
||||
|
||||
set, _, err := s.SearchRoles(ctx, types.RoleFilter{Deleted: filter.StateExcluded})
|
||||
req.NoError(err)
|
||||
req.Len(set, 4)
|
||||
|
||||
set, _, err = s.SearchRoles(ctx, types.RoleFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
|
||||
set, _, err = s.SearchRoles(ctx, types.RoleFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("archived", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
prefill[0].ArchivedAt = &(prefill[0].CreatedAt)
|
||||
s.UpdateRole(ctx, prefill[0])
|
||||
|
||||
set, _, err := s.SearchRoles(ctx, types.RoleFilter{Archived: filter.StateExcluded})
|
||||
req.NoError(err)
|
||||
req.Len(set, 4)
|
||||
|
||||
set, _, err = s.SearchRoles(ctx, types.RoleFilter{Archived: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 5)
|
||||
|
||||
set, _, err = s.SearchRoles(ctx, types.RoleFilter{Archived: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("with check", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchRoles(ctx, types.RoleFilter{
|
||||
Check: func(role *types.Role) (bool, error) {
|
||||
return role.ID == prefill[0].ID, nil
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.Equal(prefill[0].ID, set[0].ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("ordered search", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
|
||||
t.Run("metrics", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
|
||||
oct, _ = time.Parse(time.RFC3339, "2020-10-02T10:01:10Z")
|
||||
nov, _ = time.Parse(time.RFC3339, "2020-11-02T20:02:10Z")
|
||||
|
||||
octu = uint(oct.Truncate(time.Hour * 24).Unix())
|
||||
novu = uint(nov.Truncate(time.Hour * 24).Unix())
|
||||
|
||||
e = &types.RoleMetrics{
|
||||
Total: 8,
|
||||
Valid: 2,
|
||||
Deleted: 3,
|
||||
Archived: 3,
|
||||
DailyCreated: []uint{octu, 7, novu, 1},
|
||||
DailyUpdated: []uint{octu, 2},
|
||||
DailyArchived: []uint{octu, 2, novu, 1},
|
||||
DailyDeleted: []uint{novu, 3},
|
||||
}
|
||||
)
|
||||
|
||||
req.NoError(s.TruncateRoles(ctx))
|
||||
req.NoError(s.CreateRole(ctx, &types.Role{ID: id.Next(), CreatedAt: oct, UpdatedAt: &oct}))
|
||||
req.NoError(s.CreateRole(ctx, &types.Role{ID: id.Next(), CreatedAt: oct, UpdatedAt: &oct}))
|
||||
req.NoError(s.CreateRole(ctx, &types.Role{ID: id.Next(), CreatedAt: oct, ArchivedAt: &oct}))
|
||||
req.NoError(s.CreateRole(ctx, &types.Role{ID: id.Next(), CreatedAt: oct, ArchivedAt: &oct}))
|
||||
req.NoError(s.CreateRole(ctx, &types.Role{ID: id.Next(), CreatedAt: oct, ArchivedAt: &nov}))
|
||||
req.NoError(s.CreateRole(ctx, &types.Role{ID: id.Next(), CreatedAt: oct, DeletedAt: &nov}))
|
||||
req.NoError(s.CreateRole(ctx, &types.Role{ID: id.Next(), CreatedAt: oct, DeletedAt: &nov}))
|
||||
req.NoError(s.CreateRole(ctx, &types.Role{ID: id.Next(), CreatedAt: nov, DeletedAt: &nov}))
|
||||
|
||||
m, err := store.RoleMetrics(ctx, s)
|
||||
req.NoError(err)
|
||||
req.Equal(e, m)
|
||||
})
|
||||
}
|
||||
137
server/store/tests/settings_test.go
Normal file
137
server/store/tests/settings_test.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testSettingValues(t *testing.T, s store.SettingValues) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(nn ...string) *types.SettingValue {
|
||||
name := strings.Join(nn, "")
|
||||
return &types.SettingValue{
|
||||
Name: name,
|
||||
OwnedBy: id.Next(),
|
||||
UpdatedAt: *now(),
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.SettingValue) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateSettingValues(ctx))
|
||||
settings := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateSettingValue(ctx, settings))
|
||||
return req, settings
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, types.SettingValueSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateSettingValues(ctx))
|
||||
|
||||
set := make([]*types.SettingValue, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew(string(rand.Bytes(10)))
|
||||
}
|
||||
|
||||
req.NoError(s.CreateSettingValue(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.CreateSettingValue(ctx, makeNew()))
|
||||
})
|
||||
|
||||
t.Run("lookup by name and ownedBy", func(t *testing.T) {
|
||||
req, setting := truncAndCreate(t)
|
||||
fetched, err := s.LookupSettingValueByNameOwnedBy(ctx, setting.Name, setting.OwnedBy)
|
||||
req.NoError(err)
|
||||
req.Equal(setting.Name, fetched.Name)
|
||||
req.Equal(setting.OwnedBy, fetched.OwnedBy)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, setting := truncAndCreate(t)
|
||||
setting.Value = []byte(`"42"`)
|
||||
req.NoError(s.UpdateSettingValue(ctx, setting))
|
||||
|
||||
fetched, err := s.LookupSettingValueByNameOwnedBy(ctx, setting.Name, setting.OwnedBy)
|
||||
req.NoError(err)
|
||||
req.Equal(string(`"42"`), string(fetched.Value))
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateSettingValues(ctx))
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.UpsertSettingValue(ctx, &types.SettingValue{Name: "foo", Value: []byte(`"foo"`), UpdatedAt: *now()}))
|
||||
v, err := s.LookupSettingValueByNameOwnedBy(ctx, "foo", 0)
|
||||
req.NoError(err)
|
||||
req.NotNil(v)
|
||||
req.Equal(string(`"foo"`), string(v.Value))
|
||||
})
|
||||
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req.NoError(s.CreateSettingValue(ctx, &types.SettingValue{Name: "baz", Value: []byte(`"created"`), UpdatedAt: *now()}))
|
||||
req.NoError(s.UpsertSettingValue(ctx, &types.SettingValue{Name: "baz", Value: []byte(`"updated"`), UpdatedAt: *now()}))
|
||||
v, err := s.LookupSettingValueByNameOwnedBy(ctx, "baz", 0)
|
||||
req.NoError(err)
|
||||
req.NotNil(v)
|
||||
req.Equal(string(`"updated"`), string(v.Value))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Settings", func(t *testing.T) {
|
||||
req, setting := truncAndCreate(t)
|
||||
req.NoError(s.DeleteSettingValue(ctx, setting))
|
||||
set, _, err := s.SearchSettingValues(ctx, types.SettingsFilter{OwnedBy: setting.OwnedBy})
|
||||
req.NoError(err)
|
||||
req.Len(set, 0)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Run("by ownedBy", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, f, err := s.SearchSettingValues(ctx, types.SettingsFilter{OwnedBy: prefill[0].OwnedBy})
|
||||
req.NoError(err)
|
||||
req.Equal(uint64(prefill[0].OwnedBy), f.OwnedBy)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("with check", func(t *testing.T) {
|
||||
t.Skip("Should pass(afaik) but doesn't")
|
||||
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
|
||||
set, _, err := s.SearchSettingValues(ctx, types.SettingsFilter{
|
||||
Check: func(setting *types.SettingValue) (bool, error) {
|
||||
return (setting.Name == prefill[0].Name), nil
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.Equal(prefill[0].Name, set[0].Name)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("ordered search", func(t *testing.T) {
|
||||
t.Skip("not implemented")
|
||||
})
|
||||
}
|
||||
157
server/store/tests/templates_test.go
Normal file
157
server/store/tests/templates_test.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testTemplates(t *testing.T, s store.Templates) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
|
||||
makeNew = func(handle string) *types.Template {
|
||||
// minimum data set for new template
|
||||
return &types.Template{
|
||||
ID: id.Next(),
|
||||
CreatedAt: time.Now(),
|
||||
Handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.Template) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateTemplates(ctx))
|
||||
res := makeNew(string(rand.Bytes(10)))
|
||||
req.NoError(s.CreateTemplate(ctx, res))
|
||||
return req, res
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req.NoError(s.TruncateTemplates(ctx))
|
||||
template := makeNew("TemplateCRUD")
|
||||
req.NoError(s.CreateTemplate(ctx, template))
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, template := truncAndCreate(t)
|
||||
fetched, err := s.LookupTemplateByID(ctx, template.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(template.Handle, fetched.Handle)
|
||||
req.Equal(template.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("lookup by handle", func(t *testing.T) {
|
||||
req, template := truncAndCreate(t)
|
||||
fetched, err := s.LookupTemplateByHandle(ctx, template.Handle)
|
||||
req.NoError(err)
|
||||
req.Equal(template.Handle, fetched.Handle)
|
||||
req.Equal(template.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, template := truncAndCreate(t)
|
||||
template.Handle = "TemplateCRUD+2"
|
||||
|
||||
req.NoError(s.UpdateTemplate(ctx, template))
|
||||
|
||||
updated, err := s.LookupTemplateByID(ctx, template.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(template.Handle, updated.Handle)
|
||||
})
|
||||
|
||||
t.Run("upsert", func(t *testing.T) {
|
||||
t.Run("existing", func(t *testing.T) {
|
||||
req, template := truncAndCreate(t)
|
||||
template.Handle = "TemplateCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertTemplate(ctx, template))
|
||||
|
||||
updated, err := s.LookupTemplateByID(ctx, template.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(template.Handle, updated.Handle)
|
||||
})
|
||||
|
||||
t.Run("new", func(t *testing.T) {
|
||||
template := makeNew("upsert me")
|
||||
template.Handle = "ComposeChartCRUD+2"
|
||||
|
||||
req.NoError(s.UpsertTemplate(ctx, template))
|
||||
|
||||
upserted, err := s.LookupTemplateByID(ctx, template.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(template.Handle, upserted.Handle)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
t.Run("by Template", func(t *testing.T) {
|
||||
req, template := truncAndCreate(t)
|
||||
req.NoError(s.DeleteTemplate(ctx, template))
|
||||
_, err := s.LookupTemplateByID(ctx, template.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, template := truncAndCreate(t)
|
||||
req.NoError(s.DeleteTemplateByID(ctx, template.ID))
|
||||
_, err := s.LookupTemplateByID(ctx, template.ID)
|
||||
req.EqualError(err, store.ErrNotFound.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
prefill := []*types.Template{
|
||||
makeNew("one-one"),
|
||||
makeNew("one-two"),
|
||||
makeNew("two-one"),
|
||||
makeNew("two-two"),
|
||||
makeNew("two-deleted"),
|
||||
}
|
||||
|
||||
count := len(prefill)
|
||||
|
||||
prefill[4].DeletedAt = &prefill[4].CreatedAt
|
||||
valid := count - 1
|
||||
|
||||
req.NoError(s.TruncateTemplates(ctx))
|
||||
req.NoError(s.CreateTemplate(ctx, prefill...))
|
||||
|
||||
// search for all valid
|
||||
set, f, err := s.SearchTemplates(ctx, types.TemplateFilter{})
|
||||
req.NoError(err)
|
||||
req.Len(set, valid) // we've deleted one
|
||||
|
||||
// search for ALL
|
||||
set, f, err = s.SearchTemplates(ctx, types.TemplateFilter{Deleted: filter.StateInclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, count) // we've deleted one
|
||||
|
||||
// search for deleted only
|
||||
set, f, err = s.SearchTemplates(ctx, types.TemplateFilter{Deleted: filter.StateExclusive})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1) // we've deleted one
|
||||
|
||||
set, f, err = s.SearchTemplates(ctx, types.TemplateFilter{Handle: "two-one"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
|
||||
_ = f // dummy
|
||||
})
|
||||
}
|
||||
10
server/store/tests/user_groups_test.go
Normal file
10
server/store/tests/user_groups_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
)
|
||||
|
||||
func testUserGroups(t *testing.T, s store.UserGroups) {}
|
||||
474
server/store/tests/users_test.go
Normal file
474
server/store/tests/users_test.go
Normal file
@@ -0,0 +1,474 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/pkg/id"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rand"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testUsers(t *testing.T, s store.Users) {
|
||||
var (
|
||||
dummyID uint64 = 0
|
||||
ctx = context.Background()
|
||||
|
||||
makeNew = func(nn ...string) *types.User {
|
||||
// minimum data set for new user
|
||||
name := strings.Join(nn, "")
|
||||
dummyID = dummyID + 1
|
||||
return &types.User{
|
||||
ID: dummyID,
|
||||
CreatedAt: time.Now(),
|
||||
Email: "user-crud+" + name + "@crust.test",
|
||||
Username: "username_" + name,
|
||||
Handle: "handle_" + name,
|
||||
}
|
||||
}
|
||||
|
||||
truncAndCreate = func(t *testing.T) (*require.Assertions, *types.User) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateUsers(ctx))
|
||||
user := makeNew()
|
||||
req.NoError(s.CreateUser(ctx, user))
|
||||
return req, user
|
||||
}
|
||||
|
||||
truncAndFill = func(t *testing.T, l int) (*require.Assertions, types.UserSet) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateUsers(ctx))
|
||||
|
||||
set := make([]*types.User, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
set[i] = makeNew(string(rand.Bytes(10)))
|
||||
}
|
||||
|
||||
req.NoError(s.CreateUser(ctx, set...))
|
||||
return req, set
|
||||
}
|
||||
|
||||
stringifySetRange = func(set types.UserSet) string {
|
||||
if len(set) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var out = set[0].Handle[7:]
|
||||
|
||||
if len(set) > 1 {
|
||||
out += ".." + set[len(set)-1].Handle[7:]
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// in case we need some quick old-school debugging
|
||||
//dbg := func(uu ...*types.User) {
|
||||
// for i, u := range uu {
|
||||
// fmt.Printf(" => #%2d %s\n", i+1, u.Handle)
|
||||
// }
|
||||
//}
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateUsers(ctx))
|
||||
req.NoError(store.CreateUser(ctx, s, makeNew()))
|
||||
})
|
||||
|
||||
t.Run("create with duplicate email", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateUsers(ctx))
|
||||
|
||||
req.NoError(s.CreateUser(ctx, makeNew("a")))
|
||||
req.EqualError(s.CreateUser(ctx, makeNew("a")), store.ErrNotUnique.Error())
|
||||
})
|
||||
|
||||
t.Run("create with duplicate ID", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateUsers(ctx))
|
||||
user := makeNew("a")
|
||||
req.NoError(s.CreateUser(ctx, user))
|
||||
req.EqualError(s.CreateUser(ctx, user), store.ErrNotUnique.Error())
|
||||
})
|
||||
|
||||
t.Run("lookup by ID", func(t *testing.T) {
|
||||
req, user := truncAndCreate(t)
|
||||
fetched, err := store.LookupUserByID(ctx, s, user.ID)
|
||||
req.NoError(err)
|
||||
req.Equal(user.Email, fetched.Email)
|
||||
req.Equal(user.Username, fetched.Username)
|
||||
req.Equal(user.Handle, fetched.Handle)
|
||||
req.Equal(user.ID, fetched.ID)
|
||||
req.NotNil(fetched.CreatedAt)
|
||||
req.Nil(fetched.UpdatedAt)
|
||||
req.Nil(fetched.DeletedAt)
|
||||
req.Nil(fetched.SuspendedAt)
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
req, user := truncAndCreate(t)
|
||||
req.NoError(s.UpdateUser(ctx, user))
|
||||
})
|
||||
|
||||
t.Run("lookup by email", func(t *testing.T) {
|
||||
req, user := truncAndCreate(t)
|
||||
fetched, err := store.LookupUserByEmail(ctx, s, user.Email)
|
||||
req.NoError(err)
|
||||
req.Equal(user.Email, fetched.Email)
|
||||
})
|
||||
|
||||
t.Run("lookup by handle", func(t *testing.T) {
|
||||
req, user := truncAndCreate(t)
|
||||
fetched, err := store.LookupUserByHandle(ctx, s, user.Handle)
|
||||
req.NoError(err)
|
||||
req.Equal(user.ID, fetched.ID)
|
||||
})
|
||||
|
||||
t.Run("lookup by nonexisting handle", func(t *testing.T) {
|
||||
req, _ := truncAndCreate(t)
|
||||
fetched, err := store.LookupUserByHandle(ctx, s, "no such handle")
|
||||
req.EqualError(err, "not found")
|
||||
req.Nil(fetched)
|
||||
})
|
||||
|
||||
t.Run("lookup by username", func(t *testing.T) {
|
||||
req, user := truncAndCreate(t)
|
||||
fetched, err := store.LookupUserByUsername(ctx, s, user.Username)
|
||||
req.NoError(err)
|
||||
req.Equal(user.ID, fetched.ID)
|
||||
})
|
||||
|
||||
t.Run("create and update deleted with existing email", func(t *testing.T) {
|
||||
req, user := truncAndCreate(t)
|
||||
deletedUser := makeNew("copy")
|
||||
deletedUser.DeletedAt = now()
|
||||
deletedUser.Email = user.Email
|
||||
req.NoError(store.CreateUser(ctx, s, deletedUser))
|
||||
req.NoError(store.UpdateUser(ctx, s, deletedUser))
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
t.Run("by ID", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, f, err := store.SearchUsers(ctx, s, types.UserFilter{UserID: id.Strings(prefill[0].ID)})
|
||||
req.NoError(err)
|
||||
req.Equal(id.Strings(prefill[0].ID), f.UserID)
|
||||
req.Len(set, 1)
|
||||
//req.Equal(set[0].ID, user.ID)
|
||||
})
|
||||
|
||||
t.Run("by email", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, _, err := store.SearchUsers(ctx, s, types.UserFilter{Email: prefill[0].Email})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by username", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, _, err := store.SearchUsers(ctx, s, types.UserFilter{Username: prefill[0].Username})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by query", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, _, err := store.SearchUsers(ctx, s, types.UserFilter{Query: prefill[0].Handle})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
})
|
||||
|
||||
t.Run("by username", func(t *testing.T) {
|
||||
req, _ := truncAndFill(t, 5)
|
||||
set, _, err := store.SearchUsers(ctx, s, types.UserFilter{Username: "no such username"})
|
||||
req.NoError(err)
|
||||
req.Len(set, 0)
|
||||
})
|
||||
|
||||
t.Run("with check", func(t *testing.T) {
|
||||
req, prefill := truncAndFill(t, 5)
|
||||
set, _, err := store.SearchUsers(ctx, s, types.UserFilter{
|
||||
Check: func(user *types.User) (bool, error) {
|
||||
// simple check that matches with the first user from prefill
|
||||
return user.ID == prefill[0].ID, nil
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
req.Len(set, 1)
|
||||
req.Equal(prefill[0].ID, set[0].ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("paging and sorting", func(t *testing.T) {
|
||||
require.NoError(t, s.TruncateUsers(ctx))
|
||||
require.NoError(t, s.CreateUser(ctx,
|
||||
makeNew("01"),
|
||||
makeNew("02"),
|
||||
makeNew("03"),
|
||||
makeNew("04"),
|
||||
makeNew("05"),
|
||||
makeNew("06"),
|
||||
makeNew("07"),
|
||||
makeNew("08"),
|
||||
makeNew("09"),
|
||||
makeNew("10"),
|
||||
))
|
||||
|
||||
{
|
||||
tcc := []struct {
|
||||
sort string
|
||||
rval string
|
||||
}{
|
||||
{"email", "01..10"},
|
||||
{"email DESC", "10..01"},
|
||||
{"id, email", "01..10"},
|
||||
{"id DESC, email DESC", "10..01"},
|
||||
{"id DESC, email", "10..01"},
|
||||
{"id, email DESC", "01..10"},
|
||||
}
|
||||
|
||||
for _, tc := range tcc {
|
||||
t.Run(tc.sort, func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
|
||||
f = types.UserFilter{}
|
||||
set types.UserSet
|
||||
err error
|
||||
)
|
||||
|
||||
f.Sort.Set(tc.sort)
|
||||
set, f, err = store.SearchUsers(ctx, s, f)
|
||||
req.NoError(err)
|
||||
req.Equal(tc.rval, stringifySetRange(set))
|
||||
req.Nil(f.PrevPage)
|
||||
req.Nil(f.NextPage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
prevCur := 1
|
||||
nextCur := 2
|
||||
bothCur := prevCur | nextCur
|
||||
|
||||
// tests if cursors are properly set/unset by inspecting req. bits
|
||||
testCursors := func(req *require.Assertions, b int, f types.UserFilter) {
|
||||
if b&prevCur == 0 {
|
||||
req.Nil(f.PrevPage)
|
||||
} else {
|
||||
req.NotNil(f.PrevPage)
|
||||
}
|
||||
|
||||
if b&nextCur == 0 {
|
||||
req.Nil(f.NextPage)
|
||||
} else {
|
||||
req.NotNil(f.NextPage)
|
||||
}
|
||||
}
|
||||
|
||||
tcc := []struct {
|
||||
// how data is sorted
|
||||
sort string
|
||||
|
||||
// expected data
|
||||
rval []string
|
||||
|
||||
// how cursors should be set when moving forward/backward
|
||||
curr []int
|
||||
}{
|
||||
{
|
||||
"id",
|
||||
[]string{"01..03", "04..06", "07..09", "10"},
|
||||
[]int{nextCur, bothCur, bothCur, prevCur},
|
||||
},
|
||||
{
|
||||
"id DESC",
|
||||
[]string{"10..08", "07..05", "04..02", "01"},
|
||||
[]int{nextCur, bothCur, bothCur, prevCur},
|
||||
},
|
||||
{
|
||||
"email",
|
||||
[]string{"01..03", "04..06", "07..09", "10"},
|
||||
[]int{nextCur, bothCur, bothCur, prevCur},
|
||||
},
|
||||
{
|
||||
"email DESC",
|
||||
[]string{"10..08", "07..05", "04..02", "01"},
|
||||
[]int{nextCur, bothCur, bothCur, prevCur},
|
||||
},
|
||||
{
|
||||
"id DESC, email",
|
||||
[]string{"10..08", "07..05", "04..02", "01"},
|
||||
[]int{nextCur, bothCur, bothCur, prevCur},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcc {
|
||||
t.Run("crawling: "+tc.sort+"x", func(t *testing.T) {
|
||||
|
||||
var (
|
||||
req = require.New(t)
|
||||
|
||||
f = types.UserFilter{}
|
||||
set types.UserSet
|
||||
err error
|
||||
)
|
||||
|
||||
f.Sort.Set(tc.sort)
|
||||
f.Limit = 3 // 3, 3, 3, 1
|
||||
|
||||
t.Log("going from page 1 to 4")
|
||||
for p := 0; p < 4; p++ {
|
||||
t.Logf("0123 next page cursor: %35s", f.PageCursor)
|
||||
set, f, err = store.SearchUsers(ctx, s, f)
|
||||
req.NoError(err)
|
||||
req.True(tc.sort == f.Sort.String() || strings.HasPrefix(f.Sort.String(), tc.sort+","))
|
||||
|
||||
req.Equal(tc.rval[p], stringifySetRange(set))
|
||||
|
||||
testCursors(req, tc.curr[p], f)
|
||||
|
||||
// advance to next page
|
||||
f.PageCursor = f.NextPage
|
||||
}
|
||||
|
||||
t.Log("and back from 3 to 1")
|
||||
f.PageCursor = f.PrevPage
|
||||
for p := 2; p >= 0; p-- {
|
||||
f.Sort = nil
|
||||
t.Logf("_210 next page cursor: %35s", f.PageCursor)
|
||||
set, f, err = store.SearchUsers(ctx, s, f)
|
||||
t.Log(stringifySetRange(set))
|
||||
req.NoError(err)
|
||||
//req.True(tc.sort == f.Sort.String() || strings.HasPrefix(f.Sort.String(), tc.sort+","), "search should not return altered sort on filter")
|
||||
|
||||
req.Equal(tc.rval[p], stringifySetRange(set))
|
||||
testCursors(req, tc.curr[p], f)
|
||||
|
||||
// reverse to previous page
|
||||
f.PageCursor = f.PrevPage
|
||||
}
|
||||
|
||||
t.Log("and again all the way to 4th page")
|
||||
f.PageCursor = f.NextPage
|
||||
for p := 1; p < 4; p++ {
|
||||
set, f, err = store.SearchUsers(ctx, s, f)
|
||||
req.NoError(err)
|
||||
req.True(tc.sort == f.Sort.String() || strings.HasPrefix(f.Sort.String(), tc.sort+","))
|
||||
|
||||
req.Equal(tc.rval[p], stringifySetRange(set))
|
||||
testCursors(req, tc.curr[p], f)
|
||||
|
||||
// advance to next page
|
||||
f.PageCursor = f.NextPage
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("with incompatible sort", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
req.NoError(s.TruncateUsers(ctx))
|
||||
|
||||
set := []*types.User{
|
||||
makeNew("01"),
|
||||
makeNew("02"),
|
||||
makeNew("03"),
|
||||
makeNew("04"),
|
||||
makeNew("05"),
|
||||
}
|
||||
|
||||
req.NoError(s.CreateUser(ctx, set...))
|
||||
f := types.UserFilter{}
|
||||
f.Sort = filter.SortExprSet{&filter.SortExpr{Column: "email", Descending: true}, &filter.SortExpr{Column: "handle", Descending: true}}
|
||||
|
||||
f.Limit = uint(len(set))
|
||||
set, f, err := store.SearchUsers(ctx, s, f)
|
||||
req.Len(set, int(f.Limit))
|
||||
req.NoError(err)
|
||||
|
||||
f.Limit = 1
|
||||
set, f, err = store.SearchUsers(ctx, s, f)
|
||||
req.NoError(err)
|
||||
|
||||
// go to next page with different sorting
|
||||
f.PageCursor = f.NextPage
|
||||
f.Sort = filter.SortExprSet{&filter.SortExpr{Column: "username", Descending: false}}
|
||||
set, f, err = store.SearchUsers(ctx, s, f)
|
||||
req.EqualError(err, filter.ErrIncompatibleSort.Error())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("count", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
|
||||
f = types.UserFilter{}
|
||||
c1, c2 uint
|
||||
err error
|
||||
user = &types.User{ID: id.Next(), CreatedAt: time.Now(), Email: fmt.Sprintf("user-crud+%s@crust.test", time.Now().String())}
|
||||
)
|
||||
|
||||
c1, err = store.CountUsers(ctx, s, f)
|
||||
req.NoError(err)
|
||||
|
||||
req.NoError(s.CreateUser(ctx, user))
|
||||
|
||||
c2, err = store.CountUsers(ctx, s, f)
|
||||
req.NoError(err)
|
||||
req.Equal(c1+1, c2)
|
||||
|
||||
req.NoError(s.DeleteUserByID(ctx, user.ID))
|
||||
|
||||
c2, err = store.CountUsers(ctx, s, f)
|
||||
req.NoError(err)
|
||||
req.Equal(c1, c2)
|
||||
})
|
||||
|
||||
t.Run("metrics", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
|
||||
oct, _ = time.Parse(time.RFC3339, "2020-10-02T10:01:10Z")
|
||||
nov, _ = time.Parse(time.RFC3339, "2020-11-02T20:02:10Z")
|
||||
|
||||
octu = uint(oct.Truncate(time.Hour * 24).Unix())
|
||||
novu = uint(nov.Truncate(time.Hour * 24).Unix())
|
||||
|
||||
e = &types.UserMetrics{
|
||||
Total: 8,
|
||||
Valid: 2,
|
||||
Deleted: 3,
|
||||
Suspended: 3,
|
||||
DailyCreated: []uint{octu, 7, novu, 1},
|
||||
DailyUpdated: []uint{octu, 2},
|
||||
DailySuspended: []uint{octu, 2, novu, 1},
|
||||
DailyDeleted: []uint{novu, 3},
|
||||
}
|
||||
)
|
||||
|
||||
req.NoError(s.TruncateUsers(ctx))
|
||||
req.NoError(s.CreateUser(ctx, &types.User{ID: id.Next(), CreatedAt: oct, Email: "user-metrics-1@crust.test", UpdatedAt: &oct}))
|
||||
req.NoError(s.CreateUser(ctx, &types.User{ID: id.Next(), CreatedAt: oct, Email: "user-metrics-2@crust.test", UpdatedAt: &oct}))
|
||||
req.NoError(s.CreateUser(ctx, &types.User{ID: id.Next(), CreatedAt: oct, Email: "user-metrics-3@crust.test", SuspendedAt: &oct}))
|
||||
req.NoError(s.CreateUser(ctx, &types.User{ID: id.Next(), CreatedAt: oct, Email: "user-metrics-4@crust.test", SuspendedAt: &oct}))
|
||||
req.NoError(s.CreateUser(ctx, &types.User{ID: id.Next(), CreatedAt: oct, Email: "user-metrics-5@crust.test", SuspendedAt: &nov}))
|
||||
req.NoError(s.CreateUser(ctx, &types.User{ID: id.Next(), CreatedAt: oct, Email: "user-metrics-6@crust.test", DeletedAt: &nov}))
|
||||
req.NoError(s.CreateUser(ctx, &types.User{ID: id.Next(), CreatedAt: oct, Email: "user-metrics-7@crust.test", DeletedAt: &nov}))
|
||||
req.NoError(s.CreateUser(ctx, &types.User{ID: id.Next(), CreatedAt: nov, Email: "user-metrics-8@crust.test", DeletedAt: &nov}))
|
||||
|
||||
m, err := store.UserMetrics(ctx, s)
|
||||
req.NoError(err)
|
||||
req.Equal(e, m)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user