From 36498310ced0eaf99eff0882078a2aa526c27794 Mon Sep 17 00:00:00 2001 From: franklin Date: Fri, 26 Apr 2024 11:00:16 +0200 Subject: [PATCH] feat: fix lint issues, add context and revert #3 --- README.md | 22 +- api_key.go | 26 +- asset.go | 48 +-- collection.go | 175 ++++++---- collection_test.go | 7 +- content_type.go | 38 +- content_type_field_validations.go | 4 +- content_type_field_validations_test.go | 79 ++--- content_type_test.go | 463 ++++++++++++------------- contentful.go | 44 ++- contentful_test.go | 204 +++++------ entry.go | 64 ++-- entry_field.go | 26 +- entry_test.go | 128 ++++--- errors.go | 9 +- errors_test.go | 53 +-- include.go | 2 +- locale.go | 24 +- locale_test.go | 99 +++--- query.go | 63 ++-- query_test.go | 39 ++- scheduled_actions.go | 53 --- scheduled_actions_test.go | 24 -- space.go | 22 +- space_test.go | 171 ++++----- webhook.go | 24 +- webhook_test.go | 129 ++++--- 27 files changed, 1012 insertions(+), 1028 deletions(-) delete mode 100644 scheduled_actions.go delete mode 100644 scheduled_actions_test.go diff --git a/README.md b/README.md index 1481152..f860188 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ GoLang SDK for [Contentful's](https://www.contentful.com) Content Delivery, Prev # Install -`go get github.com/contentful-labs/contentful-go` +`go get github.com/foomo/contentful` # Getting started @@ -24,7 +24,7 @@ Import into your Go project or library ```go import ( - contentful "github.com/contentful-labs/contentful-go" + "github.com/foomo/contentful" ) ``` @@ -51,15 +51,11 @@ When debug mode is activated, sdk client starts to work in verbose mode and try cma.Debug = true ``` -#### Dependencies - -`contentful-go` stores its dependencies under `vendor` folder and uses [`dep`](https://github.com/golang/dep) to manage dependency resolutions. Dependencies in `vendor` folder will be loaded automatically by [Go 1.6+](https://golang.org/cmd/go/#hdr-Vendor_Directories). To install the dependencies, run `dep ensure`, for more options and documentation please visit [`dep`](https://github.com/golang/dep). - # Using the SDK ## Working with resource services -Currently SDK exposes the following resource services: +Currently, SDK exposes the following resource services: * Spaces * APIKeys @@ -72,21 +68,21 @@ Currently SDK exposes the following resource services: Every resource service has at least the following interface: ```go -List() *Collection -Get(spaceID, resourceID string) , error -Upsert(spaceID string, resourceID *Resource) error -Delete(spaceID string, resourceID *Resource) error +List(ctx) *Collection +Get(ctx, spaceID, resourceID string) , error +Upsert(ctx, spaceID string, resourceID *Resource) error +Delete(ctx, spaceID string, resourceID *Resource) error ``` #### Example ```go -space, err := cma.Spaces.Get("space-id") +space, err := cma.Spaces.Get(ctx, "space-id") if err != nil { log.Fatal(err) } -collection := cma.ContentTypes.List(space.Sys.ID) +collection := cma.ContentTypes.List(ctx, space.Sys.ID) collection, err := collection.Next() if err != nil { log.Fatal(err) diff --git a/api_key.go b/api_key.go index 9b45d2b..ecc05da 100644 --- a/api_key.go +++ b/api_key.go @@ -2,8 +2,10 @@ package contentful import ( "bytes" + "context" "encoding/json" "fmt" + "net/http" "strconv" ) @@ -28,7 +30,7 @@ type APIKeyPolicy struct { // PreviewAPIKey model type PreviewAPIKey struct { - Sys *Sys + Sys *Sys `json:"sys,omitempty"` } // MarshalJSON for custom json marshaling @@ -53,11 +55,11 @@ func (apiKey *APIKey) GetVersion() int { } // List returns all api keys collection -func (service *APIKeyService) List(spaceID string) *Collection { +func (service *APIKeyService) List(ctx context.Context, spaceID string) *Collection { path := fmt.Sprintf("/spaces/%s%s/api_keys", spaceID, getEnvPath(service.c)) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return &Collection{} } @@ -70,11 +72,11 @@ func (service *APIKeyService) List(spaceID string) *Collection { } // Get returns a single api key entity -func (service *APIKeyService) Get(spaceID, apiKeyID string) (*APIKey, error) { +func (service *APIKeyService) Get(ctx context.Context, spaceID, apiKeyID string) (*APIKey, error) { path := fmt.Sprintf("/spaces/%s%s/api_keys/%s", spaceID, getEnvPath(service.c), apiKeyID) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return nil, err } @@ -88,7 +90,7 @@ func (service *APIKeyService) Get(spaceID, apiKeyID string) (*APIKey, error) { } // Upsert updates or creates a new api key entity -func (service *APIKeyService) Upsert(spaceID string, apiKey *APIKey) error { +func (service *APIKeyService) Upsert(ctx context.Context, spaceID string, apiKey *APIKey) error { bytesArray, err := json.Marshal(apiKey) if err != nil { return err @@ -105,7 +107,7 @@ func (service *APIKeyService) Upsert(spaceID string, apiKey *APIKey) error { method = "POST" } - req, err := service.c.newRequest(method, path, nil, bytes.NewReader(bytesArray)) + req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray)) if err != nil { return err } @@ -116,11 +118,11 @@ func (service *APIKeyService) Upsert(spaceID string, apiKey *APIKey) error { } // Delete deletes a sinlge api key entity -func (service *APIKeyService) Delete(spaceID string, apiKey *APIKey) error { +func (service *APIKeyService) Delete(ctx context.Context, spaceID string, apiKey *APIKey) error { path := fmt.Sprintf("/spaces/%s%s/api_keys/%s", spaceID, getEnvPath(service.c), apiKey.Sys.ID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } diff --git a/asset.go b/asset.go index 1c227fc..f37c37e 100644 --- a/asset.go +++ b/asset.go @@ -2,8 +2,10 @@ package contentful import ( "bytes" + "context" "encoding/json" "fmt" + "net/http" "net/url" "strconv" ) @@ -69,11 +71,11 @@ func (asset *Asset) GetVersion() int { } // List returns asset collection -func (service *AssetsService) List(spaceID string) *Collection { +func (service *AssetsService) List(ctx context.Context, spaceID string) *Collection { path := fmt.Sprintf("/spaces/%s%s/assets", spaceID, getEnvPath(service.c)) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return &Collection{} } @@ -86,16 +88,16 @@ func (service *AssetsService) List(spaceID string) *Collection { } // Get returns a single asset entity -func (service *AssetsService) Get(spaceID, assetID string, locale ...string) (*Asset, error) { +func (service *AssetsService) Get(ctx context.Context, spaceID, assetID string, locale ...string) (*Asset, error) { path := fmt.Sprintf("/spaces/%s%s/assets/%s", spaceID, getEnvPath(service.c), assetID) query := url.Values{} if service.c.api == "CDA" && len(locale) > 0 { query["locale"] = locale } - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, query, nil) + req, err := service.c.newRequest(ctx, method, path, query, nil) if err != nil { return nil, err } @@ -127,17 +129,16 @@ func (service *AssetsService) Get(spaceID, assetID string, locale ...string) (*A return nil, err } return &asset, nil - } // GetLocalized returns the asset with fields without localization map -func (asset *Asset) GetLocalized() (assetNoLocale *AssetNoLocale) { +func (asset *Asset) GetLocalized() *AssetNoLocale { // No default locale available if asking for all locales, fallback to nil if asset.Sys.Locale == "" { return nil } - assetNoLocale = &AssetNoLocale{ + return &AssetNoLocale{ Sys: asset.Sys, Fields: &FileFieldsNoLocale{ Title: asset.Fields.Title[asset.Sys.Locale], @@ -145,11 +146,10 @@ func (asset *Asset) GetLocalized() (assetNoLocale *AssetNoLocale) { File: asset.Fields.File[asset.Sys.Locale], }, } - return } // Upsert updates or creates a new asset entity -func (service *AssetsService) Upsert(spaceID string, asset *Asset) error { +func (service *AssetsService) Upsert(ctx context.Context, spaceID string, asset *Asset) error { bytesArray, err := json.Marshal(asset) if err != nil { return err @@ -166,7 +166,7 @@ func (service *AssetsService) Upsert(spaceID string, asset *Asset) error { method = "POST" } - req, err := service.c.newRequest(method, path, nil, bytes.NewReader(bytesArray)) + req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray)) if err != nil { return err } @@ -177,11 +177,11 @@ func (service *AssetsService) Upsert(spaceID string, asset *Asset) error { } // Delete sends delete request -func (service *AssetsService) Delete(spaceID string, asset *Asset) error { +func (service *AssetsService) Delete(ctx context.Context, spaceID string, asset *Asset) error { path := fmt.Sprintf("/spaces/%s%s/assets/%s", spaceID, getEnvPath(service.c), asset.Sys.ID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } @@ -193,7 +193,7 @@ func (service *AssetsService) Delete(spaceID string, asset *Asset) error { } // Process the asset -func (service *AssetsService) Process(spaceID string, asset *Asset) error { +func (service *AssetsService) Process(ctx context.Context, spaceID string, asset *Asset) error { var locale string for k := range asset.Fields.Title { locale = k @@ -201,9 +201,9 @@ func (service *AssetsService) Process(spaceID string, asset *Asset) error { continue } path := fmt.Sprintf("/spaces/%s%s/assets/%s/files/%s/process", spaceID, getEnvPath(service.c), asset.Sys.ID, locale) - method := "PUT" + method := http.MethodPut - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } @@ -219,11 +219,11 @@ func (service *AssetsService) Process(spaceID string, asset *Asset) error { } // Publish publishes the asset -func (service *AssetsService) Publish(spaceID string, asset *Asset) error { +func (service *AssetsService) Publish(ctx context.Context, spaceID string, asset *Asset) error { path := fmt.Sprintf("/spaces/%s%s/assets/%s/published", spaceID, getEnvPath(service.c), asset.Sys.ID) - method := "PUT" + method := http.MethodPut - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } @@ -235,11 +235,11 @@ func (service *AssetsService) Publish(spaceID string, asset *Asset) error { } // Unpublish unpublishes the asset -func (service *AssetsService) Unpublish(spaceID string, asset *Asset) error { +func (service *AssetsService) Unpublish(ctx context.Context, spaceID string, asset *Asset) error { path := fmt.Sprintf("/spaces/%s%s/assets/%s/published", spaceID, getEnvPath(service.c), asset.Sys.ID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } diff --git a/collection.go b/collection.go index 4adb7c3..ce629b6 100644 --- a/collection.go +++ b/collection.go @@ -41,6 +41,8 @@ type Collection struct { Details *ErrorDetails } +var syncTokenRegex = regexp.MustCompile(`sync_token=([a-zA-Z0-9\\-_]+)`) + // NewCollection initializes a new collection func NewCollection(options *CollectionOptions) *Collection { query := NewQuery() @@ -78,12 +80,11 @@ func (col *Collection) Next() (*Collection, error) { } col.page++ - r, _ := regexp.Compile("sync_token=([a-zA-Z0-9\\-\\_]+)") if col.NextPageURL != "" { - syncToken := r.FindStringSubmatch(col.NextPageURL) + syncToken := syncTokenRegex.FindStringSubmatch(col.NextPageURL) col.SyncToken = syncToken[1] } else if col.NextSyncURL != "" { - syncToken := r.FindStringSubmatch(col.NextSyncURL) + syncToken := syncTokenRegex.FindStringSubmatch(col.NextSyncURL) col.SyncToken = syncToken[1] } return col, nil @@ -122,140 +123,192 @@ func (col *Collection) GetAll() (*Collection, error) { } // ToContentType cast Items to ContentType model -func (col *Collection) ToContentType() []*ContentType { +func (col *Collection) ToContentType() ([]*ContentType, error) { var contentTypes []*ContentType - byteArray, _ := json.Marshal(col.Items) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&contentTypes) + byteArray, err := json.Marshal(col.Items) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&contentTypes); err != nil { + return nil, err + } - return contentTypes + return contentTypes, nil } // ToSpace cast Items to Space model -func (col *Collection) ToSpace() []*Space { +func (col *Collection) ToSpace() ([]*Space, error) { var spaces []*Space - byteArray, _ := json.Marshal(col.Items) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&spaces) + byteArray, err := json.Marshal(col.Items) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&spaces); err != nil { + return nil, err + } - return spaces -} - -// ToScheduledAction cast Items to ScheduledActions model -func (col *Collection) ToScheduledAction() []*ScheduledActions { - var scheduledActions []*ScheduledActions - - byteArray, _ := json.Marshal(col.Items) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&scheduledActions) - - return scheduledActions + return spaces, nil } // ToEntry cast Items to Entry model -func (col *Collection) ToEntry() []*Entry { +func (col *Collection) ToEntry() ([]*Entry, error) { var entries []*Entry - byteArray, _ := json.Marshal(col.Items) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&entries) + byteArray, err := json.Marshal(col.Items) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&entries); err != nil { + return nil, err + } - return entries + return entries, nil } // ToLocale cast Items to Locale model -func (col *Collection) ToLocale() []*Locale { +func (col *Collection) ToLocale() ([]*Locale, error) { var locales []*Locale - byteArray, _ := json.Marshal(col.Items) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&locales) + byteArray, err := json.Marshal(col.Items) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&locales); err != nil { + return nil, err + } - return locales + return locales, nil } // ToAsset cast Items to Asset model -func (col *Collection) ToAsset() []*Asset { +func (col *Collection) ToAsset() ([]*Asset, error) { var assets []*Asset - byteArray, _ := json.Marshal(col.Items) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&assets) + byteArray, err := json.Marshal(col.Items) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&assets); err != nil { + return nil, err + } - return assets + return assets, nil } // ToAPIKey cast Items to APIKey model -func (col *Collection) ToAPIKey() []*APIKey { +func (col *Collection) ToAPIKey() ([]*APIKey, error) { var apiKeys []*APIKey - byteArray, _ := json.Marshal(col.Items) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&apiKeys) + byteArray, err := json.Marshal(col.Items) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&apiKeys); err != nil { + return nil, err + } - return apiKeys + return apiKeys, nil } // ToWebhook cast Items to Webhook model -func (col *Collection) ToWebhook() []*Webhook { +func (col *Collection) ToWebhook() ([]*Webhook, error) { var webhooks []*Webhook - byteArray, _ := json.Marshal(col.Items) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&webhooks) + byteArray, err := json.Marshal(col.Items) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&webhooks); err != nil { + return nil, err + } - return webhooks + return webhooks, nil } // ToIncludesEntry cast includesEntry to Entry model -func (col *Collection) ToIncludesEntry() []*Entry { +func (col *Collection) ToIncludesEntry() ([]*Entry, error) { var includesEntry []*Entry - byteArray, _ := json.Marshal(col.Includes["Entry"]) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesEntry) - return includesEntry + byteArray, err := json.Marshal(col.Includes["Entry"]) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesEntry); err != nil { + return nil, err + } + + return includesEntry, nil } // ToIncludesEntryMap returns a map of Entry's from the Includes -func (col *Collection) ToIncludesEntryMap() map[string]*Entry { +func (col *Collection) ToIncludesEntryMap() (map[string]*Entry, error) { var includesEntry []*Entry includesEntryMap := make(map[string]*Entry) - byteArray, _ := json.Marshal(col.Includes["Entry"]) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesEntry) + byteArray, err := json.Marshal(col.Includes["Entry"]) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesEntry); err != nil { + return nil, err + } + for _, e := range includesEntry { includesEntryMap[e.Sys.ID] = e } - return includesEntryMap + return includesEntryMap, nil } // ToIncludesAsset cast includesAsset to Asset model -func (col *Collection) ToIncludesAsset() []*IncludeAsset { +func (col *Collection) ToIncludesAsset() ([]*IncludeAsset, error) { var includesAsset []*IncludeAsset - byteArray, _ := json.Marshal(col.Includes["Asset"]) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesAsset) - return includesAsset + byteArray, err := json.Marshal(col.Includes["Asset"]) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesAsset); err != nil { + return nil, err + } + return includesAsset, nil } // ToIncludesAssetMap returns a map of Asset's from the Includes -func (col *Collection) ToIncludesAssetMap() map[string]*IncludeAsset { +func (col *Collection) ToIncludesAssetMap() (map[string]*IncludeAsset, error) { var includesAsset []*IncludeAsset includesAssetMap := make(map[string]*IncludeAsset) - byteArray, _ := json.Marshal(col.Includes["Asset"]) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesAsset) + byteArray, err := json.Marshal(col.Includes["Asset"]) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesAsset); err != nil { + return nil, err + } for _, a := range includesAsset { includesAssetMap[a.Sys.ID] = a } - return includesAssetMap + return includesAssetMap, nil } // ToIncludesLocalizedAssetMap returns a map of Asset's from the Includes -func (col *Collection) ToIncludesLocalizedAssetMap() map[string]*Asset { +func (col *Collection) ToIncludesLocalizedAssetMap() (map[string]*Asset, error) { var includesAsset []*Asset includesAssetMap := make(map[string]*Asset) - byteArray, _ := json.Marshal(col.Includes["Asset"]) - json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesAsset) + byteArray, err := json.Marshal(col.Includes["Asset"]) + if err != nil { + return nil, err + } + if err := json.NewDecoder(bytes.NewReader(byteArray)).Decode(&includesAsset); err != nil { + return nil, err + } for _, a := range includesAsset { includesAssetMap[a.Sys.ID] = a } - return includesAssetMap + return includesAssetMap, nil } diff --git a/collection_test.go b/collection_test.go index 85548c7..054a42f 100644 --- a/collection_test.go +++ b/collection_test.go @@ -1,6 +1,7 @@ package contentful import ( + "context" "net/http" "net/url" "os" @@ -17,7 +18,7 @@ func TestNewCollection(t *testing.T) { Filename: "error-notResolvable.json", }) - req, err := c.newRequest("GET", "/", url.Values{}, nil) + req, err := c.newRequest(context.TODO(), http.MethodGet, "/", url.Values{}, nil) if err != nil { t.Fatal(err) } @@ -48,7 +49,7 @@ func TestNewCollection(t *testing.T) { Filename: "error-nameUnknown.json", }) - req, err := c.newRequest("GET", "/", url.Values{}, nil) + req, err := c.newRequest(context.TODO(), http.MethodGet, "/", url.Values{}, nil) if err != nil { t.Fatal(err) } @@ -82,7 +83,7 @@ type roundTrip struct { func (rt roundTrip) RoundTrip(*http.Request) (*http.Response, error) { if rt.Code == 0 { - rt.Code = http.StatusOK + rt.Code = http.StatusOK //nolint:revive } f, err := os.Open("testdata/" + rt.Filename) if err != nil { diff --git a/content_type.go b/content_type.go index f91951c..e1ecb76 100644 --- a/content_type.go +++ b/content_type.go @@ -2,8 +2,10 @@ package contentful import ( "bytes" + "context" "encoding/json" "fmt" + "net/http" "strconv" ) @@ -88,7 +90,7 @@ func (field *Field) UnmarshalJSON(data []byte) error { if val, ok := payload["items"]; ok { byteArray, err := json.Marshal(val) if err != nil { - return nil + return err } var fieldTypeArrayItem FieldTypeArrayItem @@ -128,7 +130,9 @@ func (field *Field) UnmarshalJSON(data []byte) error { } // ParseValidations converts json representation to go struct -func ParseValidations(data []interface{}) (validations []FieldValidation, err error) { +func ParseValidations(data []interface{}) ([]FieldValidation, error) { + var err error + var validations []FieldValidation for _, value := range data { var validation map[string]interface{} var byteArray []byte @@ -289,11 +293,10 @@ func (ct *ContentType) GetVersion() int { } // List return a content type collection -func (service *ContentTypesService) List(spaceID string) *Collection { +func (service *ContentTypesService) List(ctx context.Context, spaceID string) *Collection { path := fmt.Sprintf("/spaces/%s%s/content_types", spaceID, getEnvPath(service.c)) - method := "GET" - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, http.MethodGet, path, nil, nil) if err != nil { return nil } @@ -306,11 +309,10 @@ func (service *ContentTypesService) List(spaceID string) *Collection { } // Get fetched a content type specified by `contentTypeID` -func (service *ContentTypesService) Get(spaceID, contentTypeID string) (*ContentType, error) { +func (service *ContentTypesService) Get(ctx context.Context, spaceID, contentTypeID string) (*ContentType, error) { path := fmt.Sprintf("/spaces/%s%s/content_types/%s", spaceID, getEnvPath(service.c), contentTypeID) - method := "GET" - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, http.MethodGet, path, nil, nil) if err != nil { return nil, err } @@ -324,7 +326,7 @@ func (service *ContentTypesService) Get(spaceID, contentTypeID string) (*Content } // Upsert updates or creates a new content type -func (service *ContentTypesService) Upsert(spaceID string, ct *ContentType) error { +func (service *ContentTypesService) Upsert(ctx context.Context, spaceID string, ct *ContentType) error { bytesArray, err := json.Marshal(ct) if err != nil { return err @@ -341,7 +343,7 @@ func (service *ContentTypesService) Upsert(spaceID string, ct *ContentType) erro method = "POST" } - req, err := service.c.newRequest(method, path, nil, bytes.NewReader(bytesArray)) + req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray)) if err != nil { return err } @@ -352,11 +354,11 @@ func (service *ContentTypesService) Upsert(spaceID string, ct *ContentType) erro } // Delete the content_type -func (service *ContentTypesService) Delete(spaceID string, ct *ContentType) error { +func (service *ContentTypesService) Delete(ctx context.Context, spaceID string, ct *ContentType) error { path := fmt.Sprintf("/spaces/%s%s/content_types/%s", spaceID, getEnvPath(service.c), ct.Sys.ID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } @@ -368,11 +370,10 @@ func (service *ContentTypesService) Delete(spaceID string, ct *ContentType) erro } // Activate the contenttype, a.k.a publish -func (service *ContentTypesService) Activate(spaceID string, ct *ContentType) error { +func (service *ContentTypesService) Activate(ctx context.Context, spaceID string, ct *ContentType) error { path := fmt.Sprintf("/spaces/%s%s/content_types/%s/published", spaceID, getEnvPath(service.c), ct.Sys.ID) - method := "PUT" - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, http.MethodPut, path, nil, nil) if err != nil { return err } @@ -384,11 +385,10 @@ func (service *ContentTypesService) Activate(spaceID string, ct *ContentType) er } // Deactivate the contenttype, a.k.a unpublish -func (service *ContentTypesService) Deactivate(spaceID string, ct *ContentType) error { +func (service *ContentTypesService) Deactivate(ctx context.Context, spaceID string, ct *ContentType) error { path := fmt.Sprintf("/spaces/%s%s/content_types/%s/published", spaceID, getEnvPath(service.c), ct.Sys.ID) - method := "DELETE" - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, http.MethodDelete, path, nil, nil) if err != nil { return err } diff --git a/content_type_field_validations.go b/content_type_field_validations.go index de96292..b051878 100644 --- a/content_type_field_validations.go +++ b/content_type_field_validations.go @@ -234,8 +234,8 @@ const ( // FieldValidationRegexPatternUSDate us date validation FieldValidationRegexPatternUSDate = `^(0?[1-9]|[12][0-9]|3[01])[- \/.](0?[1-9]|1[012])[- \/.](19|20)?\d\d$` - // FieldValidationRegexPatternEuorpeanDate euorpean date validation - FieldValidationRegexPatternEuorpeanDate = `^(0?[1-9]|[12][0-9]|3[01])[- \/.](0?[1-9]|1[012])[- \/.](19|20)?\d\d$` + // FieldValidationRegexPatternEuropeanDate european date validation + FieldValidationRegexPatternEuropeanDate = `^(0?[1-9]|[12][0-9]|3[01])[- \/.](0?[1-9]|1[012])[- \/.](19|20)?\d\d$` // FieldValidationRegexPattern12HourTime 12-hour time validation FieldValidationRegexPattern12HourTime = `^(0?[1-9]|1[012]):[0-5][0-9](:[0-5][0-9])?\s*[aApP][mM]$` diff --git a/content_type_field_validations_test.go b/content_type_field_validations_test.go index b1ed406..7437bc6 100644 --- a/content_type_field_validations_test.go +++ b/content_type_field_validations_test.go @@ -7,37 +7,35 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestFieldValidationLink(t *testing.T) { var err error - assert := assert.New(t) validation := &FieldValidationLink{ LinkContentType: []string{"test", "test2"}, } data, err := json.Marshal(validation) - assert.Nil(err) - assert.Equal("{\"linkContentType\":[\"test\",\"test2\"]}", string(data)) + require.NoError(t, err) + assert.Equal(t, "{\"linkContentType\":[\"test\",\"test2\"]}", string(data)) } func TestFieldValidationUnique(t *testing.T) { var err error - assert := assert.New(t) validation := &FieldValidationUnique{ Unique: false, } data, err := json.Marshal(validation) - assert.Nil(err) - assert.Equal("{\"unique\":false}", string(data)) + require.NoError(t, err) + assert.Equal(t, "{\"unique\":false}", string(data)) } func TestFieldValidationPredefinedValues(t *testing.T) { var err error - assert := assert.New(t) validation := &FieldValidationPredefinedValues{ In: []interface{}{5, 10, "string", 6.4}, @@ -45,13 +43,12 @@ func TestFieldValidationPredefinedValues(t *testing.T) { } data, err := json.Marshal(validation) - assert.Nil(err) - assert.Equal("{\"in\":[5,10,\"string\",6.4],\"message\":\"error message\"}", string(data)) + require.NoError(t, err) + assert.Equal(t, "{\"in\":[5,10,\"string\",6.4],\"message\":\"error message\"}", string(data)) } func TestFieldValidationRange(t *testing.T) { var err error - assert := assert.New(t) // between validation := &FieldValidationRange{ @@ -62,15 +59,15 @@ func TestFieldValidationRange(t *testing.T) { ErrorMessage: "error message", } data, err := json.Marshal(validation) - assert.Nil(err) - assert.Equal("{\"range\":{\"min\":60,\"max\":100},\"message\":\"error message\"}", string(data)) + require.NoError(t, err) + assert.Equal(t, "{\"range\":{\"min\":60,\"max\":100},\"message\":\"error message\"}", string(data)) var validationCheck FieldValidationRange err = json.NewDecoder(bytes.NewReader(data)).Decode(&validationCheck) - assert.Nil(err) - assert.Equal(float64(60), validationCheck.Range.Min) - assert.Equal(float64(100), validationCheck.Range.Max) - assert.Equal("error message", validationCheck.ErrorMessage) + require.NoError(t, err) + assert.Equal(t, float64(60), validationCheck.Range.Min) + assert.Equal(t, float64(100), validationCheck.Range.Max) + assert.Equal(t, "error message", validationCheck.ErrorMessage) // greater than equal to validation = &FieldValidationRange{ @@ -80,14 +77,14 @@ func TestFieldValidationRange(t *testing.T) { ErrorMessage: "error message", } data, err = json.Marshal(validation) - assert.Nil(err) - assert.Equal("{\"range\":{\"min\":10},\"message\":\"error message\"}", string(data)) + require.NoError(t, err) + assert.Equal(t, "{\"range\":{\"min\":10},\"message\":\"error message\"}", string(data)) validationCheck = FieldValidationRange{} err = json.NewDecoder(bytes.NewReader(data)).Decode(&validationCheck) - assert.Nil(err) - assert.Equal(float64(10), validationCheck.Range.Min) - assert.Equal(float64(0), validationCheck.Range.Max) - assert.Equal("error message", validationCheck.ErrorMessage) + require.NoError(t, err) + assert.Equal(t, float64(10), validationCheck.Range.Min) + assert.Equal(t, float64(0), validationCheck.Range.Max) + assert.Equal(t, "error message", validationCheck.ErrorMessage) // less than equal to validation = &FieldValidationRange{ @@ -97,19 +94,18 @@ func TestFieldValidationRange(t *testing.T) { ErrorMessage: "error message", } data, err = json.Marshal(validation) - assert.Nil(err) - assert.Equal("{\"range\":{\"max\":90},\"message\":\"error message\"}", string(data)) + require.NoError(t, err) + assert.Equal(t, "{\"range\":{\"max\":90},\"message\":\"error message\"}", string(data)) validationCheck = FieldValidationRange{} err = json.NewDecoder(bytes.NewReader(data)).Decode(&validationCheck) - assert.Nil(err) - assert.Equal(float64(90), validationCheck.Range.Max) - assert.Equal(float64(0), validationCheck.Range.Min) - assert.Equal("error message", validationCheck.ErrorMessage) + require.NoError(t, err) + assert.Equal(t, float64(90), validationCheck.Range.Max) + assert.Equal(t, float64(0), validationCheck.Range.Min) + assert.Equal(t, "error message", validationCheck.ErrorMessage) } func TestFieldValidationSize(t *testing.T) { var err error - assert := assert.New(t) // between validation := &FieldValidationSize{ @@ -120,20 +116,19 @@ func TestFieldValidationSize(t *testing.T) { ErrorMessage: "error message", } data, err := json.Marshal(validation) - assert.Nil(err) - assert.Equal("{\"size\":{\"min\":4,\"max\":6},\"message\":\"error message\"}", string(data)) + require.NoError(t, err) + assert.Equal(t, "{\"size\":{\"min\":4,\"max\":6},\"message\":\"error message\"}", string(data)) var validationCheck FieldValidationSize err = json.NewDecoder(bytes.NewReader(data)).Decode(&validationCheck) - assert.Nil(err) - assert.Equal(float64(4), validationCheck.Size.Min) - assert.Equal(float64(6), validationCheck.Size.Max) - assert.Equal("error message", validationCheck.ErrorMessage) + require.NoError(t, err) + assert.Equal(t, float64(4), validationCheck.Size.Min) + assert.Equal(t, float64(6), validationCheck.Size.Max) + assert.Equal(t, "error message", validationCheck.ErrorMessage) } func TestFieldValidationDate(t *testing.T) { var err error - assert := assert.New(t) layout := "2006-01-02T03:04:05" min := time.Now() @@ -150,13 +145,13 @@ func TestFieldValidationDate(t *testing.T) { ErrorMessage: "error message", } data, err := json.Marshal(validation) - assert.Nil(err) - assert.Equal("{\"dateRange\":{\"min\":\""+minStr+"\",\"max\":\""+maxStr+"\"},\"message\":\"error message\"}", string(data)) + require.NoError(t, err) + assert.Equal(t, "{\"dateRange\":{\"min\":\""+minStr+"\",\"max\":\""+maxStr+"\"},\"message\":\"error message\"}", string(data)) var validationCheck FieldValidationDate err = json.NewDecoder(bytes.NewReader(data)).Decode(&validationCheck) - assert.Nil(err) - assert.Equal(minStr, validationCheck.Range.Min.Format(layout)) - assert.Equal(maxStr, validationCheck.Range.Max.Format(layout)) - assert.Equal("error message", validationCheck.ErrorMessage) + require.NoError(t, err) + assert.Equal(t, minStr, validationCheck.Range.Min.Format(layout)) + assert.Equal(t, maxStr, validationCheck.Range.Max.Format(layout)) + assert.Equal(t, "error message", validationCheck.ErrorMessage) } diff --git a/content_type_test.go b/content_type_test.go index 79cedae..0f1d33e 100644 --- a/content_type_test.go +++ b/content_type_test.go @@ -1,6 +1,7 @@ package contentful import ( + "context" "encoding/json" "fmt" "log" @@ -9,14 +10,15 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func ExampleContentTypesService_Get() { cma := NewCMA("cma-token") - contentType, err := cma.ContentTypes.Get("space-id", "content-type-id") + contentType, err := cma.ContentTypes.Get(context.TODO(), "space-id", "content-type-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } fmt.Println(contentType.Name) @@ -25,12 +27,15 @@ func ExampleContentTypesService_Get() { func ExampleContentTypesService_List() { cma := NewCMA("cma-token") - collection, err := cma.ContentTypes.List("space-id").Next() + collection, err := cma.ContentTypes.List(context.TODO(), "space-id").Next() if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } - contentTypes := collection.ToContentType() + contentTypes, err := collection.ToContentType() + if err != nil { + log.Fatal(err) //nolint:revive + } for _, contentType := range contentTypes { fmt.Println(contentType.Sys.ID, contentType.Sys.PublishedAt) @@ -45,14 +50,14 @@ func ExampleContentTypesService_Upsert_create() { DisplayField: "field1_id", Description: "content type description", Fields: []*Field{ - &Field{ + { ID: "field1_id", Name: "field1", Type: "Symbol", Required: false, Disabled: false, }, - &Field{ + { ID: "field2_id", Name: "field2", Type: "Symbol", @@ -62,85 +67,88 @@ func ExampleContentTypesService_Upsert_create() { }, } - err := cma.ContentTypes.Upsert("space-id", contentType) + err := cma.ContentTypes.Upsert(context.TODO(), "space-id", contentType) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func ExampleContentTypesService_Upsert_update() { cma := NewCMA("cma-token") - contentType, err := cma.ContentTypes.Get("space-id", "content-type-id") + contentType, err := cma.ContentTypes.Get(context.TODO(), "space-id", "content-type-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } contentType.Name = "modified content type name" - err = cma.ContentTypes.Upsert("space-id", contentType) + err = cma.ContentTypes.Upsert(context.TODO(), "space-id", contentType) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func ExampleContentTypesService_Activate() { cma := NewCMA("cma-token") - contentType, err := cma.ContentTypes.Get("space-id", "content-type-id") + contentType, err := cma.ContentTypes.Get(context.TODO(), "space-id", "content-type-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } - err = cma.ContentTypes.Activate("space-id", contentType) + err = cma.ContentTypes.Activate(context.TODO(), "space-id", contentType) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func ExampleContentTypesService_Deactivate() { cma := NewCMA("cma-token") - contentType, err := cma.ContentTypes.Get("space-id", "content-type-id") + contentType, err := cma.ContentTypes.Get(context.TODO(), "space-id", "content-type-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } - err = cma.ContentTypes.Deactivate("space-id", contentType) + err = cma.ContentTypes.Deactivate(context.TODO(), "space-id", contentType) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func ExampleContentTypesService_Delete() { cma := NewCMA("cma-token") - contentType, err := cma.ContentTypes.Get("space-id", "content-type-id") + contentType, err := cma.ContentTypes.Get(context.TODO(), "space-id", "content-type-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } - err = cma.ContentTypes.Delete("space-id", contentType) + err = cma.ContentTypes.Delete(context.TODO(), "space-id", contentType) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func ExampleContentTypesService_Delete_allDrafts() { cma := NewCMA("cma-token") - collection, err := cma.ContentTypes.List("space-id").Next() + collection, err := cma.ContentTypes.List(context.TODO(), "space-id").Next() if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } - contentTypes := collection.ToContentType() + contentTypes, err := collection.ToContentType() + if err != nil { + log.Fatal(err) //nolint:revive + } for _, contentType := range contentTypes { if contentType.Sys.PublishedAt == "" { - err := cma.ContentTypes.Delete("space-id", contentType) + err := cma.ContentTypes.Delete(context.TODO(), "space-id", contentType) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } } @@ -148,16 +156,15 @@ func ExampleContentTypesService_Delete_allDrafts() { func TestContentTypesServiceList(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "GET") - assert.Equal(r.URL.Path, "/spaces/"+spaceID+"/content_types") + assert.Equal(t, http.MethodGet, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types", r.URL.Path) - checkHeaders(r, assert) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, readTestData("content_types.json")) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "content_types.json")) }) // test server @@ -168,22 +175,21 @@ func TestContentTypesServiceList(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - _, err = cma.ContentTypes.List(spaceID).Next() - assert.Nil(err) + _, err = cma.ContentTypes.List(context.TODO(), spaceID).Next() + require.NoError(t, err) } func TestContentTypesServiceActivate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "PUT") - assert.Equal(r.URL.Path, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6/published") + assert.Equal(t, http.MethodPut, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6/published", r.URL.Path) - checkHeaders(r, assert) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, readTestData("content_type.json")) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type.json")) }) // test server @@ -195,25 +201,24 @@ func TestContentTypesServiceActivate(t *testing.T) { cma.BaseURL = server.URL // test content type - ct, err := contentTypeFromTestData("content_type.json") - assert.Nil(err) + ct, err := contentTypeFromTestData(t, "content_type.json") + require.NoError(t, err) - err = cma.ContentTypes.Activate(spaceID, ct) - assert.Nil(err) + err = cma.ContentTypes.Activate(context.TODO(), spaceID, ct) + require.NoError(t, err) } func TestContentTypesServiceDeactivate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "DELETE") - assert.Equal(r.URL.Path, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6/published") + assert.Equal(t, http.MethodDelete, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6/published", r.URL.Path) - checkHeaders(r, assert) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, readTestData("content_type.json")) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type.json")) }) // test server @@ -225,47 +230,46 @@ func TestContentTypesServiceDeactivate(t *testing.T) { cma.BaseURL = server.URL // test content type - ct, err := contentTypeFromTestData("content_type.json") - assert.Nil(err) + ct, err := contentTypeFromTestData(t, "content_type.json") + require.NoError(t, err) - err = cma.ContentTypes.Deactivate(spaceID, ct) - assert.Nil(err) + err = cma.ContentTypes.Deactivate(context.TODO(), spaceID, ct) + require.NoError(t, err) } func TestContentTypeSaveForCreate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/content_types") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) - assert.Equal("ct-name", payload["name"]) - assert.Equal("ct-description", payload["description"]) + require.NoError(t, err) + assert.Equal(t, "ct-name", payload["name"]) + assert.Equal(t, "ct-description", payload["description"]) fields := payload["fields"].([]interface{}) - assert.Equal(2, len(fields)) + assert.Len(t, fields, 2) field1 := fields[0].(map[string]interface{}) field2 := fields[1].(map[string]interface{}) - assert.Equal("field1", field1["id"].(string)) - assert.Equal("field1-name", field1["name"].(string)) - assert.Equal("Symbol", field1["type"].(string)) + assert.Equal(t, "field1", field1["id"].(string)) + assert.Equal(t, "field1-name", field1["name"].(string)) + assert.Equal(t, "Symbol", field1["type"].(string)) - assert.Equal("field2", field2["id"].(string)) - assert.Equal("field2-name", field2["name"].(string)) - assert.Equal("Symbol", field2["type"].(string)) - assert.Equal(true, field2["disabled"].(bool)) + assert.Equal(t, "field2", field2["id"].(string)) + assert.Equal(t, "field2-name", field2["name"].(string)) + assert.Equal(t, "Symbol", field2["type"].(string)) + assert.True(t, field2["disabled"].(bool)) - assert.Equal(field1["id"].(string), payload["displayField"]) + assert.Equal(t, field1["id"].(string), payload["displayField"]) - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("content_type.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type.json")) }) // test server @@ -297,52 +301,51 @@ func TestContentTypeSaveForCreate(t *testing.T) { DisplayField: field1.ID, } - err = cma.ContentTypes.Upsert("id1", ct) - assert.Nil(err) - assert.Equal("63Vgs0BFK0USe4i2mQUGK6", ct.Sys.ID) - assert.Equal("ct-name", ct.Name) - assert.Equal("ct-description", ct.Description) + err = cma.ContentTypes.Upsert(context.TODO(), "id1", ct) + require.NoError(t, err) + assert.Equal(t, "63Vgs0BFK0USe4i2mQUGK6", ct.Sys.ID) + assert.Equal(t, "ct-name", ct.Name) + assert.Equal(t, "ct-description", ct.Description) } func TestContentTypeSaveForUpdate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "PUT") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPut, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) - assert.Equal("ct-name-updated", payload["name"]) - assert.Equal("ct-description-updated", payload["description"]) + require.NoError(t, err) + assert.Equal(t, "ct-name-updated", payload["name"]) + assert.Equal(t, "ct-description-updated", payload["description"]) fields := payload["fields"].([]interface{}) - assert.Equal(3, len(fields)) + assert.Len(t, fields, 3) field1 := fields[0].(map[string]interface{}) field2 := fields[1].(map[string]interface{}) field3 := fields[2].(map[string]interface{}) - assert.Equal("field1", field1["id"].(string)) - assert.Equal("field1-name-updated", field1["name"].(string)) - assert.Equal("String", field1["type"].(string)) + assert.Equal(t, "field1", field1["id"].(string)) + assert.Equal(t, "field1-name-updated", field1["name"].(string)) + assert.Equal(t, "String", field1["type"].(string)) - assert.Equal("field2", field2["id"].(string)) - assert.Equal("field2-name-updated", field2["name"].(string)) - assert.Equal("Integer", field2["type"].(string)) - assert.Nil(field2["disabled"]) + assert.Equal(t, "field2", field2["id"].(string)) + assert.Equal(t, "field2-name-updated", field2["name"].(string)) + assert.Equal(t, "Integer", field2["type"].(string)) + assert.Nil(t, field2["disabled"]) - assert.Equal("field3", field3["id"].(string)) - assert.Equal("field3-name", field3["name"].(string)) - assert.Equal("Date", field3["type"].(string)) + assert.Equal(t, "field3", field3["id"].(string)) + assert.Equal(t, "field3-name", field3["name"].(string)) + assert.Equal(t, "Date", field3["type"].(string)) - assert.Equal(field3["id"].(string), payload["displayField"]) + assert.Equal(t, field3["id"].(string), payload["displayField"]) - w.WriteHeader(200) - fmt.Fprintln(w, string(readTestData("content_type-updated.json"))) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type-updated.json")) }) // test server @@ -354,8 +357,8 @@ func TestContentTypeSaveForUpdate(t *testing.T) { cma.BaseURL = server.URL // test content type - ct, err := contentTypeFromTestData("content_type.json") - assert.Nil(err) + ct, err := contentTypeFromTestData(t, "content_type.json") + require.NoError(t, err) ct.Name = "ct-name-updated" ct.Description = "ct-description-updated" @@ -379,25 +382,24 @@ func TestContentTypeSaveForUpdate(t *testing.T) { ct.Fields = append(ct.Fields, field3) ct.DisplayField = ct.Fields[2].ID - cma.ContentTypes.Upsert("id1", ct) - assert.Nil(err) - assert.Equal("63Vgs0BFK0USe4i2mQUGK6", ct.Sys.ID) - assert.Equal("ct-name-updated", ct.Name) - assert.Equal("ct-description-updated", ct.Description) - assert.Equal(2, ct.Sys.Version) + err = cma.ContentTypes.Upsert(context.TODO(), "id1", ct) + require.NoError(t, err) + assert.Equal(t, "63Vgs0BFK0USe4i2mQUGK6", ct.Sys.ID) + assert.Equal(t, "ct-name-updated", ct.Name) + assert.Equal(t, "ct-description-updated", ct.Description) + assert.Equal(t, 2, ct.Sys.Version) } func TestContentTypeCreateWithoutID(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/id1/content_types") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/id1/content_types", r.RequestURI) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, string(readTestData("content_type-updated.json"))) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type-updated.json")) }) // test server @@ -414,21 +416,20 @@ func TestContentTypeCreateWithoutID(t *testing.T) { Name: "MyContentType", } - cma.ContentTypes.Upsert("id1", ct) - assert.Nil(err) + err = cma.ContentTypes.Upsert(context.TODO(), "id1", ct) + require.NoError(t, err) } func TestContentTypeCreateWithID(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "PUT") - assert.Equal(r.RequestURI, "/spaces/id1/content_types/mycontenttype") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPut, r.Method) + assert.Equal(t, "/spaces/id1/content_types/mycontenttype", r.RequestURI) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, string(readTestData("content_type-updated.json"))) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type-updated.json")) }) // test server @@ -447,20 +448,19 @@ func TestContentTypeCreateWithID(t *testing.T) { Name: "MyContentType", } - cma.ContentTypes.Upsert("id1", ct) - assert.Nil(err) + err = cma.ContentTypes.Upsert(context.TODO(), "id1", ct) + require.NoError(t, err) } func TestContentTypeDelete(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "DELETE") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6") - checkHeaders(r, assert) + assert.Equal(t, http.MethodDelete, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6", r.RequestURI) + checkHeaders(t, r) - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) }) // test server @@ -472,41 +472,40 @@ func TestContentTypeDelete(t *testing.T) { cma.BaseURL = server.URL // test content type - ct, err := contentTypeFromTestData("content_type.json") - assert.Nil(err) + ct, err := contentTypeFromTestData(t, "content_type.json") + require.NoError(t, err) // delete content type - err = cma.ContentTypes.Delete("id1", ct) - assert.Nil(err) + err = cma.ContentTypes.Delete(context.TODO(), "id1", ct) + require.NoError(t, err) } func TestContentTypeFieldRef(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/content_types") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) + require.NoError(t, err) fields := payload["fields"].([]interface{}) - assert.Equal(1, len(fields)) + assert.Len(t, fields, 1) field1 := fields[0].(map[string]interface{}) - assert.Equal("Link", field1["type"].(string)) + assert.Equal(t, "Link", field1["type"].(string)) validations := field1["validations"].([]interface{}) - assert.Equal(1, len(validations)) + assert.Len(t, validations, 1) validation := validations[0].(map[string]interface{}) linkValidationValue := validation["linkContentType"].([]interface{}) - assert.Equal(1, len(linkValidationValue)) - assert.Equal("63Vgs0BFK0USe4i2mQUGK6", linkValidationValue[0].(string)) + assert.Len(t, linkValidationValue, 1) + assert.Equal(t, "63Vgs0BFK0USe4i2mQUGK6", linkValidationValue[0].(string)) - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("content_type.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type.json")) }) // test server @@ -518,8 +517,8 @@ func TestContentTypeFieldRef(t *testing.T) { cma.BaseURL = server.URL // test content type - linkCt, err := contentTypeFromTestData("content_type.json") - assert.Nil(err) + linkCt, err := contentTypeFromTestData(t, "content_type.json") + require.NoError(t, err) field1 := &Field{ ID: "field1", @@ -539,38 +538,37 @@ func TestContentTypeFieldRef(t *testing.T) { DisplayField: field1.ID, } - err = cma.ContentTypes.Upsert("id1", ct) - assert.Nil(err) + err = cma.ContentTypes.Upsert(context.TODO(), "id1", ct) + require.NoError(t, err) } func TestContentTypeFieldArray(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/content_types") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) + require.NoError(t, err) fields := payload["fields"].([]interface{}) - assert.Equal(1, len(fields)) + assert.Len(t, fields, 1) field1 := fields[0].(map[string]interface{}) - assert.Equal("Array", field1["type"].(string)) + assert.Equal(t, "Array", field1["type"].(string)) arrayItemSchema := field1["items"].(map[string]interface{}) - assert.Equal("Text", arrayItemSchema["type"].(string)) + assert.Equal(t, "Text", arrayItemSchema["type"].(string)) arrayItemSchemaValidations := arrayItemSchema["validations"].([]interface{}) validation1 := arrayItemSchemaValidations[0].(map[string]interface{}) - assert.Equal(true, validation1["unique"].(bool)) + assert.True(t, validation1["unique"].(bool)) - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("content_type.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type.json")) }) // test server @@ -602,54 +600,53 @@ func TestContentTypeFieldArray(t *testing.T) { DisplayField: field1.ID, } - err = cma.ContentTypes.Upsert("id1", ct) - assert.Nil(err) + err = cma.ContentTypes.Upsert(context.TODO(), "id1", ct) + require.NoError(t, err) } func TestContentTypeFieldValidationRangeUniquePredefinedValues(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/content_types") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) + require.NoError(t, err) fields := payload["fields"].([]interface{}) - assert.Equal(1, len(fields)) + assert.Len(t, fields, 1) field1 := fields[0].(map[string]interface{}) - assert.Equal("Integer", field1["type"].(string)) + assert.Equal(t, "Integer", field1["type"].(string)) validations := field1["validations"].([]interface{}) // unique validation validationUnique := validations[0].(map[string]interface{}) - assert.Equal(false, validationUnique["unique"].(bool)) + assert.False(t, validationUnique["unique"].(bool)) // range validation validationRange := validations[1].(map[string]interface{}) rangeValues := validationRange["range"].(map[string]interface{}) errorMessage := validationRange["message"].(string) - assert.Equal("error message", errorMessage) - assert.Equal(float64(20), rangeValues["min"].(float64)) - assert.Equal(float64(30), rangeValues["max"].(float64)) + assert.Equal(t, "error message", errorMessage) + assert.Equal(t, float64(20), rangeValues["min"].(float64)) + assert.Equal(t, float64(30), rangeValues["max"].(float64)) // predefined validation validationPredefinedValues := validations[2].(map[string]interface{}) predefinedValues := validationPredefinedValues["in"].([]interface{}) - assert.Equal(3, len(predefinedValues)) - assert.Equal("error message 2", validationPredefinedValues["message"].(string)) - assert.Equal(float64(20), predefinedValues[0].(float64)) - assert.Equal(float64(21), predefinedValues[1].(float64)) - assert.Equal(float64(22), predefinedValues[2].(float64)) + assert.Len(t, predefinedValues, 3) + assert.Equal(t, "error message 2", validationPredefinedValues["message"].(string)) + assert.Equal(t, float64(20), predefinedValues[0].(float64)) + assert.Equal(t, float64(21), predefinedValues[1].(float64)) + assert.Equal(t, float64(22), predefinedValues[2].(float64)) - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("content_type.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type.json")) }) // test server @@ -689,41 +686,40 @@ func TestContentTypeFieldValidationRangeUniquePredefinedValues(t *testing.T) { DisplayField: field1.ID, } - err = cma.ContentTypes.Upsert("id1", ct) - assert.Nil(err) + err = cma.ContentTypes.Upsert(context.TODO(), "id1", ct) + require.NoError(t, err) } func TestContentTypeFieldTypeMedia(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/content_types") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/content_types", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) + require.NoError(t, err) fields := payload["fields"].([]interface{}) - assert.Equal(1, len(fields)) + assert.Len(t, fields, 1) field1 := fields[0].(map[string]interface{}) - assert.Equal("Link", field1["type"].(string)) - assert.Equal("Asset", field1["linkType"].(string)) + assert.Equal(t, "Link", field1["type"].(string)) + assert.Equal(t, "Asset", field1["linkType"].(string)) validations := field1["validations"].([]interface{}) // mime type validation validationMimeType := validations[0].(map[string]interface{}) linkMimetypeGroup := validationMimeType["linkMimetypeGroup"].([]interface{}) - assert.Equal(12, len(linkMimetypeGroup)) - mimetypes := []string{} + assert.Len(t, linkMimetypeGroup, 12) + var mimetypes []string for _, mimetype := range linkMimetypeGroup { mimetypes = append(mimetypes, mimetype.(string)) } - assert.Equal(mimetypes, []string{ + assert.Equal(t, []string{ MimeTypeAttachment, MimeTypePlainText, MimeTypeImage, @@ -736,7 +732,7 @@ func TestContentTypeFieldTypeMedia(t *testing.T) { MimeTypeArchive, MimeTypeCode, MimeTypeMarkup, - }) + }, mimetypes) // dimension validation validationDimension := validations[1].(map[string]interface{}) @@ -748,25 +744,25 @@ func TestContentTypeFieldTypeMedia(t *testing.T) { heightMax := int(heightData["max"].(float64)) _, ok := widthData["max"].(float64) - assert.False(ok) + assert.False(t, ok) _, ok = heightData["min"].(float64) - assert.False(ok) + assert.False(t, ok) - assert.Equal("custom error message", errorMessage) - assert.Equal(100, widthMin) - assert.Equal(300, heightMax) + assert.Equal(t, "custom error message", errorMessage) + assert.Equal(t, 100, widthMin) + assert.Equal(t, 300, heightMax) // size validation validationSize := validations[2].(map[string]interface{}) sizeData := validationSize["assetFileSize"].(map[string]interface{}) min := int(sizeData["min"].(float64)) max := int(sizeData["max"].(float64)) - assert.Equal(30, min) - assert.Equal(400, max) + assert.Equal(t, 30, min) + assert.Equal(t, 400, max) - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("content_type.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type.json")) }) // test server @@ -824,17 +820,16 @@ func TestContentTypeFieldTypeMedia(t *testing.T) { DisplayField: field1.ID, } - err = cma.ContentTypes.Upsert("id1", ct) - assert.Nil(err) + err = cma.ContentTypes.Upsert(context.TODO(), "id1", ct) + require.NoError(t, err) } func TestContentTypeFieldValidationsUnmarshal(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("content_type_with_validations.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "content_type_with_validations.json")) }) server := httptest.NewServer(handler) @@ -843,8 +838,8 @@ func TestContentTypeFieldValidationsUnmarshal(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - ct, err := cma.ContentTypes.Get(spaceID, "validationsTest") - assert.Nil(err) + ct, err := cma.ContentTypes.Get(context.TODO(), spaceID, "validationsTest") + require.NoError(t, err) uniqueValidations := []FieldValidation{} linkValidations := []FieldValidation{} @@ -859,7 +854,7 @@ func TestContentTypeFieldValidationsUnmarshal(t *testing.T) { for _, field := range ct.Fields { if field.Name == "text-short" { - assert.Equal(4, len(field.Validations)) + assert.Len(t, field.Validations, 4) uniqueValidations = append(uniqueValidations, field.Validations[0]) sizeValidations = append(sizeValidations, field.Validations[1]) regexValidations = append(regexValidations, field.Validations[2]) @@ -867,38 +862,38 @@ func TestContentTypeFieldValidationsUnmarshal(t *testing.T) { } if field.Name == "text-long" { - assert.Equal(3, len(field.Validations)) + assert.Len(t, field.Validations, 3) sizeValidations = append(sizeValidations, field.Validations[0]) regexValidations = append(regexValidations, field.Validations[1]) preDefinedValidations = append(preDefinedValidations, field.Validations[2]) } if field.Name == "number-integer" || field.Name == "number-decimal" { - assert.Equal(3, len(field.Validations)) + assert.Len(t, field.Validations, 3) uniqueValidations = append(uniqueValidations, field.Validations[0]) rangeValidations = append(rangeValidations, field.Validations[1]) preDefinedValidations = append(preDefinedValidations, field.Validations[2]) } if field.Name == "date" { - assert.Equal(1, len(field.Validations)) + assert.Len(t, field.Validations, 1) dateValidations = append(dateValidations, field.Validations[0]) } if field.Name == "location" || field.Name == "bool" { - assert.Equal(0, len(field.Validations)) + assert.Empty(t, field.Validations) } if field.Name == "media-onefile" { - assert.Equal(3, len(field.Validations)) + assert.Len(t, field.Validations, 3) mimeTypeValidations = append(mimeTypeValidations, field.Validations[0]) dimensionValidations = append(dimensionValidations, field.Validations[1]) fileSizeValidations = append(fileSizeValidations, field.Validations[2]) } if field.Name == "media-manyfiles" { - assert.Equal(1, len(field.Validations)) - assert.Equal(3, len(field.Items.Validations)) + assert.Len(t, field.Validations, 1) + assert.Len(t, field.Items.Validations, 3) sizeValidations = append(sizeValidations, field.Validations[0]) mimeTypeValidations = append(mimeTypeValidations, field.Items.Validations[0]) dimensionValidations = append(dimensionValidations, field.Items.Validations[1]) @@ -906,18 +901,18 @@ func TestContentTypeFieldValidationsUnmarshal(t *testing.T) { } if field.Name == "json" { - assert.Equal(1, len(field.Validations)) + assert.Len(t, field.Validations, 1) sizeValidations = append(sizeValidations, field.Validations[0]) } if field.Name == "ref-onref" { - assert.Equal(1, len(field.Validations)) + assert.Len(t, field.Validations, 1) linkValidations = append(linkValidations, field.Validations[0]) } if field.Name == "ref-manyRefs" { - assert.Equal(1, len(field.Validations)) - assert.Equal(1, len(field.Items.Validations)) + assert.Len(t, field.Validations, 1) + assert.Len(t, field.Items.Validations, 1) linkValidations = append(linkValidations, field.Items.Validations[0]) sizeValidations = append(sizeValidations, field.Validations[0]) } @@ -925,51 +920,51 @@ func TestContentTypeFieldValidationsUnmarshal(t *testing.T) { for _, validation := range uniqueValidations { _, ok := validation.(FieldValidationUnique) - assert.True(ok) + assert.True(t, ok) } for _, validation := range linkValidations { _, ok := validation.(FieldValidationLink) - assert.True(ok) + assert.True(t, ok) } for _, validation := range sizeValidations { _, ok := validation.(FieldValidationSize) - assert.True(ok) + assert.True(t, ok) } for _, validation := range regexValidations { _, ok := validation.(FieldValidationRegex) - assert.True(ok) + assert.True(t, ok) } for _, validation := range preDefinedValidations { _, ok := validation.(FieldValidationPredefinedValues) - assert.True(ok) + assert.True(t, ok) } for _, validation := range rangeValidations { _, ok := validation.(FieldValidationRange) - assert.True(ok) + assert.True(t, ok) } for _, validation := range dateValidations { _, ok := validation.(FieldValidationDate) - assert.True(ok) + assert.True(t, ok) } for _, validation := range mimeTypeValidations { _, ok := validation.(FieldValidationMimeType) - assert.True(ok) + assert.True(t, ok) } for _, validation := range dimensionValidations { _, ok := validation.(FieldValidationDimension) - assert.True(ok) + assert.True(t, ok) } for _, validation := range fileSizeValidations { _, ok := validation.(FieldValidationFileSize) - assert.True(ok) + assert.True(t, ok) } } diff --git a/contentful.go b/contentful.go index 9792b36..d8a6be0 100644 --- a/contentful.go +++ b/contentful.go @@ -1,10 +1,11 @@ package contentful import ( + "context" "encoding/json" + "errors" "fmt" "io" - "log" "net/http" "net/http/httputil" "net/url" @@ -25,26 +26,24 @@ type Contentful struct { BaseURL string Environment string - Spaces *SpacesService - APIKeys *APIKeyService - Assets *AssetsService - ContentTypes *ContentTypesService - Entries *EntriesService - Locales *LocalesService - Webhooks *WebhooksService - ScheduledActions *ScheduledActionsService + Spaces *SpacesService + APIKeys *APIKeyService + Assets *AssetsService + ContentTypes *ContentTypesService + Entries *EntriesService + Locales *LocalesService + Webhooks *WebhooksService } type service struct { c *Contentful } -func getEnvPath(c *Contentful) (envPath string) { +func getEnvPath(c *Contentful) string { if c.Environment != "" { - envPath = fmt.Sprintf("/environments/%s", c.Environment) - return + return fmt.Sprintf("/environments/%s", c.Environment) } - return + return "" } // NewCMA returns a CMA client @@ -69,7 +68,6 @@ func NewCMA(token string) *Contentful { c.Entries = &EntriesService{c: c} c.Locales = &LocalesService{c: c} c.Webhooks = &WebhooksService{c: c} - c.ScheduledActions = &ScheduledActionsService{c: c} return c } @@ -146,12 +144,12 @@ func (c *Contentful) SetHTTPTransport(t http.RoundTripper) *Contentful { } // SetBaseURL provides an option to change the BaseURL of the client -func (c *Contentful) SetBaseURL(url string) *Contentful { - c.BaseURL = url +func (c *Contentful) SetBaseURL(baseURL string) *Contentful { + c.BaseURL = baseURL return c } -func (c *Contentful) newRequest(method, path string, query url.Values, body io.Reader) (*http.Request, error) { +func (c *Contentful) newRequest(ctx context.Context, method, path string, query url.Values, body io.Reader) (*http.Request, error) { u, err := url.Parse(c.BaseURL) if err != nil { return nil, err @@ -165,7 +163,7 @@ func (c *Contentful) newRequest(method, path string, query url.Values, body io.R u.Path = u.Path + path u.RawQuery = query.Encode() - req, err := http.NewRequest(method, u.String(), body) + req, err := http.NewRequestWithContext(ctx, method, u.String(), body) if err != nil { return nil, err } @@ -179,7 +177,7 @@ func (c *Contentful) newRequest(method, path string, query url.Values, body io.R } func (c *Contentful) do(req *http.Request, v interface{}) error { - if c.Debug == true { + if c.Debug { command, _ := http2curl.GetCurlCommand(req) fmt.Println(command) } @@ -205,7 +203,8 @@ func (c *Contentful) do(req *http.Request, v interface{}) error { apiError := c.handleError(req, res) // return apiError if it is not rate limit error - if _, ok := apiError.(RateLimitExceededError); !ok { + var rateLimitExceededError RateLimitExceededError + if !errors.As(apiError, &rateLimitExceededError) { return apiError } @@ -228,12 +227,11 @@ func (c *Contentful) do(req *http.Request, v interface{}) error { } func (c *Contentful) handleError(req *http.Request, res *http.Response) error { - if c.Debug == true { + if c.Debug { dump, err := httputil.DumpResponse(res, true) if err != nil { - log.Fatal(err) + return err } - fmt.Printf("%q", dump) } diff --git a/contentful_test.go b/contentful_test.go index 1ecc0ce..4a93835 100644 --- a/contentful_test.go +++ b/contentful_test.go @@ -2,19 +2,22 @@ package contentful import ( "bytes" + "context" "encoding/json" "fmt" - "io/ioutil" - "log" + "io" "net/http" "net/http/httptest" "net/url" + "os" "strconv" "strings" + "sync/atomic" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -28,100 +31,93 @@ var ( organizationID = "org-id" ) -func readTestData(fileName string) string { +func readTestData(t *testing.T, fileName string) string { + t.Helper() path := "testdata/" + fileName - content, err := ioutil.ReadFile(path) - if err != nil { - log.Fatal(err) - return "" - } - + content, err := os.ReadFile(path) + require.NoError(t, err) return string(content) } -func checkHeaders(req *http.Request, assert *assert.Assertions) { - assert.Equal("Bearer "+CMAToken, req.Header.Get("Authorization")) - assert.Equal("application/vnd.contentful.management.v1+json", req.Header.Get("Content-Type")) +func checkHeaders(t *testing.T, req *http.Request) { + t.Helper() + assert.Equal(t, "Bearer "+CMAToken, req.Header.Get("Authorization")) + assert.Equal(t, "application/vnd.contentful.management.v1+json", req.Header.Get("Content-Type")) } -func spaceFromTestData(fileName string) (*Space, error) { - content := readTestData(fileName) +func spaceFromTestData(t *testing.T, fileName string) (*Space, error) { + t.Helper() + content := readTestData(t, fileName) var space Space err := json.NewDecoder(strings.NewReader(content)).Decode(&space) - if err != nil { - return nil, err - } + require.NoError(t, err) return &space, nil } -func webhookFromTestData(fileName string) (*Webhook, error) { - content := readTestData(fileName) +func webhookFromTestData(t *testing.T, fileName string) (*Webhook, error) { + t.Helper() + content := readTestData(t, fileName) var webhook Webhook err := json.NewDecoder(strings.NewReader(content)).Decode(&webhook) - if err != nil { - return nil, err - } + require.NoError(t, err) return &webhook, nil } -func contentTypeFromTestData(fileName string) (*ContentType, error) { - content := readTestData(fileName) +func contentTypeFromTestData(t *testing.T, fileName string) (*ContentType, error) { + t.Helper() + content := readTestData(t, fileName) var ct ContentType err := json.NewDecoder(strings.NewReader(content)).Decode(&ct) - if err != nil { - return nil, err - } + require.NoError(t, err) return &ct, nil } -func localeFromTestData(fileName string) (*Locale, error) { - content := readTestData(fileName) +func localeFromTestData(t *testing.T, fileName string) (*Locale, error) { + t.Helper() + content := readTestData(t, fileName) var locale Locale err := json.NewDecoder(strings.NewReader(content)).Decode(&locale) - if err != nil { - return nil, err - } + require.NoError(t, err) return &locale, nil } func setup() { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fixture := strings.Replace(r.URL.Path, "/", "-", -1) + fixture := strings.ReplaceAll(r.URL.Path, "/", "-") fixture = strings.TrimLeft(fixture, "-") var path string if e := r.URL.Query().Get("error"); e != "" { path = "testdata/error-" + e + ".json" } else { - if r.Method == "GET" { + if r.Method == http.MethodGet { path = "testdata/" + fixture + ".json" } - if r.Method == "POST" { + if r.Method == http.MethodPost { path = "testdata/" + fixture + "-new.json" } - if r.Method == "PUT" { + if r.Method == http.MethodPut { path = "testdata/" + fixture + "-updated.json" } } - file, err := ioutil.ReadFile(path) + file, err := os.ReadFile(path) if err != nil { - fmt.Fprintln(w, err) + _, _ = fmt.Fprintln(w, err) return } - fmt.Fprintln(w, string(file)) - return + _, _ = fmt.Fprintln(w, string(file)) }) server = httptest.NewServer(handler) @@ -136,65 +132,53 @@ func teardown() { } func TestContentfulNewCMA(t *testing.T) { - assert := assert.New(t) - cma := NewCMA(CMAToken) - assert.IsType(Contentful{}, *cma) - assert.Equal("https://api.contentful.com", cma.BaseURL) - assert.Equal("CMA", cma.api) - assert.Equal(CMAToken, cma.token) - assert.Equal(fmt.Sprintf("Bearer %s", CMAToken), cma.Headers["Authorization"]) - assert.Equal("application/vnd.contentful.management.v1+json", cma.Headers["Content-Type"]) - assert.Equal(fmt.Sprintf("sdk contentful.go/%s", Version), cma.Headers["X-Contentful-User-Agent"]) + assert.IsType(t, Contentful{}, *cma) + assert.Equal(t, "https://api.contentful.com", cma.BaseURL) + assert.Equal(t, "CMA", cma.api) + assert.Equal(t, CMAToken, cma.token) + assert.Equal(t, fmt.Sprintf("Bearer %s", CMAToken), cma.Headers["Authorization"]) + assert.Equal(t, "application/vnd.contentful.management.v1+json", cma.Headers["Content-Type"]) + assert.Equal(t, fmt.Sprintf("sdk contentful.go/%s", Version), cma.Headers["X-Contentful-User-Agent"]) } func TestContentfulNewCDA(t *testing.T) { - assert := assert.New(t) - cda := NewCDA(CDAToken) - assert.IsType(Contentful{}, *cda) - assert.Equal("https://cdn.contentful.com", cda.BaseURL) - assert.Equal("CDA", cda.api) - assert.Equal(CDAToken, cda.token) - assert.Equal(fmt.Sprintf("Bearer %s", CDAToken), cda.Headers["Authorization"]) - assert.Equal("application/vnd.contentful.delivery.v1+json", cda.Headers["Content-Type"]) - assert.Equal(fmt.Sprintf("contentful-go/%s", Version), cda.Headers["X-Contentful-User-Agent"]) + assert.IsType(t, Contentful{}, *cda) + assert.Equal(t, "https://cdn.contentful.com", cda.BaseURL) + assert.Equal(t, "CDA", cda.api) + assert.Equal(t, CDAToken, cda.token) + assert.Equal(t, fmt.Sprintf("Bearer %s", CDAToken), cda.Headers["Authorization"]) + assert.Equal(t, "application/vnd.contentful.delivery.v1+json", cda.Headers["Content-Type"]) + assert.Equal(t, fmt.Sprintf("contentful-go/%s", Version), cda.Headers["X-Contentful-User-Agent"]) } func TestContentfulNewCPA(t *testing.T) { - assert := assert.New(t) - cpa := NewCPA(CPAToken) - assert.IsType(Contentful{}, *cpa) - assert.Equal("https://preview.contentful.com", cpa.BaseURL) - assert.Equal("CPA", cpa.api) - assert.Equal(CPAToken, cpa.token) + assert.IsType(t, Contentful{}, *cpa) + assert.Equal(t, "https://preview.contentful.com", cpa.BaseURL) + assert.Equal(t, "CPA", cpa.api) + assert.Equal(t, CPAToken, cpa.token) } func TestContentfulSetOrganization(t *testing.T) { - assert := assert.New(t) - cma := NewCMA(CMAToken) cma.SetOrganization(organizationID) - assert.Equal(organizationID, cma.Headers["X-Contentful-Organization"]) + assert.Equal(t, organizationID, cma.Headers["X-Contentful-Organization"]) } func TestContentfulSetClient(t *testing.T) { - assert := assert.New(t) - newClient := &http.Client{} cma := NewCMA(CMAToken) cma.SetHTTPClient(newClient) - assert.Exactly(newClient, cma.client) + assert.Exactly(t, newClient, cma.client) } func TestNewRequest(t *testing.T) { setup() defer teardown() - assert := assert.New(t) - - method := "GET" + method := http.MethodGet path := "/some/path" query := url.Values{} query.Add("foo", "bar") @@ -204,12 +188,12 @@ func TestNewRequest(t *testing.T) { expectedURL.Path = path expectedURL.RawQuery = query.Encode() - req, err := c.newRequest(method, path, query, nil) - assert.Nil(err) - assert.Equal(req.Header.Get("Authorization"), "Bearer "+CMAToken) - assert.Equal(req.Header.Get("Content-Type"), "application/vnd.contentful.management.v1+json") - assert.Equal(req.Method, method) - assert.Equal(req.URL.String(), expectedURL.String()) + req, err := c.newRequest(context.TODO(), method, path, query, nil) + require.NoError(t, err) + assert.Equal(t, "Bearer "+CMAToken, req.Header.Get("Authorization")) + assert.Equal(t, "application/vnd.contentful.management.v1+json", req.Header.Get("Content-Type")) + assert.Equal(t, req.Method, method) + assert.Equal(t, req.URL.String(), expectedURL.String()) method = "POST" type RequestBody struct { @@ -220,27 +204,26 @@ func TestNewRequest(t *testing.T) { Name: "test", Age: 10, } - body, _ := json.Marshal(bodyData) - req, err = c.newRequest(method, path, query, bytes.NewReader(body)) - assert.Nil(err) - assert.Equal(req.Header.Get("Authorization"), "Bearer "+CMAToken) - assert.Equal(req.Header.Get("Content-Type"), "application/vnd.contentful.management.v1+json") - assert.Equal(req.Method, method) - assert.Equal(req.URL.String(), expectedURL.String()) + body, err := json.Marshal(bodyData) + require.NoError(t, err) + req, err = c.newRequest(context.TODO(), method, path, query, bytes.NewReader(body)) + require.NoError(t, err) + assert.Equal(t, "Bearer "+CMAToken, req.Header.Get("Authorization")) + assert.Equal(t, "application/vnd.contentful.management.v1+json", req.Header.Get("Content-Type")) + assert.Equal(t, req.Method, method) + assert.Equal(t, req.URL.String(), expectedURL.String()) defer req.Body.Close() var requestBody RequestBody err = json.NewDecoder(req.Body).Decode(&requestBody) - assert.Nil(err) - assert.Equal(requestBody, bodyData) + require.NoError(t, err) + assert.Equal(t, requestBody, bodyData) } func TestHandleError(t *testing.T) { setup() defer teardown() - assert := assert.New(t) - - method := "GET" + method := http.MethodGet path := "/some/path" requestID := "request-id" query := url.Values{} @@ -253,11 +236,13 @@ func TestHandleError(t *testing.T) { RequestID: requestID, } - marshaled, _ := json.Marshal(errResponse) + marshaled, err := json.Marshal(errResponse) + require.NoError(t, err) errResponseReader := bytes.NewReader(marshaled) - errResponseReadCloser := ioutil.NopCloser(errResponseReader) + errResponseReadCloser := io.NopCloser(errResponseReader) - req, _ := c.newRequest(method, path, query, nil) + req, err := c.newRequest(context.TODO(), method, path, query, nil) + require.NoError(t, err) responseHeaders := http.Header{} responseHeaders.Add("X-Contentful-Request-Id", requestID) res := &http.Response{ @@ -267,21 +252,20 @@ func TestHandleError(t *testing.T) { Request: req, } - err := c.handleError(req, res) - assert.IsType(AccessTokenInvalidError{}, err) - assert.Equal(req, err.(AccessTokenInvalidError).APIError.req) - assert.Equal(res, err.(AccessTokenInvalidError).APIError.res) - assert.Equal(&errResponse, err.(AccessTokenInvalidError).APIError.err) + err = c.handleError(req, res) + assert.IsType(t, AccessTokenInvalidError{}, err) + assert.Equal(t, req, err.(AccessTokenInvalidError).APIError.req) //nolint:errorlint + assert.Equal(t, res, err.(AccessTokenInvalidError).APIError.res) //nolint:errorlint + assert.Equal(t, &errResponse, err.(AccessTokenInvalidError).APIError.err) //nolint:errorlint } func TestBackoffForPerSecondLimiting(t *testing.T) { var err error - assert := assert.New(t) - rateLimited := true + var backoff atomic.Bool waitSeconds := 2 handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if rateLimited == true { + if backoff.Load() { w.Header().Set("X-Contentful-Request-Id", "request-id") w.Header().Set("Content-Type", "application/vnd.contentful.management.v1+json") w.Header().Set("X-Contentful-Ratelimit-Hour-Limit", "36000") @@ -289,11 +273,11 @@ func TestBackoffForPerSecondLimiting(t *testing.T) { w.Header().Set("X-Contentful-Ratelimit-Reset", strconv.Itoa(waitSeconds)) w.Header().Set("X-Contentful-Ratelimit-Second-Limit", "10") w.Header().Set("X-Contentful-Ratelimit-Second-Remaining", "0") - w.WriteHeader(429) + w.WriteHeader(http.StatusTooManyRequests) - w.Write([]byte(readTestData("error-ratelimit.json"))) + _, _ = w.Write([]byte(readTestData(t, "error-ratelimit.json"))) } else { - w.Write([]byte(readTestData("space-1.json"))) + _, _ = w.Write([]byte(readTestData(t, "space-1.json"))) } }) @@ -307,11 +291,11 @@ func TestBackoffForPerSecondLimiting(t *testing.T) { go func() { time.Sleep(time.Second * time.Duration(waitSeconds)) - rateLimited = false + backoff.Store(true) }() - space, err := cma.Spaces.Get("id1") - assert.Nil(err) - assert.Equal(space.Name, "Contentful Example API") - assert.Equal(space.Sys.ID, "id1") + space, err := cma.Spaces.Get(context.TODO(), "id1") + require.NoError(t, err) + assert.Equal(t, "Contentful Example API", space.Name) + assert.Equal(t, "id1", space.Sys.ID) } diff --git a/entry.go b/entry.go index 64780e2..8731645 100644 --- a/entry.go +++ b/entry.go @@ -2,8 +2,10 @@ package contentful import ( "bytes" + "context" "encoding/json" "fmt" + "net/http" "net/url" "strconv" ) @@ -11,9 +13,8 @@ import ( // EntriesService servıce type EntriesService service -//Entry model +// Entry model type Entry struct { - locale string Sys *Sys `json:"sys"` Fields map[string]interface{} `json:"fields,omitempty"` } @@ -29,17 +30,22 @@ func (entry *Entry) GetVersion() int { } // GetEntryKey returns the entry's keys -func (service *EntriesService) GetEntryKey(entry *Entry, key string) (*EntryField, error) { +func (service *EntriesService) GetEntryKey(ctx context.Context, entry *Entry, key string) (*EntryField, error) { ef := EntryField{ value: entry.Fields[key], } - col, err := service.c.ContentTypes.List(entry.Sys.Space.Sys.ID).Next() + col, err := service.c.ContentTypes.List(ctx, entry.Sys.Space.Sys.ID).Next() if err != nil { return nil, err } - for _, ct := range col.ToContentType() { + cts, err := col.ToContentType() + if err != nil { + return nil, err + } + + for _, ct := range cts { if ct.Sys.ID != entry.Sys.ContentType.Sys.ID { continue } @@ -57,11 +63,11 @@ func (service *EntriesService) GetEntryKey(entry *Entry, key string) (*EntryFiel } // List returns entries collection -func (service *EntriesService) List(spaceID string) *Collection { +func (service *EntriesService) List(ctx context.Context, spaceID string) *Collection { path := fmt.Sprintf("/spaces/%s%s/entries", spaceID, getEnvPath(service.c)) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return &Collection{} } @@ -74,17 +80,17 @@ func (service *EntriesService) List(spaceID string) *Collection { } // Sync returns entries collection -func (service *EntriesService) Sync(spaceID string, initial bool, syncToken ...string) *Collection { +func (service *EntriesService) Sync(ctx context.Context, spaceID string, initial bool, syncToken ...string) *Collection { path := fmt.Sprintf("/spaces/%s%s/sync", spaceID, getEnvPath(service.c)) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return &Collection{} } col := NewCollection(&CollectionOptions{}) - if initial == true { + if initial { col.Query.Initial("true") } if len(syncToken) == 1 { @@ -97,15 +103,15 @@ func (service *EntriesService) Sync(spaceID string, initial bool, syncToken ...s } // Get returns a single entry -func (service *EntriesService) Get(spaceID, entryID string, locale ...string) (*Entry, error) { +func (service *EntriesService) Get(ctx context.Context, spaceID, entryID string, locale ...string) (*Entry, error) { path := fmt.Sprintf("/spaces/%s%s/entries/%s", spaceID, getEnvPath(service.c), entryID) query := url.Values{} if len(locale) > 0 { query["locale"] = locale } - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, query, nil) + req, err := service.c.newRequest(ctx, method, path, query, nil) if err != nil { return &Entry{}, err } @@ -119,11 +125,11 @@ func (service *EntriesService) Get(spaceID, entryID string, locale ...string) (* } // Delete the entry -func (service *EntriesService) Delete(spaceID string, entryID string) error { +func (service *EntriesService) Delete(ctx context.Context, spaceID string, entryID string) error { path := fmt.Sprintf("/spaces/%s%s/entries/%s", spaceID, getEnvPath(service.c), entryID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } @@ -132,7 +138,7 @@ func (service *EntriesService) Delete(spaceID string, entryID string) error { } // Upsert updates or creates a new entry -func (service *EntriesService) Upsert(spaceID string, entry *Entry) error { +func (service *EntriesService) Upsert(ctx context.Context, spaceID string, entry *Entry) error { fieldsOnly := map[string]interface{}{ "fields": entry.Fields, } @@ -158,7 +164,7 @@ func (service *EntriesService) Upsert(spaceID string, entry *Entry) error { method = "POST" } - req, err := service.c.newRequest(method, path, nil, bytes.NewReader(bytesArray)) + req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray)) if err != nil { return err } @@ -170,11 +176,11 @@ func (service *EntriesService) Upsert(spaceID string, entry *Entry) error { } // Publish the entry -func (service *EntriesService) Publish(spaceID string, entry *Entry) error { +func (service *EntriesService) Publish(ctx context.Context, spaceID string, entry *Entry) error { path := fmt.Sprintf("/spaces/%s%s/entries/%s/published", spaceID, getEnvPath(service.c), entry.Sys.ID) - method := "PUT" + method := http.MethodPut - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } @@ -186,11 +192,11 @@ func (service *EntriesService) Publish(spaceID string, entry *Entry) error { } // Unpublish the entry -func (service *EntriesService) Unpublish(spaceID string, entry *Entry) error { +func (service *EntriesService) Unpublish(ctx context.Context, spaceID string, entry *Entry) error { path := fmt.Sprintf("/spaces/%s%s/entries/%s/published", spaceID, getEnvPath(service.c), entry.Sys.ID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } @@ -202,11 +208,11 @@ func (service *EntriesService) Unpublish(spaceID string, entry *Entry) error { } // Publish the entry -func (service *EntriesService) Archive(spaceID string, entry *Entry) error { +func (service *EntriesService) Archive(ctx context.Context, spaceID string, entry *Entry) error { path := fmt.Sprintf("/spaces/%s%s/entries/%s/archived", spaceID, getEnvPath(service.c), entry.Sys.ID) - method := "PUT" + method := http.MethodPut - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } diff --git a/entry_field.go b/entry_field.go index 3a94653..32440f5 100644 --- a/entry_field.go +++ b/entry_field.go @@ -13,7 +13,7 @@ func (ef *EntryField) String() string { return ef.value.(string) } -//LString returns the given lovale +// LString returns the given lovale func (ef *EntryField) LString(locale string) string { m := ef.value.(map[string]interface{}) @@ -24,12 +24,12 @@ func (ef *EntryField) LString(locale string) string { panic("no such a locale") } -//Integer converts interface to integer +// Integer converts interface to integer func (ef *EntryField) Integer() int { return int(ef.value.(float64)) } -//LInteger converts interface to integer +// LInteger converts interface to integer func (ef *EntryField) LInteger(locale string) int { m := ef.value.(map[string]interface{}) @@ -40,7 +40,7 @@ func (ef *EntryField) LInteger(locale string) int { panic("no such a locale") } -//Array converts interface to slice +// Array converts interface to slice func (ef *EntryField) Array() []string { res := []string{} @@ -56,7 +56,7 @@ func (ef *EntryField) Array() []string { return res } -//LArray converts interface to slice +// LArray converts interface to slice func (ef *EntryField) LArray(locale string) []string { m := ef.value.(map[string]interface{}) @@ -78,14 +78,14 @@ func (ef *EntryField) LArray(locale string) []string { panic("no such a locale") } -//LinkID returns link model +// LinkID returns link model func (ef *EntryField) LinkID() string { m := ef.value.(map[string]interface{}) sys := m["sys"].(map[string]interface{}) return sys["id"].(string) } -//LLinkID returns link model +// LLinkID returns link model func (ef *EntryField) LLinkID(locale string) string { m := ef.value.(map[string]interface{}) @@ -98,14 +98,14 @@ func (ef *EntryField) LLinkID(locale string) string { panic("no such a locale") } -//LinkType returns link model +// LinkType returns link model func (ef *EntryField) LinkType() string { m := ef.value.(map[string]interface{}) sys := m["sys"].(map[string]interface{}) return sys["linkType"].(string) } -//LLinkType returns link model +// LLinkType returns link model func (ef *EntryField) LLinkType(locale string) string { m := ef.value.(map[string]interface{}) @@ -118,7 +118,7 @@ func (ef *EntryField) LLinkType(locale string) string { panic("no such a locale") } -//Asset returns the linked asset +// Asset returns the linked asset func (ef *EntryField) Asset() *Asset { if ef.LinkType() != "Asset" { panic("you can only convert asset types") @@ -128,7 +128,7 @@ func (ef *EntryField) Asset() *Asset { return &Asset{} } -//LAsset returns the linked asset +// LAsset returns the linked asset func (ef *EntryField) LAsset(locale string) *Asset { if ef.LLinkType(locale) != "Asset" { panic("you can only convert asset types") @@ -138,7 +138,7 @@ func (ef *EntryField) LAsset(locale string) *Asset { return &Asset{} } -//Entry returns the linked entry +// Entry returns the linked entry func (ef *EntryField) Entry() *Entry { if ef.LinkType() != "Entry" { panic("you can only convert entry types") @@ -148,7 +148,7 @@ func (ef *EntryField) Entry() *Entry { return &Entry{} } -//LEntry returns the linked entry +// LEntry returns the linked entry func (ef *EntryField) LEntry(locale string) *Entry { if ef.LLinkType(locale) != "Entry" { panic("you can only convert entry types") diff --git a/entry_test.go b/entry_test.go index 73f6e52..ccf4e44 100644 --- a/entry_test.go +++ b/entry_test.go @@ -1,6 +1,7 @@ package contentful import ( + "context" "encoding/json" "fmt" "log" @@ -9,9 +10,10 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func ExampleEntryService_Upsert_create() { +func ExampleEntriesService_Upsert_create() { cma := NewCMA("cma-token") entry := &Entry{ @@ -30,51 +32,50 @@ func ExampleEntryService_Upsert_create() { }, } - err := cma.Entries.Upsert("space-id", entry) + err := cma.Entries.Upsert(context.TODO(), "space-id", entry) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } -func ExampleEntryService_Upsert_update() { +func ExampleEntriesService_Upsert_update() { cma := NewCMA("cma-token") - entry, err := cma.Entries.Get("space-id", "entry-id") + entry, err := cma.Entries.Get(context.TODO(), "space-id", "entry-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } entry.Fields["Description"] = map[string]interface{}{ "en-US": "modified entry content", } - err = cma.Entries.Upsert("space-id", entry) + err = cma.Entries.Upsert(context.TODO(), "space-id", entry) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func TestEntrySaveForCreate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/entries") - assert.Equal(r.Header["X-Contentful-Content-Type"], []string{"MyContentType"}) - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/entries", r.RequestURI) + assert.Equal(t, []string{"MyContentType"}, r.Header["X-Contentful-Content-Type"]) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) + require.NoError(t, err) - assert.NotNil(payload["fields"]) + assert.NotNil(t, payload["fields"]) fields := payload["fields"].(map[string]interface{}) - assert.Equal(fields["Description"], map[string]interface{}{"en-US": "Some test content..."}) + assert.Equal(t, map[string]interface{}{"en-US": "Some test content..."}, fields["Description"]) - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("entry_3.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "entry_3.json")) }) // test server @@ -100,50 +101,49 @@ func TestEntrySaveForCreate(t *testing.T) { }, } - err = cma.Entries.Upsert("id1", entry) - assert.Nil(err) - assert.Equal("foocat", entry.Sys.ID) + err = cma.Entries.Upsert(context.TODO(), "id1", entry) + require.NoError(t, err) + assert.Equal(t, "foocat", entry.Sys.ID) } -//func TestEntrySaveForUpdate(t *testing.T) { +// func TestEntrySaveForUpdate(t *testing.T) { // var err error -// assert := assert.New(t) // // handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(r.Method, "PUT") -// assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6") -// checkHeaders(r, assert) +// assert.Equal(t, r.Method, "PUT") +// assert.Equal(t, r.RequestURI, "/spaces/"+spaceID+"/content_types/63Vgs0BFK0USe4i2mQUGK6") +// checkHeaders(t, r) // // var payload map[string]interface{} // err := json.NewDecoder(r.Body).Decode(&payload) -// assert.Nil(err) -// assert.Equal("ct-name-updated", payload["name"]) -// assert.Equal("ct-description-updated", payload["description"]) +// require.NoError(t, err) +// assert.Equal(t, "ct-name-updated", payload["name"]) +// assert.Equal(t, "ct-description-updated", payload["description"]) // // fields := payload["fields"].([]interface{}) -// assert.Equal(3, len(fields)) +// assert.Equal(t, 3, len(fields)) // // field1 := fields[0].(map[string]interface{}) // field2 := fields[1].(map[string]interface{}) // field3 := fields[2].(map[string]interface{}) // -// assert.Equal("field1", field1["id"].(string)) -// assert.Equal("field1-name-updated", field1["name"].(string)) -// assert.Equal("String", field1["type"].(string)) +// assert.Equal(t, "field1", field1["id"].(string)) +// assert.Equal(t, "field1-name-updated", field1["name"].(string)) +// assert.Equal(t, "String", field1["type"].(string)) // -// assert.Equal("field2", field2["id"].(string)) -// assert.Equal("field2-name-updated", field2["name"].(string)) -// assert.Equal("Integer", field2["type"].(string)) +// assert.Equal(t, "field2", field2["id"].(string)) +// assert.Equal(t, "field2-name-updated", field2["name"].(string)) +// assert.Equal(t, "Integer", field2["type"].(string)) // assert.Nil(field2["disabled"]) // -// assert.Equal("field3", field3["id"].(string)) -// assert.Equal("field3-name", field3["name"].(string)) -// assert.Equal("Date", field3["type"].(string)) +// assert.Equal(t, "field3", field3["id"].(string)) +// assert.Equal(t, "field3-name", field3["name"].(string)) +// assert.Equal(t, "Date", field3["type"].(string)) // -// assert.Equal(field3["id"].(string), payload["displayField"]) +// assert.Equal(t, field3["id"].(string), payload["displayField"]) // // w.WriteHeader(200) -// fmt.Fprintln(w, string(readTestData("content_type-updated.json"))) +// _, _ = fmt.Fprintln(w, readTestData(t, "content_type-updated.json")) // }) // // // test server @@ -155,8 +155,8 @@ func TestEntrySaveForCreate(t *testing.T) { // cma.BaseURL = server.URL // // // test content type -// ct, err := contentTypeFromTestData("content_type.json") -// assert.Nil(err) +// ct, err := contentTypeFromTestData(t, "content_type.json") +// require.NoError(t, err) // // ct.Name = "ct-name-updated" // ct.Description = "ct-description-updated" @@ -181,24 +181,23 @@ func TestEntrySaveForCreate(t *testing.T) { // ct.DisplayField = ct.Fields[2].ID // // cma.ContentTypes.Upsert("id1", ct) -// assert.Nil(err) -// assert.Equal("63Vgs0BFK0USe4i2mQUGK6", ct.Sys.ID) -// assert.Equal("ct-name-updated", ct.Name) -// assert.Equal("ct-description-updated", ct.Description) -// assert.Equal(2, ct.Sys.Version) -//} +// require.NoError(t, err) +// assert.Equal(t, "63Vgs0BFK0USe4i2mQUGK6", ct.Sys.ID) +// assert.Equal(t, "ct-name-updated", ct.Name) +// assert.Equal(t, "ct-description-updated", ct.Description) +// assert.Equal(t, 2, ct.Sys.Version) +// } // -//func TestEntryCreateWithoutID(t *testing.T) { +// func TestEntryCreateWithoutID(t *testing.T) { // var err error -// assert := assert.New(t) // // handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(r.Method, "POST") -// assert.Equal(r.RequestURI, "/spaces/id1/content_types") -// checkHeaders(r, assert) +// assert.Equal(t, http.MethodPost, r.Method) +// assert.Equal(t, "/spaces/id1/content_types", r.RequestURI) +// checkHeaders(t, r) // // w.WriteHeader(200) -// fmt.Fprintln(w, string(readTestData("content_type-updated.json"))) +// _, _ = fmt.Fprintln(w, readTestData(t, "content_type-updated.json")) // }) // // // test server @@ -216,20 +215,19 @@ func TestEntrySaveForCreate(t *testing.T) { // } // // cma.ContentTypes.Upsert("id1", ct) -// assert.Nil(err) -//} +// require.NoError(t, err) +// } // -//func TestEntryCreateWithID(t *testing.T) { +// func TestEntryCreateWithID(t *testing.T) { // var err error -// assert := assert.New(t) // // handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(r.Method, "PUT") -// assert.Equal(r.RequestURI, "/spaces/id1/content_types/mycontenttype") -// checkHeaders(r, assert) +// assert.Equal(t, r.Method, "PUT") +// assert.Equal(t, r.RequestURI, "/spaces/id1/content_types/mycontenttype") +// checkHeaders(t, r) // // w.WriteHeader(200) -// fmt.Fprintln(w, string(readTestData("content_type-updated.json"))) +// _, _ = fmt.Fprintln(w, readTestData(t, "content_type-updated.json")) // }) // // // test server @@ -249,5 +247,5 @@ func TestEntrySaveForCreate(t *testing.T) { // } // // cma.ContentTypes.Upsert("id1", ct) -// assert.Nil(err) -//} +// require.NoError(t, err) +// } diff --git a/errors.go b/errors.go index 0f3e1ab..de9c7b9 100644 --- a/errors.go +++ b/errors.go @@ -80,21 +80,20 @@ func (e ValidationFailedError) Error() string { return msg.String() case "notResolvable": if err.Path != nil { - switch err.Path.(type) { + switch path := err.Path.(type) { case []interface{}: - path := err.Path.([]interface{}) pathString := "" for _, segment := range path { switch segment.(type) { case string: - pathString += fmt.Sprintf("/%s", segment.(string)) + pathString += fmt.Sprintf("/%s", segment) } } - msg.WriteString(fmt.Sprintf("errorName: %s, path: %s", err.Name, pathString)) + _, _ = msg.WriteString(fmt.Sprintf("errorName: %s, path: %s", err.Name, pathString)) } } default: - msg.WriteString(fmt.Sprintf("%s\n", err.Details)) + _, _ = msg.WriteString(fmt.Sprintf("%s\n", err.Details)) } } diff --git a/errors_test.go b/errors_test.go index 0bb365f..bcedbcd 100644 --- a/errors_test.go +++ b/errors_test.go @@ -1,21 +1,23 @@ package contentful import ( + "context" + "errors" "fmt" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNotFoundErrorResponse(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(404) - fmt.Fprintln(w, string(readTestData("error-notfound.json"))) + w.WriteHeader(http.StatusNotFound) + _, _ = fmt.Fprintln(w, readTestData(t, "error-notfound.json")) }) // test server @@ -27,25 +29,24 @@ func TestNotFoundErrorResponse(t *testing.T) { cma.BaseURL = server.URL // test space - _, err = cma.Spaces.Get("unknown-space-id") - assert.NotNil(err) - _, ok := err.(NotFoundError) - assert.Equal(true, ok) - notFoundError := err.(NotFoundError) - assert.Equal(404, notFoundError.APIError.res.StatusCode) - assert.Equal("request-id", notFoundError.APIError.err.RequestID) - assert.Equal("The resource could not be found.", notFoundError.APIError.err.Message) - assert.Equal("Error", notFoundError.APIError.err.Sys.Type) - assert.Equal("NotFound", notFoundError.APIError.err.Sys.ID) + _, err = cma.Spaces.Get(context.TODO(), "unknown-space-id") + require.Error(t, err) + var notFoundError NotFoundError + ok := errors.As(err, ¬FoundError) + assert.True(t, ok) + assert.Equal(t, 404, notFoundError.APIError.res.StatusCode) + assert.Equal(t, "request-id", notFoundError.APIError.err.RequestID) + assert.Equal(t, "The resource could not be found.", notFoundError.APIError.err.Message) + assert.Equal(t, "Error", notFoundError.APIError.err.Sys.Type) + assert.Equal(t, "NotFound", notFoundError.APIError.err.Sys.ID) } func TestRateLimitExceededResponse(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(403) - fmt.Fprintln(w, string(readTestData("error-ratelimit.json"))) + w.WriteHeader(http.StatusForbidden) + _, _ = fmt.Fprintln(w, readTestData(t, "error-ratelimit.json")) }) // test server @@ -58,14 +59,14 @@ func TestRateLimitExceededResponse(t *testing.T) { // test space space := &Space{Name: "test-space"} - err = cma.Spaces.Upsert(space) - assert.NotNil(err) - _, ok := err.(RateLimitExceededError) - assert.Equal(true, ok) - rateLimitExceededError := err.(RateLimitExceededError) - assert.Equal(403, rateLimitExceededError.APIError.res.StatusCode) - assert.Equal("request-id", rateLimitExceededError.APIError.err.RequestID) - assert.Equal("You are creating too many Spaces.", rateLimitExceededError.APIError.err.Message) - assert.Equal("Error", rateLimitExceededError.APIError.err.Sys.Type) - assert.Equal("RateLimitExceeded", rateLimitExceededError.APIError.err.Sys.ID) + err = cma.Spaces.Upsert(context.TODO(), space) + require.Error(t, err) + var rateLimitExceededError RateLimitExceededError + ok := errors.As(err, &rateLimitExceededError) + assert.True(t, ok) + assert.Equal(t, 403, rateLimitExceededError.APIError.res.StatusCode) + assert.Equal(t, "request-id", rateLimitExceededError.APIError.err.RequestID) + assert.Equal(t, "You are creating too many Spaces.", rateLimitExceededError.APIError.err.Message) + assert.Equal(t, "Error", rateLimitExceededError.APIError.err.Sys.Type) + assert.Equal(t, "RateLimitExceeded", rateLimitExceededError.APIError.err.Sys.ID) } diff --git a/include.go b/include.go index b4d623e..7b15571 100644 --- a/include.go +++ b/include.go @@ -1,6 +1,6 @@ package contentful -//IncludeEntry model +// IncludeEntry model type IncludeEntry struct { Fields map[string]interface{} `json:"fields,omitempty"` Sys *Sys `json:"sys"` diff --git a/locale.go b/locale.go index 6e087f0..9656e0e 100644 --- a/locale.go +++ b/locale.go @@ -2,8 +2,10 @@ package contentful import ( "bytes" + "context" "encoding/json" "fmt" + "net/http" "strconv" ) @@ -47,11 +49,11 @@ func (locale *Locale) GetVersion() int { } // List returns a locales collection -func (service *LocalesService) List(spaceID string) *Collection { +func (service *LocalesService) List(ctx context.Context, spaceID string) *Collection { path := fmt.Sprintf("/spaces/%s%s/locales", spaceID, getEnvPath(service.c)) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return &Collection{} } @@ -64,11 +66,11 @@ func (service *LocalesService) List(spaceID string) *Collection { } // Get returns a single locale entity -func (service *LocalesService) Get(spaceID, localeID string) (*Locale, error) { +func (service *LocalesService) Get(ctx context.Context, spaceID, localeID string) (*Locale, error) { path := fmt.Sprintf("/spaces/%s%s/locales/%s", spaceID, getEnvPath(service.c), localeID) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return nil, err } @@ -82,11 +84,11 @@ func (service *LocalesService) Get(spaceID, localeID string) (*Locale, error) { } // Delete the locale -func (service *LocalesService) Delete(spaceID string, locale *Locale) error { +func (service *LocalesService) Delete(ctx context.Context, spaceID string, locale *Locale) error { path := fmt.Sprintf("/spaces/%s%s/locales/%s", spaceID, getEnvPath(service.c), locale.Sys.ID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } @@ -98,7 +100,7 @@ func (service *LocalesService) Delete(spaceID string, locale *Locale) error { } // Upsert updates or creates a new locale entity -func (service *LocalesService) Upsert(spaceID string, locale *Locale) error { +func (service *LocalesService) Upsert(ctx context.Context, spaceID string, locale *Locale) error { bytesArray, err := json.Marshal(locale) if err != nil { return err @@ -115,7 +117,7 @@ func (service *LocalesService) Upsert(spaceID string, locale *Locale) error { method = "POST" } - req, err := service.c.newRequest(method, path, nil, bytes.NewReader(bytesArray)) + req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray)) if err != nil { return err } diff --git a/locale_test.go b/locale_test.go index ceef7cc..1c6430b 100644 --- a/locale_test.go +++ b/locale_test.go @@ -1,6 +1,7 @@ package contentful import ( + "context" "encoding/json" "fmt" "net/http" @@ -8,20 +9,20 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestLocalesServiceList(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "GET") - assert.Equal(r.URL.Path, "/spaces/"+spaceID+"/locales") + assert.Equal(t, http.MethodGet, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/locales", r.URL.Path) - checkHeaders(r, assert) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, readTestData("locales.json")) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "locales.json")) }) // test server @@ -32,22 +33,21 @@ func TestLocalesServiceList(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - _, err = cma.Locales.List(spaceID).Next() - assert.Nil(err) + _, err = cma.Locales.List(context.TODO(), spaceID).Next() + require.NoError(t, err) } func TestLocalesServiceGet(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "GET") - assert.Equal(r.URL.Path, "/spaces/"+spaceID+"/locales/4aGeQYgByqQFJtToAOh2JJ") + assert.Equal(t, http.MethodGet, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/locales/4aGeQYgByqQFJtToAOh2JJ", r.URL.Path) - checkHeaders(r, assert) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, readTestData("locale_1.json")) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "locale_1.json")) }) // test server @@ -58,30 +58,29 @@ func TestLocalesServiceGet(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - locale, err := cma.Locales.Get(spaceID, "4aGeQYgByqQFJtToAOh2JJ") - assert.Nil(err) - assert.Equal("U.S. English", locale.Name) - assert.Equal("en-US", locale.Code) + locale, err := cma.Locales.Get(context.TODO(), spaceID, "4aGeQYgByqQFJtToAOh2JJ") + require.NoError(t, err) + assert.Equal(t, "U.S. English", locale.Name) + assert.Equal(t, "en-US", locale.Code) } func TestLocalesServiceUpsertCreate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/locales") + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/locales", r.RequestURI) - checkHeaders(r, assert) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) - assert.Equal("German (Austria)", payload["name"]) - assert.Equal("de-AT", payload["code"]) + require.NoError(t, err) + assert.Equal(t, "German (Austria)", payload["name"]) + assert.Equal(t, "de-AT", payload["code"]) - w.WriteHeader(200) - fmt.Fprintln(w, readTestData("locale_1.json")) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "locale_1.json")) }) // test server @@ -97,28 +96,27 @@ func TestLocalesServiceUpsertCreate(t *testing.T) { Code: "de-AT", } - err = cma.Locales.Upsert(spaceID, locale) - assert.Nil(err) + err = cma.Locales.Upsert(context.TODO(), spaceID, locale) + require.NoError(t, err) } func TestLocalesServiceUpsertUpdate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "PUT") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/locales/4aGeQYgByqQFJtToAOh2JJ") + assert.Equal(t, http.MethodPut, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/locales/4aGeQYgByqQFJtToAOh2JJ", r.RequestURI) - checkHeaders(r, assert) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) - assert.Equal("modified-name", payload["name"]) - assert.Equal("modified-code", payload["code"]) + require.NoError(t, err) + assert.Equal(t, "modified-name", payload["name"]) + assert.Equal(t, "modified-code", payload["code"]) - w.WriteHeader(200) - fmt.Fprintln(w, string(readTestData("locale_1.json"))) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "locale_1.json")) }) // test server @@ -129,26 +127,25 @@ func TestLocalesServiceUpsertUpdate(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - locale, err := localeFromTestData("locale_1.json") - assert.Nil(err) + locale, err := localeFromTestData(t, "locale_1.json") + require.NoError(t, err) locale.Name = "modified-name" locale.Code = "modified-code" - err = cma.Locales.Upsert(spaceID, locale) - assert.Nil(err) + err = cma.Locales.Upsert(context.TODO(), spaceID, locale) + require.NoError(t, err) } func TestLocalesServiceDelete(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "DELETE") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/locales/4aGeQYgByqQFJtToAOh2JJ") - checkHeaders(r, assert) + assert.Equal(t, http.MethodDelete, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/locales/4aGeQYgByqQFJtToAOh2JJ", r.RequestURI) + checkHeaders(t, r) - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) }) // test server @@ -160,10 +157,10 @@ func TestLocalesServiceDelete(t *testing.T) { cma.BaseURL = server.URL // test locale - locale, err := localeFromTestData("locale_1.json") - assert.Nil(err) + locale, err := localeFromTestData(t, "locale_1.json") + require.NoError(t, err) // delete locale - err = cma.Locales.Delete(spaceID, locale) - assert.Nil(err) + err = cma.Locales.Delete(context.TODO(), spaceID, locale) + require.NoError(t, err) } diff --git a/query.go b/query.go index 6c2c813..37c839e 100644 --- a/query.go +++ b/query.go @@ -8,7 +8,7 @@ import ( "time" ) -//Query model +// Query model type Query struct { include uint16 contentType string @@ -39,7 +39,7 @@ type Query struct { sysID string } -//NewQuery initilazies a new query +// NewQuery initilazies a new query func NewQuery() *Query { return &Query{ include: 0, @@ -72,127 +72,127 @@ func NewQuery() *Query { } } -//SysID query +// SysID query func (q *Query) SysID(sid string) *Query { q.sysID = sid return q } -//Include query +// Include query func (q *Query) Include(include uint16) *Query { q.include = include return q } -//ContentType query +// ContentType query func (q *Query) ContentType(ct string) *Query { q.contentType = ct return q } -//Select query +// Select query func (q *Query) Select(fields []string) *Query { q.fields = fields return q } -//Equal equality query +// Equal equality query func (q *Query) Equal(field string, value interface{}) *Query { q.e[field] = value return q } -//NotEqual [ne] query +// NotEqual [ne] query func (q *Query) NotEqual(field string, value interface{}) *Query { q.ne[field] = value return q } -//All [all] query +// All [all] query func (q *Query) All(field string, value []string) *Query { q.all[field] = value return q } -//In [in] query +// In [in] query func (q *Query) In(field string, value []string) *Query { q.in[field] = value return q } -//NotIn [nin] query +// NotIn [nin] query func (q *Query) NotIn(field string, value []string) *Query { q.nin[field] = value return q } -//Exists [exists] query +// Exists [exists] query func (q *Query) Exists(field string) *Query { q.exists = append(q.exists, field) return q } -//NotExists [exists] query +// NotExists [exists] query func (q *Query) NotExists(field string) *Query { q.notExists = append(q.notExists, field) return q } -//LessThan [lt] query +// LessThan [lt] query func (q *Query) LessThan(field string, value interface{}) *Query { q.lt[field] = value return q } -//LessThanOrEqual [lte] query +// LessThanOrEqual [lte] query func (q *Query) LessThanOrEqual(field string, value interface{}) *Query { q.lte[field] = value return q } -//GreaterThan [gt] query +// GreaterThan [gt] query func (q *Query) GreaterThan(field string, value interface{}) *Query { q.gt[field] = value return q } -//GreaterThanOrEqual [lte] query +// GreaterThanOrEqual [lte] query func (q *Query) GreaterThanOrEqual(field string, value interface{}) *Query { q.gte[field] = value return q } -//Query param +// Query param func (q *Query) Query(qStr string) *Query { q.q = qStr return q } -//Match param +// Match param func (q *Query) Match(field, match string) *Query { q.match[field] = match return q } -//Near param +// Near param func (q *Query) Near(field string, lat, lon int16) *Query { q.near[field] = strconv.Itoa(int(lat)) + "," + strconv.Itoa(int(lon)) return q } -//Within param +// Within param func (q *Query) Within(field string, lat1, lon1, lat2, lon2 int16) *Query { q.within[field] = strconv.Itoa(int(lat1)) + "," + strconv.Itoa(int(lon1)) + "," + strconv.Itoa(int(lat2)) + "," + strconv.Itoa(int(lon2)) return q } -//WithinRadius param +// WithinRadius param func (q *Query) WithinRadius(field string, lat1, lon1, radius int16) *Query { q.within[field] = strconv.Itoa(int(lat1)) + "," + strconv.Itoa(int(lon1)) + "," + strconv.Itoa(int(radius)) return q } -//Order param +// Order param func (q *Query) Order(field string, reverse bool) *Query { if reverse { q.order = append(q.order, "-"+field) @@ -203,43 +203,43 @@ func (q *Query) Order(field string, reverse bool) *Query { return q } -//Limit query +// Limit query func (q *Query) Limit(limit uint16) *Query { q.limit = limit return q } -//Skip query +// Skip query func (q *Query) Skip(skip uint16) *Query { q.skip = skip return q } -//MimeType query +// MimeType query func (q *Query) MimeType(mime string) *Query { q.mime = mime return q } -//Locale query +// Locale query func (q *Query) Locale(locale string) *Query { q.locale = locale return q } -//SyncType query +// SyncType query func (q *Query) SyncType(syncType string) *Query { q.syncType = syncType return q } -//Initial query +// Initial query func (q *Query) Initial(initial string) *Query { q.initial = initial return q } -//SyncToken query +// SyncToken query func (q *Query) SyncToken(syncToken string) *Query { q.syncToken = syncToken return q @@ -250,7 +250,7 @@ func (q *Query) Values() url.Values { params := url.Values{} if q.include != 0 { - if q.include < 0 || q.include > 10 { + if q.include > 10 { panic("include value should be between 0 and 10") } params.Set("include", strconv.Itoa(int(q.include))) @@ -446,7 +446,6 @@ func (q *Query) Values() url.Values { } else { panic("initial value can only be true or false") } - } if q.syncToken != "" { diff --git a/query_test.go b/query_test.go index 2c5f78b..c0ce9ce 100644 --- a/query_test.go +++ b/query_test.go @@ -17,7 +17,7 @@ func TestQueryInclude(t *testing.T) { assert.Panics(t, func() { q := NewQuery().Include(11) - q.String() + _ = q.String() }, "out of range `include` should panic") } @@ -25,6 +25,7 @@ func TestQueryContentType(t *testing.T) { q := NewQuery().ContentType("content_type") expected := url.Values{} expected.Set("content_type", "content_type") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -35,6 +36,7 @@ func TestQuerySelect(t *testing.T) { expected := url.Values{} expected.Set("content_type", "ct") + expected.Set("include", "0") expected.Set("select", "field1,field2") assert.Equal(t, expected.Encode(), q.String()) @@ -46,18 +48,18 @@ func TestQuerySelect(t *testing.T) { }, "select needs content_type") assert.Panics(t, func() { - fields := []string{} + var fields []string for i := 0; i < 110; i++ { fields = append(fields, "field"+strconv.Itoa(i)) } q := NewQuery().Select(fields) - q.String() + _ = q.String() }, "select accepts 100 fields max") assert.Panics(t, func() { q := NewQuery().Select([]string{"field1", "field2.d1", "field3.d2.d3"}) - q.String() + _ = q.String() }, "select accepts depths 3 max") } @@ -65,6 +67,7 @@ func TestQueryEqual(t *testing.T) { q := NewQuery().Equal("field1", 10) expected := url.Values{} expected.Set("field1", "10") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) q = q.Equal("field1", "11") @@ -81,6 +84,7 @@ func TestQueryNotEqual(t *testing.T) { expected := url.Values{} expected.Set("field1[ne]", "10") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) q = q.NotEqual("field1", "11") @@ -96,6 +100,7 @@ func TestQueryAll(t *testing.T) { q := NewQuery().All("field1", []string{"10", "test"}) expected := url.Values{} expected.Set("field1[all]", "10,test") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -103,6 +108,7 @@ func TestQueryIn(t *testing.T) { q := NewQuery().In("sys.id", []string{"test", "test2"}) expected := url.Values{} expected.Set("sys.id[in]", "test,test2") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -110,6 +116,7 @@ func TestQueryNotIn(t *testing.T) { q := NewQuery().NotIn("sys.id", []string{"test3"}) expected := url.Values{} expected.Set("sys.id[nin]", "test3") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -117,6 +124,7 @@ func TestQueryExists(t *testing.T) { q := NewQuery().Exists("sys.id") expected := url.Values{} expected.Set("sys.id[exists]", "true") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -124,6 +132,7 @@ func TestQueryNotExists(t *testing.T) { q := NewQuery().NotExists("sys.id") expected := url.Values{} expected.Set("sys.id[exists]", "false") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -131,12 +140,14 @@ func TestQueryLessThan(t *testing.T) { q := NewQuery().LessThan("fields.date", 10) expected := url.Values{} expected.Set("fields.date[lt]", "10") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) now := time.Now() q = NewQuery().LessThan("fields.date", now) expected = url.Values{} expected.Set("fields.date[lt]", now.Format("2006-01-02 15:04:05")) + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -144,12 +155,14 @@ func TestQueryLessThanOrEqual(t *testing.T) { q := NewQuery().LessThanOrEqual("fields.date", 10) expected := url.Values{} expected.Set("fields.date[lte]", "10") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) now := time.Now() q = NewQuery().LessThanOrEqual("fields.date", now) expected = url.Values{} expected.Set("fields.date[lte]", now.Format("2006-01-02 15:04:05")) + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -157,12 +170,14 @@ func TestQueryGreaterThan(t *testing.T) { q := NewQuery().GreaterThan("fields.date", 10) expected := url.Values{} expected.Set("fields.date[gt]", "10") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) now := time.Now() q = NewQuery().GreaterThan("fields.date", now) expected = url.Values{} expected.Set("fields.date[gt]", now.Format("2006-01-02 15:04:05")) + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -170,12 +185,14 @@ func TestQueryGreaterThanOrEqual(t *testing.T) { q := NewQuery().GreaterThanOrEqual("fields.date", 10) expected := url.Values{} expected.Set("fields.date[gte]", "10") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) now := time.Now() q = NewQuery().GreaterThanOrEqual("fields.date", now) expected = url.Values{} expected.Set("fields.date[gte]", now.Format("2006-01-02 15:04:05")) + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -183,6 +200,7 @@ func TestQueryQuery(t *testing.T) { q := NewQuery().Query("query_str") expected := url.Values{} expected.Set("query", "query_str") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -190,6 +208,7 @@ func TestQueryMatch(t *testing.T) { q := NewQuery().Match("field1", "match_query") expected := url.Values{} expected.Set("field1[match]", "match_query") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -197,6 +216,7 @@ func TestQueryNear(t *testing.T) { q := NewQuery().Near("field1", 38, -120) expected := url.Values{} expected.Set("field1[near]", "38,-120") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -204,6 +224,7 @@ func TestQueryWithin(t *testing.T) { q := NewQuery().Within("field1", 38, -120, 10, 120) expected := url.Values{} expected.Set("field1[within]", "38,-120,10,120") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -211,6 +232,7 @@ func TestQueryWithinRadius(t *testing.T) { q := NewQuery().WithinRadius("field1", 38, -120, 22) expected := url.Values{} expected.Set("field1[within]", "38,-120,22") + expected.Set("include", "0") assert.Equal(t, expected.Encode(), q.String()) } @@ -218,12 +240,14 @@ func TestQueryOrder(t *testing.T) { q := NewQuery().ContentType("ct").Order("field1", false) expected := url.Values{} expected.Set("content_type", "ct") + expected.Set("include", "0") expected.Set("order", "field1") assert.Equal(t, expected.Encode(), q.String()) q = NewQuery().ContentType("ct").Order("field1", true) expected = url.Values{} expected.Set("content_type", "ct") + expected.Set("include", "0") expected.Set("order", "-field1") assert.Equal(t, expected.Encode(), q.String()) @@ -235,6 +259,7 @@ func TestQueryOrder(t *testing.T) { expected = url.Values{} expected.Set("content_type", "ct") + expected.Set("include", "0") expected.Set("order", "-field1,field2,field3") assert.Equal(t, expected.Encode(), q.String()) @@ -247,18 +272,20 @@ func TestQueryOrder(t *testing.T) { func TestQueryLimit(t *testing.T) { q := NewQuery().Limit(10) expected := url.Values{} + expected.Set("include", "0") expected.Set("limit", "10") assert.Equal(t, expected.Encode(), q.String()) assert.Panics(t, func() { q := NewQuery().Limit(3000) - q.String() + _ = q.String() }, "out of range limit should panic") } func TestQuerySkip(t *testing.T) { q := NewQuery().Skip(10) expected := url.Values{} + expected.Set("include", "0") expected.Set("skip", "10") assert.Equal(t, expected.Encode(), q.String()) } @@ -266,6 +293,7 @@ func TestQuerySkip(t *testing.T) { func TestQueryMimeType(t *testing.T) { q := NewQuery().MimeType("image") expected := url.Values{} + expected.Set("include", "0") expected.Set("mimetype_group", "image") assert.Equal(t, expected.Encode(), q.String()) } @@ -281,6 +309,7 @@ func TestQuery(t *testing.T) { expected := url.Values{} expected.Set("cat.name", "catname") expected.Set("cat.name[ne]", "dogname") + expected.Set("include", "0") expected.Set("sys.id[in]", "test,test2") expected.Set("sys.id[nin]", "test3") expected.Set("fields.cat[lt]", "4") diff --git a/scheduled_actions.go b/scheduled_actions.go deleted file mode 100644 index 02d5ddf..0000000 --- a/scheduled_actions.go +++ /dev/null @@ -1,53 +0,0 @@ -package contentful - -import ( - "fmt" - "net/url" -) - -// SpacesService model -type ScheduledActionsService service - -type ScheduledFor struct { - Datetime string `json:"datetime,omitempty"` - Timezone string `json:"timezone,omitempty"` -} - -// ScheduledActions model -type ScheduledActions struct { - Sys *Sys `json:"sys,omitempty"` - Action string `json:"action,omitempty"` - ScheduledFor *ScheduledFor `json:"scheduledFor,omitempty"` -} - -// Get returns a single scheduledActions entity -func (service *ScheduledActionsService) Get(spaceID string, entryID string, environmentID string) (*ScheduledActions, error) { - path := fmt.Sprintf("/spaces/%s/scheduled_actions", spaceID) - - query := url.Values{} - - query.Add("entity.sys.id", entryID) - query.Add("environment.sys.id", environmentID) - query.Add("sys.status[in]", "scheduled") - - method := "GET" - - req, err := service.c.newRequest(method, path, query, nil) - if err != nil { - return &ScheduledActions{}, err - } - - col := NewCollection(&CollectionOptions{}) - col.c = service.c - col.req = req - - if ok := service.c.do(req, &col); ok != nil { - return &ScheduledActions{}, ok - } - - for _, ct := range col.ToScheduledAction() { - fmt.Println(ct) - } - - return &ScheduledActions{}, nil -} diff --git a/scheduled_actions_test.go b/scheduled_actions_test.go deleted file mode 100644 index 31402e2..0000000 --- a/scheduled_actions_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package contentful - -import ( - "fmt" - "log" - "testing" - - "github.com/stretchr/testify/assert" -) - -func Test_ExampleScheduledActionsService_Get(t *testing.T) { - - cma := NewCMA("cma-token") - assert.NotNil(t, cma) - assert.NotNil(t, cma.ScheduledActions) - - scheduledActions, err := cma.ScheduledActions.Get("space-id", "entry-id", "env") - - if err != nil { - log.Fatal(err) - } - - fmt.Printf("%v", scheduledActions) -} diff --git a/space.go b/space.go index 2f12400..afb4a24 100644 --- a/space.go +++ b/space.go @@ -2,8 +2,10 @@ package contentful import ( "bytes" + "context" "encoding/json" "fmt" + "net/http" "strconv" ) @@ -39,8 +41,8 @@ func (space *Space) GetVersion() int { } // List creates a spaces collection -func (service *SpacesService) List() *Collection { - req, _ := service.c.newRequest("GET", "/spaces", nil, nil) +func (service *SpacesService) List(ctx context.Context) *Collection { + req, _ := service.c.newRequest(ctx, http.MethodGet, "/spaces", nil, nil) col := NewCollection(&CollectionOptions{}) col.c = service.c @@ -50,11 +52,11 @@ func (service *SpacesService) List() *Collection { } // Get returns a single space entity -func (service *SpacesService) Get(spaceID string) (*Space, error) { +func (service *SpacesService) Get(ctx context.Context, spaceID string) (*Space, error) { path := fmt.Sprintf("/spaces/%s", spaceID) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return &Space{}, err } @@ -68,7 +70,7 @@ func (service *SpacesService) Get(spaceID string) (*Space, error) { } // Upsert updates or creates a new space -func (service *SpacesService) Upsert(space *Space) error { +func (service *SpacesService) Upsert(ctx context.Context, space *Space) error { bytesArray, err := json.Marshal(space) if err != nil { return err @@ -85,7 +87,7 @@ func (service *SpacesService) Upsert(space *Space) error { method = "POST" } - req, err := service.c.newRequest(method, path, nil, bytes.NewReader(bytesArray)) + req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray)) if err != nil { return err } @@ -96,11 +98,11 @@ func (service *SpacesService) Upsert(space *Space) error { } // Delete the given space -func (service *SpacesService) Delete(space *Space) error { +func (service *SpacesService) Delete(ctx context.Context, space *Space) error { path := fmt.Sprintf("/spaces/%s", space.Sys.ID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } diff --git a/space_test.go b/space_test.go index 717dfc9..9bf4d24 100644 --- a/space_test.go +++ b/space_test.go @@ -1,6 +1,7 @@ package contentful import ( + "context" "encoding/json" "fmt" "log" @@ -9,14 +10,15 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func ExampleSpacesService_Get() { cma := NewCMA("cma-token") - space, err := cma.Spaces.Get("space-id") + space, err := cma.Spaces.Get(context.TODO(), "space-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } fmt.Println(space.Name) @@ -24,12 +26,16 @@ func ExampleSpacesService_Get() { func ExampleSpacesService_List() { cma := NewCMA("cma-token") - collection, err := cma.Spaces.List().Next() + collection, err := cma.Spaces.List(context.TODO()).Next() if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive + } + + spaces, err := collection.ToSpace() + if err != nil { + log.Fatal(err) //nolint:revive } - spaces := collection.ToSpace() for _, space := range spaces { fmt.Println(space.Sys.ID, space.Name) } @@ -43,69 +49,72 @@ func ExampleSpacesService_Upsert_create() { DefaultLocale: "en-US", } - err := cma.Spaces.Upsert(space) + err := cma.Spaces.Upsert(context.TODO(), space) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func ExampleSpacesService_Upsert_update() { cma := NewCMA("cma-token") - space, err := cma.Spaces.Get("space-id") + space, err := cma.Spaces.Get(context.TODO(), "space-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } space.Name = "modified" - err = cma.Spaces.Upsert(space) + err = cma.Spaces.Upsert(context.TODO(), space) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func ExampleSpacesService_Delete() { cma := NewCMA("cma-token") - space, err := cma.Spaces.Get("space-id") + space, err := cma.Spaces.Get(context.TODO(), "space-id") if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } - err = cma.Spaces.Delete(space) + err = cma.Spaces.Delete(context.TODO(), space) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } func ExampleSpacesService_Delete_all() { cma := NewCMA("cma-token") - collection, err := cma.Spaces.List().Next() + collection, err := cma.Spaces.List(context.TODO()).Next() if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } - for _, space := range collection.ToSpace() { - err := cma.Spaces.Delete(space) + spaces, err := collection.ToSpace() + if err != nil { + log.Fatal(err) //nolint:revive + } + + for _, space := range spaces { + err := cma.Spaces.Delete(context.TODO(), space) if err != nil { - log.Fatal(err) + log.Fatal(err) //nolint:revive } } } func TestSpacesServiceList(t *testing.T) { var err error - assert := assert.New(t) - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "GET") - assert.Equal(r.URL.Path, "/spaces") + assert.Equal(t, http.MethodGet, r.Method) + assert.Equal(t, "/spaces", r.URL.Path) - checkHeaders(r, assert) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, readTestData("spaces.json")) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "spaces.json")) }) // test server @@ -116,27 +125,26 @@ func TestSpacesServiceList(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - collection, err := cma.Spaces.List().Next() - assert.Nil(err) + collection, err := cma.Spaces.List(context.TODO()).Next() + require.NoError(t, err) - spaces := collection.ToSpace() - assert.Equal(2, len(spaces)) - assert.Equal("id1", spaces[0].Sys.ID) - assert.Equal("id2", spaces[1].Sys.ID) + spaces, err := collection.ToSpace() + require.NoError(t, err) + assert.Len(t, spaces, 2) + assert.Equal(t, "id1", spaces[0].Sys.ID) + assert.Equal(t, "id2", spaces[1].Sys.ID) } func TestSpacesServiceGet(t *testing.T) { var err error - assert := assert.New(t) - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "GET") - assert.Equal(r.URL.Path, "/spaces/"+spaceID) + assert.Equal(t, http.MethodGet, r.Method) + assert.Equal(t, "/spaces/"+spaceID, r.URL.Path) - checkHeaders(r, assert) + checkHeaders(t, r) - w.WriteHeader(200) - fmt.Fprintln(w, readTestData("space-1.json")) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "space-1.json")) }) // test server @@ -147,27 +155,25 @@ func TestSpacesServiceGet(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - space, err := cma.Spaces.Get(spaceID) - assert.Nil(err) - assert.Equal("id1", space.Sys.ID) + space, err := cma.Spaces.Get(context.TODO(), spaceID) + require.NoError(t, err) + assert.Equal(t, "id1", space.Sys.ID) } func TestSpaceSaveForCreate(t *testing.T) { - assert := assert.New(t) - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) - assert.Equal("new space", payload["name"]) - assert.Equal("en", payload["defaultLocale"]) + require.NoError(t, err) + assert.Equal(t, "new space", payload["name"]) + assert.Equal(t, "en", payload["defaultLocale"]) - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("spaces-newspace.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "spaces-newspace.json")) }) // test server @@ -183,30 +189,28 @@ func TestSpaceSaveForCreate(t *testing.T) { DefaultLocale: "en", } - err := cma.Spaces.Upsert(space) - assert.Nil(err) - assert.Equal("newspace", space.Sys.ID) - assert.Equal("new space", space.Name) - assert.Equal("en", space.DefaultLocale) + err := cma.Spaces.Upsert(context.TODO(), space) + require.NoError(t, err) + assert.Equal(t, "newspace", space.Sys.ID) + assert.Equal(t, "new space", space.Name) + assert.Equal(t, "en", space.DefaultLocale) } func TestSpaceSaveForUpdate(t *testing.T) { var err error - assert := assert.New(t) - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "PUT") - assert.Equal(r.RequestURI, "/spaces/newspace") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPut, r.Method) + assert.Equal(t, "/spaces/newspace", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) - assert.Equal("changed-space-name", payload["name"]) - assert.Equal("de", payload["defaultLocale"]) + require.NoError(t, err) + assert.Equal(t, "changed-space-name", payload["name"]) + assert.Equal(t, "de", payload["defaultLocale"]) - w.WriteHeader(200) - fmt.Fprintln(w, string(readTestData("spaces-newspace-updated.json"))) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "spaces-newspace-updated.json")) }) // test server @@ -217,29 +221,28 @@ func TestSpaceSaveForUpdate(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - space, err := spaceFromTestData("spaces-newspace.json") - assert.Nil(err) + space, err := spaceFromTestData(t, "spaces-newspace.json") + require.NoError(t, err) space.Name = "changed-space-name" space.DefaultLocale = "de" - err = cma.Spaces.Upsert(space) - assert.Nil(err) - assert.Equal("changed-space-name", space.Name) - assert.Equal("de", space.DefaultLocale) - assert.Equal(2, space.Sys.Version) + err = cma.Spaces.Upsert(context.TODO(), space) + require.NoError(t, err) + assert.Equal(t, "changed-space-name", space.Name) + assert.Equal(t, "de", space.DefaultLocale) + assert.Equal(t, 2, space.Sys.Version) } func TestSpaceDelete(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "DELETE") - assert.Equal(r.RequestURI, "/spaces/"+spaceID) - checkHeaders(r, assert) + assert.Equal(t, http.MethodDelete, r.Method) + assert.Equal(t, "/spaces/"+spaceID, r.RequestURI) + checkHeaders(t, r) - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) }) // test server @@ -250,9 +253,9 @@ func TestSpaceDelete(t *testing.T) { cma = NewCMA(CMAToken) cma.BaseURL = server.URL - space, err := spaceFromTestData("spaces-" + spaceID + ".json") - assert.Nil(err) + space, err := spaceFromTestData(t, "spaces-"+spaceID+".json") + require.NoError(t, err) - err = cma.Spaces.Delete(space) - assert.Nil(err) + err = cma.Spaces.Delete(context.TODO(), space) + require.NoError(t, err) } diff --git a/webhook.go b/webhook.go index 906f65b..c1a8785 100644 --- a/webhook.go +++ b/webhook.go @@ -2,8 +2,10 @@ package contentful import ( "bytes" + "context" "encoding/json" "fmt" + "net/http" "strconv" ) @@ -38,11 +40,11 @@ func (webhook *Webhook) GetVersion() int { } // List returns webhooks collection -func (service *WebhooksService) List(spaceID string) *Collection { +func (service *WebhooksService) List(ctx context.Context, spaceID string) *Collection { path := fmt.Sprintf("/spaces/%s%s/webhook_definitions", spaceID, getEnvPath(service.c)) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return &Collection{} } @@ -55,11 +57,11 @@ func (service *WebhooksService) List(spaceID string) *Collection { } // Get returns a single webhook entity -func (service *WebhooksService) Get(spaceID, webhookID string) (*Webhook, error) { +func (service *WebhooksService) Get(ctx context.Context, spaceID, webhookID string) (*Webhook, error) { path := fmt.Sprintf("/spaces/%s%s/webhook_definitions/%s", spaceID, getEnvPath(service.c), webhookID) - method := "GET" + method := http.MethodGet - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return nil, err } @@ -73,7 +75,7 @@ func (service *WebhooksService) Get(spaceID, webhookID string) (*Webhook, error) } // Upsert updates or creates a new entity -func (service *WebhooksService) Upsert(spaceID string, webhook *Webhook) error { +func (service *WebhooksService) Upsert(ctx context.Context, spaceID string, webhook *Webhook) error { bytesArray, err := json.Marshal(webhook) if err != nil { return err @@ -90,7 +92,7 @@ func (service *WebhooksService) Upsert(spaceID string, webhook *Webhook) error { method = "POST" } - req, err := service.c.newRequest(method, path, nil, bytes.NewReader(bytesArray)) + req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray)) if err != nil { return err } @@ -101,11 +103,11 @@ func (service *WebhooksService) Upsert(spaceID string, webhook *Webhook) error { } // Delete the webhook -func (service *WebhooksService) Delete(spaceID string, webhook *Webhook) error { +func (service *WebhooksService) Delete(ctx context.Context, spaceID string, webhook *Webhook) error { path := fmt.Sprintf("/spaces/%s%s/webhook_definitions/%s", spaceID, getEnvPath(service.c), webhook.Sys.ID) - method := "DELETE" + method := http.MethodDelete - req, err := service.c.newRequest(method, path, nil, nil) + req, err := service.c.newRequest(ctx, method, path, nil, nil) if err != nil { return err } diff --git a/webhook_test.go b/webhook_test.go index fc3fe65..ee74e41 100644 --- a/webhook_test.go +++ b/webhook_test.go @@ -1,6 +1,7 @@ package contentful import ( + "context" "encoding/json" "fmt" "net/http" @@ -8,43 +9,43 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestWebhookSaveForCreate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "POST") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/webhook_definitions") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/webhook_definitions", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) - assert.Equal("webhook-name", payload["name"]) - assert.Equal("https://www.example.com/test", payload["url"]) - assert.Equal("username", payload["httpBasicUsername"]) - assert.Equal("password", payload["httpBasicPassword"]) + require.NoError(t, err) + assert.Equal(t, "webhook-name", payload["name"]) + assert.Equal(t, "https://www.example.com/test", payload["url"]) + assert.Equal(t, "username", payload["httpBasicUsername"]) + assert.Equal(t, "password", payload["httpBasicPassword"]) topics := payload["topics"].([]interface{}) - assert.Equal(2, len(topics)) - assert.Equal("Entry.create", topics[0].(string)) - assert.Equal("ContentType.create", topics[1].(string)) + assert.Len(t, topics, 2) + assert.Equal(t, "Entry.create", topics[0].(string)) + assert.Equal(t, "ContentType.create", topics[1].(string)) headers := payload["headers"].([]interface{}) - assert.Equal(2, len(headers)) + assert.Len(t, headers, 2) header1 := headers[0].(map[string]interface{}) header2 := headers[1].(map[string]interface{}) - assert.Equal("header1", header1["key"].(string)) - assert.Equal("header1-value", header1["value"].(string)) + assert.Equal(t, "header1", header1["key"].(string)) + assert.Equal(t, "header1-value", header1["value"].(string)) - assert.Equal("header2", header2["key"].(string)) - assert.Equal("header2-value", header2["value"].(string)) + assert.Equal(t, "header2", header2["key"].(string)) + assert.Equal(t, "header2-value", header2["value"].(string)) - w.WriteHeader(201) - fmt.Fprintln(w, string(readTestData("webhook.json"))) + w.WriteHeader(http.StatusCreated) + _, _ = fmt.Fprintln(w, readTestData(t, "webhook.json")) }) // test server @@ -65,60 +66,59 @@ func TestWebhookSaveForCreate(t *testing.T) { HTTPBasicUsername: "username", HTTPBasicPassword: "password", Headers: []*WebhookHeader{ - &WebhookHeader{ + { Key: "header1", Value: "header1-value", }, - &WebhookHeader{ + { Key: "header2", Value: "header2-value", }, }, } - err = cma.Webhooks.Upsert(spaceID, webhook) - assert.Nil(err) - assert.Equal("7fstd9fZ9T2p3kwD49FxhI", webhook.Sys.ID) - assert.Equal("webhook-name", webhook.Name) - assert.Equal("username", webhook.HTTPBasicUsername) + err = cma.Webhooks.Upsert(context.TODO(), spaceID, webhook) + require.NoError(t, err) + assert.Equal(t, "7fstd9fZ9T2p3kwD49FxhI", webhook.Sys.ID) + assert.Equal(t, "webhook-name", webhook.Name) + assert.Equal(t, "username", webhook.HTTPBasicUsername) } func TestWebhookSaveForUpdate(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "PUT") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/webhook_definitions/7fstd9fZ9T2p3kwD49FxhI") - checkHeaders(r, assert) + assert.Equal(t, http.MethodPut, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/webhook_definitions/7fstd9fZ9T2p3kwD49FxhI", r.RequestURI) + checkHeaders(t, r) var payload map[string]interface{} err := json.NewDecoder(r.Body).Decode(&payload) - assert.Nil(err) - assert.Equal("updated-webhook-name", payload["name"]) - assert.Equal("https://www.example.com/test-updated", payload["url"]) - assert.Equal("updated-username", payload["httpBasicUsername"]) - assert.Equal("updated-password", payload["httpBasicPassword"]) + require.NoError(t, err) + assert.Equal(t, "updated-webhook-name", payload["name"]) + assert.Equal(t, "https://www.example.com/test-updated", payload["url"]) + assert.Equal(t, "updated-username", payload["httpBasicUsername"]) + assert.Equal(t, "updated-password", payload["httpBasicPassword"]) topics := payload["topics"].([]interface{}) - assert.Equal(3, len(topics)) - assert.Equal("Entry.create", topics[0].(string)) - assert.Equal("ContentType.create", topics[1].(string)) - assert.Equal("Asset.create", topics[2].(string)) + assert.Len(t, topics, 3) + assert.Equal(t, "Entry.create", topics[0].(string)) + assert.Equal(t, "ContentType.create", topics[1].(string)) + assert.Equal(t, "Asset.create", topics[2].(string)) headers := payload["headers"].([]interface{}) - assert.Equal(2, len(headers)) + assert.Len(t, headers, 2) header1 := headers[0].(map[string]interface{}) header2 := headers[1].(map[string]interface{}) - assert.Equal("header1", header1["key"].(string)) - assert.Equal("updated-header1-value", header1["value"].(string)) + assert.Equal(t, "header1", header1["key"].(string)) + assert.Equal(t, "updated-header1-value", header1["value"].(string)) - assert.Equal("header2", header2["key"].(string)) - assert.Equal("updated-header2-value", header2["value"].(string)) + assert.Equal(t, "header2", header2["key"].(string)) + assert.Equal(t, "updated-header2-value", header2["value"].(string)) - w.WriteHeader(200) - fmt.Fprintln(w, string(readTestData("webhook-updated.json"))) + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintln(w, readTestData(t, "webhook-updated.json")) }) // test server @@ -130,8 +130,8 @@ func TestWebhookSaveForUpdate(t *testing.T) { cma.BaseURL = server.URL // test webhook - webhook, err := webhookFromTestData("webhook.json") - assert.Nil(err) + webhook, err := webhookFromTestData(t, "webhook.json") + require.NoError(t, err) webhook.Name = "updated-webhook-name" webhook.URL = "https://www.example.com/test-updated" @@ -143,34 +143,33 @@ func TestWebhookSaveForUpdate(t *testing.T) { webhook.HTTPBasicUsername = "updated-username" webhook.HTTPBasicPassword = "updated-password" webhook.Headers = []*WebhookHeader{ - &WebhookHeader{ + { Key: "header1", Value: "updated-header1-value", }, - &WebhookHeader{ + { Key: "header2", Value: "updated-header2-value", }, } - err = cma.Webhooks.Upsert(spaceID, webhook) - assert.Nil(err) - assert.Equal("7fstd9fZ9T2p3kwD49FxhI", webhook.Sys.ID) - assert.Equal(1, webhook.Sys.Version) - assert.Equal("updated-webhook-name", webhook.Name) - assert.Equal("updated-username", webhook.HTTPBasicUsername) + err = cma.Webhooks.Upsert(context.TODO(), spaceID, webhook) + require.NoError(t, err) + assert.Equal(t, "7fstd9fZ9T2p3kwD49FxhI", webhook.Sys.ID) + assert.Equal(t, 1, webhook.Sys.Version) + assert.Equal(t, "updated-webhook-name", webhook.Name) + assert.Equal(t, "updated-username", webhook.HTTPBasicUsername) } func TestWebhookDelete(t *testing.T) { var err error - assert := assert.New(t) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(r.Method, "DELETE") - assert.Equal(r.RequestURI, "/spaces/"+spaceID+"/webhook_definitions/7fstd9fZ9T2p3kwD49FxhI") - checkHeaders(r, assert) + assert.Equal(t, http.MethodDelete, r.Method) + assert.Equal(t, "/spaces/"+spaceID+"/webhook_definitions/7fstd9fZ9T2p3kwD49FxhI", r.RequestURI) + checkHeaders(t, r) - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) }) // test server @@ -182,9 +181,9 @@ func TestWebhookDelete(t *testing.T) { cma.BaseURL = server.URL // test webhook - webhook, err := webhookFromTestData("webhook.json") - assert.Nil(err) + webhook, err := webhookFromTestData(t, "webhook.json") + require.NoError(t, err) - err = cma.Webhooks.Delete(spaceID, webhook) - assert.Nil(err) + err = cma.Webhooks.Delete(context.TODO(), spaceID, webhook) + require.NoError(t, err) }