mirror of https://github.com/jlelse/GoBlog
Unit and integration tests for Telegram
This commit is contained in:
parent
9c9a217c07
commit
c9af4e7efa
2
app.go
2
app.go
|
@ -36,7 +36,7 @@ type goBlog struct {
|
||||||
pPostHooks []postHookFunc
|
pPostHooks []postHookFunc
|
||||||
pUpdateHooks []postHookFunc
|
pUpdateHooks []postHookFunc
|
||||||
pDeleteHooks []postHookFunc
|
pDeleteHooks []postHookFunc
|
||||||
// HTTP
|
// HTTP Routers
|
||||||
d *dynamicHandler
|
d *dynamicHandler
|
||||||
privateMode bool
|
privateMode bool
|
||||||
privateModeHandler []func(http.Handler) http.Handler
|
privateModeHandler []func(http.Handler) http.Handler
|
||||||
|
|
|
@ -4,6 +4,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (a *goBlog) setInMemoryDatabase() {
|
||||||
|
a.db, _ = a.openDatabase(":memory:", false)
|
||||||
|
}
|
||||||
|
|
||||||
func Test_database(t *testing.T) {
|
func Test_database(t *testing.T) {
|
||||||
t.Run("Basic Database Test", func(t *testing.T) {
|
t.Run("Basic Database Test", func(t *testing.T) {
|
||||||
app := &goBlog{}
|
app := &goBlog{}
|
||||||
|
|
|
@ -5,7 +5,11 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appHttpClient = &http.Client{
|
type httpClient interface {
|
||||||
|
Do(req *http.Request) (*http.Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var appHttpClient httpClient = &http.Client{
|
||||||
Timeout: 5 * time.Minute,
|
Timeout: 5 * time.Minute,
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
DisableKeepAlives: true,
|
DisableKeepAlives: true,
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fakeHttpClient struct {
|
||||||
|
req *http.Request
|
||||||
|
res *http.Response
|
||||||
|
err error
|
||||||
|
enabled bool
|
||||||
|
// internal
|
||||||
|
alt httpClient
|
||||||
|
mx sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
var fakeAppHttpClient *fakeHttpClient
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
fakeAppHttpClient = &fakeHttpClient{
|
||||||
|
alt: appHttpClient,
|
||||||
|
}
|
||||||
|
appHttpClient = fakeAppHttpClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeHttpClient) Do(req *http.Request) (*http.Response, error) {
|
||||||
|
if !c.enabled {
|
||||||
|
return c.alt.Do(req)
|
||||||
|
}
|
||||||
|
c.req = req
|
||||||
|
return c.res, c.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeHttpClient) clean() {
|
||||||
|
c.req = nil
|
||||||
|
c.err = nil
|
||||||
|
c.res = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeHttpClient) setFakeResponse(statusCode int, body string, err error) {
|
||||||
|
c.clean()
|
||||||
|
c.err = err
|
||||||
|
c.res = &http.Response{
|
||||||
|
StatusCode: statusCode,
|
||||||
|
Body: io.NopCloser(strings.NewReader(body)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeHttpClient) lock(enabled bool) {
|
||||||
|
c.mx.Lock()
|
||||||
|
c.clean()
|
||||||
|
c.enabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeHttpClient) unlock() {
|
||||||
|
c.enabled = false
|
||||||
|
c.clean()
|
||||||
|
c.mx.Unlock()
|
||||||
|
}
|
|
@ -30,13 +30,11 @@ func (a *goBlog) sendNotification(text string) {
|
||||||
log.Println("Failed to save notification:", err.Error())
|
log.Println("Failed to save notification:", err.Error())
|
||||||
}
|
}
|
||||||
if an := a.cfg.Notifications; an != nil {
|
if an := a.cfg.Notifications; an != nil {
|
||||||
if tg := an.Telegram; tg != nil && tg.Enabled {
|
err := an.Telegram.send(n.Text, "")
|
||||||
err := sendTelegramMessage(n.Text, "", tg.BotToken, tg.ChatID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Failed to send Telegram notification:", err.Error())
|
log.Println("Failed to send Telegram notification:", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *database) saveNotification(n *notification) error {
|
func (db *database) saveNotification(n *notification) error {
|
||||||
|
|
40
telegram.go
40
telegram.go
|
@ -14,24 +14,27 @@ import (
|
||||||
const telegramBaseURL = "https://api.telegram.org/bot"
|
const telegramBaseURL = "https://api.telegram.org/bot"
|
||||||
|
|
||||||
func (a *goBlog) initTelegram() {
|
func (a *goBlog) initTelegram() {
|
||||||
enable := false
|
|
||||||
for _, b := range a.cfg.Blogs {
|
|
||||||
if tg := b.Telegram; tg != nil && tg.Enabled && tg.BotToken != "" && tg.ChatID != "" {
|
|
||||||
enable = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if enable {
|
|
||||||
a.pPostHooks = append(a.pPostHooks, func(p *post) {
|
a.pPostHooks = append(a.pPostHooks, func(p *post) {
|
||||||
if p.isPublishedSectionPost() {
|
if tg := a.cfg.Blogs[p.Blog].Telegram; tg.enabled() && p.isPublishedSectionPost() {
|
||||||
tgPost(a.cfg.Blogs[p.Blog].Telegram, p.title(), a.fullPostURL(p), a.shortPostURL(p))
|
if html := tg.generateHTML(p.title(), a.fullPostURL(p), a.shortPostURL(p)); html != "" {
|
||||||
|
if err := tg.send(html, "HTML"); err != nil {
|
||||||
|
log.Printf("Failed to send post to Telegram: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func tgPost(tg *configTelegram, title, fullURL, shortURL string) {
|
func (tg *configTelegram) enabled() bool {
|
||||||
if tg == nil || !tg.Enabled || tg.BotToken == "" || tg.ChatID == "" {
|
if tg == nil || !tg.Enabled || tg.BotToken == "" || tg.ChatID == "" {
|
||||||
return
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tg *configTelegram) generateHTML(title, fullURL, shortURL string) string {
|
||||||
|
if !tg.enabled() {
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
replacer := strings.NewReplacer("<", "<", ">", ">", "&", "&")
|
replacer := strings.NewReplacer("<", "<", ">", ">", "&", "&")
|
||||||
var message bytes.Buffer
|
var message bytes.Buffer
|
||||||
|
@ -48,19 +51,20 @@ func tgPost(tg *configTelegram, title, fullURL, shortURL string) {
|
||||||
message.WriteString(replacer.Replace(shortURL))
|
message.WriteString(replacer.Replace(shortURL))
|
||||||
message.WriteString("</a>")
|
message.WriteString("</a>")
|
||||||
}
|
}
|
||||||
if err := sendTelegramMessage(message.String(), "HTML", tg.BotToken, tg.ChatID); err != nil {
|
return message.String()
|
||||||
log.Println(err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendTelegramMessage(message, mode, token, chat string) error {
|
func (tg *configTelegram) send(message, mode string) error {
|
||||||
|
if !tg.enabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Add("chat_id", chat)
|
params.Add("chat_id", tg.ChatID)
|
||||||
params.Add("text", message)
|
params.Add("text", message)
|
||||||
if mode != "" {
|
if mode != "" {
|
||||||
params.Add("parse_mode", mode)
|
params.Add("parse_mode", mode)
|
||||||
}
|
}
|
||||||
tgURL, err := url.Parse(telegramBaseURL + token + "/sendMessage")
|
tgURL, err := url.Parse(telegramBaseURL + tg.BotToken + "/sendMessage")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create Telegram request")
|
return errors.New("failed to create Telegram request")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_configTelegram_enabled(t *testing.T) {
|
||||||
|
if (&configTelegram{}).enabled() == true {
|
||||||
|
t.Error("Telegram shouldn't be enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&configTelegram{
|
||||||
|
Enabled: true,
|
||||||
|
}).enabled() == true {
|
||||||
|
t.Error("Telegram shouldn't be enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&configTelegram{
|
||||||
|
Enabled: true,
|
||||||
|
ChatID: "abc",
|
||||||
|
}).enabled() == true {
|
||||||
|
t.Error("Telegram shouldn't be enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&configTelegram{
|
||||||
|
Enabled: true,
|
||||||
|
BotToken: "abc",
|
||||||
|
}).enabled() == true {
|
||||||
|
t.Error("Telegram shouldn't be enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&configTelegram{
|
||||||
|
Enabled: true,
|
||||||
|
BotToken: "abc",
|
||||||
|
ChatID: "abc",
|
||||||
|
}).enabled() != true {
|
||||||
|
t.Error("Telegram should be enabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_configTelegram_generateHTML(t *testing.T) {
|
||||||
|
tg := &configTelegram{
|
||||||
|
Enabled: true,
|
||||||
|
ChatID: "abc",
|
||||||
|
BotToken: "abc",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Without Instant View
|
||||||
|
|
||||||
|
expected := "Title\n\n<a href=\"https://example.com/s/1\">https://example.com/s/1</a>"
|
||||||
|
if got := tg.generateHTML("Title", "https://example.com/test", "https://example.com/s/1"); got != expected {
|
||||||
|
t.Errorf("Wrong result, got: %v", got)
|
||||||
|
}
|
||||||
|
|
||||||
|
// With Instant View
|
||||||
|
|
||||||
|
tg.InstantViewHash = "abc"
|
||||||
|
expected = "Title\n\n<a href=\"https://t.me/iv?rhash=abc&url=https%3A%2F%2Fexample.com%2Ftest\">https://example.com/s/1</a>"
|
||||||
|
if got := tg.generateHTML("Title", "https://example.com/test", "https://example.com/s/1"); got != expected {
|
||||||
|
t.Errorf("Wrong result, got: %v", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_configTelegram_send(t *testing.T) {
|
||||||
|
fakeAppHttpClient.lock(true)
|
||||||
|
defer fakeAppHttpClient.unlock()
|
||||||
|
|
||||||
|
tg := &configTelegram{
|
||||||
|
Enabled: true,
|
||||||
|
ChatID: "chatid",
|
||||||
|
BotToken: "bottoken",
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeAppHttpClient.setFakeResponse(200, "", nil)
|
||||||
|
|
||||||
|
err := tg.send("Message", "HTML")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fakeAppHttpClient.req == nil {
|
||||||
|
t.Error("Empty request")
|
||||||
|
}
|
||||||
|
if fakeAppHttpClient.err != nil {
|
||||||
|
t.Error("Error in request")
|
||||||
|
}
|
||||||
|
if fakeAppHttpClient.req.Method != http.MethodPost {
|
||||||
|
t.Error("Wrong method")
|
||||||
|
}
|
||||||
|
if u := fakeAppHttpClient.req.URL.String(); u != "https://api.telegram.org/botbottoken/sendMessage?chat_id=chatid&parse_mode=HTML&text=Message" {
|
||||||
|
t.Errorf("Wrong request URL, got: %v", u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_goBlog_initTelegram(t *testing.T) {
|
||||||
|
app := &goBlog{
|
||||||
|
pPostHooks: []postHookFunc{},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.initTelegram()
|
||||||
|
|
||||||
|
if len(app.pPostHooks) != 1 {
|
||||||
|
t.Error("Hook not registered")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_telegram(t *testing.T) {
|
||||||
|
t.Run("Send post to Telegram", func(t *testing.T) {
|
||||||
|
fakeAppHttpClient.lock(true)
|
||||||
|
defer fakeAppHttpClient.unlock()
|
||||||
|
|
||||||
|
fakeAppHttpClient.setFakeResponse(200, "", nil)
|
||||||
|
|
||||||
|
app := &goBlog{
|
||||||
|
pPostHooks: []postHookFunc{},
|
||||||
|
cfg: &config{
|
||||||
|
Server: &configServer{
|
||||||
|
PublicAddress: "https://example.com",
|
||||||
|
},
|
||||||
|
Blogs: map[string]*configBlog{
|
||||||
|
"en": {
|
||||||
|
Telegram: &configTelegram{
|
||||||
|
Enabled: true,
|
||||||
|
ChatID: "chatid",
|
||||||
|
BotToken: "bottoken",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
app.setInMemoryDatabase()
|
||||||
|
|
||||||
|
app.initTelegram()
|
||||||
|
|
||||||
|
p := &post{
|
||||||
|
Path: "/test",
|
||||||
|
Parameters: map[string][]string{
|
||||||
|
"title": {"Title"},
|
||||||
|
},
|
||||||
|
Published: time.Now().String(),
|
||||||
|
Section: "test",
|
||||||
|
Blog: "en",
|
||||||
|
Status: statusPublished,
|
||||||
|
}
|
||||||
|
|
||||||
|
app.pPostHooks[0](p)
|
||||||
|
|
||||||
|
if u := fakeAppHttpClient.req.URL.String(); u != "https://api.telegram.org/botbottoken/sendMessage?chat_id=chatid&parse_mode=HTML&text=Title%0A%0A%3Ca+href%3D%22https%3A%2F%2Fexample.com%2Fs%2F1%22%3Ehttps%3A%2F%2Fexample.com%2Fs%2F1%3C%2Fa%3E" {
|
||||||
|
t.Errorf("Wrong request URL, got: %v", u)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Telegram disabled", func(t *testing.T) {
|
||||||
|
fakeAppHttpClient.lock(true)
|
||||||
|
defer fakeAppHttpClient.unlock()
|
||||||
|
|
||||||
|
fakeAppHttpClient.setFakeResponse(200, "", nil)
|
||||||
|
|
||||||
|
app := &goBlog{
|
||||||
|
pPostHooks: []postHookFunc{},
|
||||||
|
cfg: &config{
|
||||||
|
Server: &configServer{
|
||||||
|
PublicAddress: "https://example.com",
|
||||||
|
},
|
||||||
|
Blogs: map[string]*configBlog{
|
||||||
|
"en": {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
app.setInMemoryDatabase()
|
||||||
|
|
||||||
|
app.initTelegram()
|
||||||
|
|
||||||
|
p := &post{
|
||||||
|
Path: "/test",
|
||||||
|
Parameters: map[string][]string{
|
||||||
|
"title": {"Title"},
|
||||||
|
},
|
||||||
|
Published: time.Now().String(),
|
||||||
|
Section: "test",
|
||||||
|
Blog: "en",
|
||||||
|
Status: statusPublished,
|
||||||
|
}
|
||||||
|
|
||||||
|
app.pPostHooks[0](p)
|
||||||
|
|
||||||
|
if fakeAppHttpClient.req != nil {
|
||||||
|
t.Error("There should be no request")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue