mirror of
https://github.com/go-shiori/shiori.git
synced 2025-10-06 03:35:35 +08:00
* refactor: base http server stdlib * refactor: swagger and frontend routes * fix: use global middlewares * refactor: removed gin from testutils * fix: object references in legacy webserver * refactor: legacy, swagger and system handlers * fix: added verbs to handlers * fix: server handlers ordering * refactor: bookmarks handlers * refactor: system api routes * tests: bookmark handlers * refactor: migrated api auth routes * chore: remove unused middlewares * docs: add swagger docs to refactored system api * chore: remove old auth routes * refactor: account apis * chore: removed old handlers * fix: api v1 handlers missing middlewares * refactor: migrated tag list route * refactor: bookmark routes * refactor: remove gin * chore: make styles * test: fixed tests * test: generate binary file without text * fix: global middleware missing from system api handler * fix: incorrect api handler * chore: avoid logging screenshot contents * tests: bookmarks domain * tests: shortcuts * test: missing tests * tests: server tests * test: remove test using syscall to avoid windows errors * chore: added middlewares
643 lines
20 KiB
Go
643 lines
20 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-shiori/shiori/internal/model"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type databaseTestCase func(t *testing.T, db model.DB)
|
|
type testDatabaseFactory func(t *testing.T, ctx context.Context) (model.DB, error)
|
|
|
|
func testDatabase(t *testing.T, dbFactory testDatabaseFactory) {
|
|
tests := map[string]databaseTestCase{
|
|
// Bookmarks
|
|
"testBookmarkAutoIncrement": testBookmarkAutoIncrement,
|
|
"testCreateBookmark": testCreateBookmark,
|
|
"testCreateBookmarkWithContent": testCreateBookmarkWithContent,
|
|
"testCreateBookmarkTwice": testCreateBookmarkTwice,
|
|
"testCreateBookmarkWithTag": testCreateBookmarkWithTag,
|
|
"testCreateTwoDifferentBookmarks": testCreateTwoDifferentBookmarks,
|
|
"testUpdateBookmark": testUpdateBookmark,
|
|
"testUpdateBookmarkUpdatesModifiedTime": testUpdateBookmarkUpdatesModifiedTime,
|
|
"testGetBoomarksWithTimeFilters": testGetBoomarksWithTimeFilters,
|
|
"testUpdateBookmarkWithContent": testUpdateBookmarkWithContent,
|
|
"testGetBookmark": testGetBookmark,
|
|
"testGetBookmarkNotExistent": testGetBookmarkNotExistent,
|
|
"testGetBookmarks": testGetBookmarks,
|
|
"testGetBookmarksWithSQLCharacters": testGetBookmarksWithSQLCharacters,
|
|
"testGetBookmarksCount": testGetBookmarksCount,
|
|
// Tags
|
|
"testCreateTag": testCreateTag,
|
|
"testCreateTags": testCreateTags,
|
|
// Accounts
|
|
"testCreateAccount": testCreateAccount,
|
|
"testCreateDuplicateAccount": testCreateDuplicateAccount,
|
|
"testDeleteAccount": testDeleteAccount,
|
|
"testDeleteNonExistantAccount": testDeleteNonExistantAccount,
|
|
"testUpdateAccount": testUpdateAccount,
|
|
"testUpdateAccountDuplicateUser": testUpdateAccountDuplicateUser,
|
|
"testGetAccount": testGetAccount,
|
|
"testListAccounts": testListAccounts,
|
|
"testListAccountsWithPassword": testListAccountsWithPassword,
|
|
}
|
|
|
|
for testName, testCase := range tests {
|
|
t.Run(testName, func(tInner *testing.T) {
|
|
ctx := context.TODO()
|
|
db, err := dbFactory(t, ctx)
|
|
require.NoError(tInner, err, "Error recreating database")
|
|
testCase(tInner, db)
|
|
})
|
|
}
|
|
}
|
|
|
|
func testBookmarkAutoIncrement(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
|
|
result, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
assert.Equal(t, 1, result[0].ID, "Saved bookmark must have ID %d", 1)
|
|
|
|
book = model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/obelisk",
|
|
Title: "obelisk",
|
|
}
|
|
|
|
result, err = db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
assert.Equal(t, 2, result[0].ID, "Saved bookmark must have ID %d", 2)
|
|
}
|
|
|
|
func testCreateBookmark(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/obelisk",
|
|
Title: "shiori",
|
|
}
|
|
|
|
result, err := db.SaveBookmarks(ctx, true, book)
|
|
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
assert.Equal(t, 1, result[0].ID, "Saved bookmark must have an ID set")
|
|
}
|
|
|
|
func testCreateBookmarkWithContent(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/obelisk",
|
|
Title: "shiori",
|
|
Content: "Some content",
|
|
HTML: "Some HTML content",
|
|
}
|
|
|
|
result, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
books, err := db.GetBookmarks(ctx, model.DBGetBookmarksOptions{
|
|
IDs: []int{result[0].ID},
|
|
WithContent: true,
|
|
})
|
|
assert.NoError(t, err, "Get bookmarks must not fail")
|
|
assert.Len(t, books, 1)
|
|
|
|
assert.Equal(t, 1, books[0].ID, "Saved bookmark must have an ID set")
|
|
assert.Equal(t, book.Content, books[0].Content, "Saved bookmark must have content")
|
|
assert.Equal(t, book.HTML, books[0].HTML, "Saved bookmark must have HTML")
|
|
}
|
|
|
|
func testCreateBookmarkWithTag(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/obelisk",
|
|
Title: "shiori",
|
|
Tags: []model.TagDTO{
|
|
{
|
|
Tag: model.Tag{
|
|
Name: "test-tag",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
result, err := db.SaveBookmarks(ctx, true, book)
|
|
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
assert.Equal(t, book.URL, result[0].URL)
|
|
assert.Equal(t, book.Tags[0].Name, result[0].Tags[0].Name)
|
|
}
|
|
|
|
func testCreateBookmarkTwice(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
|
|
result, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
savedBookmark := result[0]
|
|
savedBookmark.Title = "modified"
|
|
|
|
_, err = db.SaveBookmarks(ctx, true, savedBookmark)
|
|
assert.Error(t, err, "Save bookmarks must fail")
|
|
}
|
|
|
|
func testCreateTwoDifferentBookmarks(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
|
|
_, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save first bookmark must not fail")
|
|
|
|
book = model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/go-readability",
|
|
Title: "go-readability",
|
|
}
|
|
_, err = db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save second bookmark must not fail")
|
|
}
|
|
|
|
func testUpdateBookmark(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
|
|
result, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
savedBookmark := result[0]
|
|
savedBookmark.Title = "modified"
|
|
|
|
result, err = db.SaveBookmarks(ctx, false, savedBookmark)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
assert.Equal(t, "modified", result[0].Title)
|
|
assert.Equal(t, savedBookmark.ID, result[0].ID)
|
|
}
|
|
|
|
func testUpdateBookmarkWithContent(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/obelisk",
|
|
Title: "shiori",
|
|
Content: "Some content",
|
|
HTML: "Some HTML content",
|
|
}
|
|
|
|
result, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
updatedBook := result[0]
|
|
updatedBook.Content = "Some updated content"
|
|
updatedBook.HTML = "Some updated HTML content"
|
|
|
|
_, err = db.SaveBookmarks(ctx, false, updatedBook)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
books, err := db.GetBookmarks(ctx, model.DBGetBookmarksOptions{
|
|
IDs: []int{result[0].ID},
|
|
WithContent: true,
|
|
})
|
|
assert.NoError(t, err, "Get bookmarks must not fail")
|
|
assert.Len(t, books, 1)
|
|
|
|
assert.Equal(t, 1, books[0].ID, "Saved bookmark must have an ID set")
|
|
assert.Equal(t, updatedBook.Content, books[0].Content, "Saved bookmark must have updated content")
|
|
assert.Equal(t, updatedBook.HTML, books[0].HTML, "Saved bookmark must have updated HTML")
|
|
}
|
|
|
|
func testGetBookmark(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
|
|
result, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
savedBookmark, exists, err := db.GetBookmark(ctx, result[0].ID, "")
|
|
assert.True(t, exists, "Bookmark should exist")
|
|
assert.NoError(t, err, "Get bookmark should not fail")
|
|
assert.Equal(t, result[0].ID, savedBookmark.ID, "Retrieved bookmark should be the same")
|
|
assert.Equal(t, book.URL, savedBookmark.URL, "Retrieved bookmark should be the same")
|
|
}
|
|
|
|
func testGetBookmarkNotExistent(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
savedBookmark, exists, err := db.GetBookmark(ctx, 1, "")
|
|
assert.NoError(t, err, "Get bookmark should not fail")
|
|
assert.False(t, exists, "Bookmark should not exist")
|
|
assert.Equal(t, model.BookmarkDTO{}, savedBookmark)
|
|
}
|
|
|
|
func testGetBookmarks(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
|
|
bookmarks, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
savedBookmark := bookmarks[0]
|
|
|
|
results, err := db.GetBookmarks(ctx, model.DBGetBookmarksOptions{
|
|
Keyword: "go-shiori",
|
|
})
|
|
|
|
assert.NoError(t, err, "Get bookmarks should not fail")
|
|
assert.Len(t, results, 1, "results should contain one item")
|
|
assert.Equal(t, savedBookmark.ID, results[0].ID, "bookmark should be the one saved")
|
|
}
|
|
|
|
func testGetBookmarksWithSQLCharacters(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
// _ := 0
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
_, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
characters := []string{";", "%", "_", "\\", "\"", ":"}
|
|
|
|
for _, char := range characters {
|
|
t.Run("GetBookmarks/"+char, func(t *testing.T) {
|
|
_, err := db.GetBookmarks(ctx, model.DBGetBookmarksOptions{
|
|
Keyword: char,
|
|
})
|
|
assert.NoError(t, err, "Get bookmarks should not fail")
|
|
})
|
|
|
|
t.Run("GetBookmarksCount/"+char, func(t *testing.T) {
|
|
_, err := db.GetBookmarksCount(ctx, model.DBGetBookmarksOptions{
|
|
Keyword: char,
|
|
})
|
|
assert.NoError(t, err, "Get bookmarks count should not fail")
|
|
})
|
|
}
|
|
}
|
|
|
|
func testGetBookmarksCount(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
expectedCount := 1
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
|
|
_, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
count, err := db.GetBookmarksCount(ctx, model.DBGetBookmarksOptions{
|
|
Keyword: "go-shiori",
|
|
})
|
|
assert.NoError(t, err, "Get bookmarks count should not fail")
|
|
assert.Equal(t, count, expectedCount, "count should be %d", expectedCount)
|
|
}
|
|
|
|
func testCreateTag(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
tag := model.Tag{Name: "shiori"}
|
|
err := db.CreateTags(ctx, tag)
|
|
assert.NoError(t, err, "Save tag must not fail")
|
|
}
|
|
|
|
func testCreateTags(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
err := db.CreateTags(ctx, model.Tag{Name: "shiori"}, model.Tag{Name: "shiori2"})
|
|
assert.NoError(t, err, "Save tag must not fail")
|
|
}
|
|
|
|
// ----------------- ACCOUNTS -----------------
|
|
func testCreateAccount(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
acc := model.Account{
|
|
Username: "testuser",
|
|
Password: "testpass",
|
|
Owner: true,
|
|
}
|
|
insertedAccount, err := db.CreateAccount(ctx, acc)
|
|
assert.NoError(t, err, "Save account must not fail")
|
|
assert.Equal(t, acc.Username, insertedAccount.Username, "Saved account must have an username set")
|
|
assert.Equal(t, acc.Password, insertedAccount.Password, "Saved account must have a password set")
|
|
assert.Equal(t, acc.Owner, insertedAccount.Owner, "Saved account must have an owner set")
|
|
assert.NotEmpty(t, insertedAccount.ID, "Saved account must have an ID set")
|
|
}
|
|
|
|
func testDeleteAccount(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
acc := model.Account{
|
|
Username: "testuser",
|
|
Password: "testpass",
|
|
Owner: true,
|
|
}
|
|
storedAccount, err := db.CreateAccount(ctx, acc)
|
|
assert.NoError(t, err, "Save account must not fail")
|
|
|
|
err = db.DeleteAccount(ctx, storedAccount.ID)
|
|
assert.NoError(t, err, "Delete account must not fail")
|
|
|
|
_, exists, err := db.GetAccount(ctx, storedAccount.ID)
|
|
assert.False(t, exists, "Account must not exist")
|
|
assert.ErrorIs(t, err, ErrNotFound, "Get account must return not found error")
|
|
}
|
|
|
|
func testDeleteNonExistantAccount(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
err := db.DeleteAccount(ctx, model.DBID(99))
|
|
assert.ErrorIs(t, err, ErrNotFound, "Delete account must fail")
|
|
}
|
|
|
|
func testUpdateAccount(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
acc := model.Account{
|
|
Username: "testuser",
|
|
Password: "testpass",
|
|
Owner: true,
|
|
Config: model.UserConfig{
|
|
ShowId: true,
|
|
},
|
|
}
|
|
|
|
account, err := db.CreateAccount(ctx, acc)
|
|
require.Nil(t, err)
|
|
require.NotNil(t, account)
|
|
require.NotEmpty(t, account.ID)
|
|
|
|
account, _, err = db.GetAccount(ctx, account.ID)
|
|
require.Nil(t, err)
|
|
|
|
t.Run("update", func(t *testing.T) {
|
|
acc := model.Account{
|
|
ID: account.ID,
|
|
Username: "asdlasd",
|
|
Owner: false,
|
|
Password: "another",
|
|
Config: model.UserConfig{
|
|
ShowId: false,
|
|
},
|
|
}
|
|
|
|
err := db.UpdateAccount(ctx, acc)
|
|
require.Nil(t, err)
|
|
|
|
updatedAccount, exists, err := db.GetAccount(ctx, account.ID)
|
|
require.NoError(t, err)
|
|
require.True(t, exists)
|
|
require.Equal(t, acc.Username, updatedAccount.Username)
|
|
require.Equal(t, acc.Owner, updatedAccount.Owner)
|
|
require.Equal(t, acc.Config, updatedAccount.Config)
|
|
require.NotEqual(t, acc.Password, account.Password)
|
|
})
|
|
}
|
|
|
|
func testGetAccount(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
// Insert test accounts
|
|
testAccounts := []model.Account{
|
|
{Username: "foo", Password: "bar", Owner: false},
|
|
{Username: "hello", Password: "world", Owner: false},
|
|
{Username: "foo_bar", Password: "foobar", Owner: true},
|
|
}
|
|
|
|
for _, acc := range testAccounts {
|
|
storedAcc, err := db.CreateAccount(ctx, acc)
|
|
assert.Nil(t, err)
|
|
|
|
// Successful case
|
|
account, exists, err := db.GetAccount(ctx, storedAcc.ID)
|
|
assert.Nil(t, err)
|
|
assert.True(t, exists, "Expected account to exist")
|
|
assert.Equal(t, storedAcc.Username, account.Username)
|
|
}
|
|
|
|
// Failed case
|
|
account, exists, err := db.GetAccount(ctx, 99)
|
|
assert.NotNil(t, err)
|
|
assert.False(t, exists, "Expected account to exist")
|
|
assert.Empty(t, account.Username)
|
|
}
|
|
|
|
func testListAccounts(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
// prepare database
|
|
testAccounts := []model.Account{
|
|
{Username: "foo", Password: "bar", Owner: false},
|
|
{Username: "hello", Password: "world", Owner: false},
|
|
{Username: "foo_bar", Password: "foobar", Owner: true},
|
|
}
|
|
for _, acc := range testAccounts {
|
|
_, err := db.CreateAccount(ctx, acc)
|
|
assert.Nil(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
options model.DBListAccountsOptions
|
|
expected int
|
|
}{
|
|
{"default", model.DBListAccountsOptions{}, 3},
|
|
{"with owner", model.DBListAccountsOptions{Owner: true}, 1},
|
|
{"with keyword", model.DBListAccountsOptions{Keyword: "foo"}, 2},
|
|
{"with keyword and owner", model.DBListAccountsOptions{Keyword: "hello", Owner: false}, 1},
|
|
{"with no result", model.DBListAccountsOptions{Keyword: "shiori"}, 0},
|
|
{"with username", model.DBListAccountsOptions{Username: "foo"}, 1},
|
|
{"with non-existent username", model.DBListAccountsOptions{Username: "non-existant"}, 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
accounts, err := db.ListAccounts(ctx, tt.options)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.expected, len(accounts))
|
|
})
|
|
}
|
|
}
|
|
|
|
func testCreateDuplicateAccount(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
acc := model.Account{
|
|
Username: "testuser",
|
|
Password: "testpass",
|
|
Owner: false,
|
|
}
|
|
|
|
// Create first account
|
|
_, err := db.CreateAccount(ctx, acc)
|
|
assert.NoError(t, err, "First account creation must not fail")
|
|
|
|
// Try to create account with same username
|
|
_, err = db.CreateAccount(ctx, acc)
|
|
assert.ErrorIs(t, err, ErrAlreadyExists, "Creating duplicate account must return ErrAlreadyExists")
|
|
}
|
|
|
|
func testUpdateAccountDuplicateUser(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
// Create first account
|
|
acc1 := model.Account{
|
|
Username: "testuser1",
|
|
Password: "testpass",
|
|
Owner: false,
|
|
}
|
|
storedAcc1, err := db.CreateAccount(ctx, acc1)
|
|
assert.NoError(t, err, "First account creation must not fail")
|
|
|
|
// Create second account
|
|
acc2 := model.Account{
|
|
Username: "testuser2",
|
|
Password: "testpass",
|
|
Owner: false,
|
|
}
|
|
storedAcc2, err := db.CreateAccount(ctx, acc2)
|
|
assert.NoError(t, err, "Second account creation must not fail")
|
|
|
|
// Try to update second account to have same username as first
|
|
storedAcc2.Username = storedAcc1.Username
|
|
err = db.UpdateAccount(ctx, *storedAcc2)
|
|
assert.ErrorIs(t, err, ErrAlreadyExists, "Updating to duplicate username must return ErrAlreadyExists")
|
|
}
|
|
|
|
func testListAccountsWithPassword(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
_, err := db.CreateAccount(ctx, model.Account{
|
|
Username: "gopher",
|
|
Password: "shiori",
|
|
})
|
|
assert.Nil(t, err)
|
|
|
|
storedAccounts, err := db.ListAccounts(ctx, model.DBListAccountsOptions{
|
|
WithPassword: true,
|
|
})
|
|
require.NoError(t, err)
|
|
for _, acc := range storedAccounts {
|
|
require.NotEmpty(t, acc.Password)
|
|
}
|
|
}
|
|
|
|
// TODO: Consider using `t.Parallel()` once we have automated database tests spawning databases using testcontainers.
|
|
func testUpdateBookmarkUpdatesModifiedTime(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori",
|
|
Title: "shiori",
|
|
}
|
|
|
|
resultBook, err := db.SaveBookmarks(ctx, true, book)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
updatedBook := resultBook[0]
|
|
updatedBook.Title = "modified"
|
|
updatedBook.ModifiedAt = ""
|
|
|
|
time.Sleep(1 * time.Second)
|
|
resultUpdatedBooks, err := db.SaveBookmarks(ctx, false, updatedBook)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
assert.NotEqual(t, resultBook[0].ModifiedAt, resultUpdatedBooks[0].ModifiedAt)
|
|
assert.Equal(t, resultBook[0].CreatedAt, resultUpdatedBooks[0].CreatedAt)
|
|
assert.Equal(t, resultBook[0].CreatedAt, resultBook[0].ModifiedAt)
|
|
assert.NoError(t, err, "Get bookmarks must not fail")
|
|
|
|
assert.Equal(t, updatedBook.Title, resultUpdatedBooks[0].Title, "Saved bookmark must have updated Title")
|
|
}
|
|
|
|
// TODO: Consider using `t.Parallel()` once we have automated database tests spawning databases using testcontainers.
|
|
func testGetBoomarksWithTimeFilters(t *testing.T, db model.DB) {
|
|
ctx := context.TODO()
|
|
|
|
book1 := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori/one",
|
|
Title: "Added First but Modified Last",
|
|
}
|
|
book2 := model.BookmarkDTO{
|
|
URL: "https://github.com/go-shiori/shiori/second",
|
|
Title: "Added Last but Modified First",
|
|
}
|
|
|
|
// create two new bookmark
|
|
resultBook1, err := db.SaveBookmarks(ctx, true, book1)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
time.Sleep(1 * time.Second)
|
|
resultBook2, err := db.SaveBookmarks(ctx, true, book2)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
// update those bookmarks
|
|
updatedBook1 := resultBook1[0]
|
|
updatedBook1.Title = "Added First but Modified Last Updated Title"
|
|
updatedBook1.ModifiedAt = ""
|
|
|
|
updatedBook2 := resultBook2[0]
|
|
updatedBook2.Title = "Last Added but modified First Updated Title"
|
|
updatedBook2.ModifiedAt = ""
|
|
|
|
// modified bookmark2 first after one second modified bookmark1
|
|
resultUpdatedBook2, err := db.SaveBookmarks(ctx, false, updatedBook2)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
time.Sleep(1 * time.Second)
|
|
resultUpdatedBook1, err := db.SaveBookmarks(ctx, false, updatedBook1)
|
|
assert.NoError(t, err, "Save bookmarks must not fail")
|
|
|
|
// get diffrent filteter combination
|
|
booksOrderByLastAdded, err := db.GetBookmarks(ctx, model.DBGetBookmarksOptions{
|
|
IDs: []int{resultUpdatedBook1[0].ID, resultUpdatedBook2[0].ID},
|
|
OrderMethod: 1,
|
|
})
|
|
assert.NoError(t, err, "Get bookmarks must not fail")
|
|
booksOrderByLastModified, err := db.GetBookmarks(ctx, model.DBGetBookmarksOptions{
|
|
IDs: []int{resultUpdatedBook1[0].ID, resultUpdatedBook2[0].ID},
|
|
OrderMethod: 2,
|
|
})
|
|
assert.NoError(t, err, "Get bookmarks must not fail")
|
|
booksOrderById, err := db.GetBookmarks(ctx, model.DBGetBookmarksOptions{
|
|
IDs: []int{resultUpdatedBook1[0].ID, resultUpdatedBook2[0].ID},
|
|
OrderMethod: 0,
|
|
})
|
|
assert.NoError(t, err, "Get bookmarks must not fail")
|
|
|
|
// Check Last Added
|
|
assert.Equal(t, booksOrderByLastAdded[0].Title, updatedBook2.Title)
|
|
// Check Last Modified
|
|
assert.Equal(t, booksOrderByLastModified[0].Title, updatedBook1.Title)
|
|
// Second id should be 2 if order them by id
|
|
assert.Equal(t, booksOrderById[1].ID, 2)
|
|
}
|