{-# OPTIONS -Wno-ambiguous-fields #-}
module Test.Notifications where
import API.Brig
import API.Common
import API.Gundeck
import API.GundeckInternal
import Data.Time (UTCTime)
import Data.Time.Format.ISO8601 (iso8601ParseM)
import Notifications
import SetupHelpers
import Testlib.Prelude
examplePush :: (MakesValue u) => u -> App Value
examplePush :: forall u. MakesValue u => u -> App Value
examplePush u
u = do
r <- u -> App Value
forall u. MakesValue u => u -> App Value
recipient u
u
pure
$ object
[ "recipients" .= [r],
"payload" .= [object ["hello" .= "world"]]
]
testFetchAllNotifications :: App ()
testFetchAllNotifications :: App ()
testFetchAllNotifications = do
user <- Domain -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App Value
randomUserId Domain
OwnDomain
push <- examplePush user
let n = Int
10
replicateM_ n
$ bindResponse (postPush user [push])
$ \Response
res ->
Response
res.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
let c :: Maybe String = Just "deadbeef"
ns <- getNotifications user (def {client = c} :: GetNotifications) >>= getJSON 200
expected <- replicateM n (push %. "payload")
allNotifs <- ns %. "notifications" & asList
actual <- traverse (%. "payload") allNotifs
actual `shouldMatch` expected
firstNotif <-
getNotification
user
(def {client = c} :: GetNotification)
(head allNotifs %. "id")
>>= getJSON 200
firstNotif `shouldMatch` head allNotifs
lastNotif <-
getLastNotification
user
(def {client = c} :: GetNotification)
>>= getJSON 200
lastNotif `shouldMatch` last allNotifs
testLastNotification :: App ()
testLastNotification :: App ()
testLastNotification = do
user <- Domain -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App Value
randomUserId Domain
OwnDomain
userId <- user %. "id" & asString
let push String
c =
[Pair] -> Value
object
[ String
"recipients"
String -> [Value] -> Pair
forall a. ToJSON a => String -> a -> Pair
.= [ [Pair] -> Value
object
[ String
"user_id" String -> String -> Pair
forall a. ToJSON a => String -> a -> Pair
.= String
userId,
String
"route" String -> String -> Pair
forall a. ToJSON a => String -> a -> Pair
.= String
"any",
String
"clients" String -> [String] -> Pair
forall a. ToJSON a => String -> a -> Pair
.= [String
c]
]
],
String
"payload" String -> [Value] -> Pair
forall a. ToJSON a => String -> a -> Pair
.= [[Pair] -> Value
object [String
"client" String -> String -> Pair
forall a. ToJSON a => String -> a -> Pair
.= String
c]]
]
for_ ["a", "b", "c", "d", "e", "f"] $ \String
c ->
App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> [Value] -> App Response
forall user a.
(HasCallStack, MakesValue user, MakesValue a) =>
user -> [a] -> App Response
postPush Value
user [String -> Value
push String
c]) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
res ->
Response
res.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
lastNotif <- getLastNotification user def {client = Just "c"} >>= getJSON 200
lastNotif %. "payload" `shouldMatch` [object ["client" .= "c"]]
testInvalidNotification :: (HasCallStack) => App ()
testInvalidNotification :: HasCallStack => App ()
testInvalidNotification = do
user <- Domain -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App Value
randomUserId Domain
OwnDomain
do
notifId <- randomId
void
$ getNotifications user def {since = Just notifId}
>>= getJSON 400
do
notifId <- randomUUIDv1
void
$ getNotifications user def {since = Just notifId}
>>= getJSON 404
testAddClientNotification :: (HasCallStack) => App ()
testAddClientNotification :: HasCallStack => App ()
testAddClientNotification = do
alice <- Domain -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser Domain
OwnDomain CreateUser
forall a. Default a => a
def
e <- withWebSocket alice $ \WebSocket
ws -> do
App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ Value -> AddClient -> App Response
forall user.
(HasCallStack, MakesValue user) =>
user -> AddClient -> App Response
addClient Value
alice AddClient
forall a. Default a => a
def
n <- HasCallStack => (Value -> App Bool) -> WebSocket -> App Value
(Value -> App Bool) -> WebSocket -> App Value
awaitMatch Value -> App Bool
forall a. (HasCallStack, MakesValue a) => a -> App Bool
isUserClientAddNotif WebSocket
ws
nPayload n
void $ e %. "client.capabilities.capabilities" & asList
testGetServerTime :: (HasCallStack) => App ()
testGetServerTime :: HasCallStack => App ()
testGetServerTime = do
user <- Domain -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser Domain
OwnDomain CreateUser
forall a. Default a => a
def
formattedTimestampStr <-
getServerTime user `bindResponse` \Response
r -> do
Response
r.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
Response
r.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"time" App Value -> (App Value -> App String) -> App String
forall a b. a -> (a -> b) -> b
& App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString
void $ assertJust ("expected ISO 8601 format, but got: " <> formattedTimestampStr) $ iso8601ParseM @Maybe @UTCTime formattedTimestampStr