2015-10-11 04:41:23 -05:00
|
|
|
require 'rails_helper'
|
2015-09-24 17:20:59 -05:00
|
|
|
require 'stringio'
|
2013-12-31 13:37:43 -06:00
|
|
|
|
|
|
|
describe TopicEmbed do
|
|
|
|
|
2014-12-31 08:55:03 -06:00
|
|
|
it { is_expected.to belong_to :topic }
|
|
|
|
it { is_expected.to belong_to :post }
|
|
|
|
it { is_expected.to validate_presence_of :embed_url }
|
2013-12-31 13:37:43 -06:00
|
|
|
|
|
|
|
context '.import' do
|
|
|
|
|
|
|
|
let(:user) { Fabricate(:user) }
|
|
|
|
let(:title) { "How to turn a fish from good to evil in 30 seconds" }
|
|
|
|
let(:url) { 'http://eviltrout.com/123' }
|
|
|
|
let(:contents) { "hello world new post <a href='/hello'>hello</a> <img src='/images/wat.jpg'>" }
|
2015-08-18 16:15:46 -05:00
|
|
|
let!(:embeddable_host) { Fabricate(:embeddable_host) }
|
2013-12-31 13:37:43 -06:00
|
|
|
|
|
|
|
it "returns nil when the URL is malformed" do
|
2014-12-31 08:55:03 -06:00
|
|
|
expect(TopicEmbed.import(user, "invalid url", title, contents)).to eq(nil)
|
|
|
|
expect(TopicEmbed.count).to eq(0)
|
2013-12-31 13:37:43 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'creation of a post' do
|
|
|
|
let!(:post) { TopicEmbed.import(user, url, title, contents) }
|
|
|
|
|
|
|
|
it "works as expected with a new URL" do
|
2014-12-31 08:55:03 -06:00
|
|
|
expect(post).to be_present
|
2013-12-31 13:37:43 -06:00
|
|
|
|
|
|
|
# It uses raw_html rendering
|
2014-12-31 08:55:03 -06:00
|
|
|
expect(post.cook_method).to eq(Post.cook_methods[:raw_html])
|
|
|
|
expect(post.cooked).to eq(post.raw)
|
2013-12-31 13:37:43 -06:00
|
|
|
|
|
|
|
# It converts relative URLs to absolute
|
2015-09-24 17:20:59 -05:00
|
|
|
expect(post.cooked).to have_tag('a', with: { href: 'http://eviltrout.com/hello' })
|
|
|
|
expect(post.cooked).to have_tag('img', with: { src: 'http://eviltrout.com/images/wat.jpg' })
|
2013-12-31 13:37:43 -06:00
|
|
|
|
2014-12-31 08:55:03 -06:00
|
|
|
expect(post.topic.has_topic_embed?).to eq(true)
|
|
|
|
expect(TopicEmbed.where(topic_id: post.topic_id)).to be_present
|
2015-08-18 16:15:46 -05:00
|
|
|
|
|
|
|
expect(post.topic.category).to eq(embeddable_host.category)
|
2013-12-31 13:37:43 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
it "Supports updating the post" do
|
2018-04-18 14:22:43 -05:00
|
|
|
new_user = Fabricate(:user)
|
|
|
|
|
2018-05-02 02:16:00 -05:00
|
|
|
post = TopicEmbed.import(new_user, url, "I am a new title", "muhahaha new contents!")
|
2018-04-18 14:22:43 -05:00
|
|
|
|
2014-12-31 08:55:03 -06:00
|
|
|
expect(post.cooked).to match(/new contents/)
|
2018-05-02 02:16:00 -05:00
|
|
|
expect(post.topic.title).to eq("I am a new title")
|
2018-04-18 14:22:43 -05:00
|
|
|
expect(post.user).to eq(new_user)
|
2013-12-31 13:37:43 -06:00
|
|
|
end
|
|
|
|
|
2014-03-26 22:24:57 -05:00
|
|
|
it "Should leave uppercase Feed Entry URL untouched in content" do
|
|
|
|
cased_url = 'http://eviltrout.com/ABCD'
|
|
|
|
post = TopicEmbed.import(user, cased_url, title, "some random content")
|
2014-12-31 08:55:03 -06:00
|
|
|
expect(post.cooked).to match(/#{cased_url}/)
|
2014-03-26 22:24:57 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "Should leave lowercase Feed Entry URL untouched in content" do
|
|
|
|
cased_url = 'http://eviltrout.com/abcd'
|
|
|
|
post = TopicEmbed.import(user, cased_url, title, "some random content")
|
2014-12-31 08:55:03 -06:00
|
|
|
expect(post.cooked).to match(/#{cased_url}/)
|
2014-03-26 22:24:57 -05:00
|
|
|
end
|
2013-12-31 13:37:43 -06:00
|
|
|
end
|
|
|
|
|
2018-03-10 20:26:47 -06:00
|
|
|
context "post creation supports markdown rendering" do
|
|
|
|
before do
|
|
|
|
SiteSetting.embed_support_markdown = true
|
|
|
|
end
|
|
|
|
|
|
|
|
it "works as expected" do
|
|
|
|
post = TopicEmbed.import(user, url, title, "some random content")
|
|
|
|
expect(post).to be_present
|
|
|
|
|
|
|
|
# It uses regular rendering
|
|
|
|
expect(post.cook_method).to eq(Post.cook_methods[:regular])
|
|
|
|
end
|
|
|
|
end
|
2013-12-31 13:37:43 -06:00
|
|
|
end
|
|
|
|
|
2018-01-04 12:13:17 -06:00
|
|
|
context '.topic_id_for_embed' do
|
|
|
|
it "returns correct topic id irrespective of url protocol" do
|
|
|
|
topic_embed = Fabricate(:topic_embed, embed_url: "http://example.com/post/248")
|
|
|
|
|
|
|
|
expect(TopicEmbed.topic_id_for_embed('http://exAMPle.com/post/248')).to eq(topic_embed.topic_id)
|
|
|
|
expect(TopicEmbed.topic_id_for_embed('https://example.com/post/248/')).to eq(topic_embed.topic_id)
|
|
|
|
|
|
|
|
expect(TopicEmbed.topic_id_for_embed('http://example.com/post/248/2')).to eq(nil)
|
|
|
|
expect(TopicEmbed.topic_id_for_embed('http://examples.com/post/248')).to eq(nil)
|
|
|
|
expect(TopicEmbed.topic_id_for_embed('http://example.com/post/24')).to eq(nil)
|
|
|
|
expect(TopicEmbed.topic_id_for_embed('http://example.com/post')).to eq(nil)
|
|
|
|
end
|
2018-02-13 17:28:16 -06:00
|
|
|
|
|
|
|
it "finds the topic id when the embed_url contains a query string" do
|
|
|
|
topic_embed = Fabricate(:topic_embed, embed_url: "http://example.com/post/248?key=foo")
|
|
|
|
expect(TopicEmbed.topic_id_for_embed('http://example.com/post/248?key=foo')).to eq(topic_embed.topic_id)
|
|
|
|
end
|
2018-01-04 12:13:17 -06:00
|
|
|
end
|
|
|
|
|
2015-09-24 17:20:59 -05:00
|
|
|
describe '.find_remote' do
|
|
|
|
|
2016-08-22 11:43:02 -05:00
|
|
|
context ".title_scrub" do
|
|
|
|
|
|
|
|
let(:url) { 'http://eviltrout.com/123' }
|
|
|
|
let(:contents) { "<title>Through the Looking Glass - Classic Books</title><body>some content here</body>" }
|
|
|
|
let!(:embeddable_host) { Fabricate(:embeddable_host) }
|
|
|
|
let!(:file) { StringIO.new }
|
|
|
|
|
|
|
|
before do
|
|
|
|
file.stubs(:read).returns contents
|
|
|
|
TopicEmbed.stubs(:open).returns file
|
|
|
|
end
|
|
|
|
|
|
|
|
it "doesn't scrub the title by default" do
|
2016-08-30 11:01:04 -05:00
|
|
|
response = TopicEmbed.find_remote(url)
|
|
|
|
expect(response.title).to eq("Through the Looking Glass - Classic Books")
|
2016-08-22 11:43:02 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "scrubs the title when the option is enabled" do
|
|
|
|
SiteSetting.embed_title_scrubber = " - Classic Books$"
|
2016-08-30 11:01:04 -05:00
|
|
|
response = TopicEmbed.find_remote(url)
|
|
|
|
expect(response.title).to eq("Through the Looking Glass")
|
2016-08-22 11:43:02 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2015-09-24 17:20:59 -05:00
|
|
|
context 'post with allowed classes "foo" and "emoji"' do
|
|
|
|
let(:user) { Fabricate(:user) }
|
|
|
|
let(:url) { 'http://eviltrout.com/123' }
|
|
|
|
let(:contents) { "my normal size emoji <p class='foo'>Hi</p> <img class='emoji other foo' src='/images/smiley.jpg'>" }
|
|
|
|
let!(:embeddable_host) { Fabricate(:embeddable_host) }
|
|
|
|
let!(:file) { StringIO.new }
|
|
|
|
|
2016-08-30 11:01:04 -05:00
|
|
|
response = nil
|
2015-09-24 17:20:59 -05:00
|
|
|
|
2017-07-07 01:09:14 -05:00
|
|
|
before do
|
|
|
|
SiteSetting.embed_classname_whitelist = 'emoji, foo'
|
2015-09-24 17:20:59 -05:00
|
|
|
file.stubs(:read).returns contents
|
|
|
|
TopicEmbed.stubs(:open).returns file
|
2016-08-30 11:01:04 -05:00
|
|
|
response = TopicEmbed.find_remote(url)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "has no author tag" do
|
|
|
|
expect(response.author).to be_blank
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'img node has emoji class' do
|
2016-08-30 11:01:04 -05:00
|
|
|
expect(response.body).to have_tag('img', with: { class: 'emoji' })
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'img node has foo class' do
|
2016-08-30 11:01:04 -05:00
|
|
|
expect(response.body).to have_tag('img', with: { class: 'foo' })
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'p node has foo class' do
|
2016-08-30 11:01:04 -05:00
|
|
|
expect(response.body).to have_tag('p', with: { class: 'foo' })
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'nodes removes classes other than emoji' do
|
2016-08-30 11:01:04 -05:00
|
|
|
expect(response.body).to have_tag('img', without: { class: 'other' })
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'post with author metadata' do
|
|
|
|
let!(:user) { Fabricate(:user, username: 'eviltrout') }
|
|
|
|
let(:url) { 'http://eviltrout.com/321' }
|
|
|
|
let(:contents) { '<html><head><meta name="author" content="eviltrout"></head><body>rich and morty</body></html>' }
|
|
|
|
let!(:embeddable_host) { Fabricate(:embeddable_host) }
|
|
|
|
let!(:file) { StringIO.new }
|
|
|
|
|
|
|
|
response = nil
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
file.stubs(:read).returns contents
|
|
|
|
TopicEmbed.stubs(:open).returns file
|
|
|
|
response = TopicEmbed.find_remote(url)
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
2016-08-30 11:01:04 -05:00
|
|
|
it "has no author tag" do
|
|
|
|
expect(response.author).to eq(user)
|
|
|
|
end
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'post with no allowed classes' do
|
|
|
|
|
|
|
|
let(:user) { Fabricate(:user) }
|
|
|
|
let(:url) { 'http://eviltrout.com/123' }
|
|
|
|
let(:contents) { "my normal size emoji <p class='foo'>Hi</p> <img class='emoji other foo' src='/images/smiley.jpg'>" }
|
|
|
|
let!(:embeddable_host) { Fabricate(:embeddable_host) }
|
|
|
|
let!(:file) { StringIO.new }
|
|
|
|
|
2016-08-30 11:01:04 -05:00
|
|
|
response = nil
|
2015-09-24 17:20:59 -05:00
|
|
|
|
|
|
|
before(:each) do
|
2017-07-07 01:09:14 -05:00
|
|
|
SiteSetting.embed_classname_whitelist = ''
|
2015-09-24 17:20:59 -05:00
|
|
|
file.stubs(:read).returns contents
|
|
|
|
TopicEmbed.stubs(:open).returns file
|
2016-08-30 11:01:04 -05:00
|
|
|
response = TopicEmbed.find_remote(url)
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'img node doesn\'t have emoji class' do
|
2016-08-30 11:01:04 -05:00
|
|
|
expect(response.body).to have_tag('img', without: { class: 'emoji' })
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'img node doesn\'t have foo class' do
|
2016-08-30 11:01:04 -05:00
|
|
|
expect(response.body).to have_tag('img', without: { class: 'foo' })
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'p node doesn\'t foo class' do
|
2016-08-30 11:01:04 -05:00
|
|
|
expect(response.body).to have_tag('p', without: { class: 'foo' })
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'img node doesn\'t have other class' do
|
2016-08-30 11:01:04 -05:00
|
|
|
expect(response.body).to have_tag('img', without: { class: 'other' })
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
2017-03-07 10:21:26 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
context "non-ascii URL" do
|
|
|
|
let(:url) { 'http://eviltrout.com/test/ماهی' }
|
|
|
|
let(:contents) { "<title>سلام</title><body>این یک پاراگراف آزمون است.</body>" }
|
|
|
|
let!(:embeddable_host) { Fabricate(:embeddable_host) }
|
|
|
|
let!(:file) { StringIO.new }
|
2015-09-24 17:20:59 -05:00
|
|
|
|
2017-03-07 10:21:26 -06:00
|
|
|
before do
|
|
|
|
file.stubs(:read).returns contents
|
2017-09-22 10:36:44 -05:00
|
|
|
TopicEmbed.stubs(:open)
|
|
|
|
.with('http://eviltrout.com/test/%D9%85%D8%A7%D9%87%DB%8C', allow_redirections: :safe).returns file
|
2017-03-07 10:21:26 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
it "doesn't throw an error" do
|
|
|
|
response = TopicEmbed.find_remote(url)
|
|
|
|
expect(response.title).to eq("سلام")
|
|
|
|
end
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
2017-09-22 10:36:44 -05:00
|
|
|
context "encoded URL" do
|
|
|
|
let(:url) { 'http://example.com/hello%20world' }
|
|
|
|
let(:contents) { "<title>Hello World!</title><body></body>" }
|
|
|
|
let!(:embeddable_host) { Fabricate(:embeddable_host) }
|
|
|
|
let!(:file) { StringIO.new }
|
|
|
|
|
|
|
|
before do
|
|
|
|
file.stubs(:read).returns contents
|
|
|
|
TopicEmbed.stubs(:open)
|
|
|
|
.with('http://example.com/hello%20world', allow_redirections: :safe).returns file
|
|
|
|
end
|
|
|
|
|
|
|
|
it "doesn't throw an error" do
|
|
|
|
response = TopicEmbed.find_remote(url)
|
|
|
|
expect(response.title).to eq("Hello World!")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-22 07:26:06 -05:00
|
|
|
context "emails" do
|
|
|
|
let(:url) { 'http://example.com/foo' }
|
|
|
|
let(:contents) { '<p><a href="mailto:foo%40example.com">URL encoded @ symbol</a></p><p><a href="mailto:bar@example.com">normal mailto link</a></p>' }
|
|
|
|
let!(:embeddable_host) { Fabricate(:embeddable_host) }
|
|
|
|
let!(:file) { StringIO.new }
|
|
|
|
|
|
|
|
before do
|
|
|
|
file.stubs(:read).returns contents
|
|
|
|
TopicEmbed.stubs(:open).returns file
|
|
|
|
end
|
|
|
|
|
|
|
|
it "handles mailto links" do
|
|
|
|
response = TopicEmbed.find_remote(url)
|
|
|
|
expect(response.body).to have_tag('a', with: { href: 'mailto:foo%40example.com' })
|
|
|
|
expect(response.body).to have_tag('a', with: { href: 'mailto:bar@example.com' })
|
|
|
|
end
|
|
|
|
end
|
2015-09-24 17:20:59 -05:00
|
|
|
end
|
|
|
|
|
2013-12-31 13:37:43 -06:00
|
|
|
end
|