espial-0.0.41: test/Model/NotesUpsertSpec.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Model.NotesUpsertSpec (spec) where
import Model.Custom (NtSlug, hashPasswordBCryptWithPolicy, mkNtSlug)
import TestImport
import Types (DB)
t0 :: UTCTime
t0 = UTCTime (fromGregorian 2024 1 1) 0
t1 :: UTCTime
t1 = UTCTime (fromGregorian 2024 1 2) 0
createTestUser :: DB (Key User)
createTestUser = do
pwHash <- liftIO $ hashPasswordBCryptWithPolicy bcryptTestPolicy "pass"
insert $ User "testuser" pwHash Nothing False False True True False False True Nothing
createNoteAt :: Key User -> Text -> UTCTime -> DB (Key Note)
createNoteAt uid title updated = do
slug <- liftIO mkNtSlug
insert $ Note uid slug (length title) title "text" False False t0 updated
getNote' :: Key Note -> DB (Maybe Note)
getNote' nid = fmap entityVal <$> selectFirst [NoteId ==. nid] []
mkNoteEdit :: Key User -> NtSlug -> Text -> UTCTime -> Note
mkNoteEdit uid slug title clientKnownUpdated =
Note
{ noteUserId = uid,
noteSlug = slug,
noteLength = length title,
noteTitle = title,
noteText = "edited text",
noteIsMarkdown = False,
noteShared = False,
noteCreated = t0,
noteUpdated = clientKnownUpdated
}
spec :: Spec
spec = withApp $ do
describe "upsertNote" $ do
it "sets updated to now on a successful edit" $ do
beforeTime <- liftIO getCurrentTime
(uid, nid) <- runDB $ do
uid <- createTestUser
nid <- createNoteAt uid "a" t0
return (uid, nid)
slug <- liftIO mkNtSlug
let edit = mkNoteEdit uid slug "edited" t0
result <- runDB $ upsertNote uid (Just nid) edit
afterTime <- liftIO getCurrentTime
case result of
Updated (Entity resultNid _) -> liftIO $ resultNid `shouldBe` nid
other -> liftIO $ expectationFailure ("expected Updated, got " <> show other)
mnote <- runDB $ getNote' nid
case mnote of
Nothing -> liftIO $ expectationFailure "note missing after update"
Just note -> liftIO $ do
noteUpdated note >= beforeTime `shouldBe` True
noteUpdated note <= afterTime `shouldBe` True
it "fails when the stored copy was updated more recently than the client's copy" $ do
(uid, nid) <- runDB $ do
uid <- createTestUser
nid <- createNoteAt uid "a" t1
return (uid, nid)
slug <- liftIO mkNtSlug
let edit = mkNoteEdit uid slug "edited" t0
result <- runDB $ upsertNote uid (Just nid) edit
liftIO $ result `shouldBe` Failed ReasonConflictWithNewer
mnote <- runDB $ getNote' nid
liftIO $ fmap noteTitle mnote `shouldBe` Just "a"
it "creates a new note when no id is given" $ do
uid <- runDB createTestUser
slug <- liftIO mkNtSlug
let note = mkNoteEdit uid slug "new" t0
result <- runDB $ upsertNote uid Nothing note
liftIO $ case result of
Created _ -> pure ()
other -> expectationFailure ("expected Created, got " <> show other)