Merge pull request #8 from StevanFreeborn/stevanfreeborn/tests/add-integration-tests
tests: add integration tests
This commit is contained in:
+2
-1
@@ -10,4 +10,5 @@ go.work.sum
|
|||||||
*.out
|
*.out
|
||||||
*.html
|
*.html
|
||||||
cover.out
|
cover.out
|
||||||
coverage.txt
|
coverage.txt
|
||||||
|
.env
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package onspring_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAppsIntegration(t *testing.T) {
|
||||||
|
loadEnvFile(t)
|
||||||
|
client := createClient(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
t.Run("Get", func(t *testing.T) {
|
||||||
|
t.Run("should return an app", func(t *testing.T) {
|
||||||
|
appId := requireEnvInt(t, "TEST_APP_ID")
|
||||||
|
|
||||||
|
app, err := client.Apps.Get(ctx, appId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.Id != appId {
|
||||||
|
t.Errorf("Expected app id %d, got %d", appId, app.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.Name == "" {
|
||||||
|
t.Error("Expected app name to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.Href == "" {
|
||||||
|
t.Error("Expected app href to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when an invalid api key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
appId := requireEnvInt(t, "TEST_APP_ID")
|
||||||
|
|
||||||
|
_, err := invalidClient.Apps.Get(ctx, appId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when api key does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
|
||||||
|
_, err := client.Apps.Get(ctx, appIdNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 error when an app id cannot be found", func(t *testing.T) {
|
||||||
|
_, err := client.Apps.Get(ctx, 0)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("List", func(t *testing.T) {
|
||||||
|
t.Run("should return a paged list of apps", func(t *testing.T) {
|
||||||
|
page, err := client.Apps.List(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber == 0 {
|
||||||
|
t.Error("Expected page number to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageSize == 0 {
|
||||||
|
t.Error("Expected page size to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.TotalPages == 0 {
|
||||||
|
t.Error("Expected total pages to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.TotalRecords == 0 {
|
||||||
|
t.Error("Expected total records to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) == 0 {
|
||||||
|
t.Error("Expected items to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, app := range page.Items {
|
||||||
|
if app.Id == 0 {
|
||||||
|
t.Error("Expected app id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.Name == "" {
|
||||||
|
t.Error("Expected app name to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.Href == "" {
|
||||||
|
t.Error("Expected app href to not be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a paged list of apps with correct page size and number when passed paging request", func(t *testing.T) {
|
||||||
|
page, err := client.Apps.List(ctx, onspring.ForPageNumber(1), onspring.WithPageSize(1))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber != 1 {
|
||||||
|
t.Errorf("Expected page number 1, got %d", page.PageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageSize != 1 {
|
||||||
|
t.Errorf("Expected page size 1, got %d", page.PageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) != 1 {
|
||||||
|
t.Errorf("Expected 1 item, got %d", len(page.Items))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 response when an invalid page size is used", func(t *testing.T) {
|
||||||
|
_, err := client.Apps.List(ctx, onspring.WithPageSize(1001))
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 response when an invalid api key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
|
||||||
|
_, err := invalidClient.Apps.List(ctx)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAll", func(t *testing.T) {
|
||||||
|
t.Run("should iterate all apps", func(t *testing.T) {
|
||||||
|
var apps []onspring.App
|
||||||
|
|
||||||
|
for app, err := range client.Apps.ListAll(ctx, onspring.WithPageSize(1)) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
apps = append(apps, app)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(apps) == 0 {
|
||||||
|
t.Error("Expected to iterate at least one app")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("GetMany", func(t *testing.T) {
|
||||||
|
t.Run("should return a collection of apps", func(t *testing.T) {
|
||||||
|
appIds := requireEnvIntSlice(t, "TEST_APP_IDS")
|
||||||
|
|
||||||
|
batch, err := client.Apps.GetMany(ctx, appIds)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if batch.Count != len(appIds) {
|
||||||
|
t.Errorf("Expected count %d, got %d", len(appIds), batch.Count)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(batch.Items) != len(appIds) {
|
||||||
|
t.Errorf("Expected %d items, got %d", len(appIds), len(batch.Items))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, app := range batch.Items {
|
||||||
|
if app.Id == 0 {
|
||||||
|
t.Error("Expected app id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.Name == "" {
|
||||||
|
t.Error("Expected app name to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.Href == "" {
|
||||||
|
t.Error("Expected app href to not be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when an invalid api key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
appIds := requireEnvIntSlice(t, "TEST_APP_IDS")
|
||||||
|
|
||||||
|
_, err := invalidClient.Apps.GetMany(ctx, appIds)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when api key does not have access to the apps", func(t *testing.T) {
|
||||||
|
appIdsNoAccess := requireEnvIntSlice(t, "TEST_APP_IDS_NO_ACCESS")
|
||||||
|
|
||||||
|
_, err := client.Apps.GetMany(ctx, appIdsNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ const (
|
|||||||
// defaultTimeout is the default HTTP client timeout duration.
|
// defaultTimeout is the default HTTP client timeout duration.
|
||||||
defaultTimeout = 120 * time.Second
|
defaultTimeout = 120 * time.Second
|
||||||
// defaultAPIKeyHeader is the HTTP header name used for API key authentication.
|
// defaultAPIKeyHeader is the HTTP header name used for API key authentication.
|
||||||
defaultAPIKeyHeader = "x-api-key"
|
defaultAPIKeyHeader = "x-apikey"
|
||||||
// defaultAPIVersionHeader is the HTTP header name used to specify the API version.
|
// defaultAPIVersionHeader is the HTTP header name used to specify the API version.
|
||||||
defaultAPIVersionHeader = "x-api-version"
|
defaultAPIVersionHeader = "x-api-version"
|
||||||
// defaultAPIVersion is the default Onspring API version to use.
|
// defaultAPIVersion is the default Onspring API version to use.
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
API_BASE_URL=https://api.onspring.com
|
||||||
|
SANDBOX_API_KEY=your-sandbox-api-key
|
||||||
|
|
||||||
|
TEST_APP_ID=1
|
||||||
|
TEST_APP_ID_NO_ACCESS=2
|
||||||
|
TEST_APP_IDS=1,2,3
|
||||||
|
TEST_APP_IDS_NO_ACCESS=4,5,6
|
||||||
|
|
||||||
|
TEST_SURVEY_ID=1
|
||||||
|
TEST_SURVEY_RECORD_ID=1
|
||||||
|
TEST_SURVEY_AUTO_NUMBER_FIELD=1
|
||||||
|
|
||||||
|
TEST_FIELD_ID=1
|
||||||
|
TEST_FIELD_ID_NO_ACCESS=2
|
||||||
|
TEST_FIELD_IDS=1,2,3
|
||||||
|
TEST_FIELD_IDS_NO_ACCESS=4,5,6
|
||||||
|
TEST_TEXT_FIELD=1
|
||||||
|
|
||||||
|
TEST_RECORD=1
|
||||||
|
TEST_ATTACHMENT_FIELD=1
|
||||||
|
TEST_ATTACHMENT_FIELD_NO_ACCESS_FIELD=2
|
||||||
|
TEST_ATTACHMENT_FIELD_NO_ACCESS_APP=3
|
||||||
|
TEST_ATTACHMENT=1
|
||||||
|
TEST_IMAGE_FIELD=1
|
||||||
|
TEST_IMAGE=1
|
||||||
|
|
||||||
|
TEST_LIST_FIELD=1
|
||||||
|
TEST_LIST_FIELD_NO_ACCESS=2
|
||||||
|
TEST_LIST_ID=1
|
||||||
|
TEST_LIST_ID_NO_ACCESS=2
|
||||||
|
TEST_LIST_ITEM_ID_NO_ACCESS=some-guid
|
||||||
|
|
||||||
|
TEST_REPORT=1
|
||||||
|
TEST_REPORT_NO_ACCESS=2
|
||||||
|
TEST_REPORT_WITH_CHART_DATA=3
|
||||||
@@ -31,8 +31,8 @@ type Field struct {
|
|||||||
|
|
||||||
// FormulaField represents a formula field type in Onspring
|
// FormulaField represents a formula field type in Onspring
|
||||||
type FormulaField struct {
|
type FormulaField struct {
|
||||||
OutputType string `json:"outputType"`
|
OutputType string `json:"outputType"`
|
||||||
Values []string `json:"values"`
|
Values []ListValue `json:"values"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReferenceField represents a reference field type in Onspring
|
// ReferenceField represents a reference field type in Onspring
|
||||||
@@ -41,11 +41,20 @@ type ReferenceField struct {
|
|||||||
ReferenceAppId string `json:"referenceAppId"`
|
ReferenceAppId string `json:"referenceAppId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListValue represents a value option within a list field in Onspring.
|
||||||
|
type ListValue struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
SortOrder int `json:"sortOrder"`
|
||||||
|
NumericValue float64 `json:"numericValue"`
|
||||||
|
Color string `json:"color"`
|
||||||
|
}
|
||||||
|
|
||||||
// ListField represents a list field type in Onspring
|
// ListField represents a list field type in Onspring
|
||||||
type ListField struct {
|
type ListField struct {
|
||||||
Multiplicity string `json:"multiplicity"`
|
Multiplicity string `json:"multiplicity"`
|
||||||
Values []string `json:"values"`
|
Values []ListValue `json:"values"`
|
||||||
ListId int `json:"listId"`
|
ListId int `json:"listId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface for Field.
|
// UnmarshalJSON implements the json.Unmarshaler interface for Field.
|
||||||
|
|||||||
@@ -0,0 +1,232 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package onspring_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFieldsIntegration(t *testing.T) {
|
||||||
|
loadEnvFile(t)
|
||||||
|
client := createClient(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
t.Run("Get", func(t *testing.T) {
|
||||||
|
t.Run("should return a field", func(t *testing.T) {
|
||||||
|
fieldId := requireEnvInt(t, "TEST_FIELD_ID")
|
||||||
|
|
||||||
|
field, err := client.Fields.Get(ctx, fieldId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Id != fieldId {
|
||||||
|
t.Errorf("Expected field id %d, got %d", fieldId, field.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Name == "" {
|
||||||
|
t.Error("Expected field name to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.AppId == 0 {
|
||||||
|
t.Error("Expected field appId to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Type == "" {
|
||||||
|
t.Error("Expected field type to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Status == "" {
|
||||||
|
t.Error("Expected field status to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when an invalid api key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
fieldId := requireEnvInt(t, "TEST_FIELD_ID")
|
||||||
|
|
||||||
|
_, err := invalidClient.Fields.Get(ctx, fieldId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when api key does not have access to the field", func(t *testing.T) {
|
||||||
|
fieldIdNoAccess := requireEnvInt(t, "TEST_FIELD_ID_NO_ACCESS")
|
||||||
|
|
||||||
|
_, err := client.Fields.Get(ctx, fieldIdNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 error when the field does not exist", func(t *testing.T) {
|
||||||
|
_, err := client.Fields.Get(ctx, 0)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("List", func(t *testing.T) {
|
||||||
|
t.Run("should return a paged list of fields", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
page, err := client.Fields.List(ctx, surveyId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber == 0 {
|
||||||
|
t.Error("Expected page number to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.TotalRecords == 0 {
|
||||||
|
t.Error("Expected total records to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) == 0 {
|
||||||
|
t.Error("Expected items to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range page.Items {
|
||||||
|
if field.Id == 0 {
|
||||||
|
t.Error("Expected field id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Name == "" {
|
||||||
|
t.Error("Expected field name to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.AppId == 0 {
|
||||||
|
t.Error("Expected field appId to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Type == "" {
|
||||||
|
t.Error("Expected field type to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Status == "" {
|
||||||
|
t.Error("Expected field status to not be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a paged list of fields with correct page size and number when passed paging request", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
page, err := client.Fields.List(ctx, surveyId, onspring.ForPageNumber(1), onspring.WithPageSize(1))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber != 1 {
|
||||||
|
t.Errorf("Expected page number 1, got %d", page.PageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageSize != 1 {
|
||||||
|
t.Errorf("Expected page size 1, got %d", page.PageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) != 1 {
|
||||||
|
t.Errorf("Expected 1 item, got %d", len(page.Items))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 response when an invalid page size is used", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
_, err := client.Fields.List(ctx, surveyId, onspring.WithPageSize(1001))
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 response when an invalid api key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
_, err := invalidClient.Fields.List(ctx, surveyId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when api key does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
|
||||||
|
_, err := client.Fields.List(ctx, appIdNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAll", func(t *testing.T) {
|
||||||
|
t.Run("should iterate all fields for an app", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
var fields []onspring.Field
|
||||||
|
|
||||||
|
for field, err := range client.Fields.ListAll(ctx, surveyId, onspring.WithPageSize(1)) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fields) == 0 {
|
||||||
|
t.Error("Expected to iterate at least one field")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("GetMany", func(t *testing.T) {
|
||||||
|
t.Run("should return a collection of fields", func(t *testing.T) {
|
||||||
|
fieldIds := requireEnvIntSlice(t, "TEST_FIELD_IDS")
|
||||||
|
|
||||||
|
batch, err := client.Fields.GetMany(ctx, fieldIds)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if batch.Count != len(fieldIds) {
|
||||||
|
t.Errorf("Expected count %d, got %d", len(fieldIds), batch.Count)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(batch.Items) != len(fieldIds) {
|
||||||
|
t.Errorf("Expected %d items, got %d", len(fieldIds), len(batch.Items))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range batch.Items {
|
||||||
|
if field.Id == 0 {
|
||||||
|
t.Error("Expected field id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Name == "" {
|
||||||
|
t.Error("Expected field name to not be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 response when an invalid api key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
fieldIds := requireEnvIntSlice(t, "TEST_FIELD_IDS")
|
||||||
|
|
||||||
|
_, err := invalidClient.Fields.GetMany(ctx, fieldIds)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to any of the requested fields", func(t *testing.T) {
|
||||||
|
fieldIdsNoAccess := requireEnvIntSlice(t, "TEST_FIELD_IDS_NO_ACCESS")
|
||||||
|
|
||||||
|
_, err := client.Fields.GetMany(ctx, fieldIdsNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
+17
-5
@@ -138,7 +138,10 @@ func TestFields(t *testing.T) {
|
|||||||
"isRequired": true,
|
"isRequired": true,
|
||||||
"isUnique": false,
|
"isUnique": false,
|
||||||
"outputType": "Number",
|
"outputType": "Number",
|
||||||
"values": ["1", "2", "3"]
|
"values": [
|
||||||
|
{"id": "a1", "name": "Value1", "sortOrder": 1, "numericValue": 1, "color": "#fff"},
|
||||||
|
{"id": "b2", "name": "Value2", "sortOrder": 2, "numericValue": 2, "color": "#000"}
|
||||||
|
]
|
||||||
}`
|
}`
|
||||||
|
|
||||||
var field onspring.Field
|
var field onspring.Field
|
||||||
@@ -161,7 +164,10 @@ func TestFields(t *testing.T) {
|
|||||||
|
|
||||||
expectedFormulaField := onspring.FormulaField{
|
expectedFormulaField := onspring.FormulaField{
|
||||||
OutputType: "Number",
|
OutputType: "Number",
|
||||||
Values: []string{"1", "2", "3"},
|
Values: []onspring.ListValue{
|
||||||
|
{Id: "a1", Name: "Value1", SortOrder: 1, NumericValue: 1, Color: "#fff"},
|
||||||
|
{Id: "b2", Name: "Value2", SortOrder: 2, NumericValue: 2, Color: "#000"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(formulaField, expectedFormulaField) {
|
if !reflect.DeepEqual(formulaField, expectedFormulaField) {
|
||||||
@@ -220,7 +226,10 @@ func TestFields(t *testing.T) {
|
|||||||
"isRequired": false,
|
"isRequired": false,
|
||||||
"isUnique": false,
|
"isUnique": false,
|
||||||
"multiplicity": "MultiSelect",
|
"multiplicity": "MultiSelect",
|
||||||
"values": ["OptionA", "OptionB"],
|
"values": [
|
||||||
|
{"id": "aaa", "name": "OptionA", "sortOrder": 1, "numericValue": 0, "color": "#ffffff"},
|
||||||
|
{"id": "bbb", "name": "OptionB", "sortOrder": 2, "numericValue": 0, "color": "#000000"}
|
||||||
|
],
|
||||||
"listId": 456
|
"listId": 456
|
||||||
}`
|
}`
|
||||||
|
|
||||||
@@ -244,8 +253,11 @@ func TestFields(t *testing.T) {
|
|||||||
|
|
||||||
expectedListField := onspring.ListField{
|
expectedListField := onspring.ListField{
|
||||||
Multiplicity: "MultiSelect",
|
Multiplicity: "MultiSelect",
|
||||||
Values: []string{"OptionA", "OptionB"},
|
Values: []onspring.ListValue{
|
||||||
ListId: 456,
|
{Id: "aaa", Name: "OptionA", SortOrder: 1, NumericValue: 0, Color: "#ffffff"},
|
||||||
|
{Id: "bbb", Name: "OptionB", SortOrder: 2, NumericValue: 0, Color: "#000000"},
|
||||||
|
},
|
||||||
|
ListId: 456,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(listField, expectedListField) {
|
if !reflect.DeepEqual(listField, expectedListField) {
|
||||||
|
|||||||
@@ -0,0 +1,590 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package onspring_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilesIntegration(t *testing.T) {
|
||||||
|
loadEnvFile(t)
|
||||||
|
client := createClient(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
t.Run("GetInfo", func(t *testing.T) {
|
||||||
|
t.Run("should return information about a file in an attachment field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
info, err := client.Files.GetInfo(ctx, recordId, fieldId, fileId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Name == "" {
|
||||||
|
t.Error("Expected name to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.ContentType == "" {
|
||||||
|
t.Error("Expected content type to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.CreatedDate == "" {
|
||||||
|
t.Error("Expected created date to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.ModifiedDate == "" {
|
||||||
|
t.Error("Expected modified date to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Owner == "" {
|
||||||
|
t.Error("Expected owner to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Type == "" {
|
||||||
|
t.Error("Expected type to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.FileHref == "" {
|
||||||
|
t.Error("Expected file href to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return information about a file in an image field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_IMAGE_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_IMAGE")
|
||||||
|
|
||||||
|
info, err := client.Files.GetInfo(ctx, recordId, fieldId, fileId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Name == "" {
|
||||||
|
t.Error("Expected name to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.ContentType == "" {
|
||||||
|
t.Error("Expected content type to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Type == "" {
|
||||||
|
t.Error("Expected type to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 response when fieldId is not for a file field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetInfo(ctx, recordId, textFieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 response when the api key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := invalidClient.Files.GetInfo(ctx, recordId, fieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to the file field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldIdNoAccess := requireEnvInt(t, "TEST_ATTACHMENT_FIELD_NO_ACCESS_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetInfo(ctx, recordId, fieldIdNoAccess, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to the app", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldIdNoApp := requireEnvInt(t, "TEST_ATTACHMENT_FIELD_NO_ACCESS_APP")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetInfo(ctx, recordId, fieldIdNoApp, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 response when the file field cannot be found", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetInfo(ctx, recordId, 0, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 response when the file record cannot be found", func(t *testing.T) {
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetInfo(ctx, 0, fieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("GetContent", func(t *testing.T) {
|
||||||
|
t.Run("should return a file in an attachment field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
content, err := client.Files.GetContent(ctx, recordId, fieldId, fileId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(content.Data) == 0 {
|
||||||
|
t.Error("Expected data to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if content.ContentType == "" {
|
||||||
|
t.Error("Expected content type to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if content.FileName == "" {
|
||||||
|
t.Error("Expected file name to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a file in an image field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_IMAGE_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_IMAGE")
|
||||||
|
|
||||||
|
content, err := client.Files.GetContent(ctx, recordId, fieldId, fileId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(content.Data) == 0 {
|
||||||
|
t.Error("Expected data to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if content.ContentType == "" {
|
||||||
|
t.Error("Expected content type to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if content.FileName == "" {
|
||||||
|
t.Error("Expected file name to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 response when fieldId is not for a file field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetContent(ctx, recordId, textFieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 response when the api key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := invalidClient.Files.GetContent(ctx, recordId, fieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to the file field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldIdNoAccess := requireEnvInt(t, "TEST_ATTACHMENT_FIELD_NO_ACCESS_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetContent(ctx, recordId, fieldIdNoAccess, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to the app", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldIdNoApp := requireEnvInt(t, "TEST_ATTACHMENT_FIELD_NO_ACCESS_APP")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetContent(ctx, recordId, fieldIdNoApp, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 response when the file field cannot be found", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetContent(ctx, recordId, 0, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 response when the file record cannot be found", func(t *testing.T) {
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
_, err := client.Files.GetContent(ctx, 0, fieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Save", func(t *testing.T) {
|
||||||
|
t.Run("should save a file into an attachment field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-attachment.txt")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test attachment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
response, err := client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: fieldId,
|
||||||
|
FileName: "test-attachment.txt",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Id == 0 {
|
||||||
|
t.Error("Expected file id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = client.Files.Delete(context.Background(), recordId, fieldId, response.Id)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should save a file into an image field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_IMAGE_FIELD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-image.jpeg")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
response, err := client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: fieldId,
|
||||||
|
FileName: "test-image.jpeg",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Id == 0 {
|
||||||
|
t.Error("Expected file id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = client.Files.Delete(context.Background(), recordId, fieldId, response.Id)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 response when fieldId is not for a file field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-attachment.txt")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test attachment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: textFieldId,
|
||||||
|
FileName: "test-attachment.txt",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 response when the api key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-attachment.txt")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test attachment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = invalidClient.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: fieldId,
|
||||||
|
FileName: "test-attachment.txt",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to the field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldIdNoAccess := requireEnvInt(t, "TEST_ATTACHMENT_FIELD_NO_ACCESS_FIELD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-attachment.txt")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test attachment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: fieldIdNoAccess,
|
||||||
|
FileName: "test-attachment.txt",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to the app", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldIdNoApp := requireEnvInt(t, "TEST_ATTACHMENT_FIELD_NO_ACCESS_APP")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-attachment.txt")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test attachment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: fieldIdNoApp,
|
||||||
|
FileName: "test-attachment.txt",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 response when the file field cannot be found", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-attachment.txt")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test attachment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: 0,
|
||||||
|
FileName: "test-attachment.txt",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 response when the file record cannot be found", func(t *testing.T) {
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-attachment.txt")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test attachment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: 0,
|
||||||
|
FieldId: fieldId,
|
||||||
|
FileName: "test-attachment.txt",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Delete", func(t *testing.T) {
|
||||||
|
t.Run("should delete a file from an attachment field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-attachment.txt")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test attachment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
saveResponse, err := client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: fieldId,
|
||||||
|
FileName: "test-attachment-to-delete.txt",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to save file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Files.Delete(ctx, recordId, fieldId, saveResponse.Id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should delete a file from an image field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_IMAGE_FIELD")
|
||||||
|
|
||||||
|
file, err := os.Open("testdata/test-image.jpeg")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open test image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
saveResponse, err := client.Files.Save(ctx, onspring.SaveFileRequest{
|
||||||
|
RecordId: recordId,
|
||||||
|
FieldId: fieldId,
|
||||||
|
FileName: "test-image-to-delete.jpeg",
|
||||||
|
FileContents: file,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to save file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Files.Delete(ctx, recordId, fieldId, saveResponse.Id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 response when fieldId is not for a file field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
err := client.Files.Delete(ctx, recordId, textFieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 response when the api key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
err := invalidClient.Files.Delete(ctx, recordId, fieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to the field", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldIdNoAccess := requireEnvInt(t, "TEST_ATTACHMENT_FIELD_NO_ACCESS_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
err := client.Files.Delete(ctx, recordId, fieldIdNoAccess, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 response when the api key does not have access to the app", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fieldIdNoApp := requireEnvInt(t, "TEST_ATTACHMENT_FIELD_NO_ACCESS_APP")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
err := client.Files.Delete(ctx, recordId, fieldIdNoApp, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 response when the file field cannot be found", func(t *testing.T) {
|
||||||
|
recordId := requireEnvInt(t, "TEST_RECORD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
err := client.Files.Delete(ctx, recordId, 0, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 response when the file record cannot be found", func(t *testing.T) {
|
||||||
|
fieldId := requireEnvInt(t, "TEST_ATTACHMENT_FIELD")
|
||||||
|
fileId := requireEnvInt(t, "TEST_ATTACHMENT")
|
||||||
|
|
||||||
|
err := client.Files.Delete(ctx, 0, fieldId, fileId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package onspring_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loadEnvFile(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
file, err := os.Open(".env")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to open .env file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.TrimSpace(scanner.Text())
|
||||||
|
|
||||||
|
if line == "" || strings.HasPrefix(line, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
key, value, found := strings.Cut(line, "=")
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
key = strings.TrimSpace(key)
|
||||||
|
value = strings.TrimSpace(value)
|
||||||
|
|
||||||
|
t.Setenv(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
t.Fatalf("Failed to read .env file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireEnv(t *testing.T, key string) string {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
value := os.Getenv(key)
|
||||||
|
|
||||||
|
if value == "" {
|
||||||
|
t.Fatalf("Required environment variable %s is not set", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireEnvInt(t *testing.T, key string) int {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
value := requireEnv(t, key)
|
||||||
|
intValue, err := strconv.Atoi(value)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Environment variable %s is not a valid integer: %v", key, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return intValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireEnvIntSlice(t *testing.T, key string) []int {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
value := requireEnv(t, key)
|
||||||
|
parts := strings.Split(value, ",")
|
||||||
|
result := make([]int, len(parts))
|
||||||
|
|
||||||
|
for i, part := range parts {
|
||||||
|
intValue, err := strconv.Atoi(strings.TrimSpace(part))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Environment variable %s contains invalid integer '%s': %v", key, part, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result[i] = intValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func createClient(t *testing.T) *onspring.Client {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
return onspring.NewClient(
|
||||||
|
requireEnv(t, "SANDBOX_API_KEY"),
|
||||||
|
onspring.WithBaseURL(requireEnv(t, "API_BASE_URL")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createInvalidClient(t *testing.T) *onspring.Client {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
return onspring.NewClient(
|
||||||
|
"invalid-api-key",
|
||||||
|
onspring.WithBaseURL(requireEnv(t, "API_BASE_URL")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertAPIError(t *testing.T, err error, expectedStatus int) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Expected error, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiErr *onspring.OnspringAPIError
|
||||||
|
|
||||||
|
if !errors.As(err, &apiErr) {
|
||||||
|
t.Fatalf("Expected OnspringAPIError, got %T: %v", err, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if apiErr.StatusCode != expectedStatus {
|
||||||
|
t.Errorf("Expected status code %d, got %d", expectedStatus, apiErr.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addTestRecord(t *testing.T, client *onspring.Client, appId, textFieldId int) int {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
response, err := client.Records.Save(ctx, onspring.SaveRecordRequest{
|
||||||
|
AppId: appId,
|
||||||
|
Fields: map[string]any{
|
||||||
|
fmt.Sprintf("%d", textFieldId): "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test record: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = client.Records.Delete(context.Background(), appId, response.Id)
|
||||||
|
})
|
||||||
|
|
||||||
|
return response.Id
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package onspring_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestListsIntegration(t *testing.T) {
|
||||||
|
loadEnvFile(t)
|
||||||
|
client := createClient(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
t.Run("Save", func(t *testing.T) {
|
||||||
|
t.Run("should add a list item", func(t *testing.T) {
|
||||||
|
listId := requireEnvInt(t, "TEST_LIST_ID")
|
||||||
|
|
||||||
|
item := onspring.SaveListItemRequest{
|
||||||
|
Name: "Integration Test Item",
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := client.Lists.Save(ctx, listId, item)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Id == "" {
|
||||||
|
t.Error("Expected list item id to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = client.Lists.Delete(context.Background(), listId, response.Id)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should update a list item", func(t *testing.T) {
|
||||||
|
listId := requireEnvInt(t, "TEST_LIST_ID")
|
||||||
|
|
||||||
|
item := onspring.SaveListItemRequest{
|
||||||
|
Name: "Integration Test Item",
|
||||||
|
}
|
||||||
|
|
||||||
|
addResponse, err := client.Lists.Save(ctx, listId, item)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to add list item: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = client.Lists.Delete(context.Background(), listId, addResponse.Id)
|
||||||
|
})
|
||||||
|
|
||||||
|
updateItem := onspring.SaveListItemRequest{
|
||||||
|
Id: addResponse.Id,
|
||||||
|
Name: "Updated Integration Test Item",
|
||||||
|
}
|
||||||
|
|
||||||
|
updateResponse, err := client.Lists.Save(ctx, listId, updateItem)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if updateResponse.Id == "" {
|
||||||
|
t.Error("Expected list item id to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when an invalid api key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
listId := requireEnvInt(t, "TEST_LIST_ID")
|
||||||
|
|
||||||
|
item := onspring.SaveListItemRequest{
|
||||||
|
Name: "Integration Test Item",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := invalidClient.Lists.Save(ctx, listId, item)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when api key does not have access to the list", func(t *testing.T) {
|
||||||
|
listIdNoAccess := requireEnvInt(t, "TEST_LIST_ID_NO_ACCESS")
|
||||||
|
|
||||||
|
item := onspring.SaveListItemRequest{
|
||||||
|
Name: "Integration Test Item",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := client.Lists.Save(ctx, listIdNoAccess, item)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 error when the list does not exist", func(t *testing.T) {
|
||||||
|
item := onspring.SaveListItemRequest{
|
||||||
|
Name: "Integration Test Item",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := client.Lists.Save(ctx, 0, item)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Delete", func(t *testing.T) {
|
||||||
|
t.Run("should delete a list item", func(t *testing.T) {
|
||||||
|
listId := requireEnvInt(t, "TEST_LIST_ID")
|
||||||
|
|
||||||
|
item := onspring.SaveListItemRequest{
|
||||||
|
Name: "Integration Test Item To Delete",
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := client.Lists.Save(ctx, listId, item)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to add list item: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Lists.Delete(ctx, listId, response.Id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when an invalid api key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
listId := requireEnvInt(t, "TEST_LIST_ID")
|
||||||
|
|
||||||
|
err := invalidClient.Lists.Delete(ctx, listId, "some-item-id")
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when api key does not have access to the list", func(t *testing.T) {
|
||||||
|
listIdNoAccess := requireEnvInt(t, "TEST_LIST_ID_NO_ACCESS")
|
||||||
|
listItemIdNoAccess := requireEnv(t, "TEST_LIST_ITEM_ID_NO_ACCESS")
|
||||||
|
|
||||||
|
err := client.Lists.Delete(ctx, listIdNoAccess, listItemIdNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 error when the list does not exist", func(t *testing.T) {
|
||||||
|
err := client.Lists.Delete(ctx, 0, "a57e3d33-9195-4039-9ac0-c180013b043e")
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package onspring_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPingIntegration(t *testing.T) {
|
||||||
|
loadEnvFile(t)
|
||||||
|
|
||||||
|
t.Run("Get should be able to connect to the API", func(t *testing.T) {
|
||||||
|
client := createClient(t)
|
||||||
|
|
||||||
|
err := client.Ping.Get(context.Background())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,649 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package onspring_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRecordsIntegration(t *testing.T) {
|
||||||
|
loadEnvFile(t)
|
||||||
|
client := createClient(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
t.Run("Get", func(t *testing.T) {
|
||||||
|
t.Run("should get a record", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
|
||||||
|
record, err := client.Records.Get(ctx, surveyId, recordId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.AppId != surveyId {
|
||||||
|
t.Errorf("Expected appId %d, got %d", surveyId, record.AppId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.RecordId != recordId {
|
||||||
|
t.Errorf("Expected recordId %d, got %d", recordId, record.RecordId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(record.FieldData) == 0 {
|
||||||
|
t.Error("Expected field data to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range record.FieldData {
|
||||||
|
if field.FieldId == 0 {
|
||||||
|
t.Error("Expected field id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Type == "" {
|
||||||
|
t.Error("Expected field type to not be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should get a record when fieldIds and data format are passed as parameters", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
|
||||||
|
record, err := client.Records.Get(
|
||||||
|
ctx,
|
||||||
|
surveyId,
|
||||||
|
recordId,
|
||||||
|
onspring.WithFieldIds([]int{textFieldId}),
|
||||||
|
onspring.WithRecordDataFormat("Formatted"),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.AppId != surveyId {
|
||||||
|
t.Errorf("Expected appId %d, got %d", surveyId, record.AppId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.RecordId != recordId {
|
||||||
|
t.Errorf("Expected recordId %d, got %d", recordId, record.RecordId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(record.FieldData) == 0 {
|
||||||
|
t.Error("Expected field data to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when an invalid API key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
|
||||||
|
_, err := invalidClient.Records.Get(ctx, surveyId, recordId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 error when an invalid record id is used", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
_, err := client.Records.Get(ctx, surveyId, 0)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("List", func(t *testing.T) {
|
||||||
|
t.Run("should get records", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
page, err := client.Records.List(ctx, surveyId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber == 0 {
|
||||||
|
t.Error("Expected page number to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.TotalRecords == 0 {
|
||||||
|
t.Error("Expected total records to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) == 0 {
|
||||||
|
t.Error("Expected items to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range page.Items {
|
||||||
|
if record.AppId != surveyId {
|
||||||
|
t.Errorf("Expected appId %d, got %d", surveyId, record.AppId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.RecordId == 0 {
|
||||||
|
t.Error("Expected recordId to not be zero")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should get records when fieldIds, paging information, and data format are passed as parameters", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
|
||||||
|
page, err := client.Records.List(
|
||||||
|
ctx,
|
||||||
|
surveyId,
|
||||||
|
onspring.WithFieldIds([]int{textFieldId}),
|
||||||
|
onspring.WithRecordDataFormat("Formatted"),
|
||||||
|
onspring.WithPaging(onspring.ForPageNumber(1), onspring.WithPageSize(1)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber != 1 {
|
||||||
|
t.Errorf("Expected page number 1, got %d", page.PageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageSize != 1 {
|
||||||
|
t.Errorf("Expected page size 1, got %d", page.PageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) != 1 {
|
||||||
|
t.Errorf("Expected 1 item, got %d", len(page.Items))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when an invalid API key is passed", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
_, err := invalidClient.Records.List(ctx, surveyId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when the api key does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
|
||||||
|
_, err := client.Records.List(ctx, appIdNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAll", func(t *testing.T) {
|
||||||
|
t.Run("should iterate all records for an app", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
var records []onspring.Record
|
||||||
|
|
||||||
|
for record, err := range client.Records.ListAll(ctx, surveyId, onspring.WithPaging(onspring.WithPageSize(1))) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
records = append(records, record)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(records) == 0 {
|
||||||
|
t.Error("Expected to iterate at least one record")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("GetMany", func(t *testing.T) {
|
||||||
|
t.Run("should get records", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
|
||||||
|
batch, err := client.Records.GetMany(ctx, onspring.GetManyRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordIds: []int{recordId},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if batch.Count == 0 {
|
||||||
|
t.Error("Expected count to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(batch.Items) == 0 {
|
||||||
|
t.Error("Expected items to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range batch.Items {
|
||||||
|
if record.AppId != surveyId {
|
||||||
|
t.Errorf("Expected appId %d, got %d", surveyId, record.AppId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.RecordId == 0 {
|
||||||
|
t.Error("Expected recordId to not be zero")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should get records when field ids and data format are passed as parameters", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
|
||||||
|
batch, err := client.Records.GetMany(ctx, onspring.GetManyRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordIds: []int{recordId},
|
||||||
|
FieldIds: []int{textFieldId},
|
||||||
|
DataFormat: "Formatted",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if batch.Count == 0 {
|
||||||
|
t.Error("Expected count to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(batch.Items) == 0 {
|
||||||
|
t.Error("Expected items to not be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 error if too many record ids are passed", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
ids := make([]int, 101)
|
||||||
|
for i := range ids {
|
||||||
|
ids[i] = i + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := client.Records.GetMany(ctx, onspring.GetManyRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordIds: ids,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error if the api key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
|
||||||
|
_, err := invalidClient.Records.GetMany(ctx, onspring.GetManyRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordIds: []int{recordId},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error if the user does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
|
||||||
|
_, err := client.Records.GetMany(ctx, onspring.GetManyRecordsRequest{
|
||||||
|
AppId: appIdNoAccess,
|
||||||
|
RecordIds: []int{recordId},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Query", func(t *testing.T) {
|
||||||
|
t.Run("should return records", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
autoNumberField := requireEnvInt(t, "TEST_SURVEY_AUTO_NUMBER_FIELD")
|
||||||
|
filter := fmt.Sprintf("%d gt 0", autoNumberField)
|
||||||
|
|
||||||
|
page, err := client.Records.Query(ctx, onspring.QueryRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
Filter: filter,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber == 0 {
|
||||||
|
t.Error("Expected page number to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.TotalRecords == 0 {
|
||||||
|
t.Error("Expected total records to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) == 0 {
|
||||||
|
t.Error("Expected items to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range page.Items {
|
||||||
|
if record.AppId != surveyId {
|
||||||
|
t.Errorf("Expected appId %d, got %d", surveyId, record.AppId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.RecordId == 0 {
|
||||||
|
t.Error("Expected recordId to not be zero")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return records when data format, paging information, and fields are passed as parameters", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
autoNumberField := requireEnvInt(t, "TEST_SURVEY_AUTO_NUMBER_FIELD")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
filter := fmt.Sprintf("%d gt 0", autoNumberField)
|
||||||
|
|
||||||
|
page, err := client.Records.Query(
|
||||||
|
ctx,
|
||||||
|
onspring.QueryRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
Filter: filter,
|
||||||
|
FieldIds: []int{textFieldId},
|
||||||
|
DataFormat: "Formatted",
|
||||||
|
},
|
||||||
|
onspring.ForPageNumber(1),
|
||||||
|
onspring.WithPageSize(1),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber != 1 {
|
||||||
|
t.Errorf("Expected page number 1, got %d", page.PageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageSize != 1 {
|
||||||
|
t.Errorf("Expected page size 1, got %d", page.PageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) != 1 {
|
||||||
|
t.Errorf("Expected 1 item, got %d", len(page.Items))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 error if page size is invalid", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
autoNumberField := requireEnvInt(t, "TEST_SURVEY_AUTO_NUMBER_FIELD")
|
||||||
|
filter := fmt.Sprintf("%d gt 0", autoNumberField)
|
||||||
|
|
||||||
|
_, err := client.Records.Query(
|
||||||
|
ctx,
|
||||||
|
onspring.QueryRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
Filter: filter,
|
||||||
|
},
|
||||||
|
onspring.WithPageSize(1001),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error if the API key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
autoNumberField := requireEnvInt(t, "TEST_SURVEY_AUTO_NUMBER_FIELD")
|
||||||
|
filter := fmt.Sprintf("%d gt 0", autoNumberField)
|
||||||
|
|
||||||
|
_, err := invalidClient.Records.Query(ctx, onspring.QueryRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
Filter: filter,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error if the API key does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
autoNumberField := requireEnvInt(t, "TEST_SURVEY_AUTO_NUMBER_FIELD")
|
||||||
|
filter := fmt.Sprintf("%d gt 0", autoNumberField)
|
||||||
|
|
||||||
|
_, err := client.Records.Query(ctx, onspring.QueryRecordsRequest{
|
||||||
|
AppId: appIdNoAccess,
|
||||||
|
Filter: filter,
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("QueryAll", func(t *testing.T) {
|
||||||
|
t.Run("should iterate all records matching a query", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
autoNumberField := requireEnvInt(t, "TEST_SURVEY_AUTO_NUMBER_FIELD")
|
||||||
|
filter := fmt.Sprintf("%d gt 0", autoNumberField)
|
||||||
|
|
||||||
|
var records []onspring.Record
|
||||||
|
|
||||||
|
for record, err := range client.Records.QueryAll(
|
||||||
|
ctx,
|
||||||
|
onspring.QueryRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
Filter: filter,
|
||||||
|
},
|
||||||
|
onspring.WithPageSize(1),
|
||||||
|
) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
records = append(records, record)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(records) == 0 {
|
||||||
|
t.Error("Expected to iterate at least one record")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Save", func(t *testing.T) {
|
||||||
|
t.Run("should add a record when no record id is passed", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
|
||||||
|
response, err := client.Records.Save(ctx, onspring.SaveRecordRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
Fields: map[string]any{
|
||||||
|
fmt.Sprintf("%d", textFieldId): "integration test record",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Id == 0 {
|
||||||
|
t.Error("Expected record id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Warnings == nil {
|
||||||
|
t.Error("Expected warnings to not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = client.Records.Delete(context.Background(), surveyId, response.Id)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should update a record when a record id is passed", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
recordId := addTestRecord(t, client, surveyId, textFieldId)
|
||||||
|
|
||||||
|
response, err := client.Records.Save(ctx, onspring.SaveRecordRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordId: &recordId,
|
||||||
|
Fields: map[string]any{
|
||||||
|
fmt.Sprintf("%d", textFieldId): "updated integration test record",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Id == 0 {
|
||||||
|
t.Error("Expected record id to not be zero")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 error when field data is empty", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
_, err := client.Records.Save(ctx, onspring.SaveRecordRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
Fields: map[string]any{},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when the api key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
|
||||||
|
_, err := invalidClient.Records.Save(ctx, onspring.SaveRecordRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
Fields: map[string]any{
|
||||||
|
fmt.Sprintf("%d", textFieldId): "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when the api key does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
|
||||||
|
_, err := client.Records.Save(ctx, onspring.SaveRecordRequest{
|
||||||
|
AppId: appIdNoAccess,
|
||||||
|
Fields: map[string]any{
|
||||||
|
fmt.Sprintf("%d", textFieldId): "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 error when the record id is not found", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
recordId := 0
|
||||||
|
|
||||||
|
_, err := client.Records.Save(ctx, onspring.SaveRecordRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordId: &recordId,
|
||||||
|
Fields: map[string]any{
|
||||||
|
fmt.Sprintf("%d", textFieldId): "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Delete", func(t *testing.T) {
|
||||||
|
t.Run("should delete a record", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
recordId := addTestRecord(t, client, surveyId, textFieldId)
|
||||||
|
|
||||||
|
err := client.Records.Delete(ctx, surveyId, recordId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when the API key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
|
||||||
|
err := invalidClient.Records.Delete(ctx, surveyId, recordId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when the API key does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
recordId := requireEnvInt(t, "TEST_SURVEY_RECORD_ID")
|
||||||
|
|
||||||
|
err := client.Records.Delete(ctx, appIdNoAccess, recordId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 error when the record does not exist", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
err := client.Records.Delete(ctx, surveyId, 0)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DeleteMany", func(t *testing.T) {
|
||||||
|
t.Run("should delete records", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
textFieldId := requireEnvInt(t, "TEST_TEXT_FIELD")
|
||||||
|
recordId1 := addTestRecord(t, client, surveyId, textFieldId)
|
||||||
|
recordId2 := addTestRecord(t, client, surveyId, textFieldId)
|
||||||
|
|
||||||
|
err := client.Records.DeleteMany(ctx, onspring.DeleteManyRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordIds: []int{recordId1, recordId2},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 error when no record ids are provided", func(t *testing.T) {
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
err := client.Records.DeleteMany(ctx, onspring.DeleteManyRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordIds: []int{},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error when an invalid API key is used", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
surveyId := requireEnvInt(t, "TEST_SURVEY_ID")
|
||||||
|
|
||||||
|
err := invalidClient.Records.DeleteMany(ctx, onspring.DeleteManyRecordsRequest{
|
||||||
|
AppId: surveyId,
|
||||||
|
RecordIds: []int{1},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error when the API key does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
|
||||||
|
err := client.Records.DeleteMany(ctx, onspring.DeleteManyRecordsRequest{
|
||||||
|
AppId: appIdNoAccess,
|
||||||
|
RecordIds: []int{1},
|
||||||
|
})
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package onspring_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReportsIntegration(t *testing.T) {
|
||||||
|
loadEnvFile(t)
|
||||||
|
client := createClient(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
t.Run("Get", func(t *testing.T) {
|
||||||
|
t.Run("should return a report", func(t *testing.T) {
|
||||||
|
reportId := requireEnvInt(t, "TEST_REPORT")
|
||||||
|
|
||||||
|
report, err := client.Reports.Get(ctx, reportId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if report.Columns == nil {
|
||||||
|
t.Error("Expected columns to not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if report.Rows == nil {
|
||||||
|
t.Error("Expected rows to not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, row := range report.Rows {
|
||||||
|
if row.Cells == nil {
|
||||||
|
t.Error("Expected cells to not be nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return report data for a report with chart data when report data is requested", func(t *testing.T) {
|
||||||
|
reportId := requireEnvInt(t, "TEST_REPORT_WITH_CHART_DATA")
|
||||||
|
|
||||||
|
report, err := client.Reports.Get(ctx, reportId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if report.Columns == nil {
|
||||||
|
t.Error("Expected columns to not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if report.Rows == nil {
|
||||||
|
t.Error("Expected rows to not be nil")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return chart data for a report with a chart when chart data is requested", func(t *testing.T) {
|
||||||
|
reportId := requireEnvInt(t, "TEST_REPORT_WITH_CHART_DATA")
|
||||||
|
|
||||||
|
report, err := client.Reports.Get(
|
||||||
|
ctx,
|
||||||
|
reportId,
|
||||||
|
onspring.WithDataFormat("Raw"),
|
||||||
|
onspring.WithDataType("ChartData"),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if report.Columns == nil {
|
||||||
|
t.Error("Expected columns to not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if report.Rows == nil {
|
||||||
|
t.Error("Expected rows to not be nil")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 error if chart data is requested for a report without chart data", func(t *testing.T) {
|
||||||
|
reportId := requireEnvInt(t, "TEST_REPORT")
|
||||||
|
|
||||||
|
_, err := client.Reports.Get(
|
||||||
|
ctx,
|
||||||
|
reportId,
|
||||||
|
onspring.WithDataFormat("Raw"),
|
||||||
|
onspring.WithDataType("ChartData"),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error if the api key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
reportId := requireEnvInt(t, "TEST_REPORT")
|
||||||
|
|
||||||
|
_, err := invalidClient.Reports.Get(ctx, reportId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error if the api key does not have access to the report", func(t *testing.T) {
|
||||||
|
reportIdNoAccess := requireEnvInt(t, "TEST_REPORT_NO_ACCESS")
|
||||||
|
|
||||||
|
_, err := client.Reports.Get(ctx, reportIdNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 404 error if the report does not exist", func(t *testing.T) {
|
||||||
|
_, err := client.Reports.Get(ctx, 0)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusNotFound)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("List", func(t *testing.T) {
|
||||||
|
t.Run("should return a list of reports", func(t *testing.T) {
|
||||||
|
appId := requireEnvInt(t, "TEST_APP_ID")
|
||||||
|
|
||||||
|
page, err := client.Reports.List(ctx, appId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.PageNumber == 0 {
|
||||||
|
t.Error("Expected page number to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.TotalRecords == 0 {
|
||||||
|
t.Error("Expected total records to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(page.Items) == 0 {
|
||||||
|
t.Error("Expected items to not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, report := range page.Items {
|
||||||
|
if report.Id == 0 {
|
||||||
|
t.Error("Expected report id to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if report.AppId == 0 {
|
||||||
|
t.Error("Expected report appId to not be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if report.Name == "" {
|
||||||
|
t.Error("Expected report name to not be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 400 error if page size is invalid", func(t *testing.T) {
|
||||||
|
appId := requireEnvInt(t, "TEST_APP_ID")
|
||||||
|
|
||||||
|
_, err := client.Reports.List(ctx, appId, onspring.WithPageSize(1001))
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusBadRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 401 error if the api key is invalid", func(t *testing.T) {
|
||||||
|
invalidClient := createInvalidClient(t)
|
||||||
|
appId := requireEnvInt(t, "TEST_APP_ID")
|
||||||
|
|
||||||
|
_, err := invalidClient.Reports.List(ctx, appId)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should return a 403 error if the api key does not have access to the app", func(t *testing.T) {
|
||||||
|
appIdNoAccess := requireEnvInt(t, "TEST_APP_ID_NO_ACCESS")
|
||||||
|
|
||||||
|
_, err := client.Reports.List(ctx, appIdNoAccess)
|
||||||
|
|
||||||
|
assertAPIError(t, err, http.StatusForbidden)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListAll", func(t *testing.T) {
|
||||||
|
t.Run("should iterate all reports for an app", func(t *testing.T) {
|
||||||
|
appId := requireEnvInt(t, "TEST_APP_ID")
|
||||||
|
|
||||||
|
var reports []onspring.Report
|
||||||
|
|
||||||
|
for report, err := range client.Reports.ListAll(ctx, appId, onspring.WithPageSize(1)) {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
reports = append(reports, report)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(reports) == 0 {
|
||||||
|
t.Error("Expected to iterate at least one report")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
This is a test attachment.
|
||||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
Reference in New Issue
Block a user