Sort tests
This commit is contained in:
parent
e63d91bc77
commit
06b932437a
260
test_vx.py
260
test_vx.py
@ -1,260 +0,0 @@
|
||||
import os
|
||||
|
||||
import twitfix,twExtract,vxApi
|
||||
import cache
|
||||
from flask.testing import FlaskClient
|
||||
client = FlaskClient(twitfix.app)
|
||||
|
||||
# autogenerated from testgen.py
|
||||
testTextTweet="https://twitter.com/jack/status/20"
|
||||
testVideoTweet="https://twitter.com/pdxdylan/status/1540398733669666818"
|
||||
testMediaTweet="https://twitter.com/pdxdylan/status/1534672932106035200"
|
||||
testMultiMediaTweet="https://twitter.com/pdxdylan/status/1532006436703715331"
|
||||
testQRTTweet="https://twitter.com/pdxdylan/status/1611477137319514129"
|
||||
testQrtCeptionTweet="https://twitter.com/CatherineShu/status/585253766271672320"
|
||||
testQrtVideoTweet="https://twitter.com/pdxdylan/status/1674561759422578690"
|
||||
testNSFWTweet="https://twitter.com/kuyacoy/status/1581185279376838657"
|
||||
testPollTweet="https://twitter.com/norm/status/651169346518056960"
|
||||
|
||||
testTextTweet_compare={'text': 'just setting up my twttr', 'date': 'Tue Mar 21 20:50:14 +0000 2006', 'tweetURL': 'https://twitter.com/jack/status/20', 'tweetID': '20', 'conversationID': '20', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1142974214}
|
||||
testVideoTweet_compare={'text': 'TikTok embeds on Discord/Telegram bait you with a fake play button, but to see the actual video you have to go to their website.\nAs a request from a friend, I made it so that if you add "vx" before "tiktok" on any link, it fixes that. https://t.co/QYpiVXUIrW', 'date': 'Fri Jun 24 18:17:31 +0000 2022', 'tweetURL': 'https://twitter.com/pdxdylan/status/1540398733669666818', 'tweetID': '1540398733669666818', 'conversationID': '1540398733669666818', 'mediaURLs': ['https://video.twimg.com/ext_tw_video/1540396699037929472/pu/vid/762x528/YxbXbT3X7vq4LWfC.mp4?tag=12'], 'media_extended': [{'url': 'https://video.twimg.com/ext_tw_video/1540396699037929472/pu/vid/762x528/YxbXbT3X7vq4LWfC.mp4?tag=12', 'type': 'video', 'size': {'width': 762, 'height': 528}, 'duration_millis': 13650, 'thumbnail_url': 'https://pbs.twimg.com/ext_tw_video_thumb/1540396699037929472/pu/img/l187Z6B9AHHxUKPV.jpg', 'altText': None}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1656094651}
|
||||
testMediaTweet_compare={'text': 'oh. https://t.co/HgLAbiXw2E', 'date': 'Wed Jun 08 23:05:14 +0000 2022', 'tweetURL': 'https://twitter.com/pdxdylan/status/1534672932106035200', 'tweetID': '1534672932106035200', 'conversationID': '1534672673422381057', 'mediaURLs': ['https://pbs.twimg.com/media/FUxAt5LWUAMol0N.png'], 'media_extended': [{'url': 'https://pbs.twimg.com/media/FUxAt5LWUAMol0N.png', 'altText': None, 'type': 'image', 'size': {'width': 927, 'height': 534}, 'thumbnail_url': 'https://pbs.twimg.com/media/FUxAt5LWUAMol0N.png'}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1654729514}
|
||||
testMultiMediaTweet_compare={'text': 'Released #Retro64 1.0.9. Besides a lot of internal bug-fixes, this adds quicksand blocks, fixes the rendering for the castle stairs block, and adds a new model, Sonic! \nhttps://github.com/Retro64Mod/Retro64Mod/releases/tag/1.18.2-1.0.9 https://t.co/CWZaw4hzyg', 'date': 'Wed Jun 01 14:29:32 +0000 2022', 'tweetURL': 'https://twitter.com/pdxdylan/status/1532006436703715331', 'tweetID': '1532006436703715331', 'conversationID': '1532006436703715331', 'mediaURLs': ['https://pbs.twimg.com/media/FULF9oxXwAMDI-C.png', 'https://pbs.twimg.com/media/FULGaHkWYAIBV5U.png', 'https://pbs.twimg.com/media/FULGiZnWQAMBRWl.png'], 'media_extended': [{'url': 'https://pbs.twimg.com/media/FULF9oxXwAMDI-C.png', 'altText': None, 'type': 'image', 'size': {'width': 507, 'height': 507}, 'thumbnail_url': 'https://pbs.twimg.com/media/FULF9oxXwAMDI-C.png'}, {'url': 'https://pbs.twimg.com/media/FULGaHkWYAIBV5U.png', 'altText': None, 'type': 'image', 'size': {'width': 396, 'height': 431}, 'thumbnail_url': 'https://pbs.twimg.com/media/FULGaHkWYAIBV5U.png'}, {'url': 'https://pbs.twimg.com/media/FULGiZnWQAMBRWl.png', 'altText': None, 'type': 'image', 'size': {'width': 399, 'height': 341}, 'thumbnail_url': 'https://pbs.twimg.com/media/FULGiZnWQAMBRWl.png'}], 'possibly_sensitive': False, 'hashtags': ['Retro64'], 'qrtURL': None, 'allSameType': True, 'hasMedia': True, 'combinedMediaUrl': 'https://vxtwitter.com/rendercombined.jpg?imgs=https://pbs.twimg.com/media/FULF9oxXwAMDI-C.png,https://pbs.twimg.com/media/FULGaHkWYAIBV5U.png,https://pbs.twimg.com/media/FULGiZnWQAMBRWl.png', 'pollData': None, 'date_epoch': 1654093772}
|
||||
testQRTTweet_compare={'text': "vxTwitter has gotten a *ton* of usage recently, so I'd appreciate a donation to keep things running!\n", 'date': 'Fri Jan 06 21:37:43 +0000 2023', 'tweetURL': 'https://twitter.com/pdxdylan/status/1611477137319514129', 'tweetID': '1611477137319514129', 'conversationID': '1611476665821003776', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': 'https://twitter.com/i/status/1518309187515781125', 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1673041063}
|
||||
testQrtCeptionTweet_compare={'text': 'Testing retweetception ', 'date': 'Tue Apr 07 01:32:26 +0000 2015', 'tweetURL': 'https://twitter.com/CatherineShu/status/585253766271672320', 'tweetID': '585253766271672320', 'conversationID': '585253766271672320', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': 'https://twitter.com/i/status/585253161260216320', 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1428370346}
|
||||
testQrtVideoTweet_compare={'text': 'good', 'date': 'Thu Jun 29 23:33:29 +0000 2023', 'tweetURL': 'https://twitter.com/pdxdylan/status/1674561759422578690', 'tweetID': '1674561759422578690', 'conversationID': '1674561759422578690', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': 'https://twitter.com/i/status/1674197531301904388', 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1688081609}
|
||||
testNSFWTweet_compare={'text': "ngl, I'm scared on finding out the cute Sprigatito's final evolution..\n\nso i had a bot generate it for me.... and I'm forever scarred https://t.co/itMay87vcS", 'date': 'Sat Oct 15 07:28:42 +0000 2022', 'tweetURL': 'https://twitter.com/kuyacoy/status/1581185279376838657', 'tweetID': '1581185279376838657', 'conversationID': '1581185279376838657', 'mediaURLs': ['https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg'], 'media_extended': [{'url': 'https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg', 'altText': None, 'type': 'image', 'size': {'width': 760, 'height': 926}, 'thumbnail_url': 'https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg'}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1665818922}
|
||||
testPollTweet_compare={'text': 'I know when that hotline bling, that can only:', 'date': 'Mon Oct 05 22:57:25 +0000 2015', 'tweetURL': 'https://twitter.com/norm/status/651169346518056960', 'tweetID': '651169346518056960', 'conversationID': '651169346518056960', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': {'options': [{'name': 'Mean one thing', 'votes': 124875, 'percent': 78.82}, {'name': 'Mean multiple things', 'votes': 33554, 'percent': 21.18}]}, 'date_epoch': 1444085845}
|
||||
|
||||
testUser="https://twitter.com/jack"
|
||||
testUserID = "https://twitter.com/i/user/12"
|
||||
testUserWeirdURLs=["https://twitter.com/jack?lang=en","https://twitter.com/jack/with_replies","https://twitter.com/jack/media","https://twitter.com/jack/likes","https://twitter.com/jack/with_replies?lang=en","https://twitter.com/jack/media?lang=en","https://twitter.com/jack/likes?lang=en","https://twitter.com/jack/"]
|
||||
testTextTweet="https://twitter.com/jack/status/20"
|
||||
|
||||
tokens=os.getenv("VXTWITTER_WORKAROUND_TOKENS",None).split(',')
|
||||
|
||||
def compareDict(original,compare):
|
||||
for key in original:
|
||||
assert key in compare
|
||||
if type(compare[key]) is not dict:
|
||||
if (key == 'verified' or key== 'time') and compare[key]!=original[key]:
|
||||
continue # does not match as test data was from before verification changes
|
||||
assert compare[key]==original[key]
|
||||
else:
|
||||
compareDict(original[key],compare[key])
|
||||
|
||||
## Specific API tests ##
|
||||
def test_twextract_syndicationAPI():
|
||||
tweet = twExtract.extractStatus_syndication(testMediaTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testMediaTweet_compare['text']
|
||||
|
||||
def test_twextract_extractStatusV2Anon():
|
||||
tweet = twExtract.extractStatusV2AnonLegacy(testTextTweet,None)
|
||||
assert tweet["full_text"]==testTextTweet_compare['text']
|
||||
tweet = twExtract.extractStatusV2AnonLegacy(testVideoTweet,None)
|
||||
assert tweet["full_text"]==testVideoTweet_compare['text']
|
||||
tweet = twExtract.extractStatusV2AnonLegacy(testMediaTweet,None)
|
||||
assert tweet["full_text"]==testMediaTweet_compare['text']
|
||||
tweet = twExtract.extractStatusV2AnonLegacy(testMultiMediaTweet,None)
|
||||
assert tweet["full_text"][:94]==testMultiMediaTweet_compare['text'][:94]
|
||||
|
||||
|
||||
def test_twextract_v2API():
|
||||
tweet = twExtract.extractStatusV2Legacy(testMediaTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testMediaTweet_compare['text']
|
||||
|
||||
## Tweet retrieve tests ##
|
||||
def test_twextract_textTweetExtract():
|
||||
tweet = twExtract.extractStatus(testTextTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testTextTweet_compare['text']
|
||||
assert tweet["user"]["screen_name"]=="jack"
|
||||
assert 'extended_entities' not in tweet
|
||||
|
||||
def test_twextract_extractV2(): # remove this when v2 is default
|
||||
tweet = twExtract.extractStatusV2(testTextTweet,workaroundTokens=tokens)
|
||||
|
||||
def test_twextract_UserExtract():
|
||||
user = twExtract.extractUser(testUser,workaroundTokens=tokens)
|
||||
assert user["screen_name"]=="jack"
|
||||
assert user["id"]==12
|
||||
assert user["created_at"] == "Tue Mar 21 20:50:14 +0000 2006"
|
||||
|
||||
def test_twextract_UserExtractID():
|
||||
user = twExtract.extractUser(testUserID,workaroundTokens=tokens)
|
||||
assert user["screen_name"]=="jack"
|
||||
assert user["id"]==12
|
||||
assert user["created_at"] == "Tue Mar 21 20:50:14 +0000 2006"
|
||||
|
||||
def test_twextract_UserExtractWeirdURLs():
|
||||
for url in testUserWeirdURLs:
|
||||
user = twExtract.extractUser(url,workaroundTokens=tokens)
|
||||
assert user["screen_name"]=="jack"
|
||||
assert user["id"]==12
|
||||
assert user["created_at"] == "Tue Mar 21 20:50:14 +0000 2006"
|
||||
|
||||
def test_twextract_videoTweetExtract():
|
||||
tweet = twExtract.extractStatus(testVideoTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testVideoTweet_compare['text']
|
||||
assert 'extended_entities' in tweet
|
||||
assert len(tweet['extended_entities']["media"])==1
|
||||
video = tweet['extended_entities']["media"][0]
|
||||
assert video["media_url_https"]==testVideoTweet_compare['media_extended'][0]['thumbnail_url']
|
||||
assert video["type"]=="video"
|
||||
|
||||
|
||||
def test_twextract_mediaTweetExtract():
|
||||
tweet = twExtract.extractStatus(testMediaTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testMediaTweet_compare['text']
|
||||
assert 'extended_entities' in tweet
|
||||
assert len(tweet['extended_entities']["media"])==1
|
||||
video = tweet['extended_entities']["media"][0]
|
||||
|
||||
assert video["media_url_https"]==testMediaTweet_compare['media_extended'][0]['thumbnail_url']
|
||||
assert video["type"]=="photo"
|
||||
|
||||
|
||||
def test_twextract_multimediaTweetExtract():
|
||||
tweet = twExtract.extractStatus(testMultiMediaTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"][:94]==testMultiMediaTweet_compare['text'][:94]
|
||||
assert 'extended_entities' in tweet
|
||||
assert len(tweet['extended_entities']["media"])==3
|
||||
video = tweet['extended_entities']["media"][0]
|
||||
assert video["media_url_https"]==testMultiMediaTweet_compare["mediaURLs"][0]
|
||||
assert video["type"]=="photo"
|
||||
video = tweet['extended_entities']["media"][1]
|
||||
assert video["media_url_https"]==testMultiMediaTweet_compare["mediaURLs"][1]
|
||||
assert video["type"]=="photo"
|
||||
|
||||
def test_twextract_pollTweetExtract(): # basic check if poll data exists
|
||||
tweet = twExtract.extractStatus("https://twitter.com/norm/status/651169346518056960",workaroundTokens=tokens)
|
||||
assert 'card' in tweet
|
||||
assert tweet['card']['name']=="poll2choice_text_only"
|
||||
|
||||
def test_twextract_NSFW_TweetExtract():
|
||||
tweet = twExtract.extractStatus(testNSFWTweet,workaroundTokens=tokens) # For now just test that there's no error
|
||||
|
||||
def getVNFFromLink(link):
|
||||
return twitfix.getTweetData(link)
|
||||
|
||||
## VNF conversion test ##
|
||||
def test_textTweetVNF():
|
||||
vnf = getVNFFromLink(testTextTweet)
|
||||
compareDict(testTextTweet_compare,vnf)
|
||||
|
||||
def test_videoTweetVNF():
|
||||
vnf = getVNFFromLink(testVideoTweet)
|
||||
|
||||
compareDict(testVideoTweet_compare,vnf)
|
||||
|
||||
def test_mediaTweetVNF():
|
||||
vnf = getVNFFromLink(testMediaTweet)
|
||||
compareDict(testMediaTweet_compare,vnf)
|
||||
|
||||
def test_multimediaTweetVNF():
|
||||
vnf = getVNFFromLink(testMultiMediaTweet)
|
||||
compareDict(testMultiMediaTweet_compare,vnf)
|
||||
|
||||
def test_pollTweetVNF():
|
||||
vnf = getVNFFromLink(testPollTweet)
|
||||
compareDict(testPollTweet_compare,vnf)
|
||||
|
||||
def test_qrtTweet():
|
||||
cache.clearCache()
|
||||
# this is an incredibly lazy test, todo: improve it in the future
|
||||
resp = client.get(testQRTTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert testQRTTweet_compare['text'][:10] in str(resp.data)
|
||||
# test qrt-ception
|
||||
resp = client.get(testQrtCeptionTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"}) # get top level tweet
|
||||
assert resp.status_code==200
|
||||
assert "Please retweet this to spread awareness for retweets" in str(resp.data)
|
||||
qtd_tweet=cache.getVnfFromLinkCache("https://twitter.com/EliLanger/status/585253161260216320") # check that the quoted tweet for the top level tweet is cached
|
||||
assert qtd_tweet is not None
|
||||
assert qtd_tweet["qrtURL"] is not None # check that the quoted tweet for the top level tweet has a qrtURL
|
||||
assert cache.getVnfFromLinkCache("https://twitter.com/EliLanger/status/313143446842007553") is None # check that the bottom level tweet has NOT been cached
|
||||
resp = client.get("/EliLanger/status/585253161260216320",headers={"User-Agent":"test"}) # get mid level tweet
|
||||
assert resp.status_code==200
|
||||
assert cache.getVnfFromLinkCache("https://twitter.com/EliLanger/status/313143446842007553") is not None # check that the bottom level tweet has been cached now
|
||||
|
||||
def test_qrtVideoTweet():
|
||||
cache.clearCache()
|
||||
# this is an incredibly lazy test, todo: improve it in the future
|
||||
resp = client.get(testQrtVideoTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
qtd_tweet=cache.getVnfFromLinkCache("https://twitter.com/i/status/1674197531301904388")
|
||||
vurl = qtd_tweet["mediaURLs"][0]
|
||||
assert f"twitter:player:stream\" content=\"{vurl}" in str(resp.data)
|
||||
|
||||
## Test adding to cache ; cache should be empty ##
|
||||
def test_addToCache():
|
||||
cache.clearCache()
|
||||
twitfix.getTweetData(testTextTweet)
|
||||
twitfix.getTweetData(testVideoTweet)
|
||||
twitfix.getTweetData(testMediaTweet)
|
||||
twitfix.getTweetData(testMultiMediaTweet)
|
||||
#retrieve
|
||||
compareDict(testTextTweet_compare,cache.getVnfFromLinkCache(testTextTweet))
|
||||
compareDict(testVideoTweet_compare,cache.getVnfFromLinkCache(testVideoTweet))
|
||||
compareDict(testMediaTweet_compare,cache.getVnfFromLinkCache(testMediaTweet))
|
||||
compareDict(testMultiMediaTweet_compare,cache.getVnfFromLinkCache(testMultiMediaTweet))
|
||||
cache.clearCache()
|
||||
|
||||
def test_embedFromScratch():
|
||||
cache.clearCache()
|
||||
client.get(testTextTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
client.get(testVideoTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
client.get(testMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
client.get(testMultiMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
|
||||
def test_embedFromCache():
|
||||
cache.clearCache()
|
||||
twitfix.getTweetData(testTextTweet)
|
||||
twitfix.getTweetData(testVideoTweet)
|
||||
twitfix.getTweetData(testMediaTweet)
|
||||
twitfix.getTweetData(testMultiMediaTweet)
|
||||
#embed time
|
||||
resp = client.get(testTextTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
resp = client.get(testVideoTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
resp = client.get(testMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
resp = client.get(testMultiMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
|
||||
def test_embedSuggestive():
|
||||
resp = client.get(testNSFWTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert "so i had a bot generate it for me" in str(resp.data)
|
||||
assert "FfF_gKwXgAIpnpD" in str(resp.data)
|
||||
|
||||
def test_veryLongEmbed():
|
||||
cache.clearCache()
|
||||
cache.setCache({'https://twitter.com/TEST/status/1234':
|
||||
{"description":"A"*1024,"hits":0,"images":["","","","",""],"likes":1234,"nsfw":False,"pfp":"","qrt":{},"rts":1234,"screen_name":"TEST","thumbnail":"","time":"","tweet":"https://twitter.com/TEST/status/1234","type":"Text","uploader":"Test","url":""}
|
||||
})
|
||||
resp = client.get('https://twitter.com/TEST/status/1234'.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
|
||||
|
||||
def test_directEmbed():
|
||||
resp = client.get(testVideoTweet.replace("https://twitter.com","")+".mp4",headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert testVideoTweet_compare["mediaURLs"][0] in str(resp.data)
|
||||
|
||||
def test_message404():
|
||||
resp = client.get("https://twitter.com/jack/status/12345",headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert "Failed to scan your link!" in str(resp.data)
|
||||
|
||||
def test_combine():
|
||||
twt = twitfix.getTweetData(testMultiMediaTweet)
|
||||
img1 = twt["mediaURLs"][0]
|
||||
img2 = twt["mediaURLs"][1]
|
||||
resp = client.get(f"/rendercombined.jpg?imgs={img1},{img2}",headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert resp.headers["Content-Type"]=="image/jpeg"
|
||||
assert len(resp.data)>1000
|
||||
|
||||
def test_calcSyndicationToken():
|
||||
assert twExtract.calcSyndicationToken("1691389765483200513") == "43lnobuxzql"
|
27
test_vx_VNF.py
Normal file
27
test_vx_VNF.py
Normal file
@ -0,0 +1,27 @@
|
||||
import twitfix
|
||||
from vx_testdata import *
|
||||
|
||||
def getVNFFromLink(link):
|
||||
return twitfix.getTweetData(link)
|
||||
|
||||
## VNF conversion test ##
|
||||
def test_textTweetVNF():
|
||||
vnf = getVNFFromLink(testTextTweet)
|
||||
compareDict(testTextTweet_compare,vnf)
|
||||
|
||||
def test_videoTweetVNF():
|
||||
vnf = getVNFFromLink(testVideoTweet)
|
||||
|
||||
compareDict(testVideoTweet_compare,vnf)
|
||||
|
||||
def test_mediaTweetVNF():
|
||||
vnf = getVNFFromLink(testMediaTweet)
|
||||
compareDict(testMediaTweet_compare,vnf)
|
||||
|
||||
def test_multimediaTweetVNF():
|
||||
vnf = getVNFFromLink(testMultiMediaTweet)
|
||||
compareDict(testMultiMediaTweet_compare,vnf)
|
||||
|
||||
def test_pollTweetVNF():
|
||||
vnf = getVNFFromLink(testPollTweet)
|
||||
compareDict(testPollTweet_compare,vnf)
|
82
test_vx_embeds.py
Normal file
82
test_vx_embeds.py
Normal file
@ -0,0 +1,82 @@
|
||||
import os
|
||||
|
||||
import twitfix,twExtract
|
||||
import cache
|
||||
from flask.testing import FlaskClient
|
||||
from vx_testdata import *
|
||||
client = FlaskClient(twitfix.app)
|
||||
|
||||
def test_embed_qrtTweet():
|
||||
cache.clearCache()
|
||||
# this is an incredibly lazy test, todo: improve it in the future
|
||||
resp = client.get(testQRTTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert testQRTTweet_compare['text'][:10] in str(resp.data)
|
||||
# test qrt-ception
|
||||
resp = client.get(testQrtCeptionTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"}) # get top level tweet
|
||||
assert resp.status_code==200
|
||||
assert "Please retweet this to spread awareness for retweets" in str(resp.data)
|
||||
qtd_tweet=cache.getVnfFromLinkCache("https://twitter.com/EliLanger/status/585253161260216320") # check that the quoted tweet for the top level tweet is cached
|
||||
assert qtd_tweet is not None
|
||||
assert qtd_tweet["qrtURL"] is not None # check that the quoted tweet for the top level tweet has a qrtURL
|
||||
assert cache.getVnfFromLinkCache("https://twitter.com/EliLanger/status/313143446842007553") is None # check that the bottom level tweet has NOT been cached
|
||||
resp = client.get("/EliLanger/status/585253161260216320",headers={"User-Agent":"test"}) # get mid level tweet
|
||||
assert resp.status_code==200
|
||||
assert cache.getVnfFromLinkCache("https://twitter.com/EliLanger/status/313143446842007553") is not None # check that the bottom level tweet has been cached now
|
||||
|
||||
def test_embed_qrtVideoTweet():
|
||||
cache.clearCache()
|
||||
# this is an incredibly lazy test, todo: improve it in the future
|
||||
resp = client.get(testQrtVideoTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
qtd_tweet=cache.getVnfFromLinkCache("https://twitter.com/i/status/1674197531301904388")
|
||||
vurl = qtd_tweet["mediaURLs"][0]
|
||||
assert f"twitter:player:stream\" content=\"{vurl}" in str(resp.data)
|
||||
|
||||
def test_embed_FromScratch():
|
||||
cache.clearCache()
|
||||
client.get(testTextTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
client.get(testVideoTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
client.get(testMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
client.get(testMultiMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
|
||||
def test_embed_FromCache():
|
||||
cache.clearCache()
|
||||
twitfix.getTweetData(testTextTweet)
|
||||
twitfix.getTweetData(testVideoTweet)
|
||||
twitfix.getTweetData(testMediaTweet)
|
||||
twitfix.getTweetData(testMultiMediaTweet)
|
||||
#embed time
|
||||
resp = client.get(testTextTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
resp = client.get(testVideoTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
resp = client.get(testMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
resp = client.get(testMultiMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
|
||||
def test_embed_Suggestive():
|
||||
resp = client.get(testNSFWTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert "so i had a bot generate it for me" in str(resp.data)
|
||||
assert "FfF_gKwXgAIpnpD" in str(resp.data)
|
||||
|
||||
def test_embed_direct():
|
||||
resp = client.get(testVideoTweet.replace("https://twitter.com","")+".mp4",headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert testVideoTweet_compare["mediaURLs"][0] in str(resp.data)
|
||||
|
||||
def test_embed_message404():
|
||||
resp = client.get("https://twitter.com/jack/status/12345",headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert "Failed to scan your link!" in str(resp.data)
|
||||
|
||||
def test_combine():
|
||||
twt = twitfix.getTweetData(testMultiMediaTweet)
|
||||
img1 = twt["mediaURLs"][0]
|
||||
img2 = twt["mediaURLs"][1]
|
||||
resp = client.get(f"/rendercombined.jpg?imgs={img1},{img2}",headers={"User-Agent":"test"})
|
||||
assert resp.status_code==200
|
||||
assert resp.headers["Content-Type"]=="image/jpeg"
|
||||
assert len(resp.data)>1000
|
93
test_vx_extract.py
Normal file
93
test_vx_extract.py
Normal file
@ -0,0 +1,93 @@
|
||||
import os
|
||||
|
||||
import twExtract
|
||||
from vx_testdata import *
|
||||
|
||||
def test_twextract_syndicationAPI():
|
||||
tweet = twExtract.extractStatus_syndication(testMediaTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testMediaTweet_compare['text']
|
||||
|
||||
def test_twextract_extractStatusV2Anon():
|
||||
tweet = twExtract.extractStatusV2AnonLegacy(testTextTweet,None)
|
||||
assert tweet["full_text"]==testTextTweet_compare['text']
|
||||
tweet = twExtract.extractStatusV2AnonLegacy(testVideoTweet,None)
|
||||
assert tweet["full_text"]==testVideoTweet_compare['text']
|
||||
tweet = twExtract.extractStatusV2AnonLegacy(testMediaTweet,None)
|
||||
assert tweet["full_text"]==testMediaTweet_compare['text']
|
||||
tweet = twExtract.extractStatusV2AnonLegacy(testMultiMediaTweet,None)
|
||||
assert tweet["full_text"][:94]==testMultiMediaTweet_compare['text'][:94]
|
||||
|
||||
|
||||
def test_twextract_v2API():
|
||||
tweet = twExtract.extractStatusV2Legacy(testMediaTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testMediaTweet_compare['text']
|
||||
|
||||
## Tweet retrieve tests ##
|
||||
def test_twextract_textTweetExtract():
|
||||
tweet = twExtract.extractStatus(testTextTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testTextTweet_compare['text']
|
||||
assert tweet["user"]["screen_name"]=="jack"
|
||||
assert 'extended_entities' not in tweet
|
||||
|
||||
def test_twextract_extractV2(): # remove this when v2 is default
|
||||
tweet = twExtract.extractStatusV2(testTextTweet,workaroundTokens=tokens)
|
||||
|
||||
def test_twextract_UserExtract():
|
||||
user = twExtract.extractUser(testUser,workaroundTokens=tokens)
|
||||
assert user["screen_name"]=="jack"
|
||||
assert user["id"]==12
|
||||
assert user["created_at"] == "Tue Mar 21 20:50:14 +0000 2006"
|
||||
|
||||
def test_twextract_UserExtractID():
|
||||
user = twExtract.extractUser(testUserID,workaroundTokens=tokens)
|
||||
assert user["screen_name"]=="jack"
|
||||
assert user["id"]==12
|
||||
assert user["created_at"] == "Tue Mar 21 20:50:14 +0000 2006"
|
||||
|
||||
def test_twextract_UserExtractWeirdURLs():
|
||||
for url in testUserWeirdURLs:
|
||||
user = twExtract.extractUser(url,workaroundTokens=tokens)
|
||||
assert user["screen_name"]=="jack"
|
||||
assert user["id"]==12
|
||||
assert user["created_at"] == "Tue Mar 21 20:50:14 +0000 2006"
|
||||
|
||||
def test_twextract_videoTweetExtract():
|
||||
tweet = twExtract.extractStatus(testVideoTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testVideoTweet_compare['text']
|
||||
assert 'extended_entities' in tweet
|
||||
assert len(tweet['extended_entities']["media"])==1
|
||||
video = tweet['extended_entities']["media"][0]
|
||||
assert video["media_url_https"]==testVideoTweet_compare['media_extended'][0]['thumbnail_url']
|
||||
assert video["type"]=="video"
|
||||
|
||||
|
||||
def test_twextract_mediaTweetExtract():
|
||||
tweet = twExtract.extractStatus(testMediaTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"]==testMediaTweet_compare['text']
|
||||
assert 'extended_entities' in tweet
|
||||
assert len(tweet['extended_entities']["media"])==1
|
||||
video = tweet['extended_entities']["media"][0]
|
||||
|
||||
assert video["media_url_https"]==testMediaTweet_compare['media_extended'][0]['thumbnail_url']
|
||||
assert video["type"]=="photo"
|
||||
|
||||
|
||||
def test_twextract_multimediaTweetExtract():
|
||||
tweet = twExtract.extractStatus(testMultiMediaTweet,workaroundTokens=tokens)
|
||||
assert tweet["full_text"][:94]==testMultiMediaTweet_compare['text'][:94]
|
||||
assert 'extended_entities' in tweet
|
||||
assert len(tweet['extended_entities']["media"])==3
|
||||
video = tweet['extended_entities']["media"][0]
|
||||
assert video["media_url_https"]==testMultiMediaTweet_compare["mediaURLs"][0]
|
||||
assert video["type"]=="photo"
|
||||
video = tweet['extended_entities']["media"][1]
|
||||
assert video["media_url_https"]==testMultiMediaTweet_compare["mediaURLs"][1]
|
||||
assert video["type"]=="photo"
|
||||
|
||||
def test_twextract_pollTweetExtract(): # basic check if poll data exists
|
||||
tweet = twExtract.extractStatus("https://twitter.com/norm/status/651169346518056960",workaroundTokens=tokens)
|
||||
assert 'card' in tweet
|
||||
assert tweet['card']['name']=="poll2choice_text_only"
|
||||
|
||||
def test_twextract_NSFW_TweetExtract():
|
||||
tweet = twExtract.extractStatus(testNSFWTweet,workaroundTokens=tokens) # For now just test that there's no error
|
18
test_vx_misc.py
Normal file
18
test_vx_misc.py
Normal file
@ -0,0 +1,18 @@
|
||||
import twitfix, cache, twExtract
|
||||
from vx_testdata import *
|
||||
|
||||
def test_calcSyndicationToken():
|
||||
assert twExtract.calcSyndicationToken("1691389765483200513") == "43lnobuxzql"
|
||||
|
||||
def test_addToCache():
|
||||
cache.clearCache()
|
||||
twitfix.getTweetData(testTextTweet)
|
||||
twitfix.getTweetData(testVideoTweet)
|
||||
twitfix.getTweetData(testMediaTweet)
|
||||
twitfix.getTweetData(testMultiMediaTweet)
|
||||
#retrieve
|
||||
compareDict(testTextTweet_compare,cache.getVnfFromLinkCache(testTextTweet))
|
||||
compareDict(testVideoTweet_compare,cache.getVnfFromLinkCache(testVideoTweet))
|
||||
compareDict(testMediaTweet_compare,cache.getVnfFromLinkCache(testMediaTweet))
|
||||
compareDict(testMultiMediaTweet_compare,cache.getVnfFromLinkCache(testMultiMediaTweet))
|
||||
cache.clearCache()
|
39
vx_testdata.py
Normal file
39
vx_testdata.py
Normal file
@ -0,0 +1,39 @@
|
||||
import os
|
||||
|
||||
# autogenerated from testgen.py
|
||||
testTextTweet="https://twitter.com/jack/status/20"
|
||||
testVideoTweet="https://twitter.com/pdxdylan/status/1540398733669666818"
|
||||
testMediaTweet="https://twitter.com/pdxdylan/status/1534672932106035200"
|
||||
testMultiMediaTweet="https://twitter.com/pdxdylan/status/1532006436703715331"
|
||||
testQRTTweet="https://twitter.com/pdxdylan/status/1611477137319514129"
|
||||
testQrtCeptionTweet="https://twitter.com/CatherineShu/status/585253766271672320"
|
||||
testQrtVideoTweet="https://twitter.com/pdxdylan/status/1674561759422578690"
|
||||
testNSFWTweet="https://twitter.com/kuyacoy/status/1581185279376838657"
|
||||
testPollTweet="https://twitter.com/norm/status/651169346518056960"
|
||||
|
||||
testTextTweet_compare={'text': 'just setting up my twttr', 'date': 'Tue Mar 21 20:50:14 +0000 2006', 'tweetURL': 'https://twitter.com/jack/status/20', 'tweetID': '20', 'conversationID': '20', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1142974214}
|
||||
testVideoTweet_compare={'text': 'TikTok embeds on Discord/Telegram bait you with a fake play button, but to see the actual video you have to go to their website.\nAs a request from a friend, I made it so that if you add "vx" before "tiktok" on any link, it fixes that. https://t.co/QYpiVXUIrW', 'date': 'Fri Jun 24 18:17:31 +0000 2022', 'tweetURL': 'https://twitter.com/pdxdylan/status/1540398733669666818', 'tweetID': '1540398733669666818', 'conversationID': '1540398733669666818', 'mediaURLs': ['https://video.twimg.com/ext_tw_video/1540396699037929472/pu/vid/762x528/YxbXbT3X7vq4LWfC.mp4?tag=12'], 'media_extended': [{'url': 'https://video.twimg.com/ext_tw_video/1540396699037929472/pu/vid/762x528/YxbXbT3X7vq4LWfC.mp4?tag=12', 'type': 'video', 'size': {'width': 762, 'height': 528}, 'duration_millis': 13650, 'thumbnail_url': 'https://pbs.twimg.com/ext_tw_video_thumb/1540396699037929472/pu/img/l187Z6B9AHHxUKPV.jpg', 'altText': None}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1656094651}
|
||||
testMediaTweet_compare={'text': 'oh. https://t.co/HgLAbiXw2E', 'date': 'Wed Jun 08 23:05:14 +0000 2022', 'tweetURL': 'https://twitter.com/pdxdylan/status/1534672932106035200', 'tweetID': '1534672932106035200', 'conversationID': '1534672673422381057', 'mediaURLs': ['https://pbs.twimg.com/media/FUxAt5LWUAMol0N.png'], 'media_extended': [{'url': 'https://pbs.twimg.com/media/FUxAt5LWUAMol0N.png', 'altText': None, 'type': 'image', 'size': {'width': 927, 'height': 534}, 'thumbnail_url': 'https://pbs.twimg.com/media/FUxAt5LWUAMol0N.png'}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1654729514}
|
||||
testMultiMediaTweet_compare={'text': 'Released #Retro64 1.0.9. Besides a lot of internal bug-fixes, this adds quicksand blocks, fixes the rendering for the castle stairs block, and adds a new model, Sonic! \nhttps://github.com/Retro64Mod/Retro64Mod/releases/tag/1.18.2-1.0.9 https://t.co/CWZaw4hzyg', 'date': 'Wed Jun 01 14:29:32 +0000 2022', 'tweetURL': 'https://twitter.com/pdxdylan/status/1532006436703715331', 'tweetID': '1532006436703715331', 'conversationID': '1532006436703715331', 'mediaURLs': ['https://pbs.twimg.com/media/FULF9oxXwAMDI-C.png', 'https://pbs.twimg.com/media/FULGaHkWYAIBV5U.png', 'https://pbs.twimg.com/media/FULGiZnWQAMBRWl.png'], 'media_extended': [{'url': 'https://pbs.twimg.com/media/FULF9oxXwAMDI-C.png', 'altText': None, 'type': 'image', 'size': {'width': 507, 'height': 507}, 'thumbnail_url': 'https://pbs.twimg.com/media/FULF9oxXwAMDI-C.png'}, {'url': 'https://pbs.twimg.com/media/FULGaHkWYAIBV5U.png', 'altText': None, 'type': 'image', 'size': {'width': 396, 'height': 431}, 'thumbnail_url': 'https://pbs.twimg.com/media/FULGaHkWYAIBV5U.png'}, {'url': 'https://pbs.twimg.com/media/FULGiZnWQAMBRWl.png', 'altText': None, 'type': 'image', 'size': {'width': 399, 'height': 341}, 'thumbnail_url': 'https://pbs.twimg.com/media/FULGiZnWQAMBRWl.png'}], 'possibly_sensitive': False, 'hashtags': ['Retro64'], 'qrtURL': None, 'allSameType': True, 'hasMedia': True, 'combinedMediaUrl': 'https://vxtwitter.com/rendercombined.jpg?imgs=https://pbs.twimg.com/media/FULF9oxXwAMDI-C.png,https://pbs.twimg.com/media/FULGaHkWYAIBV5U.png,https://pbs.twimg.com/media/FULGiZnWQAMBRWl.png', 'pollData': None, 'date_epoch': 1654093772}
|
||||
testQRTTweet_compare={'text': "vxTwitter has gotten a *ton* of usage recently, so I'd appreciate a donation to keep things running!\n", 'date': 'Fri Jan 06 21:37:43 +0000 2023', 'tweetURL': 'https://twitter.com/pdxdylan/status/1611477137319514129', 'tweetID': '1611477137319514129', 'conversationID': '1611476665821003776', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': 'https://twitter.com/i/status/1518309187515781125', 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1673041063}
|
||||
testQrtCeptionTweet_compare={'text': 'Testing retweetception ', 'date': 'Tue Apr 07 01:32:26 +0000 2015', 'tweetURL': 'https://twitter.com/CatherineShu/status/585253766271672320', 'tweetID': '585253766271672320', 'conversationID': '585253766271672320', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': 'https://twitter.com/i/status/585253161260216320', 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1428370346}
|
||||
testQrtVideoTweet_compare={'text': 'good', 'date': 'Thu Jun 29 23:33:29 +0000 2023', 'tweetURL': 'https://twitter.com/pdxdylan/status/1674561759422578690', 'tweetID': '1674561759422578690', 'conversationID': '1674561759422578690', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': 'https://twitter.com/i/status/1674197531301904388', 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1688081609}
|
||||
testNSFWTweet_compare={'text': "ngl, I'm scared on finding out the cute Sprigatito's final evolution..\n\nso i had a bot generate it for me.... and I'm forever scarred https://t.co/itMay87vcS", 'date': 'Sat Oct 15 07:28:42 +0000 2022', 'tweetURL': 'https://twitter.com/kuyacoy/status/1581185279376838657', 'tweetID': '1581185279376838657', 'conversationID': '1581185279376838657', 'mediaURLs': ['https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg'], 'media_extended': [{'url': 'https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg', 'altText': None, 'type': 'image', 'size': {'width': 760, 'height': 926}, 'thumbnail_url': 'https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg'}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1665818922}
|
||||
testPollTweet_compare={'text': 'I know when that hotline bling, that can only:', 'date': 'Mon Oct 05 22:57:25 +0000 2015', 'tweetURL': 'https://twitter.com/norm/status/651169346518056960', 'tweetID': '651169346518056960', 'conversationID': '651169346518056960', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': {'options': [{'name': 'Mean one thing', 'votes': 124875, 'percent': 78.82}, {'name': 'Mean multiple things', 'votes': 33554, 'percent': 21.18}]}, 'date_epoch': 1444085845}
|
||||
|
||||
testUser="https://twitter.com/jack"
|
||||
testUserID = "https://twitter.com/i/user/12"
|
||||
testUserWeirdURLs=["https://twitter.com/jack?lang=en","https://twitter.com/jack/with_replies","https://twitter.com/jack/media","https://twitter.com/jack/likes","https://twitter.com/jack/with_replies?lang=en","https://twitter.com/jack/media?lang=en","https://twitter.com/jack/likes?lang=en","https://twitter.com/jack/"]
|
||||
testTextTweet="https://twitter.com/jack/status/20"
|
||||
|
||||
tokens=os.getenv("VXTWITTER_WORKAROUND_TOKENS",None).split(',')
|
||||
|
||||
def compareDict(original,compare):
|
||||
for key in original:
|
||||
assert key in compare
|
||||
if type(compare[key]) is not dict:
|
||||
if (key == 'verified' or key== 'time') and compare[key]!=original[key]:
|
||||
continue # does not match as test data was from before verification changes
|
||||
assert compare[key]==original[key]
|
||||
else:
|
||||
compareDict(original[key],compare[key])
|
Loading…
x
Reference in New Issue
Block a user