2015-10-11 17:41:23 +08:00
|
|
|
require 'rails_helper'
|
2013-02-06 03:16:51 +08:00
|
|
|
|
|
|
|
describe TopicLink do
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
it { is_expected.to validate_presence_of :url }
|
2013-02-06 03:16:51 +08:00
|
|
|
|
|
|
|
def test_uri
|
|
|
|
URI.parse(Discourse.base_url)
|
|
|
|
end
|
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
let(:topic) do
|
|
|
|
Fabricate(:topic, title: 'unique topic name')
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:user) do
|
|
|
|
topic.user
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "can't link to the same topic" do
|
2014-07-11 12:17:01 +08:00
|
|
|
ftl = TopicLink.new(url: "/t/#{topic.id}",
|
|
|
|
topic_id: topic.id,
|
|
|
|
link_topic_id: topic.id)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(ftl.valid?).to eq(false)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
describe 'external links' do
|
|
|
|
before do
|
2014-07-11 12:17:01 +08:00
|
|
|
post = Fabricate(:post, raw: "
|
2014-06-26 09:38:23 +08:00
|
|
|
http://a.com/
|
|
|
|
http://b.com/b
|
|
|
|
http://#{'a'*200}.com/invalid
|
|
|
|
http://b.com/#{'a'*500}
|
2014-07-11 12:17:01 +08:00
|
|
|
", user: user, topic: topic)
|
2014-06-26 09:38:23 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
TopicLink.extract_from(post)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2013-06-05 10:48:34 +08:00
|
|
|
it 'works' do
|
|
|
|
# has the forum topic links
|
2015-09-26 02:07:04 +08:00
|
|
|
expect(topic.topic_links.count).to eq(3)
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-06-05 10:48:34 +08:00
|
|
|
# works with markdown links
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic.topic_links.exists?(url: "http://a.com/")).to eq(true)
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-06-05 10:48:34 +08:00
|
|
|
#works with markdown links followed by a period
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic.topic_links.exists?(url: "http://b.com/b")).to eq(true)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2013-02-12 00:11:48 +08:00
|
|
|
describe 'internal links' do
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
it "extracts onebox" do
|
|
|
|
other_topic = Fabricate(:topic, user: user)
|
|
|
|
other_topic.posts.create(user: user, raw: "some content for the first post")
|
|
|
|
other_post = other_topic.posts.create(user: user, raw: "some content for the second post")
|
2013-02-14 04:22:04 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
url = "http://#{test_uri.host}/t/#{other_topic.slug}/#{other_topic.id}/#{other_post.post_number}"
|
|
|
|
invalid_url = "http://#{test_uri.host}/t/#{other_topic.slug}/9999999999999999999999999999999"
|
2013-08-09 06:14:12 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
topic.posts.create(user: user, raw: 'initial post')
|
|
|
|
post = topic.posts.create(user: user, raw: "Link to another topic:\n\n#{url}\n\n#{invalid_url}")
|
|
|
|
post.reload
|
2013-02-14 04:22:04 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
TopicLink.extract_from(post)
|
2013-02-14 04:22:04 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
link = topic.topic_links.first
|
|
|
|
# should have a link
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).to be_present
|
2014-07-11 12:17:01 +08:00
|
|
|
# should be the canonical URL
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link.url).to eq(url)
|
2013-02-14 04:22:04 +08:00
|
|
|
end
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
context 'topic link' do
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
let(:other_topic) do
|
|
|
|
Fabricate(:topic, user: user)
|
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
let(:post) do
|
|
|
|
other_topic.posts.create(user: user, raw: "some content")
|
2013-02-12 00:11:48 +08:00
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-06-05 10:48:34 +08:00
|
|
|
it 'works' do
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
# ensure other_topic has a post
|
|
|
|
post
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
url = "http://#{test_uri.host}/t/#{other_topic.slug}/#{other_topic.id}"
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
topic.posts.create(user: user, raw: 'initial post')
|
|
|
|
linked_post = topic.posts.create(user: user, raw: "Link to another topic: #{url}")
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
TopicLink.extract_from(linked_post)
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
link = topic.topic_links.first
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).to be_present
|
|
|
|
expect(link).to be_internal
|
|
|
|
expect(link.url).to eq(url)
|
|
|
|
expect(link.domain).to eq(test_uri.host)
|
2014-07-11 12:17:01 +08:00
|
|
|
link.link_topic_id == other_topic.id
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).not_to be_reflection
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
reflection = other_topic.topic_links.first
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(reflection).to be_present
|
|
|
|
expect(reflection).to be_reflection
|
|
|
|
expect(reflection.post_id).to be_present
|
|
|
|
expect(reflection.domain).to eq(test_uri.host)
|
|
|
|
expect(reflection.url).to eq("http://#{test_uri.host}/t/unique-topic-name/#{topic.id}/#{linked_post.post_number}")
|
|
|
|
expect(reflection.link_topic_id).to eq(topic.id)
|
|
|
|
expect(reflection.link_post_id).to eq(linked_post.id)
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(reflection.user_id).to eq(link.user_id)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2013-02-12 00:11:48 +08:00
|
|
|
context 'removing a link' do
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-02-12 00:11:48 +08:00
|
|
|
before do
|
2014-10-28 05:06:43 +08:00
|
|
|
post.revise(post.user, { raw: "no more linkies" })
|
2014-07-11 12:17:01 +08:00
|
|
|
TopicLink.extract_from(post)
|
2013-02-12 00:11:48 +08:00
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-02-12 00:11:48 +08:00
|
|
|
it 'should remove the link' do
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic.topic_links.where(post_id: post.id)).to be_blank
|
2013-06-05 10:48:34 +08:00
|
|
|
# should remove the reflected link
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(other_topic.topic_links).to be_blank
|
2013-02-12 00:11:48 +08:00
|
|
|
end
|
2013-02-26 00:42:20 +08:00
|
|
|
end
|
2013-02-12 00:11:48 +08:00
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-02-12 01:27:32 +08:00
|
|
|
context "link to a user on discourse" do
|
2014-07-11 12:17:01 +08:00
|
|
|
let(:post) { topic.posts.create(user: user, raw: "<a href='/users/#{user.username_lower}'>user</a>") }
|
2013-02-06 03:16:51 +08:00
|
|
|
before do
|
2013-02-12 00:11:48 +08:00
|
|
|
TopicLink.extract_from(post)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2013-02-26 00:42:20 +08:00
|
|
|
it 'does not extract a link' do
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic.topic_links).to be_blank
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
2013-02-12 00:11:48 +08:00
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-02-12 01:27:32 +08:00
|
|
|
context "link to a discourse resource like a FAQ" do
|
2014-07-11 12:17:01 +08:00
|
|
|
let(:post) { topic.posts.create(user: user, raw: "<a href='/faq'>faq link here</a>") }
|
2013-02-12 01:27:32 +08:00
|
|
|
before do
|
|
|
|
TopicLink.extract_from(post)
|
|
|
|
end
|
|
|
|
|
2013-02-26 00:42:20 +08:00
|
|
|
it 'does not extract a link' do
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic.topic_links).to be_present
|
2013-02-12 01:27:32 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
context "mention links" do
|
|
|
|
let(:post) { topic.posts.create(user: user, raw: "Hey #{user.username_lower}") }
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-02-12 00:11:48 +08:00
|
|
|
before do
|
|
|
|
TopicLink.extract_from(post)
|
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-02-26 00:42:20 +08:00
|
|
|
it 'does not extract a link' do
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic.topic_links).to be_blank
|
2014-07-11 12:17:01 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "quote links" do
|
|
|
|
it "sets quote correctly" do
|
|
|
|
linked_post = topic.posts.create(user: user, raw: "my test post")
|
|
|
|
quoting_post = Fabricate(:post, raw: "[quote=\"#{user.username}, post: #{linked_post.post_number}, topic: #{topic.id}\"]\nquote\n[/quote]")
|
|
|
|
|
|
|
|
TopicLink.extract_from(quoting_post)
|
|
|
|
link = quoting_post.topic.topic_links.first
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link.link_post_id).to eq(linked_post.id)
|
|
|
|
expect(link.quote).to eq(true)
|
2013-02-12 00:11:48 +08:00
|
|
|
end
|
2013-02-26 00:42:20 +08:00
|
|
|
end
|
|
|
|
|
2013-07-19 07:26:23 +08:00
|
|
|
context "link to a local attachments" do
|
2014-07-11 12:17:01 +08:00
|
|
|
let(:post) { topic.posts.create(user: user, raw: '<a class="attachment" href="/uploads/default/208/87bb3d8428eb4783.rb">ruby.rb</a>') }
|
2013-07-19 07:26:23 +08:00
|
|
|
|
|
|
|
it "extracts the link" do
|
|
|
|
TopicLink.extract_from(post)
|
2014-07-11 12:17:01 +08:00
|
|
|
link = topic.topic_links.first
|
2013-07-19 07:26:23 +08:00
|
|
|
# extracted the link
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).to be_present
|
2013-07-19 07:26:23 +08:00
|
|
|
# is set to internal
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).to be_internal
|
2013-07-19 07:26:23 +08:00
|
|
|
# has the correct url
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link.url).to eq("/uploads/default/208/87bb3d8428eb4783.rb")
|
2013-07-19 07:26:23 +08:00
|
|
|
# should not be the reflection
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).not_to be_reflection
|
2013-07-19 07:26:23 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
context "link to an attachments uploaded on S3" do
|
2014-07-11 12:17:01 +08:00
|
|
|
let(:post) { topic.posts.create(user: user, raw: '<a class="attachment" href="//s3.amazonaws.com/bucket/2104a0211c9ce41ed67989a1ed62e9a394c1fbd1446.rb">ruby.rb</a>') }
|
2013-07-19 07:26:23 +08:00
|
|
|
|
|
|
|
it "extracts the link" do
|
|
|
|
TopicLink.extract_from(post)
|
2014-07-11 12:17:01 +08:00
|
|
|
link = topic.topic_links.first
|
2013-07-19 07:26:23 +08:00
|
|
|
# extracted the link
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).to be_present
|
2013-07-19 07:26:23 +08:00
|
|
|
# is not internal
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).not_to be_internal
|
2013-07-19 07:26:23 +08:00
|
|
|
# has the correct url
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link.url).to eq("//s3.amazonaws.com/bucket/2104a0211c9ce41ed67989a1ed62e9a394c1fbd1446.rb")
|
2013-07-19 07:26:23 +08:00
|
|
|
# should not be the reflection
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(link).not_to be_reflection
|
2013-07-19 07:26:23 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2013-02-26 00:42:20 +08:00
|
|
|
describe 'internal link from pm' do
|
2014-07-11 12:17:01 +08:00
|
|
|
it 'works' do
|
2014-09-11 15:39:20 +08:00
|
|
|
pm = Fabricate(:topic, user: user, category_id: nil, archetype: 'private_message')
|
2014-07-11 12:17:01 +08:00
|
|
|
pm.posts.create(user: user, raw: "some content")
|
2013-02-26 00:42:20 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
url = "http://#{test_uri.host}/t/topic-slug/#{topic.id}"
|
2013-02-26 00:42:20 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
pm.posts.create(user: user, raw: 'initial post')
|
|
|
|
linked_post = pm.posts.create(user: user, raw: "Link to another topic: #{url}")
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-07-11 12:17:01 +08:00
|
|
|
TopicLink.extract_from(linked_post)
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic.topic_links.first).to eq(nil)
|
|
|
|
expect(pm.topic_links.first).not_to eq(nil)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'internal link with non-standard port' do
|
|
|
|
it 'includes the non standard port if present' do
|
2014-07-11 12:17:01 +08:00
|
|
|
other_topic = Fabricate(:topic, user: user)
|
|
|
|
SiteSetting.port = 5678
|
2013-02-06 03:16:51 +08:00
|
|
|
alternate_uri = URI.parse(Discourse.base_url)
|
2014-07-11 12:17:01 +08:00
|
|
|
|
|
|
|
url = "http://#{alternate_uri.host}:5678/t/topic-slug/#{other_topic.id}"
|
|
|
|
post = topic.posts.create(user: user,
|
|
|
|
raw: "Link to another topic: #{url}")
|
|
|
|
TopicLink.extract_from(post)
|
|
|
|
reflection = other_topic.topic_links.first
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(reflection.url).to eq("http://#{alternate_uri.host}:5678/t/unique-topic-name/#{topic.id}")
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-11-16 01:15:46 +08:00
|
|
|
describe 'counts_for and topic_map' do
|
2013-06-05 14:10:26 +08:00
|
|
|
it 'returns blank without posts' do
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(TopicLink.counts_for(Guardian.new, nil, nil)).to be_blank
|
2013-06-05 14:10:26 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with data' do
|
|
|
|
|
|
|
|
let(:post) do
|
|
|
|
topic = Fabricate(:topic)
|
|
|
|
Fabricate(:post_with_external_links, user: topic.user, topic: topic)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:counts_for) do
|
|
|
|
TopicLink.counts_for(Guardian.new, post.topic, [post])
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
it 'has the correct results' do
|
|
|
|
TopicLink.extract_from(post)
|
|
|
|
topic_link = post.topic.topic_links.first
|
2013-06-25 06:30:32 +08:00
|
|
|
TopicLinkClick.create(topic_link: topic_link, ip_address: '192.168.1.1')
|
2013-06-05 14:10:26 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(counts_for[post.id]).to be_present
|
|
|
|
expect(counts_for[post.id].find {|l| l[:url] == 'http://google.com'}[:clicks]).to eq(0)
|
|
|
|
expect(counts_for[post.id].first[:clicks]).to eq(1)
|
2013-06-05 14:10:26 +08:00
|
|
|
|
2013-11-16 01:15:46 +08:00
|
|
|
array = TopicLink.topic_map(Guardian.new, post.topic_id)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(array.length).to eq(4)
|
|
|
|
expect(array[0]["clicks"]).to eq("1")
|
2013-06-05 14:10:26 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'secures internal links correctly' do
|
|
|
|
category = Fabricate(:category)
|
|
|
|
secret_topic = Fabricate(:topic, category: category)
|
|
|
|
|
|
|
|
url = "http://#{test_uri.host}/t/topic-slug/#{secret_topic.id}"
|
|
|
|
post = Fabricate(:post, raw: "hello test topic #{url}")
|
|
|
|
TopicLink.extract_from(post)
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(TopicLink.topic_map(Guardian.new, post.topic_id).count).to eq(1)
|
|
|
|
expect(TopicLink.counts_for(Guardian.new, post.topic, [post]).length).to eq(1)
|
2013-06-05 14:10:26 +08:00
|
|
|
|
2013-07-14 09:24:16 +08:00
|
|
|
category.set_permissions(:staff => :full)
|
2013-06-05 14:10:26 +08:00
|
|
|
category.save
|
|
|
|
|
|
|
|
admin = Fabricate(:admin)
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(TopicLink.topic_map(Guardian.new, post.topic_id).count).to eq(0)
|
|
|
|
expect(TopicLink.topic_map(Guardian.new(admin), post.topic_id).count).to eq(1)
|
2013-06-05 14:10:26 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(TopicLink.counts_for(Guardian.new, post.topic, [post]).length).to eq(0)
|
|
|
|
expect(TopicLink.counts_for(Guardian.new(admin), post.topic, [post]).length).to eq(1)
|
2013-06-05 14:10:26 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|