Skip to content

Commit 9bf4187

Browse files
committed
test(converter): pin renderLinkIsUrl behavior
Add a table-driven test covering the markdown link destination check before replacing the govalidator dependency with stdlib logic. Signed-off-by: ferhat elmas <elmas.ferhat@gmail.com>
1 parent 98329f3 commit 9bf4187

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

pkg/converter/markdown_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package converter
19+
20+
import (
21+
"testing"
22+
23+
"github.com/stretchr/testify/assert"
24+
)
25+
26+
func TestRenderLinkIsUrl(t *testing.T) {
27+
cases := []struct {
28+
name string
29+
in string
30+
want bool
31+
}{
32+
{"absolute http URL", "http://example.com/path?q=1#f", true},
33+
{"absolute https URL", "https://example.com", true},
34+
{"ftp URL", "ftp://example.com/file", true},
35+
{"uppercase scheme and host", "HTTP://EXAMPLE.COM", false},
36+
{"bare domain", "example.com", true},
37+
{"bare domain with path", "example.com/questions/123", true},
38+
{"www subdomain", "www.example.com", true},
39+
{"bare IP", "10.0.0.1", true},
40+
{"IP with port and path", "10.0.0.1:8080/a", true},
41+
{"host with port", "localhost:8080", true},
42+
{"domain with port and path", "example.com:8080/x", true},
43+
{"IPv6 with port", "[::1]:8080", true},
44+
{"userinfo", "user:pass@example.com", true},
45+
{"mailto", "mailto:a@b.com", true},
46+
{"email-like destination", "a@b.co", true},
47+
{"userinfo without scheme", "user@h.co", true},
48+
{"trailing dot FQDN", "example.com.", true},
49+
{"empty", "", false},
50+
{"single word", "foo", false},
51+
{"path segment no dot", "questions/123", false},
52+
{"absolute path", "/questions/123", true},
53+
{"scheme-less authority path", "//cdn.example.com/x", true},
54+
{"anchor", "#section", false},
55+
{"leading dot", ".hidden", false},
56+
{"javascript scheme", "javascript:alert(1)", false},
57+
{"tel scheme", "tel:+1234", false},
58+
{"host with leading dot", "http://.example.com", false},
59+
{"trailing colon", "example.com:", false},
60+
{"single label with scheme", "http://localhost", true},
61+
{"single label no scheme no port", "localhost", false},
62+
{"not a url", "not a url", false},
63+
{"whitespace in path", "h.co/p q", false},
64+
{"label with leading hyphen", "-ex.com", false},
65+
{"label with trailing hyphen", "ex-.com", false},
66+
{"invalid IPv4 quad", "999.1.1.1", false},
67+
{"IPv4 with leading zeros", "01.2.3.4", false},
68+
{"three letter domain", "a.b", false},
69+
}
70+
r := &DangerousHTMLRenderer{}
71+
for _, tc := range cases {
72+
t.Run(tc.name, func(t *testing.T) {
73+
assert.Equal(t, tc.want, r.renderLinkIsUrl(tc.in))
74+
})
75+
}
76+
}

0 commit comments

Comments
 (0)