Skip to content

Commit 196c706

Browse files
committed
Fix WA templating generation and add tests
1 parent 39f06b1 commit 196c706

File tree

4 files changed

+95
-23
lines changed

4 files changed

+95
-23
lines changed

Diff for: handlers/dialog360/handler.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ func (h *handler) Send(ctx context.Context, msg courier.MsgOut, res *courier.Sen
323323
}
324324
if templating != nil {
325325
payload.Type = "template"
326-
payload.Template = whatsapp.GetTemplatePayload(*templating)
326+
payload.Template = whatsapp.GetTemplatePayload(templating)
327327
} else {
328328
if i < (len(msgParts) + len(msg.Attachments()) - 1) {
329329
// this is still a msg part

Diff for: handlers/meta/handlers.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ func (h *handler) sendWhatsAppMsg(ctx context.Context, msg courier.MsgOut, res *
811811
}
812812
if templating != nil {
813813
payload.Type = "template"
814-
payload.Template = whatsapp.GetTemplatePayload(*templating)
814+
payload.Template = whatsapp.GetTemplatePayload(templating)
815815

816816
} else {
817817
if i < (len(msgParts) + len(msg.Attachments()) - 1) {

Diff for: handlers/meta/whatsapp/templates.go

+23-21
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,23 @@ func GetTemplating(msg courier.MsgOut) (*MsgTemplating, error) {
4747
return metadata.Templating, nil
4848
}
4949

50-
func GetTemplatePayload(templating MsgTemplating) *Template {
51-
template := &Template{Name: templating.Template.Name, Language: &Language{Policy: "deterministic", Code: templating.Language}}
50+
func GetTemplatePayload(templating *MsgTemplating) *Template {
51+
template := &Template{
52+
Name: templating.Template.Name,
53+
Language: &Language{Policy: "deterministic", Code: templating.Language},
54+
Components: []*Component{},
55+
}
5256

5357
compKeys := maps.Keys(templating.Params)
5458
sort.Strings(compKeys) // so that final component order is deterministic
5559

5660
for _, k := range compKeys {
5761
v := templating.Params[k]
62+
var component *Component
5863

59-
if strings.HasPrefix(k, "button.") {
60-
61-
for _, p := range v {
62-
if p.Type == "url" {
63-
component := &Component{Type: "button", Index: strings.TrimPrefix(k, "button."), SubType: "quick_reply"}
64-
component.Params = append(component.Params, &Param{Type: "text", Text: p.Value})
65-
template.Components = append(template.Components, component)
66-
} else {
67-
component := &Component{Type: "button", Index: strings.TrimPrefix(k, "button."), SubType: "quick_reply"}
68-
component.Params = append(component.Params, &Param{Type: "payload", Payload: p.Value})
69-
template.Components = append(template.Components, component)
70-
}
71-
}
64+
if k == "header" {
65+
component = &Component{Type: "header"}
7266

73-
} else if k == "header" {
74-
component := &Component{Type: "header"}
7567
for _, p := range v {
7668
if p.Type == "image" {
7769
component.Params = append(component.Params, &Param{Type: p.Type, Image: &struct {
@@ -89,17 +81,27 @@ func GetTemplatePayload(templating MsgTemplating) *Template {
8981
component.Params = append(component.Params, &Param{Type: p.Type, Text: p.Value})
9082
}
9183
}
92-
template.Components = append(template.Components, component)
84+
} else if k == "body" {
85+
component = &Component{Type: "body"}
9386

94-
} else {
95-
component := &Component{Type: "body"}
9687
for _, p := range v {
9788
component.Params = append(component.Params, &Param{Type: p.Type, Text: p.Value})
9889
}
99-
template.Components = append(template.Components, component)
90+
} else if strings.HasPrefix(k, "button.") {
91+
component = &Component{Type: "button", Index: strings.TrimPrefix(k, "button."), SubType: "quick_reply", Params: []*Param{}}
10092

93+
for _, p := range v {
94+
if p.Type == "url" {
95+
component.Params = append(component.Params, &Param{Type: "text", Text: p.Value})
96+
} else {
97+
component.Params = append(component.Params, &Param{Type: "payload", Payload: p.Value})
98+
}
99+
}
101100
}
102101

102+
if component != nil {
103+
template.Components = append(template.Components, component)
104+
}
103105
}
104106

105107
return template

Diff for: handlers/meta/whatsapp/templates_test.go

+70
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package whatsapp_test
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"testing"
67

78
"github.com/nyaruka/courier/handlers/meta/whatsapp"
89
"github.com/nyaruka/courier/test"
910
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
1012
)
1113

1214
func TestGetTemplating(t *testing.T) {
@@ -39,3 +41,71 @@ func TestGetTemplating(t *testing.T) {
3941
assert.Equal(t, "4ed5000f-5c94-4143-9697-b7cbd230a381", tpl.Template.UUID)
4042
assert.Equal(t, "Update", tpl.Template.Name)
4143
}
44+
45+
func TestGetTemplatePayload(t *testing.T) {
46+
tcs := []struct {
47+
templating string
48+
expected *whatsapp.Template
49+
}{
50+
{
51+
templating: `{
52+
"template": {"uuid": "4ed5000f-5c94-4143-9697-b7cbd230a381", "name": "Update"},
53+
"namespace": "12345",
54+
"language": "en",
55+
"params": {}
56+
}`,
57+
expected: &whatsapp.Template{
58+
Name: "Update",
59+
Language: &whatsapp.Language{Policy: "deterministic", Code: "en"},
60+
Components: []*whatsapp.Component{},
61+
},
62+
},
63+
{
64+
templating: `{
65+
"template": {"uuid": "4ed5000f-5c94-4143-9697-b7cbd230a381", "name": "Update"},
66+
"language": "en",
67+
"params": {
68+
"header": [{"type": "text", "value": "Welome"}],
69+
"body": [{"type": "text", "value": "Hello"}, {"type": "text", "value": "Bob"}]
70+
}
71+
}`,
72+
expected: &whatsapp.Template{
73+
Name: "Update",
74+
Language: &whatsapp.Language{Policy: "deterministic", Code: "en"},
75+
Components: []*whatsapp.Component{
76+
{Type: "body", Params: []*whatsapp.Param{{Type: "text", Text: "Hello"}, {Type: "text", Text: "Bob"}}},
77+
{Type: "header", Params: []*whatsapp.Param{{Type: "text", Text: "Welome"}}},
78+
},
79+
},
80+
},
81+
{
82+
templating: `{
83+
"template": {"uuid": "4ed5000f-5c94-4143-9697-b7cbd230a381", "name": "Update"},
84+
"language": "en",
85+
"params": {
86+
"button.1": [{"type": "text", "value": "No"}],
87+
"button.0": [{"type": "text", "value": "Yes"}, {"type": "text", "value": "Bob"}]
88+
}
89+
}`,
90+
expected: &whatsapp.Template{
91+
Name: "Update",
92+
Language: &whatsapp.Language{Policy: "deterministic", Code: "en"},
93+
Components: []*whatsapp.Component{
94+
{Type: "button", SubType: "quick_reply", Index: "0", Params: []*whatsapp.Param{{Type: "payload", Payload: "Yes"}, {Type: "payload", Payload: "Bob"}}},
95+
{Type: "button", SubType: "quick_reply", Index: "1", Params: []*whatsapp.Param{{Type: "payload", Payload: "No"}}},
96+
},
97+
},
98+
},
99+
}
100+
101+
for _, tc := range tcs {
102+
metadata := json.RawMessage(fmt.Sprintf(`{"templating": %s}`, tc.templating))
103+
msg := test.NewMockMsg(1, "87995844-2017-4ba0-bc73-f3da75b32f9b", nil, "tel:+1234567890", "hi", nil).WithMetadata(metadata)
104+
templating, err := whatsapp.GetTemplating(msg)
105+
require.NoError(t, err)
106+
107+
actual := whatsapp.GetTemplatePayload(templating)
108+
109+
assert.Equal(t, tc.expected, actual)
110+
}
111+
}

0 commit comments

Comments
 (0)