2019-06-24 10:56:27 +00:00
|
|
|
defmodule Linkify.ParserTest do
|
2019-02-08 10:56:05 +00:00
|
|
|
use ExUnit.Case, async: true
|
2019-06-24 10:56:27 +00:00
|
|
|
doctest Linkify.Parser
|
2017-03-29 20:27:13 +00:00
|
|
|
|
2019-06-24 10:56:27 +00:00
|
|
|
import Linkify.Parser
|
2017-03-29 20:27:13 +00:00
|
|
|
|
2019-06-18 09:56:17 +00:00
|
|
|
describe "url?/2" do
|
2017-03-29 20:27:13 +00:00
|
|
|
test "valid scheme true" do
|
|
|
|
valid_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
assert url?(url, scheme: true, validate_tld: true)
|
2017-03-29 20:27:13 +00:00
|
|
|
end)
|
|
|
|
end
|
2019-02-05 11:22:51 +00:00
|
|
|
|
2017-03-29 20:27:13 +00:00
|
|
|
test "invalid scheme true" do
|
|
|
|
invalid_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
refute url?(url, scheme: true, validate_tld: true)
|
2017-03-29 20:27:13 +00:00
|
|
|
end)
|
|
|
|
end
|
2019-02-05 11:22:51 +00:00
|
|
|
|
2017-03-29 20:27:13 +00:00
|
|
|
test "valid scheme false" do
|
|
|
|
valid_non_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
assert url?(url, scheme: false, validate_tld: true)
|
2017-03-29 20:27:13 +00:00
|
|
|
end)
|
|
|
|
end
|
2019-02-05 11:22:51 +00:00
|
|
|
|
2017-03-29 20:27:13 +00:00
|
|
|
test "invalid scheme false" do
|
|
|
|
invalid_non_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
refute url?(url, scheme: false, validate_tld: true)
|
2017-03-29 20:27:13 +00:00
|
|
|
end)
|
|
|
|
end
|
2019-06-17 20:06:31 +00:00
|
|
|
|
|
|
|
test "checks the tld for url with a scheme when validate_tld: true" do
|
|
|
|
custom_tld_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
refute url?(url, scheme: true, validate_tld: true)
|
2019-06-17 20:06:31 +00:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "does not check the tld for url with a scheme when validate_tld: false" do
|
|
|
|
custom_tld_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
assert url?(url, scheme: true, validate_tld: false)
|
2019-06-17 20:06:31 +00:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "does not check the tld for url with a scheme when validate_tld: :no_scheme" do
|
|
|
|
custom_tld_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
assert url?(url, scheme: true, validate_tld: :no_scheme)
|
2019-06-17 20:06:31 +00:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "checks the tld for url without a scheme when validate_tld: true" do
|
|
|
|
custom_tld_non_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
refute url?(url, scheme: false, validate_tld: true)
|
2019-06-17 20:06:31 +00:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "checks the tld for url without a scheme when validate_tld: :no_scheme" do
|
|
|
|
custom_tld_non_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
refute url?(url, scheme: false, validate_tld: :no_scheme)
|
2019-06-17 20:06:31 +00:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "does not check the tld for url without a scheme when validate_tld: false" do
|
|
|
|
custom_tld_non_scheme_urls()
|
|
|
|
|> Enum.each(fn url ->
|
2019-06-18 09:56:17 +00:00
|
|
|
assert url?(url, scheme: false, validate_tld: false)
|
2019-06-17 20:06:31 +00:00
|
|
|
end)
|
|
|
|
end
|
2017-03-29 20:27:13 +00:00
|
|
|
end
|
|
|
|
|
2019-06-18 10:25:44 +00:00
|
|
|
describe "email?" do
|
|
|
|
test "identifies valid emails" do
|
|
|
|
valid_emails()
|
|
|
|
|> Enum.each(fn email ->
|
|
|
|
assert email?(email, [])
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "identifies invalid emails" do
|
|
|
|
invalid_emails()
|
|
|
|
|> Enum.each(fn email ->
|
|
|
|
refute email?(email, [])
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "does not validate tlds when validate_tld: false" do
|
|
|
|
valid_custom_tld_emails()
|
|
|
|
|> Enum.each(fn email ->
|
|
|
|
assert email?(email, validate_tld: false)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "validates tlds when validate_tld: true" do
|
|
|
|
valid_custom_tld_emails()
|
|
|
|
|> Enum.each(fn email ->
|
|
|
|
refute email?(email, validate_tld: true)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-03-29 20:27:13 +00:00
|
|
|
describe "parse" do
|
2019-02-20 10:16:51 +00:00
|
|
|
test "handle line breakes" do
|
|
|
|
text = "google.com\r\nssss"
|
2019-06-27 08:32:07 +00:00
|
|
|
expected = "<a href=\"http://google.com\">google.com</a>\r\nssss"
|
2019-02-20 10:16:51 +00:00
|
|
|
|
|
|
|
assert parse(text) == expected
|
|
|
|
end
|
|
|
|
|
2020-08-29 21:30:43 +00:00
|
|
|
test "handle angle bracket in the end" do
|
|
|
|
text = "google.com <br>"
|
|
|
|
assert parse(text) == "<a href=\"http://google.com\">google.com</a> <br>"
|
|
|
|
|
2020-09-02 11:18:02 +00:00
|
|
|
text = "google.com<br>hey"
|
|
|
|
assert parse(text) == "<a href=\"http://google.com\">google.com</a><br>hey"
|
|
|
|
|
|
|
|
text = "hey<br>google.com"
|
|
|
|
assert parse(text) == "hey<br><a href=\"http://google.com\">google.com</a>"
|
|
|
|
|
|
|
|
text = "<br />google.com"
|
|
|
|
assert parse(text) == "<br /><a href=\"http://google.com\">google.com</a>"
|
2020-08-29 21:30:43 +00:00
|
|
|
|
|
|
|
text = "google.com<"
|
|
|
|
assert parse(text) == "<a href=\"http://google.com\">google.com</a><"
|
|
|
|
|
|
|
|
text = "google.com>"
|
|
|
|
assert parse(text) == "<a href=\"http://google.com\">google.com</a>>"
|
|
|
|
end
|
|
|
|
|
2017-03-29 20:27:13 +00:00
|
|
|
test "does not link attributes" do
|
|
|
|
text = "Check out <a href='google.com'>google</a>"
|
|
|
|
assert parse(text) == text
|
|
|
|
text = "Check out <img src='google.com' alt='google.com'/>"
|
|
|
|
assert parse(text) == text
|
|
|
|
text = "Check out <span><img src='google.com' alt='google.com'/></span>"
|
|
|
|
assert parse(text) == text
|
|
|
|
end
|
|
|
|
|
2019-04-09 06:45:55 +00:00
|
|
|
test "does not link inside `<pre>` and `<code>`" do
|
|
|
|
text = "<pre>google.com</pre>"
|
|
|
|
assert parse(text) == text
|
|
|
|
|
|
|
|
text = "<code>google.com</code>"
|
|
|
|
assert parse(text) == text
|
|
|
|
|
|
|
|
text = "<pre><code>google.com</code></pre>"
|
|
|
|
assert parse(text) == text
|
|
|
|
end
|
|
|
|
|
2017-03-29 20:27:13 +00:00
|
|
|
test "links url inside html" do
|
2019-04-09 06:08:13 +00:00
|
|
|
text = "<div>google.com</div>"
|
|
|
|
|
|
|
|
expected = "<div><a href=\"http://google.com\">google.com</a></div>"
|
|
|
|
|
2019-06-27 08:32:07 +00:00
|
|
|
assert parse(text, class: false, rel: false) == expected
|
2019-04-09 06:08:13 +00:00
|
|
|
|
|
|
|
text = "Check out <div class='section'>google.com</div>"
|
|
|
|
|
|
|
|
expected =
|
|
|
|
"Check out <div class='section'><a href=\"http://google.com\">google.com</a></div>"
|
2019-02-18 11:34:38 +00:00
|
|
|
|
2019-06-27 08:32:07 +00:00
|
|
|
assert parse(text, class: false, rel: false) == expected
|
2017-03-29 20:27:13 +00:00
|
|
|
end
|
|
|
|
|
2019-04-09 07:32:30 +00:00
|
|
|
test "links url inside nested html" do
|
|
|
|
text = "<p><strong>google.com</strong></p>"
|
|
|
|
expected = "<p><strong><a href=\"http://google.com\">google.com</a></strong></p>"
|
2019-06-27 08:32:07 +00:00
|
|
|
assert parse(text, class: false, rel: false) == expected
|
2019-04-09 07:32:30 +00:00
|
|
|
end
|
|
|
|
|
2020-08-29 21:29:07 +00:00
|
|
|
test "html links inside html" do
|
|
|
|
text = ~s(<p><a href="http://google.com">google.com</a></p>)
|
|
|
|
assert parse(text) == text
|
|
|
|
|
|
|
|
text = ~s(<span><a href="http://google.com">google.com</a></span>)
|
|
|
|
assert parse(text) == text
|
|
|
|
|
|
|
|
text = ~s(<h1><a href="http://google.com">google.com</a></h1>)
|
|
|
|
assert parse(text) == text
|
|
|
|
|
|
|
|
text = ~s(<li><a href="http://google.com">google.com</a></li>)
|
|
|
|
assert parse(text) == text
|
|
|
|
end
|
|
|
|
|
2019-06-12 08:27:18 +00:00
|
|
|
test "do not link parens" do
|
|
|
|
text = " foo (https://example.com/path/folder/), bar"
|
|
|
|
|
|
|
|
expected =
|
2019-07-11 13:08:30 +00:00
|
|
|
" foo (<a href=\"https://example.com/path/folder/\">https://example.com/path/folder/</a>), bar"
|
2019-06-12 08:27:18 +00:00
|
|
|
|
2019-06-27 08:32:07 +00:00
|
|
|
assert parse(text, class: false, rel: false, scheme: true) == expected
|
2019-06-12 08:27:18 +00:00
|
|
|
|
|
|
|
text = " foo (example.com/path/folder/), bar"
|
|
|
|
|
|
|
|
expected =
|
|
|
|
" foo (<a href=\"http://example.com/path/folder/\">example.com/path/folder/</a>), bar"
|
|
|
|
|
2019-06-27 08:32:07 +00:00
|
|
|
assert parse(text, class: false, rel: false) == expected
|
2019-06-12 08:27:18 +00:00
|
|
|
end
|
|
|
|
|
2020-08-29 21:30:43 +00:00
|
|
|
test "do not link punctuation marks in the end" do
|
|
|
|
text = "google.com."
|
|
|
|
assert parse(text) == "<a href=\"http://google.com\">google.com</a>."
|
|
|
|
|
|
|
|
text = "google.com;"
|
|
|
|
assert parse(text) == "<a href=\"http://google.com\">google.com</a>;"
|
|
|
|
|
|
|
|
text = "google.com:"
|
|
|
|
assert parse(text) == "<a href=\"http://google.com\">google.com</a>:"
|
|
|
|
|
|
|
|
text = "hack google.com, please"
|
|
|
|
assert parse(text) == "hack <a href=\"http://google.com\">google.com</a>, please"
|
|
|
|
|
|
|
|
text = "(check out google.com)"
|
|
|
|
assert parse(text) == "(check out <a href=\"http://google.com\">google.com</a>)"
|
|
|
|
end
|
|
|
|
|
2019-04-09 08:03:39 +00:00
|
|
|
test "do not link urls" do
|
|
|
|
text = "google.com"
|
2019-06-21 12:05:47 +00:00
|
|
|
assert parse(text, url: false) == text
|
2019-04-09 08:03:39 +00:00
|
|
|
end
|
2019-05-01 07:48:04 +00:00
|
|
|
|
|
|
|
test "do not link `:test.test`" do
|
|
|
|
text = ":test.test"
|
|
|
|
|
|
|
|
assert parse(text, %{
|
|
|
|
scheme: true,
|
|
|
|
extra: true,
|
|
|
|
class: false,
|
|
|
|
strip_prefix: false,
|
|
|
|
new_window: false,
|
|
|
|
rel: false
|
|
|
|
}) == text
|
|
|
|
end
|
2017-03-29 20:27:13 +00:00
|
|
|
end
|
|
|
|
|
2018-01-20 00:22:07 +00:00
|
|
|
def valid_number?([list], number) do
|
|
|
|
assert List.last(list) == number
|
|
|
|
end
|
|
|
|
|
|
|
|
def valid_number?(_, _), do: false
|
|
|
|
|
2019-02-05 11:22:51 +00:00
|
|
|
def valid_scheme_urls,
|
|
|
|
do: [
|
|
|
|
"https://www.example.com",
|
|
|
|
"http://www2.example.com",
|
|
|
|
"http://home.example-site.com",
|
|
|
|
"http://blog.example.com",
|
|
|
|
"http://www.example.com/product",
|
|
|
|
"http://www.example.com/products?id=1&page=2",
|
|
|
|
"http://www.example.com#up",
|
|
|
|
"http://255.255.255.255",
|
|
|
|
"http://www.site.com:8008"
|
|
|
|
]
|
|
|
|
|
|
|
|
def invalid_scheme_urls,
|
|
|
|
do: [
|
|
|
|
"http://invalid.com/perl.cgi?key= | http://web-site.com/cgi-bin/perl.cgi?key1=value1&key2"
|
|
|
|
]
|
|
|
|
|
|
|
|
def valid_non_scheme_urls,
|
|
|
|
do: [
|
|
|
|
"www.example.com",
|
|
|
|
"www2.example.com",
|
|
|
|
"www.example.com:2000",
|
|
|
|
"www.example.com?abc=1",
|
|
|
|
"example.example-site.com",
|
|
|
|
"example.com",
|
|
|
|
"example.ca",
|
|
|
|
"example.tv",
|
|
|
|
"example.com:999?one=one",
|
|
|
|
"255.255.255.255",
|
|
|
|
"255.255.255.255:3000?one=1&two=2"
|
|
|
|
]
|
|
|
|
|
|
|
|
def invalid_non_scheme_urls,
|
|
|
|
do: [
|
|
|
|
"invalid.com/perl.cgi?key= | web-site.com/cgi-bin/perl.cgi?key1=value1&key2",
|
|
|
|
"invalid.",
|
|
|
|
"hi..there",
|
|
|
|
"555.555.5555"
|
|
|
|
]
|
|
|
|
|
2019-06-17 20:06:31 +00:00
|
|
|
def custom_tld_scheme_urls,
|
|
|
|
do: [
|
|
|
|
"http://whatever.null/",
|
|
|
|
"https://example.o/index.html",
|
|
|
|
"http://pleroma.i2p/test",
|
|
|
|
"http://misskey.loki"
|
|
|
|
]
|
|
|
|
|
|
|
|
def custom_tld_non_scheme_urls,
|
|
|
|
do: [
|
|
|
|
"whatever.null/",
|
|
|
|
"example.o/index.html",
|
|
|
|
"pleroma.i2p/test",
|
|
|
|
"misskey.loki"
|
|
|
|
]
|
2019-06-18 10:25:44 +00:00
|
|
|
|
|
|
|
def valid_emails, do: ["rms@ai.mit.edu", "vc@cock.li"]
|
|
|
|
def invalid_emails, do: ["rms[at]ai.mit.edu", "vc@cock", "xmpp:lain@trashserver.net"]
|
|
|
|
def valid_custom_tld_emails, do: ["guardian@33y6fjyhs3phzfjj.onion", "hi@company.null"]
|
2017-03-29 20:27:13 +00:00
|
|
|
end
|