mirror of https://github.com/jlelse/GoBlog
Tests for blog stats
This commit is contained in:
parent
e62e4f32d6
commit
fcf299d1a1
|
@ -267,14 +267,13 @@ func (a *goBlog) apGetRemoteActor(iri string) (*asPerson, int, error) {
|
|||
return actor, 0, nil
|
||||
}
|
||||
|
||||
func (db *database) apGetAllInboxes(blog string) ([]string, error) {
|
||||
func (db *database) apGetAllInboxes(blog string) (inboxes []string, err error) {
|
||||
rows, err := db.query("select distinct inbox from activitypub_followers where blog = @blog", sql.Named("blog", blog))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inboxes := []string{}
|
||||
var inbox string
|
||||
for rows.Next() {
|
||||
var inbox string
|
||||
err = rows.Scan(&inbox)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -44,9 +44,7 @@ func Test_authMiddleware(t *testing.T) {
|
|||
}
|
||||
|
||||
_ = app.initDatabase(false)
|
||||
app.initSessions()
|
||||
_ = app.initTemplateStrings()
|
||||
_ = app.initRendering()
|
||||
app.initComponents()
|
||||
|
||||
app.d = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
_, _ = rw.Write([]byte("ABC Test"))
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.goblog.app/app/pkgs/contenttype"
|
||||
)
|
||||
|
||||
func Test_blogStats(t *testing.T) {
|
||||
app := &goBlog{
|
||||
cfg: &config{
|
||||
Db: &configDb{
|
||||
File: filepath.Join(t.TempDir(), "test.db"),
|
||||
},
|
||||
Server: &configServer{
|
||||
PublicAddress: "https://example.com",
|
||||
},
|
||||
Blogs: map[string]*configBlog{
|
||||
"en": {
|
||||
Lang: "en",
|
||||
BlogStats: &configBlogStats{
|
||||
Enabled: true,
|
||||
Path: "/stats",
|
||||
},
|
||||
Sections: map[string]*configSection{
|
||||
"test": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultBlog: "en",
|
||||
User: &configUser{},
|
||||
Webmention: &configWebmention{
|
||||
DisableSending: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_ = app.initDatabase(false)
|
||||
app.initComponents()
|
||||
|
||||
// Insert post
|
||||
|
||||
err := app.createPost(&post{
|
||||
Content: "This is a simple **test** post",
|
||||
Blog: "en",
|
||||
Section: "test",
|
||||
Published: "2020-06-01",
|
||||
Status: statusPublished,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = app.createPost(&post{
|
||||
Content: "This is another simple **test** post",
|
||||
Blog: "en",
|
||||
Section: "test",
|
||||
Published: "2021-05-01",
|
||||
Status: statusPublished,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test stats
|
||||
|
||||
sd, err := app.db.getBlogStats("en")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, sd)
|
||||
|
||||
require.NotNil(t, sd.Total)
|
||||
assert.Equal(t, "2", sd.Total.Posts)
|
||||
assert.Equal(t, "12", sd.Total.Words)
|
||||
assert.Equal(t, "48", sd.Total.Chars)
|
||||
|
||||
// 2021
|
||||
require.NotNil(t, sd.Years)
|
||||
row := sd.Years[0]
|
||||
require.NotNil(t, row)
|
||||
assert.Equal(t, "2021", row.Name)
|
||||
assert.Equal(t, "1", row.Posts)
|
||||
assert.Equal(t, "6", row.Words)
|
||||
assert.Equal(t, "27", row.Chars)
|
||||
|
||||
// 2021-05
|
||||
require.NotNil(t, sd.Months)
|
||||
require.NotEmpty(t, sd.Months["2021"])
|
||||
row = sd.Months["2021"][0]
|
||||
require.NotNil(t, row)
|
||||
assert.Equal(t, "05", row.Name)
|
||||
assert.Equal(t, "1", row.Posts)
|
||||
assert.Equal(t, "6", row.Words)
|
||||
assert.Equal(t, "27", row.Chars)
|
||||
|
||||
// 2020
|
||||
require.NotNil(t, sd.Years)
|
||||
row = sd.Years[1]
|
||||
require.NotNil(t, row)
|
||||
assert.Equal(t, "2020", row.Name)
|
||||
assert.Equal(t, "1", row.Posts)
|
||||
assert.Equal(t, "6", row.Words)
|
||||
assert.Equal(t, "21", row.Chars)
|
||||
|
||||
// Test if cache exists
|
||||
|
||||
assert.NotNil(t, app.db.loadBlogStatsCache("en"))
|
||||
|
||||
// Test HTML
|
||||
|
||||
t.Run("Test stats table", func(t *testing.T) {
|
||||
h := http.HandlerFunc(app.serveBlogStatsTable)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/abc", nil)
|
||||
req = req.WithContext(context.WithValue(req.Context(), blogKey, "en"))
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
h(rec, req)
|
||||
|
||||
res := rec.Result()
|
||||
resBody, _ := io.ReadAll(res.Body)
|
||||
_ = res.Body.Close()
|
||||
resString := string(resBody)
|
||||
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
assert.Contains(t, resString, "class=statsyear data-year=2021")
|
||||
assert.Contains(t, res.Header.Get(contentType), contenttype.HTML)
|
||||
})
|
||||
|
||||
t.Run("Test stats page", func(t *testing.T) {
|
||||
h := http.HandlerFunc(app.serveBlogStats)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/abc", nil)
|
||||
req = req.WithContext(context.WithValue(req.Context(), blogKey, "en"))
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
h(rec, req)
|
||||
|
||||
res := rec.Result()
|
||||
resBody, _ := io.ReadAll(res.Body)
|
||||
_ = res.Body.Close()
|
||||
resString := string(resBody)
|
||||
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
assert.Contains(t, resString, "data-table=/stats.table.html")
|
||||
assert.Contains(t, res.Header.Get(contentType), contenttype.HTML)
|
||||
})
|
||||
|
||||
}
|
|
@ -31,9 +31,7 @@ func Test_captchaMiddleware(t *testing.T) {
|
|||
}
|
||||
|
||||
_ = app.initDatabase(false)
|
||||
app.initSessions()
|
||||
_ = app.initTemplateStrings()
|
||||
_ = app.initRendering()
|
||||
app.initComponents()
|
||||
|
||||
h := app.captchaMiddleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
_, _ = rw.Write([]byte("ABC Test"))
|
||||
|
|
|
@ -31,10 +31,7 @@ func Test_errors(t *testing.T) {
|
|||
}
|
||||
|
||||
_ = app.initDatabase(false)
|
||||
app.initMarkdown()
|
||||
app.initSessions()
|
||||
_ = app.initTemplateStrings()
|
||||
_ = app.initRendering()
|
||||
app.initComponents()
|
||||
|
||||
t.Run("Test 404, no HTML", func(t *testing.T) {
|
||||
h := http.HandlerFunc(app.serve404)
|
||||
|
|
48
hooks.go
48
hooks.go
|
@ -21,13 +21,15 @@ type postHookFunc func(*post)
|
|||
|
||||
func (a *goBlog) postPostHooks(p *post) {
|
||||
// Hooks after post published
|
||||
for _, cmdTmplString := range a.cfg.Hooks.PostPost {
|
||||
go func(p *post, cmdTmplString string) {
|
||||
a.cfg.Hooks.executeTemplateCommand("post-post", cmdTmplString, map[string]interface{}{
|
||||
"URL": a.fullPostURL(p),
|
||||
"Post": p,
|
||||
})
|
||||
}(p, cmdTmplString)
|
||||
if hc := a.cfg.Hooks; hc != nil {
|
||||
for _, cmdTmplString := range hc.PostPost {
|
||||
go func(p *post, cmdTmplString string) {
|
||||
a.cfg.Hooks.executeTemplateCommand("post-post", cmdTmplString, map[string]interface{}{
|
||||
"URL": a.fullPostURL(p),
|
||||
"Post": p,
|
||||
})
|
||||
}(p, cmdTmplString)
|
||||
}
|
||||
}
|
||||
for _, f := range a.pPostHooks {
|
||||
go f(p)
|
||||
|
@ -36,13 +38,15 @@ func (a *goBlog) postPostHooks(p *post) {
|
|||
|
||||
func (a *goBlog) postUpdateHooks(p *post) {
|
||||
// Hooks after post updated
|
||||
for _, cmdTmplString := range a.cfg.Hooks.PostUpdate {
|
||||
go func(p *post, cmdTmplString string) {
|
||||
a.cfg.Hooks.executeTemplateCommand("post-update", cmdTmplString, map[string]interface{}{
|
||||
"URL": a.fullPostURL(p),
|
||||
"Post": p,
|
||||
})
|
||||
}(p, cmdTmplString)
|
||||
if hc := a.cfg.Hooks; hc != nil {
|
||||
for _, cmdTmplString := range hc.PostUpdate {
|
||||
go func(p *post, cmdTmplString string) {
|
||||
a.cfg.Hooks.executeTemplateCommand("post-update", cmdTmplString, map[string]interface{}{
|
||||
"URL": a.fullPostURL(p),
|
||||
"Post": p,
|
||||
})
|
||||
}(p, cmdTmplString)
|
||||
}
|
||||
}
|
||||
for _, f := range a.pUpdateHooks {
|
||||
go f(p)
|
||||
|
@ -50,13 +54,15 @@ func (a *goBlog) postUpdateHooks(p *post) {
|
|||
}
|
||||
|
||||
func (a *goBlog) postDeleteHooks(p *post) {
|
||||
for _, cmdTmplString := range a.cfg.Hooks.PostDelete {
|
||||
go func(p *post, cmdTmplString string) {
|
||||
a.cfg.Hooks.executeTemplateCommand("post-delete", cmdTmplString, map[string]interface{}{
|
||||
"URL": a.fullPostURL(p),
|
||||
"Post": p,
|
||||
})
|
||||
}(p, cmdTmplString)
|
||||
if hc := a.cfg.Hooks; hc != nil {
|
||||
for _, cmdTmplString := range hc.PostDelete {
|
||||
go func(p *post, cmdTmplString string) {
|
||||
a.cfg.Hooks.executeTemplateCommand("post-delete", cmdTmplString, map[string]interface{}{
|
||||
"URL": a.fullPostURL(p),
|
||||
"Post": p,
|
||||
})
|
||||
}(p, cmdTmplString)
|
||||
}
|
||||
}
|
||||
for _, f := range a.pDeleteHooks {
|
||||
go f(p)
|
||||
|
|
|
@ -17,7 +17,3 @@ func getHTTPClient() httpClient {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (a *goBlog) initHTTPClient() {
|
||||
a.httpClient = getHTTPClient()
|
||||
}
|
||||
|
|
54
main.go
54
main.go
|
@ -46,8 +46,12 @@ func main() {
|
|||
}()
|
||||
}
|
||||
|
||||
app := &goBlog{}
|
||||
app.initHTTPClient()
|
||||
// Init regular garbage collection
|
||||
initGC()
|
||||
|
||||
app := &goBlog{
|
||||
httpClient: getHTTPClient(),
|
||||
}
|
||||
|
||||
// Initialize config
|
||||
if err = app.initConfig(); err != nil {
|
||||
|
@ -79,9 +83,6 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
// Init regular garbage collection
|
||||
initGC()
|
||||
|
||||
// Execute pre-start hooks
|
||||
app.preStartHooks()
|
||||
|
||||
|
@ -91,18 +92,36 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
log.Println("Initialize components...")
|
||||
|
||||
app.initMarkdown()
|
||||
|
||||
// Link check tool after init of markdown
|
||||
if len(os.Args) >= 2 && os.Args[1] == "check" {
|
||||
app.initMarkdown()
|
||||
app.checkAllExternalLinks()
|
||||
app.shutdown.ShutdownAndWait()
|
||||
return
|
||||
}
|
||||
|
||||
// More initializations
|
||||
// Initialize components
|
||||
app.initComponents()
|
||||
|
||||
// Start cron hooks
|
||||
app.startHourlyHooks()
|
||||
|
||||
// Start the server
|
||||
err = app.startServer()
|
||||
if err != nil {
|
||||
app.logErrAndQuit("Failed to start server(s):", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Wait till everything is shutdown
|
||||
app.shutdown.Wait()
|
||||
}
|
||||
|
||||
func (app *goBlog) initComponents() {
|
||||
var err error
|
||||
// Log start
|
||||
log.Println("Initialize components...")
|
||||
app.initMarkdown()
|
||||
if err = app.initTemplateAssets(); err != nil { // Needs minify
|
||||
app.logErrAndQuit("Failed to init template assets:", err.Error())
|
||||
return
|
||||
|
@ -135,21 +154,8 @@ func main() {
|
|||
app.initTelegram()
|
||||
app.initBlogStats()
|
||||
app.initSessions()
|
||||
|
||||
// Start cron hooks
|
||||
app.startHourlyHooks()
|
||||
|
||||
// Log finish
|
||||
log.Println("Initialized components")
|
||||
|
||||
// Start the server
|
||||
err = app.startServer()
|
||||
if err != nil {
|
||||
app.logErrAndQuit("Failed to start server(s):", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Wait till everything is shutdown
|
||||
app.shutdown.Wait()
|
||||
}
|
||||
|
||||
func (a *goBlog) logErrAndQuit(v ...interface{}) {
|
||||
|
|
|
@ -80,10 +80,10 @@ func (a *goBlog) checkPost(p *post) (err error) {
|
|||
p.Slug = fmt.Sprintf("%v-%02d-%02d-%v", now.Year(), int(now.Month()), now.Day(), random)
|
||||
}
|
||||
published := timeNoErr(dateparse.ParseLocal(p.Published))
|
||||
pathTmplString := a.cfg.Blogs[p.Blog].Sections[p.Section].PathTemplate
|
||||
if pathTmplString == "" {
|
||||
return errors.New("path template empty")
|
||||
}
|
||||
pathTmplString := defaultIfEmpty(
|
||||
a.cfg.Blogs[p.Blog].Sections[p.Section].PathTemplate,
|
||||
"{{printf \""+a.getRelativePath(p.Blog, "/%v/%02d/%02d/%v")+"\" .Section .Year .Month .Slug}}",
|
||||
)
|
||||
pathTmpl, err := template.New("location").Parse(pathTmplString)
|
||||
if err != nil {
|
||||
return errors.New("failed to parse location template")
|
||||
|
|
|
@ -35,7 +35,10 @@ func (a *goBlog) sendWebmentions(p *post) error {
|
|||
return err
|
||||
}
|
||||
links = append(links, contentLinks...)
|
||||
links = append(links, p.firstParameter("link"), p.firstParameter(a.cfg.Micropub.LikeParam), p.firstParameter(a.cfg.Micropub.ReplyParam), p.firstParameter(a.cfg.Micropub.BookmarkParam))
|
||||
links = append(links, p.firstParameter("link"))
|
||||
if mpc := a.cfg.Micropub; mpc != nil {
|
||||
links = append(links, p.firstParameter(a.cfg.Micropub.LikeParam), p.firstParameter(a.cfg.Micropub.ReplyParam), p.firstParameter(a.cfg.Micropub.BookmarkParam))
|
||||
}
|
||||
for _, link := range funk.UniqString(links) {
|
||||
if link == "" {
|
||||
continue
|
||||
|
|
Loading…
Reference in New Issue