diff --git a/app/entry_register_test.go b/app/entry_register_test.go new file mode 100644 index 0000000..47775d1 --- /dev/null +++ b/app/entry_register_test.go @@ -0,0 +1,23 @@ +package app_test + +import ( + "owl-blogs/app" + "owl-blogs/test" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestRegistryTypeNameNotExisting(t *testing.T) { + register := app.NewEntryTypeRegistry() + _, err := register.TypeName(&test.MockEntry{}) + require.Error(t, err) +} + +func TestRegistryTypeName(t *testing.T) { + register := app.NewEntryTypeRegistry() + register.Register(&test.MockEntry{}) + name, err := register.TypeName(&test.MockEntry{}) + require.NoError(t, err) + require.Equal(t, "MockEntry", name) +} diff --git a/cmd/owl/editor_test.go b/cmd/owl/editor_test.go index a7735a5..a2efef6 100644 --- a/cmd/owl/editor_test.go +++ b/cmd/owl/editor_test.go @@ -3,18 +3,34 @@ package main import ( "bytes" "io" + "math/rand" "mime/multipart" "net/http/httptest" "os" + "owl-blogs/domain/model" + "owl-blogs/infra" "path" "path/filepath" + "strings" "testing" + "time" "github.com/stretchr/testify/require" ) +func testDbName() string { + var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + rand.Seed(time.Now().UnixNano()) + b := make([]rune, 6) + for i := range b { + b[i] = letterRunes[rand.Intn(len(letterRunes))] + } + return "/tmp/" + string(b) + ".db" +} + func TestEditorFormGet(t *testing.T) { - app := App().FiberApp + db := infra.NewSqliteDB(testDbName()) + app := App(db).FiberApp req := httptest.NewRequest("GET", "/editor/ImageEntry", nil) resp, err := app.Test(req) @@ -23,7 +39,11 @@ func TestEditorFormGet(t *testing.T) { } func TestEditorFormPost(t *testing.T) { - app := App().FiberApp + dbName := testDbName() + db := infra.NewSqliteDB(dbName) + owlApp := App(db) + app := owlApp.FiberApp + repo := infra.NewEntryRepository(db, owlApp.Registry) fileDir, _ := os.Getwd() fileName := "../../test/fixtures/test.png" @@ -41,8 +61,17 @@ func TestEditorFormPost(t *testing.T) { io.WriteString(part, "test content") writer.Close() - req := httptest.NewRequest("POST", "/editor/ImageEntry", nil) + req := httptest.NewRequest("POST", "/editor/ImageEntry", body) + req.Header.Set("Content-Type", writer.FormDataContentType()) resp, err := app.Test(req) require.NoError(t, err) - require.Equal(t, 200, resp.StatusCode) + require.Equal(t, 302, resp.StatusCode) + require.Contains(t, resp.Header.Get("Location"), "/posts/") + + id := strings.Split(resp.Header.Get("Location"), "/")[2] + entry, err := repo.FindById(id) + require.NoError(t, err) + require.Equal(t, "test content", entry.MetaData().(*model.ImageEntryMetaData).Content) + // require.Equal(t, "test.png", entry.MetaData().(*model.ImageEntryMetaData).ImagePath) + } diff --git a/cmd/owl/main.go b/cmd/owl/main.go index 22ae34d..815b8cb 100644 --- a/cmd/owl/main.go +++ b/cmd/owl/main.go @@ -7,8 +7,9 @@ import ( "owl-blogs/web" ) -func App() *web.WebApp { - db := infra.NewSqliteDB("owlblogs.db") +const DbPath = "owlblogs.db" + +func App(db infra.Database) *web.WebApp { registry := app.NewEntryTypeRegistry() registry.Register(&model.ImageEntry{}) @@ -20,5 +21,6 @@ func App() *web.WebApp { } func main() { - App().Run() + db := infra.NewSqliteDB(DbPath) + App(db).Run() } diff --git a/domain/model/image_entry.go b/domain/model/image_entry.go index 0ac5ee2..195be9e 100644 --- a/domain/model/image_entry.go +++ b/domain/model/image_entry.go @@ -9,8 +9,8 @@ type ImageEntry struct { } type ImageEntryMetaData struct { - ImagePath string `owl:"inputType=file"` - Content EntryContent `owl:"inputType=text widget=textarea"` + ImagePath string `owl:"inputType=file"` + Content string `owl:"inputType=text widget=textarea"` } func (e *ImageEntry) ID() string { @@ -18,7 +18,7 @@ func (e *ImageEntry) ID() string { } func (e *ImageEntry) Content() EntryContent { - return e.meta.Content + return EntryContent(e.meta.Content) } func (e *ImageEntry) PublishedAt() *time.Time { @@ -26,10 +26,7 @@ func (e *ImageEntry) PublishedAt() *time.Time { } func (e *ImageEntry) MetaData() interface{} { - return &ImageEntryMetaData{ - ImagePath: e.meta.ImagePath, - Content: e.meta.Content, - } + return &e.meta } func (e *ImageEntry) Create(id string, publishedAt *time.Time, metaData EntryMetaData) error { diff --git a/web/app.go b/web/app.go index dd08d47..7b5eb6a 100644 --- a/web/app.go +++ b/web/app.go @@ -8,7 +8,8 @@ import ( type WebApp struct { FiberApp *fiber.App - entryService *app.EntryService + EntryService *app.EntryService + Registry *app.EntryTypeRegistry } func NewWebApp(entryService *app.EntryService, typeRegistry *app.EntryTypeRegistry) *WebApp { @@ -16,7 +17,7 @@ func NewWebApp(entryService *app.EntryService, typeRegistry *app.EntryTypeRegist indexHandler := NewIndexHandler(entryService) listHandler := NewListHandler(entryService) - entryHandler := NewEntryHandler(entryService) + entryHandler := NewEntryHandler(entryService, typeRegistry) mediaHandler := NewMediaHandler(entryService) rssHandler := NewRSSHandler(entryService) loginHandler := NewLoginHandler(entryService) @@ -50,7 +51,7 @@ func NewWebApp(entryService *app.EntryService, typeRegistry *app.EntryTypeRegist // app.Post("/auth/token/", userAuthTokenHandler(repo)) // app.Get("/.well-known/oauth-authorization-server", userAuthMetadataHandler(repo)) // app.NotFound = http.HandlerFunc(notFoundHandler(repo)) - return &WebApp{FiberApp: app, entryService: entryService} + return &WebApp{FiberApp: app, EntryService: entryService, Registry: typeRegistry} } func (w *WebApp) Run() { diff --git a/web/editor/entity_form_test.go b/web/editor/entry_form_test.go similarity index 100% rename from web/editor/entity_form_test.go rename to web/editor/entry_form_test.go diff --git a/web/editor_handler.go b/web/editor_handler.go index b80675c..b4d4ac3 100644 --- a/web/editor_handler.go +++ b/web/editor_handler.go @@ -53,18 +53,17 @@ func (h *EditorHandler) HandlePost(c *fiber.Ctx) error { form := editor.NewEntryForm(entryType) // get form data - metaData, err := form.Parse(c) + entry, err := form.Parse(c) if err != nil { return err } // create entry now := time.Now() - entry := entryType - err = h.entrySvc.Create(entry, &now, metaData.MetaData()) + err = h.entrySvc.Create(entry, &now, entry.MetaData()) if err != nil { return err } + return c.Redirect("/posts/" + entry.ID() + "/") - return c.SendString("Hello, Editor!") } diff --git a/web/entry_handler.go b/web/entry_handler.go index 5c39911..3b81401 100644 --- a/web/entry_handler.go +++ b/web/entry_handler.go @@ -2,18 +2,46 @@ package web import ( "owl-blogs/app" + "owl-blogs/domain/model" + "text/template" "github.com/gofiber/fiber/v2" ) type EntryHandler struct { entrySvc *app.EntryService + registry *app.EntryTypeRegistry } -func NewEntryHandler(entryService *app.EntryService) *EntryHandler { - return &EntryHandler{entrySvc: entryService} +func NewEntryHandler(entryService *app.EntryService, registry *app.EntryTypeRegistry) *EntryHandler { + return &EntryHandler{entrySvc: entryService, registry: registry} +} + +func (h *EntryHandler) getTemplate(entry model.Entry) (*template.Template, error) { + name, err := h.registry.TypeName(entry) + if err != nil { + return nil, err + } + return template.ParseFS( + templates, + "templates/base.tmpl", + "templates/views/entry/"+name+".tmpl", + ) } func (h *EntryHandler) Handle(c *fiber.Ctx) error { - return c.SendString("Hello, RSS!") + c.Set(fiber.HeaderContentType, fiber.MIMETextHTML) + + entryId := c.Params("post") + entry, err := h.entrySvc.FindById(entryId) + if err != nil { + return err + } + + template, err := h.getTemplate(entry) + if err != nil { + return err + } + + return template.ExecuteTemplate(c, "base", entry) } diff --git a/web/templates/views/entry/ImageEntry.tmpl b/web/templates/views/entry/ImageEntry.tmpl new file mode 100644 index 0000000..05441b9 --- /dev/null +++ b/web/templates/views/entry/ImageEntry.tmpl @@ -0,0 +1,17 @@ +{{define "title"}}Image Entry{{end}} + +{{define "main"}} + +{{.MetaData.ImagePath}} + +

+{{.Content}} +

+ +

+ Published: {{.PublishedAt}} +

+ + +{{end}} +