diff --git a/api/README.md b/api/README.md index 2f65266..a38348d 100644 --- a/api/README.md +++ b/api/README.md @@ -50,7 +50,7 @@ information on the total posts, pages and posts per page. { "url": "/api/v1/post/example-post", "title": "An Example Post", - "date": "2018-05-18T00:00:00Z", + "date": "2018-05-18", "content": "TEST", "created_at": "2018-05-18T15:16:17Z", "updated_at": "2018-05-18T15:16:17Z" @@ -79,7 +79,7 @@ Contains the single post. { "url": "/api/v1/post/example-post", "title": "An Example Post", - "date": "2018-05-18T00:00:00Z", + "date": "2018-05-18", "content": "TEST", "created_at": "2018-05-18T15:16:17Z", "updated_at": "2018-05-18T15:16:17Z" @@ -117,7 +117,7 @@ The date can be provided in the following formats: { "url": "/api/v1/post/a-brand-new-post", "title": "A Brand New Post", - "date": "2018-06-28T00:42:12Z", + "date": "2018-06-28", "content": "This is a brand new post, completely." } ``` @@ -141,7 +141,7 @@ Contains a randomly selected post. { "url": "/api/v1/post/example-post", "title": "An Example Post", - "date": "2018-05-18T12:53:22Z", + "date": "2018-05-18", "content": "TEST" } ``` @@ -187,7 +187,7 @@ When updating the post, the slug remains constant, even when the title changes. { "url": "/api/v1/post/a-brand-new-post", "title": "Even Braver New World", - "date": "2018-06-21T09:12:00Z", + "date": "2018-06-21", "content": "I changed a bit more on this attempt." } ``` diff --git a/internal/app/controller/apiv1/create.go b/internal/app/controller/apiv1/create.go index 101733e..bfea912 100644 --- a/internal/app/controller/apiv1/create.go +++ b/internal/app/controller/apiv1/create.go @@ -37,7 +37,7 @@ func (c *Create) Run(response http.ResponseWriter, request *http.Request) { response.WriteHeader(http.StatusCreated) encoder := json.NewEncoder(response) encoder.SetEscapeHTML(false) - encoder.Encode(journal) + encoder.Encode(MapJournalToJSON(journal)) } } } diff --git a/internal/app/controller/apiv1/data.go b/internal/app/controller/apiv1/data.go index db3d91c..58fc1e9 100644 --- a/internal/app/controller/apiv1/data.go +++ b/internal/app/controller/apiv1/data.go @@ -21,7 +21,7 @@ func MapJournalToJSON(journal model.Journal) journalToJSON { result := journalToJSON{ URL: "/api/v1/post/" + journal.Slug, Title: journal.Title, - Date: journal.Date, + Date: journal.GetEditableDate(), Content: journal.Content, } diff --git a/internal/app/controller/apiv1/stats.go b/internal/app/controller/apiv1/stats.go index c473ef6..07ca5b3 100644 --- a/internal/app/controller/apiv1/stats.go +++ b/internal/app/controller/apiv1/stats.go @@ -52,7 +52,7 @@ func (c *Stats) Run(response http.ResponseWriter, request *http.Request) { if stats.Posts.Count > 0 { firstPost := allJournals[stats.Posts.Count-1] - stats.Posts.FirstPostDate = firstPost.GetDate() + stats.Posts.FirstPostDate = firstPost.GetEditableDate() } stats.Configuration.Title = container.Configuration.Title diff --git a/internal/app/controller/apiv1/update.go b/internal/app/controller/apiv1/update.go index 9bf0c6f..26f6bd3 100644 --- a/internal/app/controller/apiv1/update.go +++ b/internal/app/controller/apiv1/update.go @@ -51,7 +51,7 @@ func (c *Update) Run(response http.ResponseWriter, request *http.Request) { journal = js.Save(journal) encoder := json.NewEncoder(response) encoder.SetEscapeHTML(false) - encoder.Encode(journal) + encoder.Encode(MapJournalToJSON(journal)) } } } diff --git a/internal/app/controller/web/view_test.go b/internal/app/controller/web/view_test.go index 3151099..9596db8 100644 --- a/internal/app/controller/web/view_test.go +++ b/internal/app/controller/web/view_test.go @@ -63,7 +63,7 @@ func TestView_Run(t *testing.T) { t.Error("Expected previous and next links to be shown in page") } - // Test that timestamp metadata section is NOT displayed when timestamps are nil + // Test that timestamp labels are displayed when timestamps are present response.Reset() request, _ = http.NewRequest("GET", "/slug", strings.NewReader("")) // Reset database to single mode @@ -72,10 +72,7 @@ func TestView_Run(t *testing.T) { db.Rows = &database.MockJournal_SingleRow{} controller.Init(container, []string{"", "slug"}, request) controller.Run(response, request) - if strings.Contains(response.Content, "class=\"metadata\"") { - t.Error("Expected metadata section to NOT be displayed when timestamps are nil") - } - if strings.Contains(response.Content, "Created:") || strings.Contains(response.Content, "Last updated:") { - t.Error("Expected timestamp labels to NOT be displayed when timestamps are nil") + if !strings.Contains(response.Content, "Created:") || !strings.Contains(response.Content, "Last Updated:") { + t.Error("Expected timestamp labels to be displayed when timestamps are present") } } diff --git a/internal/app/model/visit.go b/internal/app/model/visit.go index e9921cd..d0e4950 100644 --- a/internal/app/model/visit.go +++ b/internal/app/model/visit.go @@ -110,7 +110,7 @@ func (vs *Visits) GetDailyStats(days int) []DailyVisit { query := ` SELECT - date, + DATE(date), COALESCE(SUM(CASE WHEN url LIKE '/api/%' THEN hits ELSE 0 END), 0) as api_hits, COALESCE(SUM(CASE WHEN url NOT LIKE '/api/%' THEN hits ELSE 0 END), 0) as web_hits, COALESCE(SUM(hits), 0) as total diff --git a/journal_test.go b/journal_test.go index 479e4a0..1224258 100644 --- a/journal_test.go +++ b/journal_test.go @@ -96,7 +96,7 @@ func TestApiv1List(t *testing.T) { defer res.Body.Close() body, _ := io.ReadAll(res.Body) - expected := `{"links":{},"pagination":{"current_page":1,"total_pages":1,"posts_per_page":20,"total_posts":3},"posts":[{"url":"/api/v1/post/test-3","title":"A Final Test","date":"2018-03-01T00:00:00Z","content":"
Test finally!
"},{"url":"/api/v1/post/test-2","title":"Another Test","date":"2018-02-01T00:00:00Z","content":"Test again!
"},{"url":"/api/v1/post/test","title":"Test","date":"2018-01-01T00:00:00Z","content":"Test!
"}]}` + expected := `{"links":{},"pagination":{"current_page":1,"total_pages":1,"posts_per_page":20,"total_posts":3},"posts":[{"url":"/api/v1/post/test-3","title":"A Final Test","date":"2018-03-01","content":"Test finally!
"},{"url":"/api/v1/post/test-2","title":"Another Test","date":"2018-02-01","content":"Test again!
"},{"url":"/api/v1/post/test","title":"Test","date":"2018-01-01","content":"Test!
"}]}` // Use contains to get rid of any extra whitespace that we can discount if !strings.Contains(string(body[:]), expected) { @@ -122,7 +122,7 @@ func TestApiV1Single(t *testing.T) { defer res.Body.Close() body, _ := io.ReadAll(res.Body) - expected := `{"url":"/api/v1/post/test","title":"Test","date":"2018-01-01T00:00:00Z","content":"Test!
"}` + expected := `{"url":"/api/v1/post/test","title":"Test","date":"2018-01-01","content":"Test!
"}` // Use contains to get rid of any extra whitespace that we can discount if !strings.Contains(string(body[:]), expected) { @@ -191,7 +191,7 @@ func TestApiV1Create(t *testing.T) { bodyStr := string(body[:]) // Check for expected fields - expectedFields := []string{`"id":4`, `"slug":"test-4"`, `"title":"Test 4"`, `"date":"2018-06-01T00:00:00Z"`, `"content":"Test 4!
"`, `"created_at"`, `"updated_at"`} + expectedFields := []string{`"url":"/api/v1/post/test-4"`, `"title":"Test 4"`, `"date":"2018-06-01"`, `"content":"Test 4!
"`, `"created_at"`, `"updated_at"`} for _, field := range expectedFields { if !strings.Contains(bodyStr, field) { t.Errorf("Expected response to contain %s\nGot:\n\t%s", field, bodyStr) @@ -265,7 +265,7 @@ func TestApiV1Create_RepeatTitles(t *testing.T) { bodyStr := string(body[:]) // Check for expected fields - expectedFields := []string{`"url":"/api/v1/post/repeated-1"`, `"title":"Repeated"`, `"date":"2019-02-01T00:00:00Z"`, `"content":"Repeated content test again!
"`, `"created_at"`, `"updated_at"`} + expectedFields := []string{`"url":"/api/v1/post/repeated-1"`, `"title":"Repeated"`, `"date":"2019-02-01"`, `"content":"Repeated content test again!
"`, `"created_at"`, `"updated_at"`} for _, field := range expectedFields { if !strings.Contains(bodyStr, field) { t.Errorf("Expected response to contain %s\nGot:\n\t%s", field, bodyStr) @@ -293,7 +293,7 @@ func TestApiV1Update(t *testing.T) { bodyStr := string(body[:]) // Check for expected fields - expectedFields := []string{`"id":1`, `"slug":"test"`, `"title":"A different title"`, `"date":"2018-01-01T00:00:00Z"`, `"content":"Test!
"`, `"updated_at"`} + expectedFields := []string{`"url":"/api/v1/post/test"`, `"title":"A different title"`, `"date":"2018-01-01"`, `"content":"Test!
"`, `"updated_at"`} for _, field := range expectedFields { if !strings.Contains(bodyStr, field) { t.Errorf("Expected response to contain %s\nGot:\n\t%s", field, bodyStr) @@ -359,7 +359,7 @@ func TestApiV1Stats(t *testing.T) { now := time.Now() date := now.Format("2006-01-02") month := now.Format("2006-01") - expected := fmt.Sprintf(`{"posts":{"count":3,"first_post_date":"Monday January 1, 2018"},"configuration":{"title":"Jamie's Journal","description":"A private journal containing Jamie's innermost thoughts","theme":"default","posts_per_page":20,"google_analytics":false,"create_enabled":true,"edit_enabled":true},"visits":{"daily":[{"date":"%sT00:00:00Z","api_hits":1,"web_hits":0,"total":1}],"monthly":[{"month":"%s","api_hits":1,"web_hits":0,"total":1}]}}`, date, month) + expected := fmt.Sprintf(`{"posts":{"count":3,"first_post_date":"2018-01-01"},"configuration":{"title":"Jamie's Journal","description":"A private journal containing Jamie's innermost thoughts","theme":"default","posts_per_page":20,"google_analytics":false,"create_enabled":true,"edit_enabled":true},"visits":{"daily":[{"date":"%s","api_hits":1,"web_hits":0,"total":1}],"monthly":[{"month":"%s","api_hits":1,"web_hits":0,"total":1}]}}`, date, month) // Use contains to get rid of any extra whitespace that we can discount if !strings.Contains(string(body[:]), expected) { diff --git a/pkg/session/store.go b/pkg/session/store.go index f9d9460..61e7245 100644 --- a/pkg/session/store.go +++ b/pkg/session/store.go @@ -76,6 +76,8 @@ func (s *DefaultStore) Get(r *http.Request) (*Session, error) { } if err == nil { s.cachedSession = session + } else { + s.cachedSession = NewSession() } } diff --git a/test/mocks/database/database.go b/test/mocks/database/database.go index b8621cc..034c170 100644 --- a/test/mocks/database/database.go +++ b/test/mocks/database/database.go @@ -90,8 +90,10 @@ func (m *MockJournal_SingleRow) Scan(dest ...interface{}) error { *dest[2].(*string) = "Title" *dest[3].(*string) = "2018-02-01" *dest[4].(*string) = "Content" - *dest[5].(**time.Time) = nil - *dest[6].(**time.Time) = nil + createdAt := time.Date(2018, 2, 1, 10, 0, 0, 0, time.UTC) + updatedAt := time.Date(2018, 2, 1, 10, 0, 0, 0, time.UTC) + *dest[5].(**time.Time) = &createdAt + *dest[6].(**time.Time) = &updatedAt } return nil } diff --git a/web/static/openapi.yml b/web/static/openapi.yml index fb244dd..59f52e0 100644 --- a/web/static/openapi.yml +++ b/web/static/openapi.yml @@ -113,8 +113,8 @@ components: example: 'My Journal Post' date: type: string - format: date-time - example: '2018-06-21T09:12:00Z' + format: date + example: '2018-06-21' content: type: string example: 'Some post content.' @@ -172,7 +172,7 @@ components: date: type: string format: date - example: '2018-06-2' + example: '2018-06-21' content: type: string example: 'Some post content.' @@ -206,7 +206,8 @@ components: example: 42 first_post_date: type: string - example: 'Monday January 1, 2018' + format: date + example: '2018-01-01' configuration: type: object required: @@ -226,7 +227,7 @@ components: example: "A private journal containing Jamie's innermost thoughts" theme: type: string - example: "default" + example: 'default' posts_per_page: type: integer example: 20 @@ -251,7 +252,7 @@ components: date: type: string format: date - example: "2023-12-25" + example: '2023-12-25' api_hits: type: integer example: 15 @@ -269,7 +270,7 @@ components: properties: month: type: string - example: "2023-12" + example: '2023-12' api_hits: type: integer example: 450