mirror of
https://github.com/dnote/dnote
synced 2026-03-14 22:45:50 +01:00
673 lines
20 KiB
Go
673 lines
20 KiB
Go
/* Copyright (C) 2019, 2020, 2021 Monomax Software Pty Ltd
|
|
*
|
|
* This file is part of Dnote.
|
|
*
|
|
* Dnote is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Dnote is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with Dnote. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/dnote/dnote/pkg/assert"
|
|
"github.com/dnote/dnote/pkg/clock"
|
|
"github.com/dnote/dnote/pkg/server/app"
|
|
"github.com/dnote/dnote/pkg/server/config"
|
|
"github.com/dnote/dnote/pkg/server/database"
|
|
"github.com/dnote/dnote/pkg/server/presenters"
|
|
"github.com/dnote/dnote/pkg/server/testutils"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func TestGetBooks(t *testing.T) {
|
|
defer testutils.ClearData(testutils.DB)
|
|
|
|
// Setup
|
|
server := MustNewServer(t, &app.App{
|
|
Clock: clock.NewMock(),
|
|
Config: config.Config{
|
|
PageTemplateDir: "../views",
|
|
},
|
|
})
|
|
defer server.Close()
|
|
|
|
user := testutils.SetupUserData()
|
|
testutils.SetupAccountData(user, "alice@test.com", "pass1234")
|
|
anotherUser := testutils.SetupUserData()
|
|
testutils.SetupAccountData(anotherUser, "bob@test.com", "pass1234")
|
|
|
|
b1 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "js",
|
|
USN: 1123,
|
|
Deleted: false,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b1), "preparing b1")
|
|
b2 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "css",
|
|
USN: 1125,
|
|
Deleted: false,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b2), "preparing b2")
|
|
b3 := database.Book{
|
|
UserID: anotherUser.ID,
|
|
Label: "css",
|
|
USN: 1128,
|
|
Deleted: false,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b3), "preparing b3")
|
|
b4 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "",
|
|
USN: 1129,
|
|
Deleted: true,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b4), "preparing b4")
|
|
|
|
// Execute
|
|
endpoint := "/api/v3/books"
|
|
|
|
req := testutils.MakeReq(server.URL, "GET", endpoint, "")
|
|
res := testutils.HTTPAuthDo(t, req, user)
|
|
|
|
// Test
|
|
assert.StatusCodeEquals(t, res, http.StatusOK, "")
|
|
|
|
var payload []presenters.Book
|
|
if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
|
|
t.Fatal(errors.Wrap(err, "decoding payload"))
|
|
}
|
|
|
|
var b1Record, b2Record database.Book
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b1.ID).First(&b1Record), "finding b1")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b2.ID).First(&b2Record), "finding b2")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b2.ID).First(&b2Record), "finding b2")
|
|
|
|
expected := []presenters.Book{
|
|
{
|
|
UUID: b2Record.UUID,
|
|
CreatedAt: b2Record.CreatedAt,
|
|
UpdatedAt: b2Record.UpdatedAt,
|
|
Label: b2Record.Label,
|
|
USN: b2Record.USN,
|
|
},
|
|
{
|
|
UUID: b1Record.UUID,
|
|
CreatedAt: b1Record.CreatedAt,
|
|
UpdatedAt: b1Record.UpdatedAt,
|
|
Label: b1Record.Label,
|
|
USN: b1Record.USN,
|
|
},
|
|
}
|
|
|
|
assert.DeepEqual(t, payload, expected, "payload mismatch")
|
|
}
|
|
|
|
func TestGetBooksByName(t *testing.T) {
|
|
defer testutils.ClearData(testutils.DB)
|
|
|
|
// Setup
|
|
server := MustNewServer(t, &app.App{
|
|
Clock: clock.NewMock(),
|
|
Config: config.Config{
|
|
PageTemplateDir: "../views",
|
|
},
|
|
})
|
|
defer server.Close()
|
|
|
|
user := testutils.SetupUserData()
|
|
testutils.SetupAccountData(user, "alice@test.com", "pass1234")
|
|
anotherUser := testutils.SetupUserData()
|
|
testutils.SetupAccountData(anotherUser, "bob@test.com", "pass1234")
|
|
|
|
b1 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "js",
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b1), "preparing b1")
|
|
b2 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "css",
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b2), "preparing b2")
|
|
b3 := database.Book{
|
|
UserID: anotherUser.ID,
|
|
Label: "js",
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b3), "preparing b3")
|
|
|
|
// Execute
|
|
endpoint := "/api/v3/books?name=js"
|
|
|
|
req := testutils.MakeReq(server.URL, "GET", endpoint, "")
|
|
res := testutils.HTTPAuthDo(t, req, user)
|
|
|
|
// Test
|
|
assert.StatusCodeEquals(t, res, http.StatusOK, "")
|
|
|
|
var payload []presenters.Book
|
|
if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
|
|
t.Fatal(errors.Wrap(err, "decoding payload"))
|
|
}
|
|
|
|
var b1Record database.Book
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b1.ID).First(&b1Record), "finding b1")
|
|
|
|
expected := []presenters.Book{
|
|
{
|
|
UUID: b1Record.UUID,
|
|
CreatedAt: b1Record.CreatedAt,
|
|
UpdatedAt: b1Record.UpdatedAt,
|
|
Label: b1Record.Label,
|
|
USN: b1Record.USN,
|
|
},
|
|
}
|
|
|
|
assert.DeepEqual(t, payload, expected, "payload mismatch")
|
|
}
|
|
|
|
func TestGetBook(t *testing.T) {
|
|
defer testutils.ClearData(testutils.DB)
|
|
|
|
// Setup
|
|
server := MustNewServer(t, &app.App{
|
|
Clock: clock.NewMock(),
|
|
Config: config.Config{
|
|
PageTemplateDir: "../views",
|
|
},
|
|
})
|
|
defer server.Close()
|
|
|
|
user := testutils.SetupUserData()
|
|
testutils.SetupAccountData(user, "alice@test.com", "pass1234")
|
|
anotherUser := testutils.SetupUserData()
|
|
testutils.SetupAccountData(anotherUser, "bob@test.com", "pass1234")
|
|
|
|
b1 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "js",
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b1), "preparing b1")
|
|
b2 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "css",
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b2), "preparing b2")
|
|
b3 := database.Book{
|
|
UserID: anotherUser.ID,
|
|
Label: "js",
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b3), "preparing b3")
|
|
|
|
// Execute
|
|
endpoint := fmt.Sprintf("/api/v3/books/%s", b1.UUID)
|
|
req := testutils.MakeReq(server.URL, "GET", endpoint, "")
|
|
res := testutils.HTTPAuthDo(t, req, user)
|
|
|
|
// Test
|
|
assert.StatusCodeEquals(t, res, http.StatusOK, "")
|
|
|
|
var payload presenters.Book
|
|
if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
|
|
t.Fatal(errors.Wrap(err, "decoding payload"))
|
|
}
|
|
|
|
var b1Record database.Book
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b1.ID).First(&b1Record), "finding b1")
|
|
|
|
expected := presenters.Book{
|
|
UUID: b1Record.UUID,
|
|
CreatedAt: b1Record.CreatedAt,
|
|
UpdatedAt: b1Record.UpdatedAt,
|
|
Label: b1Record.Label,
|
|
USN: b1Record.USN,
|
|
}
|
|
|
|
assert.DeepEqual(t, payload, expected, "payload mismatch")
|
|
}
|
|
|
|
func TestGetBookNonOwner(t *testing.T) {
|
|
defer testutils.ClearData(testutils.DB)
|
|
|
|
// Setup
|
|
server := MustNewServer(t, &app.App{
|
|
Clock: clock.NewMock(),
|
|
Config: config.Config{
|
|
PageTemplateDir: "../views",
|
|
},
|
|
})
|
|
defer server.Close()
|
|
|
|
user := testutils.SetupUserData()
|
|
testutils.SetupAccountData(user, "alice@test.com", "pass1234")
|
|
nonOwner := testutils.SetupUserData()
|
|
testutils.SetupAccountData(nonOwner, "bob@test.com", "pass1234")
|
|
|
|
b1 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "js",
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b1), "preparing b1")
|
|
|
|
// Execute
|
|
endpoint := fmt.Sprintf("/api/v3/books/%s", b1.UUID)
|
|
req := testutils.MakeReq(server.URL, "GET", endpoint, "")
|
|
res := testutils.HTTPAuthDo(t, req, nonOwner)
|
|
|
|
// Test
|
|
assert.StatusCodeEquals(t, res, http.StatusNotFound, "")
|
|
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
if err != nil {
|
|
t.Fatal(errors.Wrap(err, "reading body"))
|
|
}
|
|
assert.DeepEqual(t, string(body), "", "payload mismatch")
|
|
}
|
|
|
|
func TestCreateBook(t *testing.T) {
|
|
t.Run("success", func(t *testing.T) {
|
|
defer testutils.ClearData(testutils.DB)
|
|
|
|
// Setup
|
|
server := MustNewServer(t, &app.App{
|
|
Clock: clock.NewMock(),
|
|
Config: config.Config{
|
|
PageTemplateDir: "../views",
|
|
},
|
|
})
|
|
defer server.Close()
|
|
|
|
user := testutils.SetupUserData()
|
|
testutils.SetupAccountData(user, "alice@test.com", "pass1234")
|
|
testutils.MustExec(t, testutils.DB.Model(&user).Update("max_usn", 101), "preparing user max_usn")
|
|
|
|
req := testutils.MakeReq(server.URL, "POST", "/api/v3/books", `{"name": "js"}`)
|
|
|
|
// Execute
|
|
res := testutils.HTTPAuthDo(t, req, user)
|
|
|
|
// Test
|
|
assert.StatusCodeEquals(t, res, http.StatusCreated, "")
|
|
|
|
var bookRecord database.Book
|
|
var userRecord database.User
|
|
var bookCount, noteCount int
|
|
testutils.MustExec(t, testutils.DB.Model(&database.Book{}).Count(&bookCount), "counting books")
|
|
testutils.MustExec(t, testutils.DB.Model(&database.Note{}).Count(¬eCount), "counting notes")
|
|
testutils.MustExec(t, testutils.DB.First(&bookRecord), "finding book")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", user.ID).First(&userRecord), "finding user record")
|
|
|
|
maxUSN := 102
|
|
|
|
assert.Equalf(t, bookCount, 1, "book count mismatch")
|
|
assert.Equalf(t, noteCount, 0, "note count mismatch")
|
|
|
|
assert.NotEqual(t, bookRecord.UUID, "", "book uuid should have been generated")
|
|
assert.Equal(t, bookRecord.Label, "js", "book name mismatch")
|
|
assert.Equal(t, bookRecord.UserID, user.ID, "book user_id mismatch")
|
|
assert.Equal(t, bookRecord.USN, maxUSN, "book user_id mismatch")
|
|
assert.Equal(t, userRecord.MaxUSN, maxUSN, "user max_usn mismatch")
|
|
|
|
var got CreateBookResp
|
|
if err := json.NewDecoder(res.Body).Decode(&got); err != nil {
|
|
t.Fatal(errors.Wrap(err, "decoding"))
|
|
}
|
|
expected := CreateBookResp{
|
|
Book: presenters.Book{
|
|
UUID: bookRecord.UUID,
|
|
USN: bookRecord.USN,
|
|
CreatedAt: bookRecord.CreatedAt,
|
|
UpdatedAt: bookRecord.UpdatedAt,
|
|
Label: "js",
|
|
},
|
|
}
|
|
|
|
assert.DeepEqual(t, got, expected, "payload mismatch")
|
|
})
|
|
|
|
t.Run("duplicate", func(t *testing.T) {
|
|
defer testutils.ClearData(testutils.DB)
|
|
|
|
// Setup
|
|
server := MustNewServer(t, &app.App{
|
|
Clock: clock.NewMock(),
|
|
Config: config.Config{
|
|
PageTemplateDir: "../views",
|
|
},
|
|
})
|
|
defer server.Close()
|
|
|
|
user := testutils.SetupUserData()
|
|
testutils.SetupAccountData(user, "alice@test.com", "pass1234")
|
|
testutils.MustExec(t, testutils.DB.Model(&user).Update("max_usn", 101), "preparing user max_usn")
|
|
|
|
b1 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "js",
|
|
USN: 58,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b1), "preparing book data")
|
|
|
|
// Execute
|
|
req := testutils.MakeReq(server.URL, "POST", "/api/v3/books", `{"name": "js"}`)
|
|
res := testutils.HTTPAuthDo(t, req, user)
|
|
|
|
// Test
|
|
assert.StatusCodeEquals(t, res, http.StatusConflict, "")
|
|
|
|
var bookRecord database.Book
|
|
var bookCount, noteCount int
|
|
var userRecord database.User
|
|
testutils.MustExec(t, testutils.DB.Model(&database.Book{}).Count(&bookCount), "counting books")
|
|
testutils.MustExec(t, testutils.DB.Model(&database.Note{}).Count(¬eCount), "counting notes")
|
|
testutils.MustExec(t, testutils.DB.First(&bookRecord), "finding book")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", user.ID).First(&userRecord), "finding user record")
|
|
|
|
assert.Equalf(t, bookCount, 1, "book count mismatch")
|
|
assert.Equalf(t, noteCount, 0, "note count mismatch")
|
|
|
|
assert.Equal(t, bookRecord.Label, "js", "book name mismatch")
|
|
assert.Equal(t, bookRecord.UserID, user.ID, "book user_id mismatch")
|
|
assert.Equal(t, bookRecord.USN, b1.USN, "book usn mismatch")
|
|
assert.Equal(t, userRecord.MaxUSN, 101, "user max_usn mismatch")
|
|
})
|
|
}
|
|
|
|
func TestUpdateBook(t *testing.T) {
|
|
updatedLabel := "updated-label"
|
|
|
|
b1UUID := "ead8790f-aff9-4bdf-8eec-f734ccd29202"
|
|
b2UUID := "0ecaac96-8d72-4e04-8925-5a21b79a16da"
|
|
|
|
type payloadData struct {
|
|
Name *string `schema:"name" json:"name,omitempty"`
|
|
}
|
|
|
|
testCases := []struct {
|
|
payload testutils.PayloadWrapper
|
|
bookUUID string
|
|
bookDeleted bool
|
|
bookLabel string
|
|
expectedBookLabel string
|
|
}{
|
|
{
|
|
payload: testutils.PayloadWrapper{
|
|
Data: payloadData{
|
|
Name: &updatedLabel,
|
|
},
|
|
},
|
|
bookUUID: b1UUID,
|
|
bookDeleted: false,
|
|
bookLabel: "original-label",
|
|
expectedBookLabel: updatedLabel,
|
|
},
|
|
// if a deleted book is updated, it should be un-deleted
|
|
{
|
|
payload: testutils.PayloadWrapper{
|
|
Data: payloadData{
|
|
Name: &updatedLabel,
|
|
},
|
|
},
|
|
bookUUID: b1UUID,
|
|
bookDeleted: true,
|
|
bookLabel: "",
|
|
expectedBookLabel: updatedLabel,
|
|
},
|
|
}
|
|
|
|
for idx, tc := range testCases {
|
|
t.Run(fmt.Sprintf("test case %d", idx), func(t *testing.T) {
|
|
defer testutils.ClearData(testutils.DB)
|
|
|
|
// Setup
|
|
server := MustNewServer(t, &app.App{
|
|
Clock: clock.NewMock(),
|
|
Config: config.Config{
|
|
PageTemplateDir: "../views",
|
|
},
|
|
})
|
|
defer server.Close()
|
|
|
|
user := testutils.SetupUserData()
|
|
testutils.SetupAccountData(user, "alice@test.com", "pass1234")
|
|
testutils.MustExec(t, testutils.DB.Model(&user).Update("max_usn", 101), "preparing user max_usn")
|
|
|
|
b1 := database.Book{
|
|
UUID: tc.bookUUID,
|
|
UserID: user.ID,
|
|
Label: tc.bookLabel,
|
|
Deleted: tc.bookDeleted,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b1), "preparing b1")
|
|
b2 := database.Book{
|
|
UUID: b2UUID,
|
|
UserID: user.ID,
|
|
Label: "js",
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b2), "preparing b2")
|
|
|
|
// Execute
|
|
endpoint := fmt.Sprintf("/api/v3/books/%s", tc.bookUUID)
|
|
req := testutils.MakeReq(server.URL, "PATCH", endpoint, tc.payload.ToJSON(t))
|
|
res := testutils.HTTPAuthDo(t, req, user)
|
|
|
|
// Test
|
|
assert.StatusCodeEquals(t, res, http.StatusOK, fmt.Sprintf("status code mismatch for test case %d", idx))
|
|
|
|
var bookRecord database.Book
|
|
var userRecord database.User
|
|
var noteCount, bookCount int
|
|
testutils.MustExec(t, testutils.DB.Model(&database.Book{}).Count(&bookCount), "counting books")
|
|
testutils.MustExec(t, testutils.DB.Model(&database.Note{}).Count(¬eCount), "counting notes")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b1.ID).First(&bookRecord), "finding book")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", user.ID).First(&userRecord), "finding user record")
|
|
|
|
assert.Equalf(t, bookCount, 2, "book count mismatch")
|
|
assert.Equalf(t, noteCount, 0, "note count mismatch")
|
|
|
|
assert.Equalf(t, bookRecord.UUID, tc.bookUUID, "book uuid mismatch")
|
|
assert.Equalf(t, bookRecord.Label, tc.expectedBookLabel, "book label mismatch")
|
|
assert.Equalf(t, bookRecord.USN, 102, "book usn mismatch")
|
|
assert.Equalf(t, bookRecord.Deleted, false, "book Deleted mismatch")
|
|
|
|
assert.Equal(t, userRecord.MaxUSN, 102, fmt.Sprintf("user max_usn mismatch for test case %d", idx))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteBook(t *testing.T) {
|
|
testCases := []struct {
|
|
label string
|
|
deleted bool
|
|
expectedB2USN int
|
|
expectedMaxUSN int
|
|
expectedN2USN int
|
|
expectedN3USN int
|
|
}{
|
|
{
|
|
label: "n1 content",
|
|
deleted: false,
|
|
expectedMaxUSN: 61,
|
|
expectedB2USN: 61,
|
|
expectedN2USN: 59,
|
|
expectedN3USN: 60,
|
|
},
|
|
{
|
|
label: "",
|
|
deleted: true,
|
|
expectedMaxUSN: 59,
|
|
expectedB2USN: 59,
|
|
expectedN2USN: 5,
|
|
expectedN3USN: 6,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(fmt.Sprintf("originally deleted %t", tc.deleted), func(t *testing.T) {
|
|
defer testutils.ClearData(testutils.DB)
|
|
|
|
// Setup
|
|
server := MustNewServer(t, &app.App{
|
|
Clock: clock.NewMock(),
|
|
Config: config.Config{
|
|
PageTemplateDir: "../views",
|
|
},
|
|
})
|
|
defer server.Close()
|
|
|
|
user := testutils.SetupUserData()
|
|
testutils.SetupAccountData(user, "alice@test.com", "pass1234")
|
|
testutils.MustExec(t, testutils.DB.Model(&user).Update("max_usn", 58), "preparing user max_usn")
|
|
anotherUser := testutils.SetupUserData()
|
|
testutils.SetupAccountData(anotherUser, "bob@test.com", "pass1234")
|
|
testutils.MustExec(t, testutils.DB.Model(&anotherUser).Update("max_usn", 109), "preparing another user max_usn")
|
|
|
|
b1 := database.Book{
|
|
UserID: user.ID,
|
|
Label: "js",
|
|
USN: 1,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b1), "preparing a book data")
|
|
b2 := database.Book{
|
|
UserID: user.ID,
|
|
Label: tc.label,
|
|
USN: 2,
|
|
Deleted: tc.deleted,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b2), "preparing a book data")
|
|
b3 := database.Book{
|
|
UserID: anotherUser.ID,
|
|
Label: "linux",
|
|
USN: 3,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&b3), "preparing a book data")
|
|
|
|
var n2Body string
|
|
if !tc.deleted {
|
|
n2Body = "n2 content"
|
|
}
|
|
var n3Body string
|
|
if !tc.deleted {
|
|
n3Body = "n3 content"
|
|
}
|
|
|
|
n1 := database.Note{
|
|
UserID: user.ID,
|
|
BookUUID: b1.UUID,
|
|
Body: "n1 content",
|
|
USN: 4,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&n1), "preparing a note data")
|
|
n2 := database.Note{
|
|
UserID: user.ID,
|
|
BookUUID: b2.UUID,
|
|
Body: n2Body,
|
|
USN: 5,
|
|
Deleted: tc.deleted,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&n2), "preparing a note data")
|
|
n3 := database.Note{
|
|
UserID: user.ID,
|
|
BookUUID: b2.UUID,
|
|
Body: n3Body,
|
|
USN: 6,
|
|
Deleted: tc.deleted,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&n3), "preparing a note data")
|
|
n4 := database.Note{
|
|
UserID: user.ID,
|
|
BookUUID: b2.UUID,
|
|
Body: "",
|
|
USN: 7,
|
|
Deleted: true,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&n4), "preparing a note data")
|
|
n5 := database.Note{
|
|
UserID: anotherUser.ID,
|
|
BookUUID: b3.UUID,
|
|
Body: "n5 content",
|
|
USN: 8,
|
|
}
|
|
testutils.MustExec(t, testutils.DB.Save(&n5), "preparing a note data")
|
|
|
|
// Execute
|
|
endpoint := fmt.Sprintf("/api/v3/books/%s", b2.UUID)
|
|
|
|
req := testutils.MakeReq(server.URL, "DELETE", endpoint, "")
|
|
res := testutils.HTTPAuthDo(t, req, user)
|
|
|
|
// Test
|
|
assert.StatusCodeEquals(t, res, http.StatusOK, "")
|
|
|
|
var b1Record, b2Record, b3Record database.Book
|
|
var n1Record, n2Record, n3Record, n4Record, n5Record database.Note
|
|
var userRecord database.User
|
|
var bookCount, noteCount int
|
|
|
|
testutils.MustExec(t, testutils.DB.Model(&database.Book{}).Count(&bookCount), "counting books")
|
|
testutils.MustExec(t, testutils.DB.Model(&database.Note{}).Count(¬eCount), "counting notes")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b1.ID).First(&b1Record), "finding b1")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b2.ID).First(&b2Record), "finding b2")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", b3.ID).First(&b3Record), "finding b3")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", n1.ID).First(&n1Record), "finding n1")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", n2.ID).First(&n2Record), "finding n2")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", n3.ID).First(&n3Record), "finding n3")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", n4.ID).First(&n4Record), "finding n4")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", n5.ID).First(&n5Record), "finding n5")
|
|
testutils.MustExec(t, testutils.DB.Where("id = ?", user.ID).First(&userRecord), "finding user record")
|
|
|
|
assert.Equal(t, bookCount, 3, "book count mismatch")
|
|
assert.Equal(t, noteCount, 5, "note count mismatch")
|
|
|
|
assert.Equal(t, userRecord.MaxUSN, tc.expectedMaxUSN, "user max_usn mismatch")
|
|
|
|
assert.Equal(t, b1Record.Deleted, false, "b1 deleted mismatch")
|
|
assert.Equal(t, b1Record.Label, b1.Label, "b1 content mismatch")
|
|
assert.Equal(t, b1Record.USN, b1.USN, "b1 usn mismatch")
|
|
assert.Equal(t, b2Record.Deleted, true, "b2 deleted mismatch")
|
|
assert.Equal(t, b2Record.Label, "", "b2 content mismatch")
|
|
assert.Equal(t, b2Record.USN, tc.expectedB2USN, "b2 usn mismatch")
|
|
assert.Equal(t, b3Record.Deleted, false, "b3 deleted mismatch")
|
|
assert.Equal(t, b3Record.Label, b3.Label, "b3 content mismatch")
|
|
assert.Equal(t, b3Record.USN, b3.USN, "b3 usn mismatch")
|
|
|
|
assert.Equal(t, n1Record.USN, n1.USN, "n1 usn mismatch")
|
|
assert.Equal(t, n1Record.Deleted, false, "n1 deleted mismatch")
|
|
assert.Equal(t, n1Record.Body, n1.Body, "n1 content mismatch")
|
|
|
|
assert.Equal(t, n2Record.USN, tc.expectedN2USN, "n2 usn mismatch")
|
|
assert.Equal(t, n2Record.Deleted, true, "n2 deleted mismatch")
|
|
assert.Equal(t, n2Record.Body, "", "n2 content mismatch")
|
|
|
|
assert.Equal(t, n3Record.USN, tc.expectedN3USN, "n3 usn mismatch")
|
|
assert.Equal(t, n3Record.Deleted, true, "n3 deleted mismatch")
|
|
assert.Equal(t, n3Record.Body, "", "n3 content mismatch")
|
|
|
|
// if already deleted, usn should remain the same and hence should not contribute to bumping the max_usn
|
|
assert.Equal(t, n4Record.USN, n4.USN, "n4 usn mismatch")
|
|
assert.Equal(t, n4Record.Deleted, true, "n4 deleted mismatch")
|
|
assert.Equal(t, n4Record.Body, "", "n4 content mismatch")
|
|
|
|
assert.Equal(t, n5Record.USN, n5.USN, "n5 usn mismatch")
|
|
assert.Equal(t, n5Record.Deleted, false, "n5 deleted mismatch")
|
|
assert.Equal(t, n5Record.Body, n5.Body, "n5 content mismatch")
|
|
})
|
|
}
|
|
}
|