packages feed

twitchapi-0.0.2: test/Helix/Users.hs

{-# LANGUAGE ScopedTypeVariables #-}

module Helix.Users ( main ) where

import qualified Data.Aeson            as JSON
import qualified Data.ByteString.Lazy  as BS
import qualified Data.List             as List
import qualified Data.Text             as T
import qualified Data.Text.Encoding    as T
import qualified Data.Time             as Time
import qualified Data.Time.RFC3339     as Time ( parseTimeRFC3339 )
import qualified Data.Time.Clock.POSIX as Time ( POSIXTime, posixSecondsToUTCTime )

import qualified Web.TwitchAPI.Helix.Users as Users

import Data.Char   ( isDigit, isLetter )
import Text.Printf ( printf )

import Test.QuickCheck
import Test.Hspec

main :: IO ()
main = do
    hspec $ describe "Users Interactions (Twitch Fixtures)" $ do
        it "Parses Twitch's Single-User JSON Fixture" $ property prop_userJSONFixture
        it "Parses Twitch's Multi-User JSON Fixture" $ property prop_usersJSONFixture
        it "Parses Twitch's Follow JSON Fixture" $ property prop_followsJSONFixture
        it "Parses Twitch's Block List JSON Fixture" $ property prop_blocksJSONFixture
        it "Parses Twitch's Extensions List JSON Fixture" $ property prop_extensionsJSONFixture
        it "Parses Twitch's Active Extensions List JSON Fixture" $ property prop_activeExtensionsJSONFixture

prop_userJSONFixture :: Bool
prop_userJSONFixture =
    let broadcasterType = Users.Partner
        description = "Supporting third-party developers building Twitch integrations from chatbots to game integrations."
        displayName = "TwitchDev"
        userId = 141981764
        login = "twitchdev"
        offlineImageURL = "https://static-cdn.jtvnw.net/jtv_user_pictures/3f13ab61-ec78-4fe6-8481-8682cb3b0ac2-channel_offline_image-1920x1080.png"
        profileImageURL = "https://static-cdn.jtvnw.net/jtv_user_pictures/8a6381c7-d0c0-4576-b179-38bd5ce1d6af-profile_image-300x300.png"
        userType = Users.NormalUser
        email = Just "not-real@email.com"
        createdAt = Time.zonedTimeToUTC <$> Time.parseTimeRFC3339 "2016-12-14T20:32:28Z"
        record = Users.UserEntry broadcasterType description displayName userId login offlineImageURL profileImageURL userType email createdAt
        response = Right $ Users.UsersResponse [record]
        parsed = parseJSON singleUserJSON :: Either String Users.UsersResponse
    in response == parsed

prop_usersJSONFixture :: Bool
prop_usersJSONFixture =
    let broadcasterType = Users.Partner
        description = "Supporting third-party developers building Twitch integrations from chatbots to game integrations."
        displayName = "TwitchDev"
        userId = 141981764
        login = "twitchdev"
        offlineImageURL = "https://static-cdn.jtvnw.net/jtv_user_pictures/3f13ab61-ec78-4fe6-8481-8682cb3b0ac2-channel_offline_image-1920x1080.png"
        profileImageURL = "https://static-cdn.jtvnw.net/jtv_user_pictures/8a6381c7-d0c0-4576-b179-38bd5ce1d6af-profile_image-300x300.png"
        userType = Users.NormalUser
        email = Just "not-real@email.com"
        createdAt = Time.zonedTimeToUTC <$> Time.parseTimeRFC3339 "2016-12-14T20:32:28Z"
        record = Users.UserEntry broadcasterType description displayName userId login offlineImageURL profileImageURL userType email createdAt
        response = Right $ Users.UsersResponse [record, record]
        parsed = parseJSON multiUserJSON :: Either String Users.UsersResponse
    in response == parsed

prop_followsJSONFixture :: Bool
prop_followsJSONFixture =
    let a_from_id = 171003792
        a_from_login = "iiisutha067iii"
        a_from_name = "IIIsutha067III"
        a_to_id = 23161357
        a_to_name = "LIRIK"
        a_followed = Time.zonedTimeToUTC <$> Time.parseTimeRFC3339 "2017-08-22T22:55:24Z"

        b_from_id = 113627897
        b_from_login = "birdman616"
        b_from_name = "Birdman616"
        b_to_id = 23161357
        b_to_name = "LIRIK"
        b_followed = Time.zonedTimeToUTC <$> Time.parseTimeRFC3339 "2017-08-22T22:55:04Z"

        a = Users.FollowEntry a_from_id a_from_login a_from_name a_to_id a_to_name a_followed
        b = Users.FollowEntry b_from_id b_from_login b_from_name b_to_id b_to_name b_followed
        total = 12345
        cursor = "eyJiIjpudWxsLCJhIjoiMTUwMzQ0MTc3NjQyNDQyMjAwMCJ9"
        response = Right $ Users.FollowsResponse total [a, b] cursor
        parsed = parseJSON followsJSON :: Either String Users.FollowsResponse
    in response == parsed

prop_blocksJSONFixture :: Bool
prop_blocksJSONFixture =
    let a_user_id = 135093069
        a_user_login = "bluelava"
        a_display_name = "BlueLava"

        b_user_id = 27419011
        b_user_login = "travistyoj"
        b_display_name = "TravistyOJ"

        a = Users.BlockListEntry a_user_id a_user_login a_display_name
        b = Users.BlockListEntry b_user_id b_user_login b_display_name
        response = Right $ Users.BlockListResponse [a, b]
        parsed = parseJSON blocksJSON :: Either String Users.BlockListResponse
    in response == parsed

prop_extensionsJSONFixture :: Bool
prop_extensionsJSONFixture =
    let a_i = "wi08ebtatdc7oj83wtl9uxwz807l8b"
        a_v = "1.1.8"
        a_n = "Streamlabs Leaderboard"
        a_c = True
        a_t = [Users.Panel]

        b_i = "d4uvtfdr04uq6raoenvj7m86gdk16v"
        b_v = "2.0.2"
        b_n = "Prime Subscription and Loot Reminder"
        b_c = True
        b_t = [Users.Overlay]


        c_i = "rh6jq1q334hqc2rr1qlzqbvwlfl3x0"
        c_v = "1.1.0"
        c_n = "TopClip"
        c_c = True
        c_t = [Users.Mobile, Users.Panel]

        d_i = "zfh2irvx2jb4s60f02jq0ajm8vwgka"
        d_v = "1.0.19"
        d_n = "Streamlabs"
        d_c = True
        d_t = [Users.Mobile, Users.Overlay]

        e_i = "lqnf3zxk0rv0g7gq92mtmnirjz2cjj"
        e_v = "0.0.1"
        e_n = "Dev Experience Test"
        e_c = True
        e_t = [Users.Component, Users.Mobile, Users.Panel, Users.Overlay]

        a = Users.ExtensionsEntry a_c a_i a_n a_t a_v
        b = Users.ExtensionsEntry b_c b_i b_n b_t b_v
        c = Users.ExtensionsEntry c_c c_i c_n c_t c_v
        d = Users.ExtensionsEntry d_c d_i d_n d_t d_v
        e = Users.ExtensionsEntry e_c e_i e_n e_t e_v
        response = Right $ Users.ExtensionsResponse [a, b, c, d, e]
        parsed = parseJSON extensionsJSON :: Either String Users.ExtensionsResponse
    in response == parsed

prop_activeExtensionsJSONFixture :: Bool
prop_activeExtensionsJSONFixture =
    let p_1_i = "rh6jq1q334hqc2rr1qlzqbvwlfl3x0"
        p_1_v = "1.1.0"
        p_1_n = "TopClip"

        p_2_i = "wi08ebtatdc7oj83wtl9uxwz807l8b"
        p_2_v = "1.1.8"
        p_2_n = "Streamlabs Leaderboard"

        p_3_i = "naty2zwfp7vecaivuve8ef1hohh6bo"
        p_3_v = "1.0.9"
        p_3_n = "Streamlabs Stream Schedule & Countdown"

        o_i = "zfh2irvx2jb4s60f02jq0ajm8vwgka"
        o_v = "1.0.19"
        o_n = "Streamlabs"

        c_i = "lqnf3zxk0rv0g7gq92mtmnirjz2cjj"
        c_v = "0.0.1"
        c_n = "Dev Experience Test"
        c_x = 0
        c_y = 0

        p = [ Users.ActiveExtensionEntry True p_1_i p_1_v p_1_n
            , Users.ActiveExtensionEntry True p_2_i p_2_v p_2_n
            , Users.ActiveExtensionEntry True p_3_i p_3_v p_3_n
            ]
        o = [ Users.ActiveExtensionEntry True o_i o_v o_n ]
        c = [ Users.ActiveComponentExtensionEntry True c_i c_v c_n c_x c_y ]
        response = Right $ Users.ActiveExtensionsResponse c o p
        parsed = parseJSON activeExtensionsJSON :: Either String Users.ActiveExtensionsResponse
    in response == parsed

parseJSON :: JSON.FromJSON a => String -> Either String a
parseJSON x = JSON.eitherDecode $ (BS.fromStrict . T.encodeUtf8 . T.pack) x

-- Server Responses

singleUserJSON :: String
singleUserJSON = "{\"data\": [{\"id\": \"141981764\",\"login\": \"twitchdev\",\"display_name\": \"TwitchDev\",\"type\": \"\",\"broadcaster_type\": \"partner\",\"description\": \"Supporting third-party developers building Twitch integrations from chatbots to game integrations.\",\"profile_image_url\": \"https://static-cdn.jtvnw.net/jtv_user_pictures/8a6381c7-d0c0-4576-b179-38bd5ce1d6af-profile_image-300x300.png\",\"offline_image_url\": \"https://static-cdn.jtvnw.net/jtv_user_pictures/3f13ab61-ec78-4fe6-8481-8682cb3b0ac2-channel_offline_image-1920x1080.png\",\"view_count\": 5980557,\"email\": \"not-real@email.com\",\"created_at\": \"2016-12-14T20:32:28Z\"}]}"

multiUserJSON :: String
multiUserJSON = "{\"data\": [{\"id\": \"141981764\",\"login\": \"twitchdev\",\"display_name\": \"TwitchDev\",\"type\": \"\",\"broadcaster_type\": \"partner\",\"description\": \"Supporting third-party developers building Twitch integrations from chatbots to game integrations.\",\"profile_image_url\": \"https://static-cdn.jtvnw.net/jtv_user_pictures/8a6381c7-d0c0-4576-b179-38bd5ce1d6af-profile_image-300x300.png\",\"offline_image_url\": \"https://static-cdn.jtvnw.net/jtv_user_pictures/3f13ab61-ec78-4fe6-8481-8682cb3b0ac2-channel_offline_image-1920x1080.png\",\"view_count\": 5980557,\"email\": \"not-real@email.com\",\"created_at\": \"2016-12-14T20:32:28Z\"}, {\"id\": \"141981764\",\"login\": \"twitchdev\",\"display_name\": \"TwitchDev\",\"type\": \"\",\"broadcaster_type\": \"partner\",\"description\": \"Supporting third-party developers building Twitch integrations from chatbots to game integrations.\",\"profile_image_url\": \"https://static-cdn.jtvnw.net/jtv_user_pictures/8a6381c7-d0c0-4576-b179-38bd5ce1d6af-profile_image-300x300.png\",\"offline_image_url\": \"https://static-cdn.jtvnw.net/jtv_user_pictures/3f13ab61-ec78-4fe6-8481-8682cb3b0ac2-channel_offline_image-1920x1080.png\",\"view_count\": 5980557,\"email\": \"not-real@email.com\",\"created_at\": \"2016-12-14T20:32:28Z\"}]}"

followsJSON :: String
followsJSON = "{\"total\": 12345,\"data\":[{\"from_id\": \"171003792\",\"from_login\": \"iiisutha067iii\",\"from_name\": \"IIIsutha067III\",\"to_id\": \"23161357\",\"to_name\": \"LIRIK\",\"followed_at\": \"2017-08-22T22:55:24Z\"},{\"from_id\": \"113627897\",\"from_login\": \"birdman616\",\"from_name\": \"Birdman616\",\"to_id\": \"23161357\",\"to_name\": \"LIRIK\",\"followed_at\": \"2017-08-22T22:55:04Z\"}],\"pagination\":{\"cursor\": \"eyJiIjpudWxsLCJhIjoiMTUwMzQ0MTc3NjQyNDQyMjAwMCJ9\"}}"

blocksJSON :: String
blocksJSON = "{\"data\": [{\"user_id\": \"135093069\",\"user_login\": \"bluelava\",\"display_name\": \"BlueLava\"},{\"user_id\": \"27419011\",\"user_login\": \"travistyoj\",\"display_name\": \"TravistyOJ\"}]}"

extensionsJSON :: String
extensionsJSON = "{\"data\": [{\"id\": \"wi08ebtatdc7oj83wtl9uxwz807l8b\",\"version\": \"1.1.8\",\"name\": \"Streamlabs Leaderboard\",\"can_activate\": true,\"type\": [\"panel\"]},{\"id\": \"d4uvtfdr04uq6raoenvj7m86gdk16v\",\"version\": \"2.0.2\",\"name\": \"Prime Subscription and Loot Reminder\",\"can_activate\": true,\"type\": [\"overlay\"]},{\"id\": \"rh6jq1q334hqc2rr1qlzqbvwlfl3x0\",\"version\": \"1.1.0\",\"name\": \"TopClip\",\"can_activate\": true,\"type\": [\"mobile\",\"panel\"]},{\"id\": \"zfh2irvx2jb4s60f02jq0ajm8vwgka\",\"version\": \"1.0.19\",\"name\": \"Streamlabs\",\"can_activate\": true,\"type\": [\"mobile\",\"overlay\"]},{\"id\": \"lqnf3zxk0rv0g7gq92mtmnirjz2cjj\",\"version\": \"0.0.1\",\"name\": \"Dev Experience Test\",\"can_activate\": true,\"type\": [\"component\",\"mobile\",\"panel\",\"overlay\"]}]}"

activeExtensionsJSON :: String
activeExtensionsJSON = "{\"data\": {\"panel\": {\"1\": {\"active\": true,\"id\": \"rh6jq1q334hqc2rr1qlzqbvwlfl3x0\",\"version\": \"1.1.0\",\"name\": \"TopClip\"},\"2\": {\"active\": true,\"id\": \"wi08ebtatdc7oj83wtl9uxwz807l8b\",\"version\": \"1.1.8\",\"name\": \"Streamlabs Leaderboard\"},\"3\": {\"active\": true,\"id\": \"naty2zwfp7vecaivuve8ef1hohh6bo\",\"version\": \"1.0.9\",\"name\": \"Streamlabs Stream Schedule & Countdown\"}},\"overlay\": {\"1\": {\"active\": true,\"id\": \"zfh2irvx2jb4s60f02jq0ajm8vwgka\",\"version\": \"1.0.19\",\"name\": \"Streamlabs\"}},\"component\": {\"1\": {\"active\": true,\"id\": \"lqnf3zxk0rv0g7gq92mtmnirjz2cjj\",\"version\": \"0.0.1\",\"name\": \"Dev Experience Test\",\"x\": 0,\"y\": 0},\"2\": {\"active\": false}}}}"