packages feed

scuttlebutt-types-0.2.0: test/MessageSpec.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}

module MessageSpec where

import Test.Hspec
import Ssb.Types.Message
import Ssb.Types.Link
import Ssb.Types.Key
import Ssb.Types.Hash
import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import Data.Maybe

import Prelude hiding (sequence)

spec :: Spec
spec = do
	messageSpec
	postSpec
	aboutSpec
	contactSpec
	voteSpec
	privateContentSpec
	pubSpec

originalMessage :: ByteString
originalMessage = "\
\{\
\  \"previous\": \"%3AWRZYdDHKOmLOWvzHbwJFjx9g8hOQH/NXZkwciA63Y=.sha256\",\
\  \"author\": \"@EMovhfIrFk4NihAKnRNhrfRaqIhBv1Wj8pTxJNgvCCY=.ed25519\",\
\  \"sequence\": 184,\
\  \"timestamp\": 1449954503740,\
\  \"hash\": \"sha256\",\
\  \"content\": {\
\    \"type\": \"post\",\
\    \"text\": \"@johnny use https://github.com/ssbc/ssb-msgs and https://github.com/ssbc/ssb-ref is probably useful too.\",\
\    \"root\": \"%rf1JvoFg1pHE6TkuuMxsjBNevFck7LQvXGhkLMNlaYs=.sha256\",\
\    \"branch\": \"%G37a4PUTbysiETQazyYATwLkfn/ZzigmIheAx905MLU=.sha256\",\
\    \"mentions\": [\
\      {\
\        \"link\": \"@dnr1swLSAgf36g+FzGjNLgmytj2IIyDaYeKZ7F5GdzY=.ed25519\",\
\        \"name\": \"johnny\"\
\      }\
\    ]\
\  },\
\  \"signature\": \"28GiO52GFjJnrwpKo359FamEes7JB9gTiiZaidKLL1C1NRueqGq2IAYQ1V+T2AnBgUJLRZUIyNtLTlBcx4RGAA==.sig.ed25519\"\
\}"

messageSpec :: Spec
messageSpec = describe "message" $ do
	it "extracts message content" $ do
		let (Just message) = (decode originalMessage) :: Maybe (Message AnyContent)
		previous message `shouldBe` MessageLink <$> parseSha256 "3AWRZYdDHKOmLOWvzHbwJFjx9g8hOQH/NXZkwciA63Y="
		author message `shouldBe` fromJust (FeedLink <$> parseEd25519PublicKey "EMovhfIrFk4NihAKnRNhrfRaqIhBv1Wj8pTxJNgvCCY=")
		sequence message `shouldBe` 184
		timestamp message `shouldBe` 1449954503740
		hash message `shouldBe` "sha256"
		signature message `shouldBe` "28GiO52GFjJnrwpKo359FamEes7JB9gTiiZaidKLL1C1NRueqGq2IAYQ1V+T2AnBgUJLRZUIyNtLTlBcx4RGAA==.sig.ed25519"

postSpec :: Spec
postSpec = describe "post" $ do
	it "extracts message post" $ do
		let (Just message) = (decode originalMessage) :: Maybe (Message Post)
		text (content message) `shouldBe`
			"@johnny use https://github.com/ssbc/ssb-msgs and https://github.com/ssbc/ssb-ref is probably useful too."
		channel (content message) `shouldBe` Nothing
		root (content message) `shouldBe`
			MessageLink <$> parseSha256 "rf1JvoFg1pHE6TkuuMxsjBNevFck7LQvXGhkLMNlaYs="
		branch (content message) `shouldBe`
			MessageLink <$> parseSha256 "G37a4PUTbysiETQazyYATwLkfn/ZzigmIheAx905MLU="
		recps (content message) `shouldBe` Nothing
		map (linkTo . mentionLink) <$> (mentions (content message)) `shouldBe`
			Just [ "dnr1swLSAgf36g+FzGjNLgmytj2IIyDaYeKZ7F5GdzY=" ]

	it "does not parse content that is not a post" $ do
		(decode originalAbout :: Maybe (Message Post)) `shouldBe` Nothing

originalAbout :: ByteString
originalAbout = "\
\{\
\  \"previous\": \"%6+FS+LB8nDkgHZKanIB6kK5AYBK2SZYH55q5zv/5XIQ=.sha256\",\
\  \"author\": \"@4RUNgFpvI4ZHH6mPPC9GLzsdv33Cs2JGMMcs8rJSMuU=.ed25519\",\
\  \"sequence\": 5,\
\  \"timestamp\": 1464267463411,\
\  \"hash\": \"sha256\",\
\  \"content\": {\
\    \"type\": \"about\",\
\    \"about\": \"@4RUNgFpvI4ZHH6mPPC9GLzsdv33Cs2JGMMcs8rJSMuU=.ed25519\",\
\    \"image\": {\
\      \"link\": \"&Ro1xCJNDIwwKul2SLSU1e4hrwekPcBI6OrBFN0JWnQM=.sha256\",\
\      \"size\": 502712,\
\      \"type\": \"image/png\",\
\      \"width\": 512,\
\      \"height\": 512\
\    }\
\  },\
\  \"signature\": \"mPC156lndHN2oES/UE0GPK/Z8QgFLG8B/bba2TycXzPZZ7IShQhmFiasE0r0ZBTfRmU9KyuVdfwVYogkY2IACA==.sig.ed25519\"\
\}"

aboutSpec :: Spec
aboutSpec = describe "about" $ do
	it "extracts message about" $ do
		let Just message = (decode originalAbout) :: Maybe (Message About)
		linkTo (about (content message)) `shouldBe` "4RUNgFpvI4ZHH6mPPC9GLzsdv33Cs2JGMMcs8rJSMuU="
		name (content message) `shouldBe` Nothing
		fmap aboutImageLink (image (content message)) `shouldBe`
			BlobLink <$> parseSha256 "Ro1xCJNDIwwKul2SLSU1e4hrwekPcBI6OrBFN0JWnQM="
		fmap aboutImageSize (image (content message)) `shouldBe`
			Just (Just 502712)
		fmap aboutImageType (image (content message)) `shouldBe`
			Just (Just "image/png")
		fmap aboutImageWidth (image (content message)) `shouldBe`
			Just (Just 512)
		fmap aboutImageHeight (image (content message)) `shouldBe`
			Just (Just 512)

originalContact :: ByteString
originalContact = "\
\{\
\  \"previous\": \"%kLJuVKntE9LsPeTSyiVSNnb2vkiGXzBUMeDPoGr6BBw=.sha256\",\
\  \"author\": \"@ye+QM09iPcDJD6YvQYjoQc7sLF/IFhmNbEqgdzQo3lQ=.ed25519\",\
\  \"sequence\": 5442,\
\  \"timestamp\": 1488618790507,\
\  \"hash\": \"sha256\",\
\  \"content\": {\
\    \"type\": \"contact\",\
\    \"contact\": \"@o91tsjBgL0l0zs475aRWYSAXFxvirZS7VrXmirY/msI=.ed25519\",\
\    \"following\": true\
\  },\
\  \"signature\": \"zknuPbUwMeBaDZzZ9iBETOPbZ7SYqetd3RVkq2mYSyr4QI/7uwho3GnerIF3fLcvW3MgRM5SvFvSTnpxxQFoCg==.sig.ed25519\"\
\}"

contactSpec :: Spec
contactSpec = describe "contact" $ do
	it "extracts message contact" $ do
		let Just message = (decode originalContact) :: Maybe (Message Contact)
		content message `shouldBe` Contact
			{ contact = fromJust $ FeedLink <$> parseEd25519PublicKey "o91tsjBgL0l0zs475aRWYSAXFxvirZS7VrXmirY/msI="
			, following = True
			, blocking = False
			}

originalVote :: ByteString
originalVote = "\
\{\
\ \"previous\": \"%jiyo59Or2Rrm+05QJIZ/fLfCeBhiaJ+tjJgW/USgtYs=.sha256\",\
\  \"author\": \"@/02iw6SFEPIHl8nMkYSwcCgRWxiG6VP547Wcp1NW8Bo=.ed25519\",\
\  \"sequence\": 3304,\
\  \"timestamp\": 1459235596255,\
\  \"hash\": \"sha256\",\
\  \"content\": {\
\    \"type\": \"vote\",\
\    \"vote\": {\
\      \"link\": \"%lu9JsdUl4astKykyaVFdkLb7//tS0K08BMs6dT+fErA=.sha256\",\
\      \"value\": 1\
\    }\
\  },\
\  \"signature\": \"iw/wREQJ4UEecnfuFNIiZt9kMZXkQc8SP2jmhVbUvPj9Eo50D2yJKfza+Qf/tYwOuFaE9et4pbucPD/4OMlbAg==.sig.ed25519\"\
\}"

voteSpec :: Spec
voteSpec = describe "vote" $ do
	it "extracts message vote" $ do
		let Just message = (decode originalVote) :: Maybe (Message Vote)
		voteValue (content message) `shouldBe` 1
		voteExpression (content message) `shouldBe` Nothing
		linkTo (voteLink (content message)) `shouldBe` "lu9JsdUl4astKykyaVFdkLb7//tS0K08BMs6dT+fErA="

-- Not a real private message content, because the test couldn't decrypt it anyway.
originalPrivateContent :: ByteString
originalPrivateContent = "\
\{\
\  \"previous\": \"%RFY6DRn3syOm7GodwpNTePx0I4ZWyZMVsmZ4V1QqiDQ=.sha256\",\
\  \"author\": \"@9nTgtYmvW4HID6ayt6Icwc8WZxdifx5SlSKKIX/X/1g=.ed25519\",\
\  \"sequence\": 245,\
\  \"timestamp\": 1481349557377,\
\  \"hash\": \"sha256\",\
\  \"content\": \"dummy\",\
\  \"signature\": \"2urg9PG4+esti1DIf4DnFfsUXXnOzwXHv+QnflKQQ0145pNw+SIXeYkhNhzqdFm2fz7wzWb7YVlFMPIL11EaBQ==.sig.ed25519\"\
\}"

privateContentSpec :: Spec
privateContentSpec = describe "private" $ do
	it "extracts message private" $ do
		let Just message = (decode originalPrivateContent) :: Maybe (Message PrivateContent)
		author message `shouldBe` fromJust (FeedLink <$> parseEd25519PublicKey "9nTgtYmvW4HID6ayt6Icwc8WZxdifx5SlSKKIX/X/1g=")
		content message `shouldBe` PrivateContent "dummy"

originalPub :: ByteString
originalPub = "\
\{\
\  \"previous\": \"%qYdhzyTbQwrdTOpKVvFS0nFCOvK5SekDhxLjHs6i1jo=.sha256\",\
\  \"author\": \"@26RTWG0+zR1DLO43p4VjB/UzTNKgQ+TNvLey37E/YdI=.ed25519\",\
\  \"sequence\": 3,\
\  \"timestamp\": 1497928539321,\
\  \"hash\": \"sha256\",\
\  \"content\": {\
\    \"type\": \"pub\",\
\    \"address\": {\
\      \"host\": \"ssb.hypersignal.xyz\",\
\      \"port\": 8008,\
\      \"key\": \"@XRg7pXoQqsWDDk4dmgvSWHUqzwS6BmqMo4IdbMKPjWA=.ed25519\"\
\    }\
\  },\
\  \"signature\": \"nWBpjqbnw4sGkaD+0OpxzmTo5VeGOnRcj2hxWjATlO9e7F9eK2yJACOaa5hzGT1E967uFhwmvwUA6FMq3Z0MBQ==.sig.ed25519\"\
\}"

pubSpec :: Spec
pubSpec = describe "pub" $ do
	it "extracts message pub" $ do
		let Just message = (decode originalPub) :: Maybe (Message Pub)
		pubHost (content message) `shouldBe` "ssb.hypersignal.xyz"
		pubPort (content message) `shouldBe` 8008
		Just (unFeedLink (pubKey (content message))) `shouldBe`
			parseEd25519PublicKey "XRg7pXoQqsWDDk4dmgvSWHUqzwS6BmqMo4IdbMKPjWA="