Replace hardcoded English strings throughout the plugin with localized messages via a new i18n system supporting English and Spanish. Store the requester's locale on the download task so background job messages are properly localized. Replace the starter template README with project-specific documentation covering features, usage, configuration, and development. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
165 lines
3.9 KiB
Go
165 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestParseLanguageFlag(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantLanguage string
|
|
wantQuery string
|
|
}{
|
|
{
|
|
name: "no flag",
|
|
input: "The Great Gatsby",
|
|
wantLanguage: "",
|
|
wantQuery: "The Great Gatsby",
|
|
},
|
|
{
|
|
name: "flag with space",
|
|
input: "--language en The Great Gatsby",
|
|
wantLanguage: "en",
|
|
wantQuery: "The Great Gatsby",
|
|
},
|
|
{
|
|
name: "flag with equals",
|
|
input: "--language=en The Great Gatsby",
|
|
wantLanguage: "en",
|
|
wantQuery: "The Great Gatsby",
|
|
},
|
|
{
|
|
name: "flag in middle",
|
|
input: "The Great --language en Gatsby",
|
|
wantLanguage: "en",
|
|
wantQuery: "The Great Gatsby", // Double space from flag removal, trimmed only at edges
|
|
},
|
|
{
|
|
name: "flag only no query",
|
|
input: "--language en",
|
|
wantLanguage: "en",
|
|
wantQuery: "",
|
|
},
|
|
{
|
|
name: "extra whitespace",
|
|
input: " --language es Don Quixote ",
|
|
wantLanguage: "es",
|
|
wantQuery: "Don Quixote",
|
|
},
|
|
{
|
|
name: "empty input",
|
|
input: "",
|
|
wantLanguage: "",
|
|
wantQuery: "",
|
|
},
|
|
{
|
|
name: "flag at end",
|
|
input: "Don Quixote --language es",
|
|
wantLanguage: "es",
|
|
wantQuery: "Don Quixote",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
lang, query := parseLanguageFlag(tt.input)
|
|
assert.Equal(t, tt.wantLanguage, lang)
|
|
assert.Equal(t, tt.wantQuery, query)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEphemeralResponse(t *testing.T) {
|
|
resp := ephemeralResponse("test message")
|
|
assert.Equal(t, model.CommandResponseTypeEphemeral, resp.ResponseType)
|
|
assert.Equal(t, "test message", resp.Text)
|
|
}
|
|
|
|
func TestRenderPostMessage(t *testing.T) {
|
|
makePlugin := func(template string) *Plugin {
|
|
return &Plugin{
|
|
configurationLock: sync.RWMutex{},
|
|
configuration: &configuration{
|
|
PostTemplate: template,
|
|
},
|
|
}
|
|
}
|
|
|
|
t.Run("default template", func(t *testing.T) {
|
|
p := makePlugin("")
|
|
task := &DownloadTask{BookTitle: "My Book"}
|
|
|
|
msg, err := p.renderPostMessage(task)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "### My Book", msg)
|
|
})
|
|
|
|
t.Run("custom template", func(t *testing.T) {
|
|
p := makePlugin("**{{.Title}}** by {{.AuthorsList}}")
|
|
task := &DownloadTask{
|
|
BookTitle: "My Book",
|
|
BookAuthors: []string{"Author A", "Author B"},
|
|
}
|
|
|
|
msg, err := p.renderPostMessage(task)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "**My Book** by Author A, Author B", msg)
|
|
})
|
|
|
|
t.Run("localized title takes precedence", func(t *testing.T) {
|
|
p := makePlugin("")
|
|
task := &DownloadTask{
|
|
BookTitle: "Original Title",
|
|
LocalizedTitle: "Titulo Localizado",
|
|
}
|
|
|
|
msg, err := p.renderPostMessage(task)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "### Titulo Localizado", msg)
|
|
})
|
|
|
|
t.Run("invalid template returns error", func(t *testing.T) {
|
|
p := makePlugin("{{.Invalid")
|
|
task := &DownloadTask{BookTitle: "Test"}
|
|
|
|
_, err := p.renderPostMessage(task)
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestHandleRequestBook_EmptyQuery(t *testing.T) {
|
|
p := &Plugin{
|
|
configurationLock: sync.RWMutex{},
|
|
configuration: &configuration{
|
|
ShelfmarkHost: "http://localhost:8084",
|
|
ChannelID: "ch1",
|
|
},
|
|
}
|
|
|
|
resp, err := p.handleRequestBook(&model.CommandArgs{
|
|
Command: "/requestbook",
|
|
}, "en")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
assert.Contains(t, resp.Text, "Usage:")
|
|
}
|
|
|
|
func TestHandleRequestBook_InvalidConfig(t *testing.T) {
|
|
p := &Plugin{
|
|
configurationLock: sync.RWMutex{},
|
|
configuration: &configuration{},
|
|
}
|
|
|
|
resp, err := p.handleRequestBook(&model.CommandArgs{
|
|
Command: "/requestbook some book",
|
|
}, "en")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
assert.Contains(t, resp.Text, "not configured")
|
|
}
|