Skip to content

Commit c403f94

Browse files
authored
Merge pull request #420 from bulat-khusnimardanov/bugfix/custom-fields-granular-reset
Added check for custom filed with null value
2 parents d6f8ef5 + 5bd4712 commit c403f94

13 files changed

+565
-8
lines changed

commercetools/custom_fields.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,14 +297,21 @@ func CustomFieldUpdateActions[T SetCustomTypeAction, F SetCustomFieldAction](ctx
297297

298298
var result []any
299299
for key := range changes {
300-
val, err := customFieldEncodeType(t, key, changes[key])
301-
if err != nil {
302-
return nil, err
300+
if changes[key] == nil {
301+
result = append(result, F{
302+
Name: key,
303+
Value: nil,
304+
})
305+
} else {
306+
val, err := customFieldEncodeType(t, key, changes[key])
307+
if err != nil {
308+
return nil, err
309+
}
310+
result = append(result, F{
311+
Name: key,
312+
Value: val,
313+
})
303314
}
304-
result = append(result, F{
305-
Name: key,
306-
Value: val,
307-
})
308315
}
309316
return result, nil
310317
}

commercetools/custom_fields_test.go

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
package commercetools
22

33
import (
4+
"bytes"
5+
"context"
6+
"fmt"
7+
"testing"
8+
"text/template"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
413
"github.com/labd/commercetools-go-sdk/platform"
514
"github.com/stretchr/testify/assert"
6-
"testing"
715
)
816

917
var customFieldEncodeValueTests = []struct {
@@ -66,3 +74,178 @@ func TestCustomFieldEncodeValue(t *testing.T) {
6674
})
6775
}
6876
}
77+
78+
// List of the resources with custom fields support
79+
var customFieldResourceTypes = []string{"commercetools_channel", "commercetools_cart_discount", "commercetools_category",
80+
"commercetools_customer_group", "commercetools_discount_code", "commercetools_shipping_method", "commercetools_store"}
81+
82+
// List of the custom field types
83+
var customFieldTypes = []string{"String", "Boolean", "Number", "LocalizedString", "Enum", "LocalizedEnum", "Money",
84+
"Date", "Time", "DateTime", "Reference", "Set"}
85+
86+
func TestAccCustomField_SetAndRemove(t *testing.T) {
87+
for _, customFieldResourceType := range customFieldResourceTypes {
88+
fmt.Println("Testing custom fields for:", customFieldResourceType)
89+
resourceShortName := "ct" + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
90+
resourceFullName := customFieldResourceType + "." + resourceShortName
91+
resourceKey := "key" + resourceShortName
92+
93+
// Define Test Steps
94+
var customFieldsAccTestSteps = []resource.TestStep{
95+
{
96+
Config: getResourceConfig(customFieldResourceType, resourceShortName, resourceKey, customFieldTypes),
97+
Check: resource.ComposeAggregateTestCheckFunc(
98+
func(s *terraform.State) error {
99+
customFields, err := getResourceCustomFields(s, customFieldResourceType, resourceFullName)
100+
if err != nil {
101+
return err
102+
}
103+
productType, err := testGetProductType(s, "commercetools_product_type.test")
104+
if err != nil {
105+
return err
106+
}
107+
assert.EqualValues(t, true, customFields.Fields["Boolean-field"], fmt.Sprintf("Boolean-field unexpected value for %s resource.", customFieldResourceType))
108+
assert.EqualValues(t, 1234, customFields.Fields["Number-field"], fmt.Sprintf("Number-field unexpected value for %s resource.", customFieldResourceType))
109+
assert.EqualValues(t, "foobar", customFields.Fields["String-field"], fmt.Sprintf("String-field unexpected value for %s resource.", customFieldResourceType))
110+
assert.EqualValues(t, map[string]interface{}{"en": "Localized String", "fr": "Chaîne localisée"}, customFields.Fields["LocalizedString-field"], fmt.Sprintf("LocalizedString-field unexpected value for %s resource.", customFieldResourceType))
111+
assert.EqualValues(t, "value2", customFields.Fields["Enum-field"], fmt.Sprintf("Enum-field unexpected value for %s resource.", customFieldResourceType))
112+
assert.EqualValues(t, "value1", customFields.Fields["LocalizedEnum-field"], fmt.Sprintf("LocalizedEnum-field unexpected value for %s resource.", customFieldResourceType))
113+
assert.EqualValues(t, map[string]interface{}{"centAmount": float64(150000), "currencyCode": "EUR", "fractionDigits": float64(2), "type": "centPrecision"}, customFields.Fields["Money-field"], fmt.Sprintf("Money-field unexpected value for %s resource.", customFieldResourceType))
114+
assert.EqualValues(t, "2023-08-29", customFields.Fields["Date-field"], fmt.Sprintf("Date-field unexpected value for %s resource.", customFieldResourceType))
115+
assert.EqualValues(t, "20:22:11.123", customFields.Fields["Time-field"], fmt.Sprintf("Time-field unexpected value for %s resource.", customFieldResourceType))
116+
assert.EqualValues(t, "2023-08-29T20:22:11.123Z", customFields.Fields["DateTime-field"], fmt.Sprintf("DateTime-field unexpected value for %s resource.", customFieldResourceType))
117+
assert.EqualValues(t, map[string]interface{}{"id": productType.ID, "typeId": "product-type"}, customFields.Fields["Reference-field"], fmt.Sprintf("Reference-field unexpected value for %s resource.", customFieldResourceType))
118+
assert.EqualValues(t, []any{"ENUM-1", "ENUM-3"}, customFields.Fields["Set-field"], fmt.Sprintf("Set-field unexpected value' for %s resource.", customFieldResourceType))
119+
return nil
120+
},
121+
),
122+
},
123+
}
124+
125+
// Remove Custom fields from the resource one by one
126+
for index := range customFieldTypes {
127+
var customFieldTypesReduced = []string{}
128+
for i := range customFieldTypes {
129+
if i == index {
130+
continue
131+
}
132+
customFieldTypesReduced = append(customFieldTypesReduced, customFieldTypes[i])
133+
}
134+
fieldTypeValue := customFieldTypes[index]
135+
136+
customFieldsAccTestSteps = append(customFieldsAccTestSteps, resource.TestStep{
137+
Config: getResourceConfig(customFieldResourceType, resourceShortName, resourceKey, customFieldTypesReduced),
138+
Check: resource.ComposeAggregateTestCheckFunc(
139+
func(s *terraform.State) error {
140+
customFields, err := getResourceCustomFields(s, customFieldResourceType, resourceFullName)
141+
if err != nil {
142+
return err
143+
}
144+
assert.Nil(t, customFields.Fields[fmt.Sprintf("%s-field", fieldTypeValue)], fmt.Sprintf("%s-field expected to be removed.", fieldTypeValue))
145+
return nil
146+
},
147+
),
148+
})
149+
}
150+
151+
// Remove all Custom fields from the resource
152+
customFieldsAccTestSteps = append(customFieldsAccTestSteps, resource.TestStep{
153+
Config: getResourceConfig(customFieldResourceType, resourceShortName, resourceKey, []string{}),
154+
Check: resource.ComposeAggregateTestCheckFunc(
155+
func(s *terraform.State) error {
156+
customFields, err := getResourceCustomFields(s, customFieldResourceType, resourceFullName)
157+
if err != nil {
158+
return err
159+
}
160+
assert.Nil(t, customFields, fmt.Sprintf("%v-field expected to be nil.", customFields))
161+
return nil
162+
},
163+
),
164+
})
165+
166+
resource.Test(t, resource.TestCase{
167+
PreCheck: func() { testAccPreCheck(t) },
168+
Providers: testAccProviders,
169+
Steps: customFieldsAccTestSteps,
170+
})
171+
}
172+
}
173+
174+
func getResourceConfig(resourceType, resourceName, resourceKey string, customFields []string) string {
175+
// Load templates
176+
tpl, err := template.ParseGlob("testdata/custom_fields_test/*")
177+
if err != nil {
178+
panic(err)
179+
}
180+
181+
templateData := map[string]any{
182+
"resource_type": resourceType,
183+
"resource_name": resourceName,
184+
"resource_key": resourceKey,
185+
"custom": customFields,
186+
}
187+
188+
var out bytes.Buffer
189+
err = tpl.ExecuteTemplate(&out, "main", templateData)
190+
if err != nil {
191+
panic(err)
192+
}
193+
194+
return out.String()
195+
}
196+
197+
func getResourceCustomFields(s *terraform.State, resourceType, identifier string) (*platform.CustomFields, error) {
198+
switch resourceType {
199+
case "commercetools_channel":
200+
channel, err := testGetChannel(s, identifier)
201+
return channel.Custom, err
202+
case "commercetools_cart_discount":
203+
cartDiscount, err := testGetCartDiscount(s, identifier)
204+
return cartDiscount.Custom, err
205+
case "commercetools_category":
206+
category, err := testGetCategory(s, identifier)
207+
return category.Custom, err
208+
case "commercetools_customer_group":
209+
customerGroup, err := testGetCustomerGroup(s, identifier)
210+
return customerGroup.Custom, err
211+
case "commercetools_discount_code":
212+
discountCode, err := testGetDiscountCode(s, identifier)
213+
return discountCode.Custom, err
214+
case "commercetools_shipping_method":
215+
shippingMethod, err := testGetShippingMethod(s, identifier)
216+
return shippingMethod.Custom, err
217+
case "commercetools_store":
218+
store, err := testGetStore(s, identifier)
219+
return store.Custom, err
220+
default:
221+
panic(fmt.Sprintf("Unknown resource type %s", resourceType))
222+
}
223+
}
224+
225+
func testGetCategory(s *terraform.State, identifier string) (*platform.Category, error) {
226+
rs, ok := s.RootModule().Resources[identifier]
227+
if !ok {
228+
return nil, fmt.Errorf("Category %s not found", identifier)
229+
}
230+
231+
client := getClient(testAccProvider.Meta())
232+
result, err := client.Categories().WithId(rs.Primary.ID).Get().Execute(context.Background())
233+
if err != nil {
234+
return nil, err
235+
}
236+
return result, nil
237+
}
238+
239+
func testGetShippingMethod(s *terraform.State, identifier string) (*platform.ShippingMethod, error) {
240+
rs, ok := s.RootModule().Resources[identifier]
241+
if !ok {
242+
return nil, fmt.Errorf("Shipping Method %s not found", identifier)
243+
}
244+
245+
client := getClient(testAccProvider.Meta())
246+
result, err := client.ShippingMethods().WithId(rs.Primary.ID).Get().Execute(context.Background())
247+
if err != nil {
248+
return nil, err
249+
}
250+
return result, nil
251+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{{define "commercetools_cart_discount"}}
2+
resource "commercetools_cart_discount" "{{.resource_name}}" {
3+
key = "{{.resource_key}}"
4+
name = {
5+
en = "relative name"
6+
}
7+
description = {
8+
en = "relative description"
9+
}
10+
sort_order = "0.9"
11+
predicate = "1=1"
12+
stacking_mode = "Stacking"
13+
requires_discount_code = true
14+
valid_from = "2018-01-02T15:04:05Z"
15+
valid_until = "2019-01-02T15:04:05Z"
16+
target {
17+
type = "lineItems"
18+
predicate = "1=1"
19+
}
20+
value {
21+
type = "relative"
22+
permyriad = 1000
23+
}
24+
{{if .custom}}{{template "custom" .}}{{end}}
25+
}
26+
{{end}}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{{define "commercetools_category"}}
2+
resource "commercetools_category" "{{.resource_name}}" {
3+
key = "{{.resource_key}}"
4+
name = {
5+
en = "commercetools category name"
6+
}
7+
slug = {
8+
en = "commercetools_category"
9+
}
10+
{{if .custom}}{{template "custom" .}}{{end}}
11+
}
12+
{{end}}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{{define "commercetools_channel"}}
2+
resource "commercetools_channel" {{.resource_name}} {
3+
key = "{{.resource_key}}"
4+
roles = ["ProductDistribution"]
5+
name = {
6+
nl-NL = "Channel"
7+
}
8+
description = {
9+
nl-NL = "Channel"
10+
}
11+
{{if .custom}}{{template "custom" .}}{{end}}
12+
}
13+
{{end}}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{{define "custom"}}
2+
custom {
3+
type_id = commercetools_type.test.id
4+
fields = {
5+
{{range $key, $value := .custom}}
6+
{{if eq $value "Boolean"}}
7+
"Boolean-field" : true
8+
{{end}}
9+
{{if eq $value "Number"}}
10+
"Number-field" : 1234
11+
{{end}}
12+
{{if eq $value "String"}}
13+
"String-field" : "foobar"
14+
{{end}}
15+
{{if eq $value "LocalizedString"}}
16+
"LocalizedString-field" = jsonencode({
17+
en = "Localized String"
18+
fr = "Chaîne localisée"
19+
})
20+
{{end}}
21+
{{if eq $value "Enum"}}
22+
"Enum-field" : "value2"
23+
{{end}}
24+
{{if eq $value "LocalizedEnum"}}
25+
"LocalizedEnum-field" = "value1"
26+
{{end}}
27+
{{if eq $value "Money"}}
28+
"Money-field" = jsonencode({
29+
"type" : "centPrecision",
30+
"currencyCode" : "EUR",
31+
"centAmount" : 150000,
32+
"fractionDigits" : 2
33+
})
34+
{{end}}
35+
{{if eq $value "Date"}}
36+
"Date-field" : "2023-08-29"
37+
{{end}}
38+
{{if eq $value "Time"}}
39+
"Time-field" : "20:22:11.123"
40+
{{end}}
41+
{{if eq $value "DateTime"}}
42+
"DateTime-field" : "2023-08-29T20:22:11.123Z"
43+
{{end}}
44+
{{if eq $value "Reference"}}
45+
"Reference-field" = jsonencode({
46+
"typeId": "product-type",
47+
"id": commercetools_product_type.test.id
48+
})
49+
{{end}}
50+
{{if eq $value "Set"}}
51+
"Set-field" = jsonencode(["ENUM-1", "ENUM-3"])
52+
{{end}}
53+
{{end}}
54+
}
55+
}
56+
{{end}}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{{define "commercetools_customer_group"}}
2+
resource "commercetools_customer_group" "{{.resource_name}}" {
3+
key = "{{.resource_key}}"
4+
name = "Test Customer Group"
5+
{{if .custom}}{{template "custom" .}}{{end}}
6+
}
7+
{{end}}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
{{define "commercetools_discount_code"}}
3+
resource "commercetools_cart_discount" "commercetools_cart_discount_test" {
4+
key = "commercetools_cart_discount_test"
5+
name = {
6+
en = "relative name"
7+
}
8+
description = {
9+
en = "relative description"
10+
}
11+
sort_order = "0.9"
12+
predicate = "1=1"
13+
stacking_mode = "Stacking"
14+
requires_discount_code = true
15+
valid_from = "2018-01-02T15:04:05Z"
16+
valid_until = "2019-01-02T15:04:05Z"
17+
target {
18+
type = "lineItems"
19+
predicate = "1=1"
20+
}
21+
value {
22+
type = "relative"
23+
permyriad = 1000
24+
}
25+
}
26+
27+
resource "commercetools_discount_code" "{{.resource_name}}" {
28+
code = "2"
29+
cart_discounts = [commercetools_cart_discount.commercetools_cart_discount_test.id]
30+
{{if .custom}}{{template "custom" .}}{{end}}
31+
}
32+
{{end}}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{{define "commercetools_product_type"}}
2+
resource "commercetools_product_type" "test" {
3+
key = "product-type"
4+
name = "Product Type"
5+
}
6+
{{end}}

0 commit comments

Comments
 (0)