You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

html_internal_test.go 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // Copyright 2018 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package markup
  5. import (
  6. "fmt"
  7. "strconv"
  8. "strings"
  9. "testing"
  10. "code.gitea.io/gitea/modules/setting"
  11. "code.gitea.io/gitea/modules/util"
  12. "github.com/stretchr/testify/assert"
  13. )
  14. const AppURL = "http://localhost:3000/"
  15. const Repo = "gogits/gogs"
  16. const AppSubURL = AppURL + Repo + "/"
  17. // alphanumLink an HTML link to an alphanumeric-style issue
  18. func alphanumIssueLink(baseURL, class, name string) string {
  19. return link(util.URLJoin(baseURL, name), class, name)
  20. }
  21. // numericLink an HTML to a numeric-style issue
  22. func numericIssueLink(baseURL, class string, index int, marker string) string {
  23. return link(util.URLJoin(baseURL, strconv.Itoa(index)), class, fmt.Sprintf("%s%d", marker, index))
  24. }
  25. // link an HTML link
  26. func link(href, class, contents string) string {
  27. if class != "" {
  28. class = " class=\"" + class + "\""
  29. }
  30. return fmt.Sprintf("<a href=\"%s\"%s>%s</a>", href, class, contents)
  31. }
  32. var numericMetas = map[string]string{
  33. "format": "https://someurl.com/{user}/{repo}/{index}",
  34. "user": "someUser",
  35. "repo": "someRepo",
  36. "style": IssueNameStyleNumeric,
  37. }
  38. var alphanumericMetas = map[string]string{
  39. "format": "https://someurl.com/{user}/{repo}/{index}",
  40. "user": "someUser",
  41. "repo": "someRepo",
  42. "style": IssueNameStyleAlphanumeric,
  43. }
  44. // these values should match the Repo const above
  45. var localMetas = map[string]string{
  46. "user": "gogits",
  47. "repo": "gogs",
  48. }
  49. func TestRender_IssueIndexPattern(t *testing.T) {
  50. // numeric: render inputs without valid mentions
  51. test := func(s string) {
  52. testRenderIssueIndexPattern(t, s, s, nil)
  53. testRenderIssueIndexPattern(t, s, s, &postProcessCtx{metas: numericMetas})
  54. }
  55. // should not render anything when there are no mentions
  56. test("")
  57. test("this is a test")
  58. test("test 123 123 1234")
  59. test("#")
  60. test("# # #")
  61. test("# 123")
  62. test("#abcd")
  63. test("test#1234")
  64. test("#1234test")
  65. test("#abcd")
  66. test("test!1234")
  67. test("!1234test")
  68. test(" test !1234test")
  69. test("/home/gitea/#1234")
  70. test("/home/gitea/!1234")
  71. // should not render issue mention without leading space
  72. test("test#54321 issue")
  73. // should not render issue mention without trailing space
  74. test("test #54321issue")
  75. }
  76. func TestRender_IssueIndexPattern2(t *testing.T) {
  77. setting.AppURL = AppURL
  78. setting.AppSubURL = AppSubURL
  79. // numeric: render inputs with valid mentions
  80. test := func(s, expectedFmt, marker string, indices ...int) {
  81. var path, prefix string
  82. if marker == "!" {
  83. path = "pulls"
  84. prefix = "http://localhost:3000/someUser/someRepo/pulls/"
  85. } else {
  86. path = "issues"
  87. prefix = "https://someurl.com/someUser/someRepo/"
  88. }
  89. links := make([]interface{}, len(indices))
  90. for i, index := range indices {
  91. links[i] = numericIssueLink(util.URLJoin(setting.AppSubURL, path), "ref-issue", index, marker)
  92. }
  93. expectedNil := fmt.Sprintf(expectedFmt, links...)
  94. testRenderIssueIndexPattern(t, s, expectedNil, &postProcessCtx{metas: localMetas})
  95. for i, index := range indices {
  96. links[i] = numericIssueLink(prefix, "ref-issue", index, marker)
  97. }
  98. expectedNum := fmt.Sprintf(expectedFmt, links...)
  99. testRenderIssueIndexPattern(t, s, expectedNum, &postProcessCtx{metas: numericMetas})
  100. }
  101. // should render freestanding mentions
  102. test("#1234 test", "%s test", "#", 1234)
  103. test("test #8 issue", "test %s issue", "#", 8)
  104. test("!1234 test", "%s test", "!", 1234)
  105. test("test !8 issue", "test %s issue", "!", 8)
  106. test("test issue #1234", "test issue %s", "#", 1234)
  107. test("fixes issue #1234.", "fixes issue %s.", "#", 1234)
  108. // should render mentions in parentheses / brackets
  109. test("(#54321 issue)", "(%s issue)", "#", 54321)
  110. test("[#54321 issue]", "[%s issue]", "#", 54321)
  111. test("test (#9801 extra) issue", "test (%s extra) issue", "#", 9801)
  112. test("test (!9801 extra) issue", "test (%s extra) issue", "!", 9801)
  113. test("test (#1)", "test (%s)", "#", 1)
  114. // should render multiple issue mentions in the same line
  115. test("#54321 #1243", "%s %s", "#", 54321, 1243)
  116. test("wow (#54321 #1243)", "wow (%s %s)", "#", 54321, 1243)
  117. test("(#4)(#5)", "(%s)(%s)", "#", 4, 5)
  118. test("#1 (#4321) test", "%s (%s) test", "#", 1, 4321)
  119. // should render with :
  120. test("#1234: test", "%s: test", "#", 1234)
  121. test("wow (#54321: test)", "wow (%s: test)", "#", 54321)
  122. }
  123. func TestRender_IssueIndexPattern3(t *testing.T) {
  124. setting.AppURL = AppURL
  125. setting.AppSubURL = AppSubURL
  126. // alphanumeric: render inputs without valid mentions
  127. test := func(s string) {
  128. testRenderIssueIndexPattern(t, s, s, &postProcessCtx{metas: alphanumericMetas})
  129. }
  130. test("")
  131. test("this is a test")
  132. test("test 123 123 1234")
  133. test("#")
  134. test("# 123")
  135. test("#abcd")
  136. test("test #123")
  137. test("abc-1234") // issue prefix must be capital
  138. test("ABc-1234") // issue prefix must be _all_ capital
  139. test("ABCDEFGHIJK-1234") // the limit is 10 characters in the prefix
  140. test("ABC1234") // dash is required
  141. test("test ABC- test") // number is required
  142. test("test -1234 test") // prefix is required
  143. test("testABC-123 test") // leading space is required
  144. test("test ABC-123test") // trailing space is required
  145. test("ABC-0123") // no leading zero
  146. }
  147. func TestRender_IssueIndexPattern4(t *testing.T) {
  148. setting.AppURL = AppURL
  149. setting.AppSubURL = AppSubURL
  150. // alphanumeric: render inputs with valid mentions
  151. test := func(s, expectedFmt string, names ...string) {
  152. links := make([]interface{}, len(names))
  153. for i, name := range names {
  154. links[i] = alphanumIssueLink("https://someurl.com/someUser/someRepo/", "ref-issue", name)
  155. }
  156. expected := fmt.Sprintf(expectedFmt, links...)
  157. testRenderIssueIndexPattern(t, s, expected, &postProcessCtx{metas: alphanumericMetas})
  158. }
  159. test("OTT-1234 test", "%s test", "OTT-1234")
  160. test("test T-12 issue", "test %s issue", "T-12")
  161. test("test issue ABCDEFGHIJ-1234567890", "test issue %s", "ABCDEFGHIJ-1234567890")
  162. }
  163. func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *postProcessCtx) {
  164. if ctx == nil {
  165. ctx = new(postProcessCtx)
  166. }
  167. ctx.procs = []processor{issueIndexPatternProcessor}
  168. if ctx.urlPrefix == "" {
  169. ctx.urlPrefix = AppSubURL
  170. }
  171. res, err := ctx.postProcess([]byte(input))
  172. assert.NoError(t, err)
  173. assert.Equal(t, expected, string(res))
  174. }
  175. func TestRender_AutoLink(t *testing.T) {
  176. setting.AppURL = AppURL
  177. setting.AppSubURL = AppSubURL
  178. test := func(input, expected string) {
  179. buffer, err := PostProcess([]byte(input), setting.AppSubURL, localMetas, false)
  180. assert.Equal(t, err, nil)
  181. assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
  182. buffer, err = PostProcess([]byte(input), setting.AppSubURL, localMetas, true)
  183. assert.Equal(t, err, nil)
  184. assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
  185. }
  186. // render valid issue URLs
  187. test(util.URLJoin(setting.AppSubURL, "issues", "3333"),
  188. numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), "ref-issue", 3333, "#"))
  189. // render valid commit URLs
  190. tmp := util.URLJoin(AppSubURL, "commit", "d8a994ef243349f321568f9e36d5c3f444b99cae")
  191. test(tmp, "<a href=\""+tmp+"\" class=\"commit\"><code class=\"nohighlight\">d8a994ef24</code></a>")
  192. tmp += "#diff-2"
  193. test(tmp, "<a href=\""+tmp+"\" class=\"commit\"><code class=\"nohighlight\">d8a994ef24 (diff-2)</code></a>")
  194. // render other commit URLs
  195. tmp = "https://external-link.gitea.io/go-gitea/gitea/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2"
  196. test(tmp, "<a href=\""+tmp+"\" class=\"commit\"><code class=\"nohighlight\">d8a994ef24 (diff-2)</code></a>")
  197. }
  198. func TestRender_FullIssueURLs(t *testing.T) {
  199. setting.AppURL = AppURL
  200. setting.AppSubURL = AppSubURL
  201. test := func(input, expected string) {
  202. ctx := new(postProcessCtx)
  203. ctx.procs = []processor{fullIssuePatternProcessor}
  204. if ctx.urlPrefix == "" {
  205. ctx.urlPrefix = AppSubURL
  206. }
  207. ctx.metas = localMetas
  208. result, err := ctx.postProcess([]byte(input))
  209. assert.NoError(t, err)
  210. assert.Equal(t, expected, string(result))
  211. }
  212. test("Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6",
  213. "Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6")
  214. test("Look here http://localhost:3000/person/repo/issues/4",
  215. `Look here <a href="http://localhost:3000/person/repo/issues/4" class="ref-issue">person/repo#4</a>`)
  216. test("http://localhost:3000/person/repo/issues/4#issuecomment-1234",
  217. `<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234" class="ref-issue">person/repo#4</a>`)
  218. test("http://localhost:3000/gogits/gogs/issues/4",
  219. `<a href="http://localhost:3000/gogits/gogs/issues/4" class="ref-issue">#4</a>`)
  220. }
  221. func TestRegExp_sha1CurrentPattern(t *testing.T) {
  222. trueTestCases := []string{
  223. "d8a994ef243349f321568f9e36d5c3f444b99cae",
  224. "abcdefabcdefabcdefabcdefabcdefabcdefabcd",
  225. "(abcdefabcdefabcdefabcdefabcdefabcdefabcd)",
  226. "[abcdefabcdefabcdefabcdefabcdefabcdefabcd]",
  227. "abcdefabcdefabcdefabcdefabcdefabcdefabcd.",
  228. }
  229. falseTestCases := []string{
  230. "test",
  231. "abcdefg",
  232. "e59ff077-2d03-4e6b-964d-63fbaea81f",
  233. "abcdefghijklmnopqrstuvwxyzabcdefghijklmn",
  234. "abcdefghijklmnopqrstuvwxyzabcdefghijklmO",
  235. }
  236. for _, testCase := range trueTestCases {
  237. assert.True(t, sha1CurrentPattern.MatchString(testCase))
  238. }
  239. for _, testCase := range falseTestCases {
  240. assert.False(t, sha1CurrentPattern.MatchString(testCase))
  241. }
  242. }
  243. func TestRegExp_anySHA1Pattern(t *testing.T) {
  244. testCases := map[string][]string{
  245. "https://github.com/jquery/jquery/blob/a644101ed04d0beacea864ce805e0c4f86ba1cd1/test/unit/event.js#L2703": {
  246. "a644101ed04d0beacea864ce805e0c4f86ba1cd1",
  247. "/test/unit/event.js",
  248. "#L2703",
  249. },
  250. "https://github.com/jquery/jquery/blob/a644101ed04d0beacea864ce805e0c4f86ba1cd1/test/unit/event.js": {
  251. "a644101ed04d0beacea864ce805e0c4f86ba1cd1",
  252. "/test/unit/event.js",
  253. "",
  254. },
  255. "https://github.com/jquery/jquery/commit/0705be475092aede1eddae01319ec931fb9c65fc": {
  256. "0705be475092aede1eddae01319ec931fb9c65fc",
  257. "",
  258. "",
  259. },
  260. "https://github.com/jquery/jquery/tree/0705be475092aede1eddae01319ec931fb9c65fc/src": {
  261. "0705be475092aede1eddae01319ec931fb9c65fc",
  262. "/src",
  263. "",
  264. },
  265. "https://try.gogs.io/gogs/gogs/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2": {
  266. "d8a994ef243349f321568f9e36d5c3f444b99cae",
  267. "",
  268. "#diff-2",
  269. },
  270. }
  271. for k, v := range testCases {
  272. assert.Equal(t, anySHA1Pattern.FindStringSubmatch(k)[1:], v)
  273. }
  274. }
  275. func TestRegExp_shortLinkPattern(t *testing.T) {
  276. trueTestCases := []string{
  277. "[[stuff]]",
  278. "[[]]",
  279. "[[stuff|title=Difficult name with spaces*!]]",
  280. }
  281. falseTestCases := []string{
  282. "test",
  283. "abcdefg",
  284. "[[]",
  285. "[[",
  286. "[]",
  287. "]]",
  288. "abcdefghijklmnopqrstuvwxyz",
  289. }
  290. for _, testCase := range trueTestCases {
  291. assert.True(t, shortLinkPattern.MatchString(testCase))
  292. }
  293. for _, testCase := range falseTestCases {
  294. assert.False(t, shortLinkPattern.MatchString(testCase))
  295. }
  296. }