# frozen_string_literal: true 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/vyki_e/status/363116819147538433" @onebox_fixture = "twitterstatus" end let(:full_name) { "Vyki Englert" } let(:screen_name) { "vyki_e" } let(:avatar) { "732349210264133632/RTNgZLrm_400x400.jpg" } let(:timestamp) { "6:59 PM - 1 Aug 2013" } let(:link) { @link } let(:favorite_count) { "0" } let(:retweets_count) { "0" } end shared_context "with quoted tweet info" do before do @link = "https://twitter.com/metallica/status/1128068672289890305" @onebox_fixture = "twitterstatus_quoted" stub_request(:get, @link.downcase).to_return( status: 200, body: onebox_response(@onebox_fixture), ) end let(:full_name) { "Metallica" } let(:screen_name) { "Metallica" } let(:avatar) { "profile_images/766360293953802240/kt0hiSmv_400x400.jpg" } let(:timestamp) { "10:45 PM - 13 May 2019" } let(:link) { @link } let(:favorite_count) { "1.7K" } let(:retweets_count) { "201" } 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) { "" } let(:timestamp) { "3:02 PM - 27 Jun 2021" } let(:link) { @link } let(:favorite_count) { "90" } let(:retweets_count) { "0" } end shared_examples "includes quoted tweet data" do it "includes quoted tweet" do expect(html).to include( "If you bought a ticket for tonight’s @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 not match the url" do onebox = Onebox::Matcher.new(link, { allowed_iframe_regexes: [/.*/] }).oneboxed expect(onebox).not_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/1.1/statuses/show.json?id=1428031057186627589&tweet_mode=extended", ).to_return(status: 429, body: "{}", headers: {}) Rails.logger.expects(:warn).with(regexp_matches(/rate limit/)).at_least_once expect(html).to eq("") end end context "with twitter client" do before do @twitter_client = stub( "TwitterClient", status: api_response, prettify_tweet: tweet_content, twitter_credentials_missing?: false, prettify_number: favorite_count, ) @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) do "I'm a sucker for pledges. @Peers Pledge #sharingeconomy peers.org/action/peers-p…" end let(:api_response) do { created_at: "Fri Aug 02 01:59:30 +0000 2013", id: 363_116_819_147_538_400, id_str: "363116819147538433", text: "I'm a sucker for pledges. @Peers Pledge #sharingeconomy http://t.co/T4Sc47KAzh", truncated: false, entities: { hashtags: [{ text: "sharingeconomy", indices: [41, 56] }], symbols: [], user_mentions: [ { screen_name: "peers", name: "Peers", id: 1_428_357_889, id_str: "1428357889", indices: [27, 33], }, ], urls: [ { url: "http://t.co/T4Sc47KAzh", expanded_url: "http://www.peers.org/action/peers-pledgea/", display_url: "peers.org/action/peers-p…", indices: [57, 79], }, ], }, source: "Twitter for Websites", in_reply_to_status_id: nil, in_reply_to_status_id_str: nil, in_reply_to_user_id: nil, in_reply_to_user_id_str: nil, in_reply_to_screen_name: nil, user: { id: 1_087_064_150, id_str: "1087064150", name: "Vyki Englert", screen_name: "vyki_e", location: "Los Angeles, CA", description: "Rides bikes, writes code, likes maps. @CompilerLA / @CityGrows / Brigade Captain @HackforLA", url: "http://t.co/YCAP3asRG1", entities: { url: { urls: [ { url: "http://t.co/YCAP3asRG1", expanded_url: "http://www.compiler.la", display_url: "compiler.la", indices: [0, 22], }, ], }, description: { urls: [], }, }, protected: false, followers_count: 1128, friends_count: 2244, listed_count: 83, created_at: "Sun Jan 13 19:53:00 +0000 2013", favourites_count: 2928, utc_offset: -25_200, time_zone: "Pacific Time (US & Canada)", geo_enabled: true, verified: false, statuses_count: 3295, lang: "en", contributors_enabled: false, is_translator: false, is_translation_enabled: false, profile_background_color: "ACDED6", profile_background_image_url: "http://abs.twimg.com/images/themes/theme18/bg.gif", profile_background_image_url_https: "https://abs.twimg.com/images/themes/theme18/bg.gif", profile_background_tile: false, profile_image_url: "http://pbs.twimg.com/profile_images/732349210264133632/RTNgZLrm_normal.jpg", profile_image_url_https: "https://pbs.twimg.com/profile_images/732349210264133632/RTNgZLrm_normal.jpg", profile_banner_url: "https://pbs.twimg.com/profile_banners/1087064150/1424315468", profile_link_color: "4E99D1", profile_sidebar_border_color: "EEEEEE", profile_sidebar_fill_color: "F6F6F6", profile_text_color: "333333", profile_use_background_image: true, has_extended_profile: false, default_profile: false, default_profile_image: false, following: false, follow_request_sent: false, notifications: false, }, geo: nil, coordinates: nil, place: nil, contributors: nil, is_quote_status: false, retweet_count: 0, favorite_count: 0, favorited: false, retweeted: false, possibly_sensitive: false, possibly_sensitive_appealable: false, lang: "en", } 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 #MetInParis last night for helping us support @EMMAUSolidarite & @PompiersParis. #AWMH #MetalicaGivesBack https://t.co/gLtZSdDFmN" end let(:api_response) do { created_at: "Mon May 13 22:45:04 +0000 2019", id: 1_128_068_672_289_890_305, id_str: "1128068672289890305", full_text: "Thank you to everyone who came out for #MetInParis last night for helping us support @EMMAUSolidarite & @PompiersParis. #AWMH #MetalicaGivesBack https://t.co/gLtZSdDFmN", truncated: false, display_text_range: [0, 148], entities: { hashtags: [ { text: "MetInParis", indices: [39, 50] }, { text: "AWMH", indices: [124, 129] }, { text: "MetalicaGivesBack", indices: [130, 148] }, ], symbols: [], user_mentions: [ { screen_name: "EMMAUSolidarite", name: "EMMAÜS Solidarité", id: 2_912_493_406, id_str: "2912493406", indices: [85, 101], }, { screen_name: "PompiersParis", name: "Pompiers de Paris", id: 1_342_191_438, id_str: "1342191438", indices: [108, 122], }, ], urls: [ { url: "https://t.co/gLtZSdDFmN", expanded_url: "https://twitter.com/AWMHFoundation/status/1127646016931487744", display_url: "twitter.com/AWMHFoundation…", indices: [149, 172], }, ], }, source: "Twitter Web Client", in_reply_to_status_id: nil, in_reply_to_status_id_str: nil, in_reply_to_user_id: nil, in_reply_to_user_id_str: nil, in_reply_to_screen_name: nil, user: { id: 238_475_531, id_str: "238475531", name: "Metallica", screen_name: "Metallica", location: "San Francisco, CA", description: "http://t.co/EAkqroM0OA | http://t.co/BEu6OVRhKG", url: "http://t.co/kVxaQpmqSI", entities: { url: { urls: [ { url: "http://t.co/kVxaQpmqSI", expanded_url: "http://www.metallica.com", display_url: "metallica.com", indices: [0, 22], }, ], }, description: { urls: [ { url: "http://t.co/EAkqroM0OA", expanded_url: "http://metallica.com", display_url: "metallica.com", indices: [0, 22], }, { url: "http://t.co/BEu6OVRhKG", expanded_url: "http://livemetallica.com", display_url: "livemetallica.com", indices: [25, 47], }, ], }, }, protected: false, followers_count: 5_760_661, friends_count: 31, listed_count: 12_062, created_at: "Sat Jan 15 07:34:59 +0000 2011", favourites_count: 567, utc_offset: nil, time_zone: nil, geo_enabled: true, verified: true, statuses_count: 3764, lang: nil, contributors_enabled: false, is_translator: false, is_translation_enabled: false, profile_background_color: "000000", profile_background_image_url: "http://abs.twimg.com/images/themes/theme9/bg.gif", profile_background_image_url_https: "https://abs.twimg.com/images/themes/theme9/bg.gif", profile_background_tile: false, profile_image_url: "http://pbs.twimg.com/profile_images/766360293953802240/kt0hiSmv_normal.jpg", profile_image_url_https: "https://pbs.twimg.com/profile_images/766360293953802240/kt0hiSmv_normal.jpg", profile_banner_url: "https://pbs.twimg.com/profile_banners/238475531/1479538295", profile_link_color: "2FC2EF", profile_sidebar_border_color: "000000", profile_sidebar_fill_color: "252429", profile_text_color: "666666", profile_use_background_image: false, has_extended_profile: false, default_profile: false, default_profile_image: false, following: false, follow_request_sent: false, notifications: false, translator_type: "regular", }, geo: nil, coordinates: nil, place: nil, contributors: nil, is_quote_status: true, quoted_status_id: 1_127_646_016_931_487_744, quoted_status_id_str: "1127646016931487744", quoted_status_permalink: { url: "https://t.co/gLtZSdDFmN", expanded: "https://twitter.com/AWMHFoundation/status/1127646016931487744", display: "twitter.com/AWMHFoundation…", }, quoted_status: { created_at: "Sun May 12 18:45:35 +0000 2019", id: 1_127_646_016_931_487_744, id_str: "1127646016931487744", full_text: "If you bought a ticket for tonight’s @Metallica show at Stade de France, you have helped contribute to @EMMAUSolidarite & @PompiersParis. #MetallicaGivesBack #AWMH #MetInParis https://t.co/wlUtDQbQEK", truncated: false, display_text_range: [0, 179], entities: { hashtags: [ { text: "MetallicaGivesBack", indices: [142, 161] }, { text: "AWMH", indices: [162, 167] }, { text: "MetInParis", indices: [168, 179] }, ], symbols: [], user_mentions: [ { screen_name: "Metallica", name: "Metallica", id: 238_475_531, id_str: "238475531", indices: [37, 47], }, { screen_name: "EMMAUSolidarite", name: "EMMAÜS Solidarité", id: 2_912_493_406, id_str: "2912493406", indices: [103, 119], }, { screen_name: "PompiersParis", name: "Pompiers de Paris", id: 1_342_191_438, id_str: "1342191438", indices: [126, 140], }, ], urls: [], media: [ { id: 1_127_645_176_183_250_944, id_str: "1127645176183250944", indices: [180, 203], media_url: "http://pbs.twimg.com/media/D6YzUC8V4AApDdF.jpg", media_url_https: "https://pbs.twimg.com/media/D6YzUC8V4AApDdF.jpg", url: "https://t.co/wlUtDQbQEK", display_url: "pic.twitter.com/wlUtDQbQEK", expanded_url: "https://twitter.com/AWMHFoundation/status/1127646016931487744/photo/1", type: "photo", sizes: { large: { w: 2048, h: 1498, resize: "fit", }, thumb: { w: 150, h: 150, resize: "crop", }, medium: { w: 1200, h: 877, resize: "fit", }, small: { w: 680, h: 497, resize: "fit", }, }, }, ], }, extended_entities: { media: [ { id: 1_127_645_176_183_250_944, id_str: "1127645176183250944", indices: [180, 203], media_url: "http://pbs.twimg.com/media/D6YzUC8V4AApDdF.jpg", media_url_https: "https://pbs.twimg.com/media/D6YzUC8V4AApDdF.jpg", url: "https://t.co/wlUtDQbQEK", display_url: "pic.twitter.com/wlUtDQbQEK", expanded_url: "https://twitter.com/AWMHFoundation/status/1127646016931487744/photo/1", type: "photo", sizes: { large: { w: 2048, h: 1498, resize: "fit", }, thumb: { w: 150, h: 150, resize: "crop", }, medium: { w: 1200, h: 877, resize: "fit", }, small: { w: 680, h: 497, resize: "fit", }, }, }, { id: 1_127_645_195_384_774_657, id_str: "1127645195384774657", indices: [180, 203], media_url: "http://pbs.twimg.com/media/D6YzVKeV4AEPpSQ.jpg", media_url_https: "https://pbs.twimg.com/media/D6YzVKeV4AEPpSQ.jpg", url: "https://t.co/wlUtDQbQEK", display_url: "pic.twitter.com/wlUtDQbQEK", expanded_url: "https://twitter.com/AWMHFoundation/status/1127646016931487744/photo/1", type: "photo", sizes: { thumb: { w: 150, h: 150, resize: "crop", }, medium: { w: 1200, h: 922, resize: "fit", }, small: { w: 680, h: 522, resize: "fit", }, large: { w: 2048, h: 1574, resize: "fit", }, }, }, ], }, source: "Twitter Web Client", in_reply_to_status_id: nil, in_reply_to_status_id_str: nil, in_reply_to_user_id: nil, in_reply_to_user_id_str: nil, in_reply_to_screen_name: nil, user: { id: 886_959_980_254_871_552, id_str: "886959980254871552", name: "All Within My Hands Foundation", screen_name: "AWMHFoundation", location: "", description: "", url: "https://t.co/KgwIPrVVhg", entities: { url: { urls: [ { url: "https://t.co/KgwIPrVVhg", expanded_url: "http://allwithinmyhands.org", display_url: "allwithinmyhands.org", indices: [0, 23], }, ], }, description: { urls: [], }, }, protected: false, followers_count: 5962, friends_count: 6, listed_count: 15, created_at: "Mon Jul 17 14:45:13 +0000 2017", favourites_count: 30, utc_offset: nil, time_zone: nil, geo_enabled: true, verified: false, statuses_count: 241, lang: nil, contributors_enabled: false, is_translator: false, is_translation_enabled: false, profile_background_color: "000000", profile_background_image_url: "http://abs.twimg.com/images/themes/theme1/bg.png", profile_background_image_url_https: "https://abs.twimg.com/images/themes/theme1/bg.png", profile_background_tile: false, profile_image_url: "http://pbs.twimg.com/profile_images/935181032185241600/D8FoOIRJ_normal.jpg", profile_image_url_https: "https://pbs.twimg.com/profile_images/935181032185241600/D8FoOIRJ_normal.jpg", profile_banner_url: "https://pbs.twimg.com/profile_banners/886959980254871552/1511799663", profile_link_color: "000000", profile_sidebar_border_color: "000000", profile_sidebar_fill_color: "000000", profile_text_color: "000000", profile_use_background_image: false, has_extended_profile: false, default_profile: false, default_profile_image: false, following: false, follow_request_sent: false, notifications: false, translator_type: "none", }, geo: nil, coordinates: nil, place: nil, contributors: nil, is_quote_status: false, retweet_count: 46, favorite_count: 275, favorited: false, retweeted: false, possibly_sensitive: false, possibly_sensitive_appealable: false, lang: "en", }, retweet_count: 201, favorite_count: 1664, favorited: false, retweeted: false, possibly_sensitive: false, possibly_sensitive_appealable: false, lang: "en", } 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