mattermost-community-enterp.../public/model/slack_attachment_test.go
Claude ec1f89217a Merge: Complete Mattermost Server with Community Enterprise
Full Mattermost server source with integrated Community Enterprise features.
Includes vendor directory for offline/air-gapped builds.

Structure:
- enterprise-impl/: Enterprise feature implementations
- enterprise-community/: Init files that register implementations
- enterprise/: Bridge imports (community_imports.go)
- vendor/: All dependencies for offline builds

Build (online):
  go build ./cmd/mattermost

Build (offline/air-gapped):
  go build -mod=vendor ./cmd/mattermost

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 23:59:07 +09:00

248 lines
5.2 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSlackAttachment_IsValid(t *testing.T) {
tests := map[string]struct {
attachment *SlackAttachment
wantErr string
}{
"valid attachment": {
attachment: &SlackAttachment{
Text: "This is a test",
},
wantErr: "",
},
"invalid color": {
attachment: &SlackAttachment{
Color: "invalid",
},
wantErr: "invalid style 'invalid' - must be one of [good, warning, danger] or a hex color",
},
"valid predefined color": {
attachment: &SlackAttachment{
Color: "good",
},
wantErr: "",
},
"valid warning color": {
attachment: &SlackAttachment{
Color: "warning",
},
wantErr: "",
},
"valid danger color": {
attachment: &SlackAttachment{
Color: "danger",
},
wantErr: "",
},
"valid hex color": {
attachment: &SlackAttachment{
Color: "#FF0000",
},
wantErr: "",
},
"author link without name": {
attachment: &SlackAttachment{
AuthorLink: "http://example.com",
},
wantErr: "author link cannot be set without author name",
},
"invalid author link": {
attachment: &SlackAttachment{
AuthorName: "Author",
AuthorLink: "invalid-url",
},
wantErr: "invalid author link URL",
},
"invalid author icon": {
attachment: &SlackAttachment{
AuthorIcon: "invalid-url",
},
wantErr: "invalid author icon URL",
},
"title link without title": {
attachment: &SlackAttachment{
TitleLink: "http://example.com",
},
wantErr: "title link cannot be set without title",
},
"invalid title link": {
attachment: &SlackAttachment{
Title: "Title",
TitleLink: "invalid-url",
},
wantErr: "invalid title link URL",
},
"invalid image URL": {
attachment: &SlackAttachment{
ImageURL: "invalid-url",
},
wantErr: "invalid image URL",
},
"invalid thumb URL": {
attachment: &SlackAttachment{
ThumbURL: "invalid-url",
},
wantErr: "invalid thumb URL",
},
"invalid footer icon": {
attachment: &SlackAttachment{
FooterIcon: "invalid-url",
},
wantErr: "invalid footer icon URL",
},
"invalid timestamp type": {
attachment: &SlackAttachment{
Timestamp: []string{"invalid"},
},
wantErr: "timestamp must be either a string or int64",
},
"valid timestamp string": {
attachment: &SlackAttachment{
Timestamp: "1234567890",
},
wantErr: "",
},
"valid timestamp int64": {
attachment: &SlackAttachment{
Timestamp: int64(1234567890),
},
wantErr: "",
},
"invalid action": {
attachment: &SlackAttachment{
Actions: []*PostAction{
{
Name: "", // Invalid - missing name
},
},
},
wantErr: "action must have a name",
},
"invalid field value type": {
attachment: &SlackAttachment{
Fields: []*SlackAttachmentField{
{
Title: "Title",
Value: []string{"invalid"},
},
},
},
wantErr: "value must be either a string or int",
},
"valid fields": {
attachment: &SlackAttachment{
Fields: []*SlackAttachmentField{
{
Title: "Title",
Value: "string value",
},
{
Title: "Number",
Value: 42,
},
},
},
wantErr: "",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
err := tc.attachment.IsValid()
if tc.wantErr == "" {
assert.NoError(t, err, name)
} else {
assert.ErrorContains(t, err, tc.wantErr, name)
}
})
}
}
func TestParseSlackAttachment(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
post := &Post{}
attachments := []*SlackAttachment{}
ParseSlackAttachment(post, attachments)
expectedPost := &Post{
Type: PostTypeSlackAttachment,
Props: map[string]any{
PostPropsAttachments: []*SlackAttachment{},
},
}
assert.Equal(t, expectedPost, post)
})
t.Run("list with nil", func(t *testing.T) {
post := &Post{}
attachments := []*SlackAttachment{
nil,
}
ParseSlackAttachment(post, attachments)
expectedPost := &Post{
Type: PostTypeSlackAttachment,
Props: map[string]any{
PostPropsAttachments: []*SlackAttachment{},
},
}
assert.Equal(t, expectedPost, post)
})
}
func TestSlackAttachment_Equals_PrimitiveAndNonPrimitiveField(t *testing.T) {
// Field with primitive type (string)
attachment1 := &SlackAttachment{
Fields: []*SlackAttachmentField{
{
Title: "Field1",
Value: "value",
Short: true,
},
},
}
attachment2 := &SlackAttachment{
Fields: []*SlackAttachmentField{
{
Title: "Field1",
Value: "value",
Short: true,
},
},
}
assert.True(t, attachment1.Equals(attachment2), "Attachments with identical primitive field values should be equal")
// Field with non-primitive type ([]interface{})
attachment3 := &SlackAttachment{
Fields: []*SlackAttachmentField{
{
Title: "Field1",
Value: []any{"value", 2},
Short: true,
},
},
}
attachment4 := &SlackAttachment{
Fields: []*SlackAttachmentField{
{
Title: "Field1",
Value: []any{"value", 2},
Short: true,
},
},
}
assert.True(t, attachment3.Equals(attachment4), "Attachments with identical non-primitive ([]interface{}) field values should be equal")
}