1
0
mirror of synced 2024-11-24 05:56:04 +03:00

Mock data in tests (#76)

* mock all data in tests
* update test matrix config
This commit is contained in:
Pavel 2021-11-22 16:08:53 +03:00 committed by GitHub
parent b5df3a70bc
commit 1306d648f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 481 additions and 347 deletions

View File

@ -10,9 +10,6 @@ on:
env:
GO111MODULE: on
MG_URL: ${{ secrets.MG_URL }}
MG_TOKEN: ${{ secrets.MG_TOKEN }}
MG_CHANNEL: ${{ secrets.MG_CHANNEL }}
jobs:
golangci:
@ -31,9 +28,8 @@ jobs:
name: Tests
runs-on: ubuntu-latest
strategy:
max-parallel: 1
matrix:
go-version: ['1.11', '1.12', '1.13', '1.14', '1.15']
go-version: ['1.11', '1.12', '1.13', '1.14', '1.15', '1.16', '1.17']
steps:
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v2

1
go.mod
View File

@ -5,4 +5,5 @@ go 1.11
require (
github.com/google/go-querystring v1.0.0
github.com/stretchr/testify v1.4.0
gopkg.in/h2non/gock.v1 v1.1.2
)

7
go.sum
View File

@ -2,13 +2,18 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -7,18 +7,19 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"time"
"github.com/google/go-querystring/query"
)
// New initialize client
// New initialize client.
func New(url string, token string) *MgClient {
return NewWithClient(url, token, &http.Client{Timeout: time.Minute})
}
// NewWithClient initializes client with provided http client
// NewWithClient initializes client with provided http client.
func NewWithClient(url string, token string, client *http.Client) *MgClient {
return &MgClient{
URL: url,
@ -59,7 +60,7 @@ func (c *MgClient) TransportTemplates() ([]Template, int, error) {
return resp, status, err
}
// ActivateTransportChannel implements template activation
// ActivateTemplate implements template activation
//
// Example:
// var client = v1.New("https://token.url", "cb8ccf05e38a47543ad8477d4999be73bff503ea6")
@ -140,7 +141,8 @@ func (c *MgClient) UpdateTemplate(request Template) (int, error) {
return 0, errors.New("`ChannelID` and `Code` cannot be blank")
}
data, status, err := c.PutRequest(fmt.Sprintf("/channels/%d/templates/%s", request.ChannelID, request.Code), outgoing)
data, status, err := c.PutRequest(
fmt.Sprintf("/channels/%d/templates/%s", request.ChannelID, url.PathEscape(request.Code)), outgoing)
if err != nil {
return status, err
}
@ -165,7 +167,7 @@ func (c *MgClient) UpdateTemplate(request Template) (int, error) {
// }
func (c *MgClient) DeactivateTemplate(channelID uint64, templateCode string) (int, error) {
data, status, err := c.DeleteRequest(
fmt.Sprintf("/channels/%d/templates/%s", channelID, templateCode), []byte{})
fmt.Sprintf("/channels/%d/templates/%s", channelID, url.PathEscape(templateCode)), []byte{})
if err != nil {
return status, err
}
@ -313,7 +315,7 @@ func (c *MgClient) UpdateTransportChannel(request Channel) (UpdateResponse, int,
var resp UpdateResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PutRequest(fmt.Sprintf("/channels/%d", request.ID), []byte(outgoing))
data, status, err := c.PutRequest(fmt.Sprintf("/channels/%d", request.ID), outgoing)
if err != nil {
return resp, status, err
}
@ -442,7 +444,7 @@ func (c *MgClient) UpdateMessages(request EditMessageRequest) (MessagesResponse,
var resp MessagesResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PutRequest("/messages", []byte(outgoing))
data, status, err := c.PutRequest("/messages", outgoing)
if err != nil {
return resp, status, err
}
@ -554,7 +556,7 @@ func (c *MgClient) DeleteMessage(request DeleteData) (*MessagesResponse, int, er
data, status, err := c.DeleteRequest(
"/messages",
[]byte(outgoing),
outgoing,
)
if err != nil {
return nil, status, err
@ -605,7 +607,7 @@ func (c *MgClient) GetFile(request string) (FullFileResponse, int, error) {
return resp, status, err
}
// UploadFile upload file
// UploadFile upload file.
func (c *MgClient) UploadFile(request io.Reader) (UploadFileResponse, int, error) {
var resp UploadFileResponse
@ -625,7 +627,7 @@ func (c *MgClient) UploadFile(request io.Reader) (UploadFileResponse, int, error
return resp, status, err
}
// UploadFileByURL upload file by url
// UploadFileByURL upload file by url.
func (c *MgClient) UploadFileByURL(request UploadFileByUrlRequest) (UploadFileResponse, int, error) {
var resp UploadFileResponse
outgoing, _ := json.Marshal(&request)
@ -658,7 +660,7 @@ func (c *MgClient) Error(info []byte) error {
return errors.New(values[0].(string))
}
// MakeTimestamp returns current unix timestamp
// MakeTimestamp returns current unix timestamp.
func MakeTimestamp() int64 {
return time.Now().UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
}

View File

@ -5,105 +5,113 @@ import (
"encoding/base64"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"gopkg.in/h2non/gock.v1"
)
var (
mgURL = os.Getenv("MG_URL")
mgToken = os.Getenv("MG_TOKEN")
channelID, _ = strconv.ParseUint(os.Getenv("MG_CHANNEL"), 10, 64)
ext = strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
tplCode = fmt.Sprintf("testTemplate_%d", time.Now().UnixNano())
tplChannel uint64 = 0
)
type MGClientTest struct {
suite.Suite
}
func client() *MgClient {
c := New(mgURL, mgToken)
func TestMGClient(t *testing.T) {
suite.Run(t, new(MGClientTest))
}
func (t *MGClientTest) client() *MgClient {
c := New("https://mg-test.retailcrm.pro", "mg_token")
c.Debug = true
return c
}
func templateChannel(t *testing.T) uint64 {
if tplChannel == 0 {
c := client()
resp, _, err := c.ActivateTransportChannel(Channel{
Type: "telegram",
Name: "@test_channel_templates",
func (t *MGClientTest) gock() *gock.Request {
return gock.New("https://mg-test.retailcrm.pro").MatchHeader("x-transport-token", "mg_token")
}
func (t *MGClientTest) transportURL(path string) string {
return "/api/transport/v1/" + strings.TrimLeft(path, "/")
}
func (t *MGClientTest) Test_TransportChannels() {
c := t.client()
chName := "WhatsApp Channel"
createdAt := "2021-11-22T08:20:46.479979Z"
defer gock.Off()
t.gock().
Get(t.transportURL("channels")).
Reply(http.StatusOK).
JSON([]ChannelListItem{{
ID: 1,
ExternalID: "external_id",
Type: "whatsapp",
Name: &chName,
Settings: ChannelSettings{
Status: Status{
Delivered: ChannelFeatureBoth,
Read: ChannelFeatureBoth,
Delivered: ChannelFeatureNone,
Read: ChannelFeatureSend,
},
Text: ChannelSettingsText{
Creating: ChannelFeatureBoth,
Editing: ChannelFeatureBoth,
Quoting: ChannelFeatureBoth,
Deleting: ChannelFeatureBoth,
MaxCharsCount: 5000,
Deleting: ChannelFeatureReceive,
MaxCharsCount: 4096,
},
Product: Product{
Creating: ChannelFeatureBoth,
Editing: ChannelFeatureBoth,
Deleting: ChannelFeatureBoth,
Creating: ChannelFeatureReceive,
Editing: ChannelFeatureReceive,
},
Order: Order{
Creating: ChannelFeatureBoth,
Editing: ChannelFeatureBoth,
Deleting: ChannelFeatureBoth,
Creating: ChannelFeatureReceive,
Editing: ChannelFeatureReceive,
},
File: ChannelSettingsFilesBase{
Creating: ChannelFeatureBoth,
Editing: ChannelFeatureBoth,
Quoting: ChannelFeatureBoth,
Deleting: ChannelFeatureBoth,
Max: 1000000,
CommentMaxCharsCount: 128,
Deleting: ChannelFeatureReceive,
Max: 1,
},
Image: ChannelSettingsFilesBase{
Creating: ChannelFeatureBoth,
Editing: ChannelFeatureBoth,
Quoting: ChannelFeatureBoth,
Deleting: ChannelFeatureBoth,
Deleting: ChannelFeatureReceive,
Max: 1, // nolint:gomnd
},
Suggestions: ChannelSettingsSuggestions{
Text: ChannelFeatureBoth,
Phone: ChannelFeatureBoth,
Email: ChannelFeatureBoth,
},
CustomerExternalID: ChannelFeatureCustomerExternalIDPhone,
SendingPolicy: SendingPolicy{
NewCustomer: ChannelFeatureSendingPolicyTemplate,
},
},
})
if err != nil {
t.FailNow()
}
tplChannel = resp.ChannelID
}
return tplChannel
}
func TestMgClient_TransportChannels(t *testing.T) {
c := client()
CreatedAt: createdAt,
UpdatedAt: &createdAt,
ActivatedAt: createdAt,
DeactivatedAt: nil,
IsActive: true,
}})
data, status, err := c.TransportChannels(Channels{Active: true})
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
if err != nil {
t.Errorf("%d %v", status, err)
}
t.Logf("Channels found: %v", len(data))
t.Assert().Len(data, 1)
}
func TestMgClient_ActivateTransportChannel(t *testing.T) {
c := client()
func (t *MGClientTest) Test_ActivateTransportChannel() {
c := t.client()
ch := Channel{
ID: channelID,
ID: 1,
Type: "telegram",
Name: "@my_shopping_bot",
Settings: ChannelSettings{
@ -135,17 +143,27 @@ func TestMgClient_ActivateTransportChannel(t *testing.T) {
},
}
defer gock.Off()
t.gock().
Post(t.transportURL("channels")).
Reply(http.StatusCreated).
JSON(ActivateResponse{
ChannelID: 1,
ExternalID: "external_id_1",
ActivatedAt: time.Now(),
})
data, status, err := c.ActivateTransportChannel(ch)
t.Require().NoError(err)
t.Assert().Equal(http.StatusCreated, status)
if err != nil {
t.Errorf("%d %v", status, err)
}
t.Logf("Activate selected channel: %v", data.ChannelID)
t.Assert().Equal(uint64(1), data.ChannelID)
t.Assert().Equal("external_id_1", data.ExternalID)
t.Assert().NotEmpty(data.ActivatedAt.String())
}
func TestMgClient_ActivateNewTransportChannel(t *testing.T) {
c := client()
func (t *MGClientTest) Test_ActivateNewTransportChannel() {
c := t.client()
ch := Channel{
Type: "telegram",
Name: "@my_shopping_bot",
@ -177,31 +195,44 @@ func TestMgClient_ActivateNewTransportChannel(t *testing.T) {
},
}
defer gock.Off()
t.gock().
Post(t.transportURL("channels")).
Reply(http.StatusCreated).
JSON(ActivateResponse{
ChannelID: 1,
ExternalID: "external_id_1",
ActivatedAt: time.Now(),
})
t.gock().
Delete(t.transportURL("channels/1")).
Reply(http.StatusOK).
JSON(DeleteResponse{
ChannelID: 1,
DeactivatedAt: time.Now(),
})
data, status, err := c.ActivateTransportChannel(ch)
t.Require().NoError(err)
t.Assert().Equal(http.StatusCreated, status)
if err != nil {
t.Errorf("%d %v", status, err)
}
t.Logf("New channel ID %v", data.ChannelID)
t.Assert().Equal(uint64(1), data.ChannelID)
t.Assert().Equal("external_id_1", data.ExternalID)
t.Assert().NotEmpty(data.ActivatedAt.String())
deleteData, status, err := c.DeactivateTransportChannel(data.ChannelID)
if err != nil {
t.Errorf("%d %v", status, err)
}
if deleteData.DeactivatedAt.String() == "" {
t.Errorf("%v", err)
}
t.Logf("Deactivate new channel with ID %v", deleteData.ChannelID)
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
t.Assert().NotEmpty(deleteData.DeactivatedAt.String())
t.Assert().Equal(uint64(1), deleteData.ChannelID)
}
func TestMgClient_UpdateTransportChannel(t *testing.T) {
c := client()
func (t *MGClientTest) Test_UpdateTransportChannel() {
c := t.client()
ch := Channel{
ID: channelID,
ID: 1,
Name: "@my_shopping_bot_2",
Settings: ChannelSettings{
Status: Status{
@ -231,44 +262,79 @@ func TestMgClient_UpdateTransportChannel(t *testing.T) {
},
}
defer gock.Off()
t.gock().
Put(t.transportURL("channels/1")).
Reply(http.StatusOK).
JSON(UpdateResponse{
ChannelID: uint64(1),
ExternalID: "external_id_1",
UpdatedAt: time.Now(),
})
data, status, err := c.UpdateTransportChannel(ch)
if status != http.StatusOK {
t.Errorf("%v", err)
}
t.Logf("Update selected channel: %v", data.ChannelID)
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
t.Assert().Equal(uint64(1), data.ChannelID)
t.Assert().Equal("external_id_1", data.ExternalID)
t.Assert().NotEmpty(data.UpdatedAt.String())
}
func TestMgClient_TransportTemplates(t *testing.T) {
c := client()
func (t *MGClientTest) Test_TransportTemplates() {
c := t.client()
defer gock.Off()
t.gock().
Get(t.transportURL("templates")).
Reply(http.StatusOK).
JSON([]Template{{
Code: "tpl_code",
ChannelID: 1,
Name: "Test Template",
Enabled: true,
Type: TemplateTypeText,
Template: []TemplateItem{
{
Type: TemplateItemTypeText,
Text: "Hello, ",
},
{
Type: TemplateItemTypeVar,
VarType: TemplateVarFirstName,
},
{
Type: TemplateItemTypeText,
Text: "! We're glad to see you back in our store.",
},
},
}})
data, status, err := c.TransportTemplates()
assert.NoError(t, err, fmt.Sprintf("%d %s", status, err))
t.Logf("Templates found: %#v", len(data))
t.Assert().NoError(err, fmt.Sprintf("%d %s", status, err))
t.Assert().Equal(http.StatusOK, status)
t.Assert().Len(data, 1)
for _, item := range data {
for _, tpl := range item.Template {
if tpl.Type == TemplateItemTypeText {
assert.Empty(t, tpl.VarType)
t.Assert().Empty(tpl.VarType)
} else {
assert.Empty(t, tpl.Text)
assert.NotEmpty(t, tpl.VarType)
t.Assert().Empty(tpl.Text)
t.Assert().NotEmpty(tpl.VarType)
if _, ok := templateVarAssoc[tpl.VarType]; !ok {
t.Errorf("unknown TemplateVar type %s", tpl.VarType)
t.T().Errorf("unknown TemplateVar type %s", tpl.VarType)
}
}
}
}
}
func TestMgClient_ActivateTemplate(t *testing.T) {
c := client()
func (t *MGClientTest) Test_ActivateTemplate() {
c := t.client()
req := ActivateTemplateRequest{
Code: tplCode,
Name: tplCode,
Code: "tplCode",
Name: "tplCode",
Type: TemplateTypeText,
Template: []TemplateItem{
{
@ -286,17 +352,22 @@ func TestMgClient_ActivateTemplate(t *testing.T) {
},
}
status, err := c.ActivateTemplate(templateChannel(t), req)
assert.NoError(t, err, fmt.Sprintf("%d %s", status, err))
defer gock.Off()
t.gock().
Post("/channels/1/templates").
Reply(http.StatusCreated).
JSON(map[string]interface{}{})
t.Logf("Activated template with code `%s`", req.Code)
status, err := c.ActivateTemplate(1, req)
t.Assert().NoError(err, fmt.Sprintf("%d %s", status, err))
t.Assert().Equal(http.StatusCreated, status)
}
func TestMgClient_UpdateTemplate(t *testing.T) {
c := client()
func (t *MGClientTest) Test_UpdateTemplate() {
c := t.client()
tpl := Template{
Code: tplCode,
ChannelID: templateChannel(t),
Code: "encodable#code",
ChannelID: 1,
Name: "updated name",
Enabled: true,
Type: TemplateTypeText,
@ -316,21 +387,36 @@ func TestMgClient_UpdateTemplate(t *testing.T) {
},
}
defer gock.Off()
t.gock().
Filter(func(r *http.Request) bool {
return r.Method == http.MethodPut &&
r.URL.Path == "/api/transport/v1/channels/1/templates/encodable#code"
}).
Reply(http.StatusOK).
JSON(map[string]interface{}{})
t.gock().
Get(t.transportURL("templates")).
Reply(http.StatusOK).
JSON([]Template{tpl})
status, err := c.UpdateTemplate(tpl)
assert.NoError(t, err, fmt.Sprintf("%d %s", status, err))
t.Assert().NoError(err, fmt.Sprintf("%d %s", status, err))
templates, status, err := c.TransportTemplates()
assert.NoError(t, err, fmt.Sprintf("%d %s", status, err))
t.Assert().NoError(err, fmt.Sprintf("%d %s", status, err))
for _, template := range templates {
if template.Code == tpl.Code {
assert.Equal(t, tpl.Name, template.Name)
t.Assert().Equal(tpl.Name, template.Name)
}
}
}
func TestMgClient_UpdateTemplateFail(t *testing.T) {
c := client()
func (t *MGClientTest) Test_UpdateTemplateFail() {
c := t.client()
tpl := Template{
Name: "updated name",
Enabled: true,
@ -351,23 +437,39 @@ func TestMgClient_UpdateTemplateFail(t *testing.T) {
},
}
defer gock.Off()
t.gock().
Reply(http.StatusBadRequest).
JSON(map[string][]string{
"errors": {"Some weird error message..."},
})
status, err := c.UpdateTemplate(tpl)
assert.Error(t, err, fmt.Sprintf("%d %s", status, err))
t.Assert().Error(err, fmt.Sprintf("%d %s", status, err))
}
func TestMgClient_DeactivateTemplate(t *testing.T) {
c := client()
status, err := c.DeactivateTemplate(templateChannel(t), tplCode)
assert.NoError(t, err, fmt.Sprintf("%d %s", status, err))
func (t *MGClientTest) Test_DeactivateTemplate() {
c := t.client()
defer gock.Off()
t.gock().
Filter(func(r *http.Request) bool {
return r.Method == http.MethodDelete &&
r.URL.Path == t.transportURL("channels/1/templates/test_template#code")
}).
Reply(http.StatusOK).
JSON(map[string]interface{}{})
status, err := c.DeactivateTemplate(1, "test_template#code")
t.Assert().NoError(err, fmt.Sprintf("%d %s", status, err))
}
func TestMgClient_TextMessages(t *testing.T) {
c := client()
t.Logf("%v", ext)
func (t *MGClientTest) Test_TextMessages() {
c := t.client()
snd := SendData{
Message: Message{
ExternalID: ext,
ExternalID: "external_id",
Type: MsgTypeText,
Text: "hello!",
},
@ -377,38 +479,61 @@ func TestMgClient_TextMessages(t *testing.T) {
Nickname: "octopus",
Firstname: "Joe",
},
Channel: channelID,
Channel: 1,
ExternalChatID: "24798237492374",
}
defer gock.Off()
t.gock().
Post(t.transportURL("messages")).
Reply(http.StatusOK).
JSON(MessagesResponse{
MessageID: 1,
Time: time.Now(),
})
data, status, err := c.Messages(snd)
if status != http.StatusOK {
t.Errorf("%v", err)
}
if data.Time.String() == "" {
t.Errorf("%v", err)
}
t.Logf("Message %v is sent", data.MessageID)
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
t.Assert().NotEmpty(data.Time.String())
t.Assert().Equal(1, data.MessageID)
}
func TestMgClient_ImageMessages(t *testing.T) {
c := client()
t.Logf("%v", ext)
func (t *MGClientTest) Test_ImageMessages() {
c := t.client()
defer gock.Off()
t.gock().
Post(t.transportURL("files/upload_by_url")).
Reply(http.StatusOK).
JSON(UploadFileResponse{
ID: "1",
Hash: "1",
Type: "image/png",
MimeType: "",
Size: 1024,
CreatedAt: time.Now(),
})
t.gock().
Post(t.transportURL("messages")).
Reply(http.StatusOK).
JSON(MessagesResponse{
MessageID: 1,
Time: time.Now(),
})
uploadFileResponse, st, err := c.UploadFileByURL(UploadFileByUrlRequest{
Url: "https://via.placeholder.com/1",
})
if st != http.StatusOK {
t.Errorf("%v", err)
}
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, st)
t.Assert().Equal("1", uploadFileResponse.ID)
snd := SendData{
Message: Message{
ExternalID: ext + "file",
ExternalID: "file",
Type: MsgTypeImage,
Items: []Item{{ID: uploadFileResponse.ID}},
},
@ -418,135 +543,138 @@ func TestMgClient_ImageMessages(t *testing.T) {
Nickname: "octopus",
Firstname: "Joe",
},
Channel: channelID,
Channel: 1,
ExternalChatID: "24798237492374",
}
data, status, err := c.Messages(snd)
if status != http.StatusOK {
t.Errorf("%v", err)
}
if data.Time.String() == "" {
t.Errorf("%v", err)
}
t.Logf("Message %v is sent", data.MessageID)
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
t.Assert().NotEmpty(data.Time.String())
t.Assert().Equal(1, data.MessageID)
}
func TestMgClient_UpdateMessages(t *testing.T) {
c := client()
t.Logf("%v", ext)
func (t *MGClientTest) Test_UpdateMessages() {
c := t.client()
sndU := EditMessageRequest{
EditMessageRequestMessage{
ExternalID: ext,
ExternalID: "editing",
Text: "hello hello!",
},
channelID,
1,
}
defer gock.Off()
t.gock().
Put(t.transportURL("messages")).
Reply(http.StatusOK).
JSON(MessagesResponse{
MessageID: 1,
Time: time.Now(),
})
dataU, status, err := c.UpdateMessages(sndU)
if status != http.StatusOK {
t.Errorf("%v", err)
}
if dataU.Time.String() == "" {
t.Errorf("%v", err)
}
t.Logf("Message %v updated", dataU.MessageID)
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
t.Assert().NotEmpty(dataU.Time.String())
t.Assert().Equal(1, dataU.MessageID)
}
func TestMgClient_MarkMessageReadAndDelete(t *testing.T) {
c := client()
t.Logf("%v", ext)
func (t *MGClientTest) Test_MarkMessageReadAndDelete() {
c := t.client()
snd := MarkMessageReadRequest{
MarkMessageReadRequestMessage{
ExternalID: ext,
ExternalID: "external_1",
},
channelID,
1,
}
defer gock.Off()
t.gock().
Post(t.transportURL("messages/read")).
Reply(http.StatusOK).
JSON(MarkMessageReadResponse{})
t.gock().
Delete(t.transportURL("messages")).
JSON(DeleteData{
Message: Message{
ExternalID: "deleted",
},
Channel: 1,
}).
Reply(http.StatusOK).
JSON(MessagesResponse{
MessageID: 2,
Time: time.Now(),
})
_, status, err := c.MarkMessageRead(snd)
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
if status != http.StatusOK {
t.Errorf("%v", err)
}
t.Logf("Message ext marked as read")
sndD := DeleteData{
previousChatMessage, status, err := c.DeleteMessage(DeleteData{
Message{
ExternalID: ext,
ExternalID: "deleted",
},
channelID,
}
previousChatMessage, status, err := c.DeleteMessage(sndD)
if status != http.StatusOK {
t.Errorf("%v", err)
}
t.Logf("Message %v deleted", ext)
if previousChatMessage != nil {
t.Logf("Previous chat message %+v", *previousChatMessage)
}
sndD = DeleteData{
Message{
ExternalID: ext + "file",
},
channelID,
}
previousChatMessage, status, err = c.DeleteMessage(sndD)
if status != http.StatusOK {
t.Errorf("%v", err)
}
t.Logf("Message %v deleted", ext+"file")
if previousChatMessage != nil {
t.Logf("Previous chat message %+v", *previousChatMessage)
}
1,
})
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
t.Assert().Equal(2, previousChatMessage.MessageID)
}
func TestMgClient_DeactivateTransportChannel(t *testing.T) {
c := client()
deleteData, status, err := c.DeactivateTransportChannel(channelID)
func (t *MGClientTest) Test_DeactivateTransportChannel() {
c := t.client()
if err != nil {
t.Errorf("%d %v", status, err)
}
defer gock.Off()
t.gock().
Delete(t.transportURL("channels/1")).
Reply(http.StatusOK).
JSON(DeleteResponse{
ChannelID: 1,
DeactivatedAt: time.Now(),
})
if deleteData.DeactivatedAt.String() == "" {
t.Errorf("%v", err)
}
t.Logf("Deactivate selected channel: %v", deleteData.ChannelID)
deleteData, status, err := c.DeactivateTransportChannel(1)
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
t.Assert().NotEmpty(deleteData.DeactivatedAt.String())
t.Assert().Equal(uint64(1), deleteData.ChannelID)
}
func TestMgClient_UploadFile(t *testing.T) {
c := client()
t.Logf("%v", ext)
func (t *MGClientTest) Test_UploadFile() {
c := t.client()
// 1x1 png picture
img := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII="
binary, err := base64.StdEncoding.DecodeString(img)
if err != nil {
t.Errorf("cannot convert base64 to binary: %s", err)
t.T().Errorf("cannot convert base64 to binary: %s", err)
}
resp := UploadFileResponse{
ID: "1",
Hash: "1",
Type: "image/png",
MimeType: "",
Size: 1024,
CreatedAt: time.Now(),
}
defer gock.Off()
t.gock().
Post(t.transportURL("files/upload")).
Body(bytes.NewReader(binary)).
Reply(http.StatusOK).
JSON(resp)
data, status, err := c.UploadFile(bytes.NewReader(binary))
t.Require().NoError(err)
t.Assert().Equal(http.StatusOK, status)
if status != http.StatusOK {
t.Errorf("%v", err)
}
t.Logf("Message %+v is sent", data)
resp.CreatedAt = data.CreatedAt
t.Assert().Equal(resp, data)
}

View File

@ -12,7 +12,7 @@ import (
var prefix = "/api/transport/v1"
// GetRequest implements GET Request
// GetRequest implements GET Request.
func (c *MgClient) GetRequest(url string, parameters []byte) ([]byte, int, error) {
return makeRequest(
"GET",
@ -22,7 +22,7 @@ func (c *MgClient) GetRequest(url string, parameters []byte) ([]byte, int, error
)
}
// PostRequest implements POST Request
// PostRequest implements POST Request.
func (c *MgClient) PostRequest(url string, parameters io.Reader) ([]byte, int, error) {
return makeRequest(
"POST",
@ -32,7 +32,7 @@ func (c *MgClient) PostRequest(url string, parameters io.Reader) ([]byte, int, e
)
}
// PutRequest implements PUT Request
// PutRequest implements PUT Request.
func (c *MgClient) PutRequest(url string, parameters []byte) ([]byte, int, error) {
return makeRequest(
"PUT",
@ -42,7 +42,7 @@ func (c *MgClient) PutRequest(url string, parameters []byte) ([]byte, int, error
)
}
// DeleteRequest implements DELETE Request
// DeleteRequest implements DELETE Request.
func (c *MgClient) DeleteRequest(url string, parameters []byte) ([]byte, int, error) {
return makeRequest(
"DELETE",
@ -63,7 +63,7 @@ func makeRequest(reqType, url string, buf io.Reader, c *MgClient) ([]byte, int,
req.Header.Set("X-Transport-Token", c.Token)
if c.Debug {
if strings.Index(url, "/files/upload") != -1 {
if strings.Contains(url, "/files/upload") {
log.Printf("MG TRANSPORT API Request: %s %s %s [file data]", reqType, url, c.Token)
} else {
log.Printf("MG TRANSPORT API Request: %s %s %s %v", reqType, url, c.Token, buf)

View File

@ -10,24 +10,24 @@ import (
const TemplateTypeText = "text"
const (
// TemplateItemTypeText is a type for text chunk in template
// TemplateItemTypeText is a type for text chunk in template.
TemplateItemTypeText uint8 = iota
// TemplateItemTypeVar is a type for variable in template
// TemplateItemTypeVar is a type for variable in template.
TemplateItemTypeVar
)
const (
// TemplateVarCustom is a custom variable type
// TemplateVarCustom is a custom variable type.
TemplateVarCustom = "custom"
// TemplateVarName is a name variable type
// TemplateVarName is a name variable type.
TemplateVarName = "name"
// TemplateVarFirstName is a first name variable type
// TemplateVarFirstName is a first name variable type.
TemplateVarFirstName = "first_name"
// TemplateVarLastName is a last name variable type
// TemplateVarLastName is a last name variable type.
TemplateVarLastName = "last_name"
)
// templateVarAssoc for checking variable validity, only for internal use
// templateVarAssoc for checking variable validity, only for internal use.
var templateVarAssoc = map[string]interface{}{
TemplateVarCustom: nil,
TemplateVarName: nil,
@ -35,7 +35,7 @@ var templateVarAssoc = map[string]interface{}{
TemplateVarLastName: nil,
}
// Template struct
// Template struct.
type Template struct {
Code string `json:"code"`
ChannelID uint64 `json:"channel_id,omitempty"`
@ -45,14 +45,14 @@ type Template struct {
Template []TemplateItem `json:"template"`
}
// TemplateItem is a part of template
// TemplateItem is a part of template.
type TemplateItem struct {
Type uint8
Text string
VarType string
}
// MarshalJSON controls how TemplateItem will be marshaled into JSON
// MarshalJSON controls how TemplateItem will be marshaled into JSON.
func (t TemplateItem) MarshalJSON() ([]byte, error) {
switch t.Type {
case TemplateItemTypeText:
@ -71,7 +71,7 @@ func (t TemplateItem) MarshalJSON() ([]byte, error) {
return nil, errors.New("unknown TemplateItem type")
}
// UnmarshalJSON will correctly unmarshal TemplateItem
// UnmarshalJSON will correctly unmarshal TemplateItem.
func (t *TemplateItem) UnmarshalJSON(b []byte) error {
var obj interface{}
err := json.Unmarshal(b, &obj)

View File

@ -7,62 +7,62 @@ import (
"time"
)
//noinspection ALL
// noinspection ALL.
const (
// ChannelFeatureNone channel can not implement feature
// ChannelFeatureNone channel can not implement feature.
ChannelFeatureNone string = "none"
// ChannelFeatureReceive channel implement feature on receive
// ChannelFeatureReceive channel implement feature on receive.
ChannelFeatureReceive string = "receive"
// ChannelFeatureSend channel implement feature on send
// ChannelFeatureSend channel implement feature on send.
ChannelFeatureSend string = "send"
// ChannelFeatureBoth channel implement feature on both directions
// ChannelFeatureBoth channel implement feature on both directions.
ChannelFeatureBoth string = "both"
// ChannelFeatureAny channel implement feature on any
// ChannelFeatureAny channel implement feature on any.
ChannelFeatureAny string = "any"
// ChannelFeatureSendingPolicyNo channel can not implement feature
// ChannelFeatureSendingPolicyNo channel can not implement feature.
ChannelFeatureSendingPolicyNo string = "no"
// ChannelFeatureSendingPolicyTemplate channel can implement template
// ChannelFeatureSendingPolicyTemplate channel can implement template.
ChannelFeatureSendingPolicyTemplate string = "template"
// ChannelFeatureCustomerExternalIDPhone customer externalId is phone
// ChannelFeatureCustomerExternalIDPhone customer externalId is phone.
ChannelFeatureCustomerExternalIDPhone string = "phone"
// MsgTypeText text message
// MsgTypeText text message.
MsgTypeText string = "text"
// MsgTypeSystem system message
// MsgTypeSystem system message.
MsgTypeSystem string = "system"
// MsgTypeCommand command (for bots)
// MsgTypeCommand command (for bots).
MsgTypeCommand string = "command"
// MsgTypeOrder order card
// MsgTypeOrder order card.
MsgTypeOrder string = "order"
// MsgTypeProduct product card
// MsgTypeProduct product card.
MsgTypeProduct string = "product"
// MsgTypeFile file card
// MsgTypeFile file card.
MsgTypeFile string = "file"
// MsgTypeImage image card
// MsgTypeImage image card.
MsgTypeImage string = "image"
// MsgTypeAudio audio
// MsgTypeAudio audio.
MsgTypeAudio string = "audio"
// MsgOrderStatusCodeNew order status group new
// MsgOrderStatusCodeNew order status group new.
MsgOrderStatusCodeNew = "new"
// MsgOrderStatusCodeApproval order status group approval
// MsgOrderStatusCodeApproval order status group approval.
MsgOrderStatusCodeApproval = "approval"
// MsgOrderStatusCodeAssembling order status group assembling
// MsgOrderStatusCodeAssembling order status group assembling.
MsgOrderStatusCodeAssembling = "assembling"
// MsgOrderStatusCodeDelivery order status group delivery
// MsgOrderStatusCodeDelivery order status group delivery.
MsgOrderStatusCodeDelivery = "delivery"
// MsgOrderStatusCodeComplete order status group complete
// MsgOrderStatusCodeComplete order status group complete.
MsgOrderStatusCodeComplete = "complete"
// MsgOrderStatusCodeCancel order status group cancel
// MsgOrderStatusCodeCancel order status group cancel.
MsgOrderStatusCodeCancel = "cancel"
FileSizeLimit = 20 * 1024 * 1024
)
const (
// OriginatorCustomer means message was created by customer
// OriginatorCustomer means message was created by customer.
OriginatorCustomer Originator = iota + 1
// OriginatorChannel means message was created by channel, for example via messenger mobile application
// OriginatorChannel means message was created by channel, for example via messenger mobile application.
OriginatorChannel
)
@ -70,13 +70,13 @@ type ErrorType string
const (
GeneralError ErrorType = "general"
CustomerNotExistsError = "customer_not_exists"
ReplyTimedOutError = "reply_timed_out"
SpamSuspicionError = "spam_suspicion"
AccessRestrictedError = "access_restricted"
CustomerNotExistsError ErrorType = "customer_not_exists"
ReplyTimedOutError ErrorType = "reply_timed_out"
SpamSuspicionError ErrorType = "spam_suspicion"
AccessRestrictedError ErrorType = "access_restricted"
)
// MgClient type
// MgClient type.
type MgClient struct {
URL string `json:"url"`
Token string `json:"token"`
@ -84,17 +84,17 @@ type MgClient struct {
httpClient *http.Client `json:"-"`
}
// Channel type
// Channel type.
type Channel struct {
ID uint64 `json:"id,omitempty"`
ExternalID string `json:"external_id,omitempty"`
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
AvatarUrl string `json:"avatar_url,omitempty"`
Settings ChannelSettings `json:"settings,omitempty,brackets"`
Settings ChannelSettings `json:"settings,omitempty"`
}
// ChannelSettings struct
// ChannelSettings struct.
type ChannelSettings struct {
Status Status `json:"status"`
Text ChannelSettingsText `json:"text"`
@ -107,27 +107,27 @@ type ChannelSettings struct {
Suggestions ChannelSettingsSuggestions `json:"suggestions,omitempty"`
}
// Product type
// Product type.
type Product struct {
Creating string `json:"creating,omitempty"`
Editing string `json:"editing,omitempty"`
Deleting string `json:"deleting,omitempty"`
}
// Order type
// Order type.
type Order struct {
Creating string `json:"creating,omitempty"`
Editing string `json:"editing,omitempty"`
Deleting string `json:"deleting,omitempty"`
}
// Status struct
// Status struct.
type Status struct {
Delivered string `json:"delivered,omitempty"`
Read string `json:"read,omitempty"`
}
// ChannelSettingsText struct
// ChannelSettingsText struct.
type ChannelSettingsText struct {
Creating string `json:"creating,omitempty"`
Editing string `json:"editing,omitempty"`
@ -136,7 +136,7 @@ type ChannelSettingsText struct {
MaxCharsCount uint16 `json:"max_chars_count,omitempty"`
}
// ChannelSettingsFilesBase struct
// ChannelSettingsFilesBase struct.
type ChannelSettingsFilesBase struct {
Creating string `json:"creating,omitempty"`
Editing string `json:"editing,omitempty"`
@ -158,7 +158,7 @@ type ChannelSettingsSuggestions struct {
Email string `json:"email,omitempty"`
}
// FullFileResponse uploaded file data
// FullFileResponse uploaded file data.
type FullFileResponse struct {
ID string `json:"id,omitempty"`
Type string `json:"type,omitempty"`
@ -166,7 +166,7 @@ type FullFileResponse struct {
Url string `json:"url,omitempty"`
}
// UploadFileResponse uploaded file data
// UploadFileResponse uploaded file data.
type UploadFileResponse struct {
ID string `json:"id"`
Hash string `json:"hash"`
@ -178,38 +178,38 @@ type UploadFileResponse struct {
CreatedAt time.Time `json:"created_at"`
}
// FileMeta file metadata
// FileMeta file metadata.
type FileMeta struct {
Width *int `json:"width,omitempty"`
Height *int `json:"height,omitempty"`
}
// UploadFileByUrlRequest file url to upload
// UploadFileByUrlRequest file url to upload.
type UploadFileByUrlRequest struct {
Url string `json:"url"`
}
// ActivateResponse channel activation response
// ActivateResponse channel activation response.
type ActivateResponse struct {
ChannelID uint64 `json:"id"`
ExternalID string `json:"external_id"`
ActivatedAt time.Time `json:"activated_at"`
}
// UpdateResponse channel update response
// UpdateResponse channel update response.
type UpdateResponse struct {
ChannelID uint64 `json:"id"`
ExternalID string `json:"external_id"`
UpdatedAt time.Time `json:"updated_at"`
}
// DeleteResponse channel deactivation response
// DeleteResponse channel deactivation response.
type DeleteResponse struct {
ChannelID uint64 `json:"id"`
DeactivatedAt time.Time `json:"deactivated_at"`
}
// ChannelListItem response struct
// ChannelListItem response struct.
type ChannelListItem struct {
ID uint64 `json:"id"`
ExternalID string `json:"external_id"`
@ -223,7 +223,7 @@ type ChannelListItem struct {
IsActive bool `json:"is_active"`
}
// Channels request type
// Channels request type.
type Channels struct {
ID int `url:"id,omitempty" json:"id,omitempty"`
Types []string `url:"types,omitempty" json:"types,omitempty"`
@ -235,7 +235,7 @@ type Channels struct {
Limit int `url:"limit,omitempty" json:"limit,omitempty"`
}
// Customer struct
// Customer struct.
type Customer struct {
ExternalID string `json:"external_id"`
Nickname string `json:"nickname"`
@ -249,7 +249,7 @@ type Customer struct {
Email string `json:"email,omitempty"`
}
// Message struct
// Message struct.
type Message struct {
ExternalID string `json:"external_id"`
Type string `json:"type,omitempty"`
@ -258,26 +258,26 @@ type Message struct {
Items []Item `json:"items,omitempty"`
}
// SendMessage struct
// SendMessage struct.
type SendMessage struct {
Message
SentAt time.Time `json:"sent_at,omitempty"`
}
// EditMessageRequest type
// EditMessageRequest type.
type EditMessageRequest struct {
Message EditMessageRequestMessage `json:"message"`
Channel uint64 `json:"channel"`
}
// EditMessageRequestMessage type
// EditMessageRequestMessage type.
type EditMessageRequestMessage struct {
ExternalID string `json:"external_id"`
Text string `json:"text"`
EditedAt int64 `json:"edited_at"`
}
// SendData struct
// SendData struct.
type SendData struct {
Message Message `json:"message"`
Originator Originator `json:"originator,omitempty"`
@ -288,51 +288,51 @@ type SendData struct {
ReplyDeadline *time.Time `json:"reply_deadline,omitempty"`
}
// Item struct
// Item struct.
type Item struct {
ID string `json:"id"`
Caption string `json:"caption"`
}
// SendMessageRequestQuote type
// SendMessageRequestQuote type.
type SendMessageRequestQuote struct {
ExternalID string `json:"external_id"`
}
// MarkMessageReadResponse type
// MarkMessageReadResponse type.
type MarkMessageReadResponse struct{}
// MarkMessageReadRequest type
// MarkMessageReadRequest type.
type MarkMessageReadRequest struct {
Message MarkMessageReadRequestMessage `json:"message"`
ChannelID uint64 `json:"channel_id"`
}
// MarkMessageReadRequestMessage type
// MarkMessageReadRequestMessage type.
type MarkMessageReadRequestMessage struct {
ExternalID string `json:"external_id"`
}
// AckMessageRequest type
// AckMessageRequest type.
type AckMessageRequest struct {
ExternalMessageID string `json:"external_message_id"`
Channel uint64 `json:"channel"`
Error *MessageSentError `json:"error,omitempty"`
}
// DeleteData struct
// DeleteData struct.
type DeleteData struct {
Message Message `json:"message"`
Channel uint64 `json:"channel"`
}
// MessagesResponse message event response
// MessagesResponse message event response.
type MessagesResponse struct {
MessageID int `json:"message_id,omitempty"`
Time time.Time `json:"time,omitempty"`
}
// WebhookRequest type
// WebhookRequest type.
type WebhookRequest struct {
Type string `json:"type"`
Meta TransportRequestMeta `json:"meta"`
@ -340,20 +340,20 @@ type WebhookRequest struct {
}
// WebhookMessageSentResponse type
// Consider using this structure while processing webhook request
// Consider using this structure while processing webhook request.
type WebhookMessageSentResponse struct {
ExternalMessageID string `json:"external_message_id"`
Error *MessageSentError `json:"error,omitempty"`
Async bool `json:"async"`
}
// MessageSentError type
// MessageSentError type.
type MessageSentError struct {
Code ErrorType `json:"code"`
Message string `json:"message"`
}
// WebhookData request data
// WebhookData request data.
type WebhookData struct {
ExternalUserID string `json:"external_user_id"`
ExternalMessageID string `json:"external_message_id,omitempty"`
@ -394,7 +394,7 @@ type TemplateInfo struct {
Args []string `json:"args,omitempty"`
}
// FileItem struct
// FileItem struct.
type FileItem struct {
ID string `json:"id"`
Size int `json:"size"`
@ -403,20 +403,20 @@ type FileItem struct {
Width *int `json:"width,omitempty"`
}
// MessageDataUser user data from webhook
// MessageDataUser user data from webhook.
type MessageDataUser struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Avatar string `json:"avatar"`
}
// MessageDataBot bot data from webhook
// MessageDataBot bot data from webhook.
type MessageDataBot struct {
Name string `json:"name"`
Avatar string `json:"avatar"`
}
// MessageDataProduct product data from webhook
// MessageDataProduct product data from webhook.
type MessageDataProduct struct {
ID uint64 `json:"id"`
Name string `json:"name"`
@ -429,7 +429,7 @@ type MessageDataProduct struct {
Quantity *MessageDataOrderQuantity `json:"quantity,omitempty"`
}
// MessageDataOrder order data from webhook
// MessageDataOrder order data from webhook.
type MessageDataOrder struct {
Number string `json:"number"`
Url string `json:"url,omitempty"`
@ -442,13 +442,13 @@ type MessageDataOrder struct {
Items []MessageDataOrderItem `json:"items,omitempty"`
}
// MessageDataOrderStatus type
// MessageDataOrderStatus type.
type MessageDataOrderStatus struct {
Code string `json:"code,omitempty"`
Name string `json:"name,omitempty"`
}
// MessageDataOrderItem type
// MessageDataOrderItem type.
type MessageDataOrderItem struct {
Name string `json:"name,omitempty"`
Url string `json:"url,omitempty"`
@ -457,32 +457,32 @@ type MessageDataOrderItem struct {
Price *MessageDataOrderCost `json:"price,omitempty"`
}
// MessageDataOrderCost type
// MessageDataOrderCost type.
type MessageDataOrderCost struct {
Value float32 `json:"value,omitempty"`
Currency string `json:"currency"`
}
// MessageDataOrderQuantity type
// MessageDataOrderQuantity type.
type MessageDataOrderQuantity struct {
Value float32 `json:"value"`
Unit string `json:"unit"`
}
// MessageDataOrderPayment type
// MessageDataOrderPayment type.
type MessageDataOrderPayment struct {
Name string `json:"name"`
Status *MessageDataOrderPaymentStatus `json:"status"`
Amount *MessageDataOrderCost `json:"amount"`
}
// MessageDataOrderPaymentStatus type
// MessageDataOrderPaymentStatus type.
type MessageDataOrderPaymentStatus struct {
Name string `json:"name"`
Payed bool `json:"payed"`
Paid bool `json:"paid"`
}
// MessageDataOrderDelivery type
// MessageDataOrderDelivery type.
type MessageDataOrderDelivery struct {
Name string `json:"name"`
Price *MessageDataOrderCost `json:"price"`
@ -490,7 +490,7 @@ type MessageDataOrderDelivery struct {
Comment string `json:"comment,omitempty"`
}
// TransportRequestMeta request metadata
// TransportRequestMeta request metadata.
type TransportRequestMeta struct {
ID uint64 `json:"id"`
Timestamp int64 `json:"timestamp"`
@ -505,10 +505,10 @@ type ActivateTemplateRequest struct {
var ErrInvalidOriginator = errors.New("invalid originator")
// Originator of message
// Originator of message.
type Originator byte
// MarshalText marshals originator to text
// MarshalText marshals originator to text.
func (o Originator) MarshalText() ([]byte, error) {
switch o {
case OriginatorCustomer:

View File

@ -1,3 +1,4 @@
//go:build !go1.14
// +build !go1.14
package v1

View File

@ -1,3 +1,4 @@
//go:build go1.14
// +build go1.14
package v1