discourse/spec/lib/onebox/engine/twitter_status_onebox_spec.rb

434 lines
15 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
include ActionView::Helpers::NumberHelper
RSpec.describe Onebox::Engine::TwitterStatusOnebox do
shared_examples_for "#to_html" do
it "includes tweet" do
expect(html).to include(tweet_content)
end
# TODO: handle t.co links
# it "includes link" do
# expect(html).to include("http://www.peers.org/action/peers-pledgea")
# end
it "gets the correct timestamp" do
expect(html).to include(timestamp)
end
it "includes name" do
expect(html).to include(full_name)
end
it "includes username" do
expect(html).to include(screen_name)
end
it "includes user avatar" do
expect(html).to include(avatar)
end
it "includes twitter link" do
expect(html).to include(link)
end
it "includes twitter likes" do
expect(html).to include(favorite_count)
end
it "includes twitter retweets" do
expect(html).to include(retweets_count)
end
end
shared_context "with standard tweet info" do
before do
@link = "https://twitter.com/MKBHD/status/1625192182859632661"
@onebox_fixture = "twitterstatus"
end
let(:full_name) { "Marques Brownlee" }
let(:screen_name) { "MKBHD" }
let(:avatar) { "https://pbs.twimg.com/profile_images/1468001914302390278/B_Xv_8gu_normal.jpg" }
let(:timestamp) { "5:56 PM - 13 Feb 2023" }
let(:link) { @link }
let(:favorite_count) { "47K" }
let(:retweets_count) { "1.5K" }
end
shared_context "with quoted tweet info" do
before do
@link = "https://twitter.com/Metallica/status/1128068672289890305"
@onebox_fixture = "twitterstatus_quoted"
stub_request(:head, @link)
stub_request(:get, @link).to_return(status: 200, body: onebox_response(@onebox_fixture))
end
let(:full_name) { "Metallica" }
let(:screen_name) { "Metallica" }
let(:avatar) { "https://pbs.twimg.com/profile_images/1597280886809952256/gsJvGiqU_normal.jpg" }
let(:timestamp) { "10:45 PM - 13 May 2019" }
let(:link) { @link }
let(:favorite_count) { "1.4K" }
let(:retweets_count) { "170" }
end
shared_context "with featured image info" do
before do
@link = "https://twitter.com/codinghorror/status/1409351083177046020"
@onebox_fixture = "twitterstatus_featured_image"
stub_request(:get, @link.downcase).to_return(
status: 200,
body: onebox_response(@onebox_fixture),
)
end
let(:full_name) { "Jeff Atwood" }
let(:screen_name) { "codinghorror" }
let(:avatar) { "https://pbs.twimg.com/profile_images/1517287320235298816/Qx-O6UCY_normal.jpg" }
let(:timestamp) { "3:02 PM - 27 Jun 2021" }
let(:link) { @link }
let(:favorite_count) { "90" }
let(:retweets_count) { "5" }
end
shared_examples "includes quoted tweet data" do
it "includes quoted tweet" do
expect(html).to include(
"If you bought a ticket for tonights @Metallica show at Stade de France, you have helped",
)
end
it "includes quoted tweet name" do
expect(html).to include("All Within My Hands Foundation")
end
it "includes quoted username" do
expect(html).to include("AWMHFoundation")
end
it "includes quoted tweet link" do
expect(html).to include("https://twitter.com/AWMHFoundation/status/1127646016931487744")
end
end
context "without twitter client" do
let(:link) { "https://twitter.com/discourse/status/1428031057186627589" }
let(:html) { described_class.new(link).to_html }
it "does match the url" do
onebox = Onebox::Matcher.new(link, { allowed_iframe_regexes: [/.*/] }).oneboxed
expect(onebox).to be(described_class)
end
it "logs a warn message if rate limited" do
SiteSetting.twitter_consumer_key = "twitter_consumer_key"
SiteSetting.twitter_consumer_secret = "twitter_consumer_secret"
stub_request(:post, "https://api.twitter.com/oauth2/token").to_return(
status: 200,
body: "{\"access_token\":\"token\"}",
headers: {
},
)
stub_request(
:get,
"https://api.twitter.com/2/tweets/1428031057186627589?tweet.fields=id,author_id,text,created_at,entities,referenced_tweets,public_metrics&user.fields=id,name,username,profile_image_url&media.fields=type,height,width,variants,preview_image_url,url&expansions=attachments.media_keys,referenced_tweets.id.author_id",
).to_return(status: 429, body: "{}", headers: {})
Rails.logger.expects(:warn).with(regexp_matches(/rate limit/)).at_least_once
expect(html).to eq("")
end
describe "it resorts to html open graph tags" do
context "with a standard tweet" do
let(:tweet_content) { "I've never played Minecraft" }
include_context "with standard tweet info"
before { @onebox_fixture = "twitterstatus_noclient" }
include_context "with engines"
let(:avatar) do
"https://pbs.twimg.com/profile_images/1468001914302390278/B_Xv_8gu_200x200.jpg"
end
let(:timestamp) { "" }
let(:favorite_count) { "" }
let(:retweets_count) { "" }
it_behaves_like "an engine"
it_behaves_like "#to_html"
end
end
end
describe "when the domain is x.com" do
before do
@link = "https://x.com/MKBHD/status/1625192182859632661"
@onebox_fixture = "xstatus_noclient"
end
include_context "with engines"
let(:tweet_content) { "I've never played Minecraft" }
let(:full_name) { "Marques Brownlee" }
let(:screen_name) { "MKBHD" }
let(:avatar) { "" }
let(:timestamp) { "" }
let(:favorite_count) { "" }
let(:retweets_count) { "" }
it_behaves_like "an engine"
it_behaves_like "#to_html"
end
context "with twitter client" do
before do
@twitter_client =
stub(
"TwitterClient",
status: api_response,
prettify_tweet: tweet_content,
twitter_credentials_missing?: false,
)
@previous_options = Onebox.options.to_h
Onebox.options = { twitter_client: @twitter_client }
end
after { Onebox.options = @previous_options }
context "with a standard tweet" do
let(:tweet_content) { "I've never played Minecraft" }
let(:api_response) do
{
data: {
edit_history_tweet_ids: ["1625192182859632661"],
created_at: "2023-02-13T17:56:25.000Z",
author_id: "29873662",
public_metrics: {
retweet_count: 1460,
reply_count: 2734,
like_count: 46_756,
quote_count: 477,
bookmark_count: 168,
impression_count: 4_017_878,
},
text: "I've never played Minecraft",
entities: {
annotations: [
{
start: 18,
end: 26,
probability: 0.9807,
type: "Other",
normalized_text: "Minecraft",
},
],
},
id: "1625192182859632661",
},
includes: {
users: [
{
name: "Marques Brownlee",
id: "29873662",
profile_image_url:
"https://pbs.twimg.com/profile_images/1468001914302390278/B_Xv_8gu_normal.jpg",
username: "MKBHD",
},
],
},
}
end
include_context "with standard tweet info"
include_context "with engines"
it_behaves_like "an engine"
it_behaves_like "#to_html"
end
context "with quoted tweet" do
let(:tweet_content) do
"Thank you to everyone who came out for <a href='https://twitter.com/search?q=%23MetInParis' target='_blank'>#MetInParis</a> last night for helping us support <a href='https://twitter.com/EMMAUSolidarite' target='_blank'>@EMMAUSolidarite</a> &amp; <a href='https://twitter.com/PompiersParis' target='_blank'>@PompiersParis</a>. <a href='https://twitter.com/search?q=%23AWMH' target='_blank'>#AWMH</a> <a href='https://twitter.com/search?q=%23MetalicaGivesBack' target='_blank'>#MetalicaGivesBack</a> <a href=\"https://t.co/gLtZSdDFmN\" target=\"_blank\">https://t.co/gLtZSdDFmN</a>"
end
let(:api_response) do
{
data: {
text:
"Thank you to everyone who came out for #MetInParis last night for helping us support @EMMAUSolidarite &amp; @PompiersParis. #AWMH #MetalicaGivesBack https://t.co/gLtZSdDFmN",
edit_history_tweet_ids: ["1128068672289890305"],
entities: {
mentions: [
{ start: 85, end: 101, username: "EMMAUSolidarite", id: "2912493406" },
{ start: 108, end: 122, username: "PompiersParis", id: "1342191438" },
],
urls: [
{
start: 149,
end: 172,
url: "https://t.co/gLtZSdDFmN",
expanded_url: "https://twitter.com/AWMHFoundation/status/1127646016931487744",
display_url: "twitter.com/AWMHFoundation…",
},
],
hashtags: [
{ start: 39, end: 50, tag: "MetInParis" },
{ start: 124, end: 129, tag: "AWMH" },
{ start: 130, end: 148, tag: "MetalicaGivesBack" },
],
annotations: [
{
start: 40,
end: 49,
probability: 0.6012,
type: "Other",
normalized_text: "MetInParis",
},
{
start: 125,
end: 128,
probability: 0.5884,
type: "Other",
normalized_text: "AWMH",
},
{
start: 131,
end: 147,
probability: 0.6366,
type: "Other",
normalized_text: "MetalicaGivesBack",
},
],
},
id: "1128068672289890305",
referenced_tweets: [{ type: "quoted", id: "1127646016931487744" }],
created_at: "2019-05-13T22:45:04.000Z",
public_metrics: {
retweet_count: 171,
reply_count: 21,
like_count: 1424,
quote_count: 0,
bookmark_count: 2,
impression_count: 0,
},
author_id: "238475531",
},
includes: {
users: [
{
profile_image_url:
"https://pbs.twimg.com/profile_images/1597280886809952256/gsJvGiqU_normal.jpg",
name: "Metallica",
id: "238475531",
username: "Metallica",
},
{
profile_image_url:
"https://pbs.twimg.com/profile_images/935181032185241600/D8FoOIRJ_normal.jpg",
name: "All Within My Hands Foundation",
id: "886959980254871552",
username: "AWMHFoundation",
},
],
tweets: [
{
text:
"If you bought a ticket for tonights @Metallica show at Stade de France, you have helped contribute to @EMMAUSolidarite &amp; @PompiersParis. #MetallicaGivesBack #AWMH #MetInParis https://t.co/wlUtDQbQEK",
edit_history_tweet_ids: ["1127646016931487744"],
entities: {
mentions: [
{ start: 37, end: 47, username: "Metallica", id: "238475531" },
{ start: 103, end: 119, username: "EMMAUSolidarite", id: "2912493406" },
{ start: 126, end: 140, username: "PompiersParis", id: "1342191438" },
],
urls: [
{
start: 180,
end: 203,
url: "https://t.co/wlUtDQbQEK",
expanded_url:
"https://twitter.com/AWMHFoundation/status/1127646016931487744/photo/1",
display_url: "pic.twitter.com/wlUtDQbQEK",
media_key: "3_1127645176183250944",
},
{
start: 180,
end: 203,
url: "https://t.co/wlUtDQbQEK",
expanded_url:
"https://twitter.com/AWMHFoundation/status/1127646016931487744/photo/1",
display_url: "pic.twitter.com/wlUtDQbQEK",
media_key: "3_1127645195384774657",
},
],
hashtags: [
{ start: 142, end: 161, tag: "MetallicaGivesBack" },
{ start: 162, end: 167, tag: "AWMH" },
{ start: 168, end: 179, tag: "MetInParis" },
],
annotations: [
{
start: 56,
end: 70,
probability: 0.7845,
type: "Place",
normalized_text: "Stade de France",
},
{
start: 143,
end: 160,
probability: 0.5569,
type: "Organization",
normalized_text: "MetallicaGivesBack",
},
{
start: 163,
end: 166,
probability: 0.4496,
type: "Other",
normalized_text: "AWMH",
},
{
start: 169,
end: 178,
probability: 0.3784,
type: "Place",
normalized_text: "MetInParis",
},
],
},
id: "1127646016931487744",
created_at: "2019-05-12T18:45:35.000Z",
attachments: {
media_keys: %w[3_1127645176183250944 3_1127645195384774657],
},
public_metrics: {
retweet_count: 34,
reply_count: 5,
like_count: 241,
quote_count: 9,
bookmark_count: 0,
impression_count: 0,
},
author_id: "886959980254871552",
},
],
},
}
end
include_context "with quoted tweet info"
include_context "with engines"
it_behaves_like "an engine"
it_behaves_like "#to_html"
it_behaves_like "includes quoted tweet data"
end
end
end