mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-01-27 23:46:18 +02:00
898 lines
23 KiB
Go
898 lines
23 KiB
Go
package forms_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"maps"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/pocketbase/pocketbase/core"
|
|
"github.com/pocketbase/pocketbase/forms"
|
|
"github.com/pocketbase/pocketbase/tests"
|
|
"github.com/pocketbase/pocketbase/tools/filesystem"
|
|
)
|
|
|
|
func TestRecordUpsertLoad(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
demo1Col, err := testApp.FindCollectionByNameOrId("demo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
usersCol, err := testApp.FindCollectionByNameOrId("users")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
file, err := filesystem.NewFileFromBytes([]byte("test"), "test.txt")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
scenarios := []struct {
|
|
name string
|
|
data map[string]any
|
|
record *core.Record
|
|
managerAccessLevel bool
|
|
superuserAccessLevel bool
|
|
expected []string
|
|
notExpected []string
|
|
}{
|
|
{
|
|
name: "base collection record",
|
|
data: map[string]any{
|
|
"text": "test_text",
|
|
"custom": "123", // should be ignored
|
|
"number": "456", // should be normalized by the setter
|
|
"select_many+": []string{"optionB", "optionC"}, // test modifier fields
|
|
"created": "2022-01:01 10:00:00.000Z", // should be ignored
|
|
// ignore special auth fields
|
|
"oldPassword": "123",
|
|
"password": "456",
|
|
"passwordConfirm": "789",
|
|
},
|
|
record: core.NewRecord(demo1Col),
|
|
expected: []string{
|
|
`"text":"test_text"`,
|
|
`"number":456`,
|
|
`"select_many":["optionB","optionC"]`,
|
|
`"password":""`,
|
|
`"oldPassword":""`,
|
|
`"passwordConfirm":""`,
|
|
`"created":""`,
|
|
`"updated":""`,
|
|
`"json":null`,
|
|
},
|
|
notExpected: []string{
|
|
`"custom"`,
|
|
`"select_many-"`,
|
|
`"select_many+"`,
|
|
},
|
|
},
|
|
{
|
|
name: "auth collection record",
|
|
data: map[string]any{
|
|
"email": "test@example.com",
|
|
// special auth fields
|
|
"oldPassword": "123",
|
|
"password": "456",
|
|
"passwordConfirm": "789",
|
|
},
|
|
record: core.NewRecord(usersCol),
|
|
expected: []string{
|
|
`"email":"test@example.com"`,
|
|
`"oldPassword":"123"`,
|
|
`"password":"456"`,
|
|
`"passwordConfirm":"789"`,
|
|
},
|
|
},
|
|
{
|
|
name: "hidden fields (manager)",
|
|
data: map[string]any{
|
|
"email": "test@example.com",
|
|
"tokenKey": "abc", // should be ignored
|
|
// special auth fields
|
|
"password": "456",
|
|
"oldPassword": "123",
|
|
"passwordConfirm": "789",
|
|
},
|
|
managerAccessLevel: true,
|
|
record: core.NewRecord(usersCol),
|
|
expected: []string{
|
|
`"email":"test@example.com"`,
|
|
`"tokenKey":""`,
|
|
`"password":"456"`,
|
|
`"oldPassword":"123"`,
|
|
`"passwordConfirm":"789"`,
|
|
},
|
|
},
|
|
{
|
|
name: "hidden fields (superuser)",
|
|
data: map[string]any{
|
|
"email": "test@example.com",
|
|
"tokenKey": "abc",
|
|
// special auth fields
|
|
"password": "456",
|
|
"oldPassword": "123",
|
|
"passwordConfirm": "789",
|
|
},
|
|
superuserAccessLevel: true,
|
|
record: core.NewRecord(usersCol),
|
|
expected: []string{
|
|
`"email":"test@example.com"`,
|
|
`"tokenKey":"abc"`,
|
|
`"password":"456"`,
|
|
`"oldPassword":"123"`,
|
|
`"passwordConfirm":"789"`,
|
|
},
|
|
},
|
|
{
|
|
name: "with file field",
|
|
data: map[string]any{
|
|
"file_one": file,
|
|
"url": file, // should be ignored for non-file fields
|
|
},
|
|
record: core.NewRecord(demo1Col),
|
|
expected: []string{
|
|
`"file_one":{`,
|
|
`"originalName":"test.txt"`,
|
|
`"url":""`,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
t.Run(s.name, func(t *testing.T) {
|
|
form := forms.NewRecordUpsert(testApp, s.record)
|
|
|
|
if s.managerAccessLevel {
|
|
form.GrantManagerAccess()
|
|
}
|
|
|
|
if s.superuserAccessLevel {
|
|
form.GrantSuperuserAccess()
|
|
}
|
|
|
|
// ensure that the form access level was updated
|
|
if !form.HasManageAccess() && (s.superuserAccessLevel || s.managerAccessLevel) {
|
|
t.Fatalf("Expected the form to have manage access level (manager or superuser)")
|
|
}
|
|
|
|
form.Load(s.data)
|
|
|
|
loaded := map[string]any{
|
|
"oldPassword": form.OldPassword,
|
|
"password": form.Password,
|
|
"passwordConfirm": form.PasswordConfirm,
|
|
}
|
|
maps.Copy(loaded, s.record.FieldsData())
|
|
maps.Copy(loaded, s.record.CustomData())
|
|
|
|
raw, err := json.Marshal(loaded)
|
|
if err != nil {
|
|
t.Fatalf("Failed to serialize data: %v", err)
|
|
}
|
|
|
|
rawStr := string(raw)
|
|
|
|
for _, str := range s.expected {
|
|
if !strings.Contains(rawStr, str) {
|
|
t.Fatalf("Couldn't find %q in \n%v", str, rawStr)
|
|
}
|
|
}
|
|
|
|
for _, str := range s.notExpected {
|
|
if strings.Contains(rawStr, str) {
|
|
t.Fatalf("Didn't expect %q in \n%v", str, rawStr)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRecordUpsertDrySubmitFailure(t *testing.T) {
|
|
runTest := func(t *testing.T, testApp core.App) {
|
|
col, err := testApp.FindCollectionByNameOrId("demo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
originalId := "imy661ixudk5izi"
|
|
|
|
record, err := testApp.FindRecordById(col, originalId)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
oldRaw, err := json.Marshal(record)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
file, err := filesystem.NewFileFromBytes([]byte("test"), "test.txt")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
form := forms.NewRecordUpsert(testApp, record)
|
|
form.Load(map[string]any{
|
|
"text": "test_update",
|
|
"file_one": file,
|
|
"select_one": "!invalid", // should be allowed even if invalid since validations are not executed
|
|
})
|
|
|
|
calls := ""
|
|
testApp.OnRecordValidate(col.Name).BindFunc(func(e *core.RecordEvent) error {
|
|
calls += "a" // shouldn't be called
|
|
return e.Next()
|
|
})
|
|
|
|
result := form.DrySubmit(func(txApp core.App, drySavedRecord *core.Record) error {
|
|
calls += "b"
|
|
return errors.New("error...")
|
|
})
|
|
|
|
if result == nil {
|
|
t.Fatal("Expected DrySubmit error, got nil")
|
|
}
|
|
|
|
if calls != "b" {
|
|
t.Fatalf("Expected calls %q, got %q", "ab", calls)
|
|
}
|
|
|
|
// refresh the record to ensure that the changes weren't persisted
|
|
record, err = testApp.FindRecordById(col, originalId)
|
|
if err != nil {
|
|
t.Fatalf("Expected record with the original id %q to exist, got\n%v", originalId, record.PublicExport())
|
|
}
|
|
|
|
newRaw, err := json.Marshal(record)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !bytes.Equal(oldRaw, newRaw) {
|
|
t.Fatalf("Expected record\n%s\ngot\n%s", oldRaw, newRaw)
|
|
}
|
|
|
|
testFilesCount(t, testApp, record, 0)
|
|
}
|
|
|
|
t.Run("without parent transaction", func(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
runTest(t, testApp)
|
|
})
|
|
|
|
t.Run("with parent transaction", func(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
testApp.RunInTransaction(func(txApp core.App) error {
|
|
runTest(t, txApp)
|
|
return nil
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestRecordUpsertDrySubmitCreateSuccess(t *testing.T) {
|
|
runTest := func(t *testing.T, testApp core.App) {
|
|
col, err := testApp.FindCollectionByNameOrId("demo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
record := core.NewRecord(col)
|
|
|
|
file, err := filesystem.NewFileFromBytes([]byte("test"), "test.txt")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
form := forms.NewRecordUpsert(testApp, record)
|
|
form.Load(map[string]any{
|
|
"id": "test",
|
|
"text": "test_update",
|
|
"file_one": file,
|
|
"select_one": "!invalid", // should be allowed even if invalid since validations are not executed
|
|
})
|
|
|
|
calls := ""
|
|
testApp.OnRecordValidate(col.Name).BindFunc(func(e *core.RecordEvent) error {
|
|
calls += "a" // shouldn't be called
|
|
return e.Next()
|
|
})
|
|
|
|
result := form.DrySubmit(func(txApp core.App, drySavedRecord *core.Record) error {
|
|
calls += "b"
|
|
return nil
|
|
})
|
|
|
|
if result != nil {
|
|
t.Fatalf("Expected DrySubmit success, got error: %v", result)
|
|
}
|
|
|
|
if calls != "b" {
|
|
t.Fatalf("Expected calls %q, got %q", "ab", calls)
|
|
}
|
|
|
|
// refresh the record to ensure that the changes weren't persisted
|
|
_, err = testApp.FindRecordById(col, record.Id)
|
|
if err == nil {
|
|
t.Fatal("Expected the created record to be deleted")
|
|
}
|
|
|
|
testFilesCount(t, testApp, record, 0)
|
|
}
|
|
|
|
t.Run("without parent transaction", func(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
runTest(t, testApp)
|
|
})
|
|
|
|
t.Run("with parent transaction", func(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
testApp.RunInTransaction(func(txApp core.App) error {
|
|
runTest(t, txApp)
|
|
return nil
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestRecordUpsertDrySubmitUpdateSuccess(t *testing.T) {
|
|
runTest := func(t *testing.T, testApp core.App) {
|
|
col, err := testApp.FindCollectionByNameOrId("demo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
record, err := testApp.FindRecordById(col, "imy661ixudk5izi")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
oldRaw, err := json.Marshal(record)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
file, err := filesystem.NewFileFromBytes([]byte("test"), "test.txt")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
form := forms.NewRecordUpsert(testApp, record)
|
|
form.Load(map[string]any{
|
|
"text": "test_update",
|
|
"file_one": file,
|
|
})
|
|
|
|
calls := ""
|
|
testApp.OnRecordValidate(col.Name).BindFunc(func(e *core.RecordEvent) error {
|
|
calls += "a" // shouldn't be called
|
|
return e.Next()
|
|
})
|
|
|
|
result := form.DrySubmit(func(txApp core.App, drySavedRecord *core.Record) error {
|
|
calls += "b"
|
|
return nil
|
|
})
|
|
|
|
if result != nil {
|
|
t.Fatalf("Expected DrySubmit success, got error: %v", result)
|
|
}
|
|
|
|
if calls != "b" {
|
|
t.Fatalf("Expected calls %q, got %q", "ab", calls)
|
|
}
|
|
|
|
// refresh the record to ensure that the changes weren't persisted
|
|
record, err = testApp.FindRecordById(col, record.Id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
newRaw, err := json.Marshal(record)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !bytes.Equal(oldRaw, newRaw) {
|
|
t.Fatalf("Expected record\n%s\ngot\n%s", oldRaw, newRaw)
|
|
}
|
|
|
|
testFilesCount(t, testApp, record, 0)
|
|
}
|
|
|
|
t.Run("without parent transaction", func(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
runTest(t, testApp)
|
|
})
|
|
|
|
t.Run("with parent transaction", func(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
testApp.RunInTransaction(func(txApp core.App) error {
|
|
runTest(t, txApp)
|
|
return nil
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestRecordUpsertSubmitValidations(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
app, _ := tests.NewTestApp()
|
|
defer app.Cleanup()
|
|
|
|
demo2Col, err := app.FindCollectionByNameOrId("demo2")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
demo2Rec, err := app.FindRecordById(demo2Col, "llvuca81nly1qls")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
usersCol, err := app.FindCollectionByNameOrId("users")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
userRec, err := app.FindRecordById(usersCol, "4q1xlclmfloku33")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
scenarios := []struct {
|
|
name string
|
|
record *core.Record
|
|
data map[string]any
|
|
managerAccess bool
|
|
expectedErrors []string
|
|
}{
|
|
// base
|
|
{
|
|
name: "new base collection record with empty data",
|
|
record: core.NewRecord(demo2Col),
|
|
data: map[string]any{},
|
|
expectedErrors: []string{"title"},
|
|
},
|
|
{
|
|
name: "new base collection record with invalid data",
|
|
record: core.NewRecord(demo2Col),
|
|
data: map[string]any{
|
|
"title": "",
|
|
// should be ignored
|
|
"custom": "abc",
|
|
"oldPassword": "123",
|
|
"password": "456",
|
|
"passwordConfirm": "789",
|
|
},
|
|
expectedErrors: []string{"title"},
|
|
},
|
|
{
|
|
name: "new base collection record with valid data",
|
|
record: core.NewRecord(demo2Col),
|
|
data: map[string]any{
|
|
"title": "abc",
|
|
// should be ignored
|
|
"custom": "abc",
|
|
"oldPassword": "123",
|
|
"password": "456",
|
|
"passwordConfirm": "789",
|
|
},
|
|
expectedErrors: []string{},
|
|
},
|
|
{
|
|
name: "existing base collection record with empty data",
|
|
record: demo2Rec,
|
|
data: map[string]any{},
|
|
expectedErrors: []string{},
|
|
},
|
|
{
|
|
name: "existing base collection record with invalid data",
|
|
record: demo2Rec,
|
|
data: map[string]any{
|
|
"title": "",
|
|
},
|
|
expectedErrors: []string{"title"},
|
|
},
|
|
{
|
|
name: "existing base collection record with valid data",
|
|
record: demo2Rec,
|
|
data: map[string]any{
|
|
"title": "abc",
|
|
},
|
|
expectedErrors: []string{},
|
|
},
|
|
|
|
// auth
|
|
{
|
|
name: "new auth collection record with empty data",
|
|
record: core.NewRecord(usersCol),
|
|
data: map[string]any{},
|
|
expectedErrors: []string{"password", "passwordConfirm"},
|
|
},
|
|
{
|
|
name: "new auth collection record with invalid record and invalid form data (without manager acess)",
|
|
record: core.NewRecord(usersCol),
|
|
data: map[string]any{
|
|
"verified": true,
|
|
"emailVisibility": true,
|
|
"email": "test@example.com",
|
|
"password": "456",
|
|
"passwordConfirm": "789",
|
|
"username": "!invalid",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
"oldPassword": "123",
|
|
},
|
|
// fail the form validator
|
|
expectedErrors: []string{"verified", "passwordConfirm"},
|
|
},
|
|
{
|
|
name: "new auth collection record with invalid record and valid form data (without manager acess)",
|
|
record: core.NewRecord(usersCol),
|
|
data: map[string]any{
|
|
"verified": false,
|
|
"emailVisibility": true,
|
|
"email": "test@example.com",
|
|
"password": "456",
|
|
"passwordConfirm": "456",
|
|
"username": "!invalid",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
"oldPassword": "123",
|
|
},
|
|
// fail the record fields validator
|
|
expectedErrors: []string{"password", "username"},
|
|
},
|
|
{
|
|
name: "new auth collection record with invalid record and invalid form data (with manager acess)",
|
|
record: core.NewRecord(usersCol),
|
|
managerAccess: true,
|
|
data: map[string]any{
|
|
"verified": true,
|
|
"emailVisibility": true,
|
|
"email": "test@example.com",
|
|
"password": "456",
|
|
"passwordConfirm": "789",
|
|
"username": "!invalid",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
"oldPassword": "123",
|
|
},
|
|
// fail the form validator
|
|
expectedErrors: []string{"passwordConfirm"},
|
|
},
|
|
{
|
|
name: "new auth collection record with invalid record and valid form data (with manager acess)",
|
|
record: core.NewRecord(usersCol),
|
|
managerAccess: true,
|
|
data: map[string]any{
|
|
"verified": true,
|
|
"emailVisibility": true,
|
|
"email": "test@example.com",
|
|
"password": "456",
|
|
"passwordConfirm": "456",
|
|
"username": "!invalid",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
"oldPassword": "123",
|
|
},
|
|
// fail the record fields validator
|
|
expectedErrors: []string{"password", "username"},
|
|
},
|
|
{
|
|
name: "new auth collection record with valid data",
|
|
record: core.NewRecord(usersCol),
|
|
data: map[string]any{
|
|
"emailVisibility": true,
|
|
"email": "test_new@example.com",
|
|
"password": "1234567890",
|
|
"passwordConfirm": "1234567890",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
"oldPassword": "123",
|
|
},
|
|
expectedErrors: []string{},
|
|
},
|
|
{
|
|
name: "new auth collection record with valid data and duplicated email",
|
|
record: core.NewRecord(usersCol),
|
|
data: map[string]any{
|
|
"email": "test@example.com",
|
|
"password": "1234567890",
|
|
"passwordConfirm": "1234567890",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
"oldPassword": "123",
|
|
},
|
|
// fail the unique db validator
|
|
expectedErrors: []string{"email"},
|
|
},
|
|
{
|
|
name: "existing auth collection record with empty data",
|
|
record: userRec,
|
|
data: map[string]any{},
|
|
expectedErrors: []string{},
|
|
},
|
|
{
|
|
name: "existing auth collection record with invalid record data and invalid form data (without manager access)",
|
|
record: userRec,
|
|
data: map[string]any{
|
|
"verified": true,
|
|
"email": "test_new@example.com", // not allowed to change
|
|
"oldPassword": "123",
|
|
"password": "456",
|
|
"passwordConfirm": "789",
|
|
"username": "!invalid",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
},
|
|
// fail form validator
|
|
expectedErrors: []string{"verified", "email", "oldPassword", "passwordConfirm"},
|
|
},
|
|
{
|
|
name: "existing auth collection record with invalid record data and valid form data (without manager access)",
|
|
record: userRec,
|
|
data: map[string]any{
|
|
"oldPassword": "1234567890",
|
|
"password": "12345678901",
|
|
"passwordConfirm": "12345678901",
|
|
"username": "!invalid",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
},
|
|
// fail record fields validator
|
|
expectedErrors: []string{"username"},
|
|
},
|
|
{
|
|
name: "existing auth collection record with invalid record data and invalid form data (with manager access)",
|
|
record: userRec,
|
|
managerAccess: true,
|
|
data: map[string]any{
|
|
"verified": true,
|
|
"email": "test_new@example.com",
|
|
"oldPassword": "123", // should be ignored
|
|
"password": "456",
|
|
"passwordConfirm": "789",
|
|
"username": "!invalid",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
},
|
|
// fail form validator
|
|
expectedErrors: []string{"passwordConfirm"},
|
|
},
|
|
{
|
|
name: "existing auth collection record with invalid record data and valid form data (with manager access)",
|
|
record: userRec,
|
|
managerAccess: true,
|
|
data: map[string]any{
|
|
"verified": true,
|
|
"email": "test_new@example.com",
|
|
"oldPassword": "1234567890",
|
|
"password": "12345678901",
|
|
"passwordConfirm": "12345678901",
|
|
"username": "!invalid",
|
|
// should be ignored (custom or hidden fields)
|
|
"tokenKey": strings.Repeat("a", 2),
|
|
"custom": "abc",
|
|
},
|
|
// fail record fields validator
|
|
expectedErrors: []string{"username"},
|
|
},
|
|
{
|
|
name: "existing auth collection record with base valid data",
|
|
record: userRec,
|
|
data: map[string]any{
|
|
"name": "test",
|
|
},
|
|
expectedErrors: []string{},
|
|
},
|
|
{
|
|
name: "existing auth collection record with valid password and invalid oldPassword data",
|
|
record: userRec,
|
|
data: map[string]any{
|
|
"name": "test",
|
|
"oldPassword": "invalid",
|
|
"password": "1234567890",
|
|
"passwordConfirm": "1234567890",
|
|
},
|
|
expectedErrors: []string{"oldPassword"},
|
|
},
|
|
{
|
|
name: "existing auth collection record with valid password data",
|
|
record: userRec,
|
|
data: map[string]any{
|
|
"name": "test",
|
|
"oldPassword": "1234567890",
|
|
"password": "0987654321",
|
|
"passwordConfirm": "0987654321",
|
|
},
|
|
expectedErrors: []string{},
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
t.Run(s.name, func(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
form := forms.NewRecordUpsert(testApp, s.record.Original())
|
|
if s.managerAccess {
|
|
form.GrantManagerAccess()
|
|
}
|
|
form.Load(s.data)
|
|
|
|
result := form.Submit()
|
|
|
|
tests.TestValidationErrors(t, result, s.expectedErrors)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRecordUpsertSubmitFailure(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
col, err := testApp.FindCollectionByNameOrId("demo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
record, err := testApp.FindRecordById(col, "imy661ixudk5izi")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
file, err := filesystem.NewFileFromBytes([]byte("test"), "test.txt")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
form := forms.NewRecordUpsert(testApp, record)
|
|
form.Load(map[string]any{
|
|
"text": "test_update",
|
|
"file_one": file,
|
|
"select_one": "invalid",
|
|
})
|
|
|
|
validateCalls := 0
|
|
testApp.OnRecordValidate(col.Name).BindFunc(func(e *core.RecordEvent) error {
|
|
validateCalls++
|
|
return e.Next()
|
|
})
|
|
|
|
result := form.Submit()
|
|
|
|
if result == nil {
|
|
t.Fatal("Expected Submit error, got nil")
|
|
}
|
|
|
|
if validateCalls != 1 {
|
|
t.Fatalf("Expected validateCalls %d, got %d", 1, validateCalls)
|
|
}
|
|
|
|
// refresh the record to ensure that the changes weren't persisted
|
|
record, err = testApp.FindRecordById(col, record.Id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if v := record.GetString("text"); v == "test_update" {
|
|
t.Fatalf("Expected record.text to remain the same, got %q", v)
|
|
}
|
|
|
|
if v := record.GetString("select_one"); v != "" {
|
|
t.Fatalf("Expected record.select_one to remain the same, got %q", v)
|
|
}
|
|
|
|
if v := record.GetString("file_one"); v != "" {
|
|
t.Fatalf("Expected record.file_one to remain the same, got %q", v)
|
|
}
|
|
|
|
testFilesCount(t, testApp, record, 0)
|
|
}
|
|
|
|
func TestRecordUpsertSubmitSuccess(t *testing.T) {
|
|
testApp, _ := tests.NewTestApp()
|
|
defer testApp.Cleanup()
|
|
|
|
col, err := testApp.FindCollectionByNameOrId("demo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
record, err := testApp.FindRecordById(col, "imy661ixudk5izi")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
file, err := filesystem.NewFileFromBytes([]byte("test"), "test.txt")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
form := forms.NewRecordUpsert(testApp, record)
|
|
form.Load(map[string]any{
|
|
"text": "test_update",
|
|
"file_one": file,
|
|
"select_one": "optionC",
|
|
})
|
|
|
|
validateCalls := 0
|
|
testApp.OnRecordValidate(col.Name).BindFunc(func(e *core.RecordEvent) error {
|
|
validateCalls++
|
|
return e.Next()
|
|
})
|
|
|
|
result := form.Submit()
|
|
|
|
if result != nil {
|
|
t.Fatalf("Expected Submit success, got error: %v", result)
|
|
}
|
|
|
|
if validateCalls != 1 {
|
|
t.Fatalf("Expected validateCalls %d, got %d", 1, validateCalls)
|
|
}
|
|
|
|
// refresh the record to ensure that the changes were persisted
|
|
record, err = testApp.FindRecordById(col, record.Id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if v := record.GetString("text"); v != "test_update" {
|
|
t.Fatalf("Expected record.text %q, got %q", "test_update", v)
|
|
}
|
|
|
|
if v := record.GetString("select_one"); v != "optionC" {
|
|
t.Fatalf("Expected record.select_one %q, got %q", "optionC", v)
|
|
}
|
|
|
|
if v := record.GetString("file_one"); v != file.Name {
|
|
t.Fatalf("Expected record.file_one %q, got %q", file.Name, v)
|
|
}
|
|
|
|
testFilesCount(t, testApp, record, 2) // the file + attrs
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
func testFilesCount(t *testing.T, app core.App, record *core.Record, count int) {
|
|
storageDir := filepath.Join(app.DataDir(), "storage", record.Collection().Id, record.Id)
|
|
|
|
entries, _ := os.ReadDir(storageDir)
|
|
if len(entries) != count {
|
|
t.Errorf("Expected %d entries, got %d\n%v", count, len(entries), entries)
|
|
}
|
|
}
|