{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
module TypesTest where
import Data.Aeson
import qualified Data.Aeson.Types as Aeson
import qualified Data.HashMap.Strict as M
import Data.Maybe
import Data.Time.Clock.POSIX
import Fixtures
import Instances()
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.TH
import Web.Twitter.Types
case_parseStatus :: Assertion
case_parseStatus = withFixtureJSON "status01.json" $ \obj -> do
statusCreatedAt obj @?= "Sat Sep 10 22:23:38 +0000 2011"
statusId obj @?= 112652479837110273
statusText obj @?= "@twitter meets @seepicturely at #tcdisrupt cc.@boscomonkey @episod http://t.co/6J2EgYM"
statusSource obj @?= "<a href=\"http://instagr.am\" rel=\"nofollow\">Instagram</a>"
statusTruncated obj @?= False
statusEntities obj @?= Nothing
statusExtendedEntities obj @?= Nothing
statusInReplyToStatusId obj @?= Nothing
statusInReplyToUserId obj @?= Just 783214
statusFavorited obj @?= Just False
statusQuotedStatus obj @?= Nothing
statusQuotedStatusId obj @?= Nothing
statusRetweetCount obj @?= 0
(userScreenName . statusUser) obj @?= "imeoin"
statusRetweetedStatus obj @?= Nothing
statusPlace obj @?= Nothing
statusFavoriteCount obj @?= 0
statusLang obj @?= Nothing
statusPossiblySensitive obj @?= Just False
statusCoordinates obj @?= Nothing
case_parseStatusQuoted :: Assertion
case_parseStatusQuoted = withFixtureJSON "status_quoted.json" $ \obj -> do
statusId obj @?= 641660763770372100
statusText obj @?= "Wow! Congrats! https://t.co/EPMMldEcci"
statusQuotedStatusId obj @?= Just 641653574284537900
let qs = fromJust $ statusQuotedStatus obj
statusCreatedAt qs @?= "Wed Sep 09 16:45:08 +0000 2015"
statusId qs @?= 641653574284537900
statusText qs @?= "Very happy to say that I'm joining @mesosphere as a Distributed Systems Engineer!"
statusSource qs @?= "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>"
let ent = fromJust $ statusEntities qs
enURLs ent @?= []
enMedia ent @?= []
enHashTags ent @?= []
map (userEntityUserId . entityBody) (enUserMentions ent) @?= [1872399366]
map (userEntityUserScreenName . entityBody) (enUserMentions ent) @?= ["mesosphere"]
statusExtendedEntities qs @?= Nothing
statusInReplyToStatusId qs @?= Nothing
statusInReplyToUserId qs @?= Nothing
statusFavorited qs @?= Just False
statusQuotedStatus qs @?= Nothing
statusQuotedStatusId qs @?= Nothing
statusRetweetCount qs @?= 7
(userScreenName . statusUser) qs @?= "neil_conway"
statusRetweeted qs @?= Just False
statusRetweetedStatus qs @?= Nothing
statusPlace qs @?= Nothing
statusFavoriteCount qs @?= 63
statusLang qs @?= Just "en"
statusPossiblySensitive qs @?= Nothing
statusCoordinates qs @?= Nothing
case_parseStatusWithPhoto :: Assertion
case_parseStatusWithPhoto = withFixtureJSON "status_thimura_with_photo.json" $ \obj -> do
statusId obj @?= 491143410770657280
statusText obj @?= "近所の海です http://t.co/FjSOU8dDoD"
statusTruncated obj @?= False
let ent = fromJust $ statusEntities obj
enHashTags ent @?= []
enUserMentions ent @?= []
enURLs ent @?= []
length (enMedia ent) @?= 1
map (meMediaURLHttps . entityBody) (enMedia ent) @?= ["https://pbs.twimg.com/media/BtDkUVaCQAIpWBU.jpg"]
let exents = fromJust $ statusExtendedEntities obj
let media = exeMedia exents
length media @?= 1
let exent = entityBody $ head media
exeID exent @?= 491143397378244610
ueURL (exeURL exent) @?= "http://t.co/FjSOU8dDoD"
statusInReplyToStatusId obj @?= Nothing
statusInReplyToUserId obj @?= Nothing
statusFavorited obj @?= Just False
statusRetweetCount obj @?= 4
(userScreenName . statusUser) obj @?= "thimura"
statusRetweetedStatus obj @?= Nothing
statusPlace obj @?= Nothing
statusFavoriteCount obj @?= 9
statusLang obj @?= Just "ja"
statusPossiblySensitive obj @?= Just False
statusCoordinates obj @?= Nothing
case_parseStatusIncludeEntities :: Assertion
case_parseStatusIncludeEntities = withFixtureJSON "status_with_entity.json" $ \obj -> do
statusId obj @?= 112652479837110273
statusRetweetCount obj @?= 0
(userScreenName . statusUser) obj @?= "imeoin"
let ent = fromMaybe (Entities [] [] [] []) $ statusEntities obj
(map entityIndices . enHashTags) ent @?= [[32,42]]
(hashTagText . entityBody . head . enHashTags) ent @?= "tcdisrupt"
case_parseSearchStatusMetadata :: Assertion
case_parseSearchStatusMetadata = withFixtureJSON "search_haskell.json" $ \obj -> do
let status = (searchResultStatuses obj) :: [Status]
length status @?= 1
let metadata = searchResultSearchMetadata obj
searchMetadataMaxId metadata @?= 495597397733433345
searchMetadataSinceId metadata @?= 0
searchMetadataRefreshURL metadata @?= "?since_id=495597397733433345&q=haskell&include_entities=1"
searchMetadataNextResults metadata @?= Just "?max_id=495594369802440705&q=haskell&include_entities=1"
searchMetadataCount metadata @?= 1
searchMetadataCompletedIn metadata @?= Just 0.043
searchMetadataSinceIdStr metadata @?= "0"
searchMetadataQuery metadata @?= "haskell"
searchMetadataMaxIdStr metadata @?= "495597397733433345"
case_parseSearchStatusBodyStatus :: Assertion
case_parseSearchStatusBodyStatus = withFixtureJSON "search_haskell.json" $ \obj -> do
let status = (searchResultStatuses obj) :: [Status]
length status @?= 1
statusText (head status) @?= "haskell"
case_parseSearchStatusBodySearchStatus :: Assertion
case_parseSearchStatusBodySearchStatus = withFixtureJSON "search_haskell.json" $ \obj -> do
let status = (searchResultStatuses obj) :: [SearchStatus]
length status @?= 1
searchStatusText (head status) @?= "haskell"
data DMList = DMList
{ dmList :: [DirectMessage]
} deriving (Show, Eq)
instance FromJSON DMList where
parseJSON = withObject "DMList" $ \obj -> DMList <$> obj .: "events"
case_parseDirectMessageList :: Assertion
case_parseDirectMessageList =
withFixtureJSON "direct_message_event_list.json" $ \obj -> do
dmList obj @?=
[ DirectMessage
{ dmId = 123123123123123123
, dmCreatedTimestamp = read "2019-10-13 18:15:48.951 UTC"
, dmTargetRecipientId = 186712193
, dmSenderId = 69179963
, dmText = "hello @thimura"
, dmEntities =
Entities
{ enHashTags = []
, enUserMentions =
[ Entity
{ entityBody =
UserEntity
{ userEntityUserId = 69179963
, userEntityUserName = "ちむら"
, userEntityUserScreenName = "thimura"
}
, entityIndices = [6, 14]
}
]
, enURLs = []
, enMedia = []
}
}
, DirectMessage
{ dmId = 25252525252525
, dmCreatedTimestamp = read "2019-10-13 18:06:46.14 UTC"
, dmTargetRecipientId = 186712193
, dmSenderId = 69179963
, dmText = "hello"
, dmEntities = Entities {enHashTags = [], enUserMentions = [], enURLs = [], enMedia = []}
}
]
case_parseEventFavorite :: Assertion
case_parseEventFavorite = withFixtureJSON "event_favorite_thimura.json" $ \obj -> do
evCreatedAt obj @?= "Sat Aug 02 16:32:01 +0000 2014"
evEvent obj @?= "favorite"
let Just (ETStatus targetObj) = evTargetObject obj
statusId targetObj @?= 495597326736449536
statusText targetObj @?= "haskell"
let ETUser targetUser = evTarget obj
userScreenName targetUser @?= "thimura"
let ETUser sourceUser = evSource obj
userScreenName sourceUser @?= "thimura_shinku"
case_parseEventUnfavorite :: Assertion
case_parseEventUnfavorite = withFixtureJSON "event_unfavorite_thimura.json" $ \obj -> do
evCreatedAt obj @?= "Sat Aug 02 16:32:10 +0000 2014"
evEvent obj @?= "unfavorite"
let Just (ETStatus targetObj) = evTargetObject obj
statusId targetObj @?= 495597326736449536
statusText targetObj @?= "haskell"
let ETUser targetUser = evTarget obj
userScreenName targetUser @?= "thimura"
let ETUser sourceUser = evSource obj
userScreenName sourceUser @?= "thimura_shinku"
case_parseDelete :: Assertion
case_parseDelete = withFixtureJSON "delete.json" $ \obj -> do
delId obj @?= 495607981833064448
delUserId obj @?= 2566877347
case_parseErrorMsg :: Assertion
case_parseErrorMsg = withFixtureJSON "error_not_authorized.json" $ \value ->
case parseStatus value of
Aeson.Error str -> "Not authorized" @=? str
Aeson.Success _ -> assertFailure "errorMsgJson should be parsed as an error."
where
parseStatus :: Value -> Aeson.Result Status
parseStatus = Aeson.parse parseJSON
case_parseMediaEntity :: Assertion
case_parseMediaEntity = withFixtureJSON "media_entity.json" $ \obj -> do
let entities = statusEntities obj
assertBool "entities should not empty" $ isJust entities
let Just ent = entities
media = enMedia ent
length media @?= 1
let me = entityBody $ head media
meType me @?= "photo"
meId me @?= 114080493040967680
let sizes = meSizes me
assertBool "sizes must contains \"thumb\"" $ M.member "thumb" sizes
assertBool "sizes must contains \"large\"" $ M.member "large" sizes
let Just mediaSize = M.lookup "large" sizes
msWidth mediaSize @?= 226
msHeight mediaSize @?= 238
msResize mediaSize @?= "fit"
ueURL (meURL me) @?= "http://t.co/rJC5Pxsu"
meMediaURLHttps me @?= "https://pbs.twimg.com/media/AZVLmp-CIAAbkyy.jpg"
case_parseEmptyEntity :: Assertion
case_parseEmptyEntity = withJSON "{}" $ \entity -> do
length (enHashTags entity) @?= 0
length (enUserMentions entity) @?= 0
length (enURLs entity) @?= 0
length (enMedia entity) @?= 0
case_parseEntityHashTag :: Assertion
case_parseEntityHashTag = withFixtureJSON "entity01.json" $ \entity -> do
length (enHashTags entity) @?= 1
length (enUserMentions entity) @?= 1
length (enURLs entity) @?= 1
length (enMedia entity) @?= 0
let urlEntity = entityBody . head . enURLs $ entity
ueURL urlEntity @?= "http://t.co/IOwBrTZR"
ueExpanded urlEntity @?= "http://www.youtube.com/watch?v=oHg5SJYRHA0"
ueDisplay urlEntity @?= "youtube.com/watch?v=oHg5SJ\x2026"
let mentionsUser = entityBody . head . enUserMentions $ entity
userEntityUserName mentionsUser @?= "Twitter API"
userEntityUserScreenName mentionsUser @?= "twitterapi"
userEntityUserId mentionsUser @?= 6253282
let HashTagEntity hashtag = entityBody . head . enHashTags $ entity
hashtag @?= "lol"
case_parseExtendedEntities :: Assertion
case_parseExtendedEntities = withFixtureJSON "media_extended_entity.json" $ \obj -> do
let entities = statusExtendedEntities obj
assertBool "entities should not empty" $ isJust entities
let Just ent = entities
media = exeMedia ent
length media @?= 4
let me = entityBody $ head media
ueURL (exeURL me) @?= "https://t.co/Qi316FhOwe"
exeMediaUrl me @?= "http://pbs.twimg.com/media/Coju86fUIAEUcRC.jpg"
exeExtAltText me @?= Just "A small tabby kitten"
exeType me @?= "photo"
case_parseUser :: Assertion
case_parseUser = withFixtureJSON "user_thimura.json" $ \obj -> do
userId obj @?= 69179963
userName obj @?= "ちむら"
userScreenName obj @?= "thimura"
userDescription obj @?= Just "真紅かわいい"
userLocation obj @?= Just "State# Irotoridori.No.World"
userProfileImageURL obj @?= Just "http://pbs.twimg.com/profile_images/414044387346116609/VNMfLpY7_normal.png"
userURL obj @?= Just "http://t.co/TFUAsAffX0"
userProtected obj @?= False
userFollowersCount obj @?= 754
userFriendsCount obj @?= 780
userStatusesCount obj @?= 24709
userLang obj @?= Just "en"
userCreatedAt obj @?= "Thu Aug 27 02:48:06 +0000 2009"
userFavoritesCount obj @?= 17313
case_parseUserLangNull :: Assertion
case_parseUserLangNull = withFixtureJSON "user_thimura_lang_null.json" $ \obj -> do
userId obj @?= 69179963
userName obj @?= "ちむら"
userScreenName obj @?= "thimura"
userDescription obj @?= Just "真紅かわいい"
userLocation obj @?= Just "State# Irotoridori.No.World"
userProfileImageURL obj @?= Just "http://pbs.twimg.com/profile_images/414044387346116609/VNMfLpY7_normal.png"
userURL obj @?= Just "http://t.co/TFUAsAffX0"
userProtected obj @?= False
userFollowersCount obj @?= 754
userFriendsCount obj @?= 780
userStatusesCount obj @?= 24709
-- N.B. the only difference between this one and case_parseUser is in lang
userLang obj @?= Nothing
userCreatedAt obj @?= "Thu Aug 27 02:48:06 +0000 2009"
userFavoritesCount obj @?= 17313
case_parseList :: Assertion
case_parseList = withFixtureJSON "list_thimura_haskell.json" $ \obj -> do
listId obj @?= 20849097
listName obj @?= "haskell"
listFullName obj @?= "@thimura/haskell"
listMemberCount obj @?= 50
listSubscriberCount obj @?= 1
listMode obj @?= "public"
(userScreenName . listUser) obj @?= "thimura"
tests :: TestTree
tests = $(testGroupGenerator)