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

html_internal_test.go 11 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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 string, name string) string {
  19. return link(util.URLJoin(baseURL, name), name)
  20. }
  21. // numericLink an HTML to a numeric-style issue
  22. func numericIssueLink(baseURL string, index int) string {
  23. return link(util.URLJoin(baseURL, strconv.Itoa(index)), fmt.Sprintf("#%d", index))
  24. }
  25. // urlContentsLink an HTML link whose contents is the target URL
  26. func urlContentsLink(href string) string {
  27. return link(href, href)
  28. }
  29. // link an HTML link
  30. func link(href, contents string) string {
  31. return fmt.Sprintf("<a href=\"%s\">%s</a>", href, contents)
  32. }
  33. var numericMetas = map[string]string{
  34. "format": "https://someurl.com/{user}/{repo}/{index}",
  35. "user": "someUser",
  36. "repo": "someRepo",
  37. "style": IssueNameStyleNumeric,
  38. }
  39. var alphanumericMetas = map[string]string{
  40. "format": "https://someurl.com/{user}/{repo}/{index}",
  41. "user": "someUser",
  42. "repo": "someRepo",
  43. "style": IssueNameStyleAlphanumeric,
  44. }
  45. func TestRender_IssueIndexPattern(t *testing.T) {
  46. // numeric: render inputs without valid mentions
  47. test := func(s string) {
  48. testRenderIssueIndexPattern(t, s, s, nil)
  49. testRenderIssueIndexPattern(t, s, s, &postProcessCtx{metas: numericMetas})
  50. }
  51. // should not render anything when there are no mentions
  52. test("")
  53. test("this is a test")
  54. test("test 123 123 1234")
  55. test("#")
  56. test("# # #")
  57. test("# 123")
  58. test("#abcd")
  59. test("test#1234")
  60. test("#1234test")
  61. test(" test #1234test")
  62. // should not render issue mention without leading space
  63. test("test#54321 issue")
  64. // should not render issue mention without trailing space
  65. test("test #54321issue")
  66. }
  67. func TestRender_IssueIndexPattern2(t *testing.T) {
  68. setting.AppURL = AppURL
  69. setting.AppSubURL = AppSubURL
  70. // numeric: render inputs with valid mentions
  71. test := func(s, expectedFmt string, indices ...int) {
  72. links := make([]interface{}, len(indices))
  73. for i, index := range indices {
  74. links[i] = numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), index)
  75. }
  76. expectedNil := fmt.Sprintf(expectedFmt, links...)
  77. testRenderIssueIndexPattern(t, s, expectedNil, nil)
  78. for i, index := range indices {
  79. links[i] = numericIssueLink("https://someurl.com/someUser/someRepo/", index)
  80. }
  81. expectedNum := fmt.Sprintf(expectedFmt, links...)
  82. testRenderIssueIndexPattern(t, s, expectedNum, &postProcessCtx{metas: numericMetas})
  83. }
  84. // should render freestanding mentions
  85. test("#1234 test", "%s test", 1234)
  86. test("test #8 issue", "test %s issue", 8)
  87. test("test issue #1234", "test issue %s", 1234)
  88. // should render mentions in parentheses
  89. test("(#54321 issue)", "(%s issue)", 54321)
  90. test("test (#9801 extra) issue", "test (%s extra) issue", 9801)
  91. test("test (#1)", "test (%s)", 1)
  92. // should render multiple issue mentions in the same line
  93. test("#54321 #1243", "%s %s", 54321, 1243)
  94. test("wow (#54321 #1243)", "wow (%s %s)", 54321, 1243)
  95. test("(#4)(#5)", "(%s)(%s)", 4, 5)
  96. test("#1 (#4321) test", "%s (%s) test", 1, 4321)
  97. }
  98. func TestRender_IssueIndexPattern3(t *testing.T) {
  99. setting.AppURL = AppURL
  100. setting.AppSubURL = AppSubURL
  101. // alphanumeric: render inputs without valid mentions
  102. test := func(s string) {
  103. testRenderIssueIndexPattern(t, s, s, &postProcessCtx{metas: alphanumericMetas})
  104. }
  105. test("")
  106. test("this is a test")
  107. test("test 123 123 1234")
  108. test("#")
  109. test("# 123")
  110. test("#abcd")
  111. test("test #123")
  112. test("abc-1234") // issue prefix must be capital
  113. test("ABc-1234") // issue prefix must be _all_ capital
  114. test("ABCDEFGHIJK-1234") // the limit is 10 characters in the prefix
  115. test("ABC1234") // dash is required
  116. test("test ABC- test") // number is required
  117. test("test -1234 test") // prefix is required
  118. test("testABC-123 test") // leading space is required
  119. test("test ABC-123test") // trailing space is required
  120. test("ABC-0123") // no leading zero
  121. }
  122. func TestRender_IssueIndexPattern4(t *testing.T) {
  123. setting.AppURL = AppURL
  124. setting.AppSubURL = AppSubURL
  125. // alphanumeric: render inputs with valid mentions
  126. test := func(s, expectedFmt string, names ...string) {
  127. links := make([]interface{}, len(names))
  128. for i, name := range names {
  129. links[i] = alphanumIssueLink("https://someurl.com/someUser/someRepo/", name)
  130. }
  131. expected := fmt.Sprintf(expectedFmt, links...)
  132. testRenderIssueIndexPattern(t, s, expected, &postProcessCtx{metas: alphanumericMetas})
  133. }
  134. test("OTT-1234 test", "%s test", "OTT-1234")
  135. test("test T-12 issue", "test %s issue", "T-12")
  136. test("test issue ABCDEFGHIJ-1234567890", "test issue %s", "ABCDEFGHIJ-1234567890")
  137. }
  138. func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *postProcessCtx) {
  139. if ctx == nil {
  140. ctx = new(postProcessCtx)
  141. }
  142. ctx.procs = []processor{issueIndexPatternProcessor}
  143. if ctx.urlPrefix == "" {
  144. ctx.urlPrefix = AppSubURL
  145. }
  146. res, err := ctx.postProcess([]byte(input))
  147. assert.NoError(t, err)
  148. assert.Equal(t, expected, string(res))
  149. }
  150. func TestRender_AutoLink(t *testing.T) {
  151. setting.AppURL = AppURL
  152. setting.AppSubURL = AppSubURL
  153. test := func(input, expected string) {
  154. buffer, err := PostProcess([]byte(input), setting.AppSubURL, nil, false)
  155. assert.Equal(t, err, nil)
  156. assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
  157. buffer, err = PostProcess([]byte(input), setting.AppSubURL, nil, true)
  158. assert.Equal(t, err, nil)
  159. assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
  160. }
  161. // render valid issue URLs
  162. test(util.URLJoin(setting.AppSubURL, "issues", "3333"),
  163. numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), 3333))
  164. // render valid commit URLs
  165. tmp := util.URLJoin(AppSubURL, "commit", "d8a994ef243349f321568f9e36d5c3f444b99cae")
  166. test(tmp, "<a href=\""+tmp+"\">d8a994ef24</a>")
  167. tmp += "#diff-2"
  168. test(tmp, "<a href=\""+tmp+"\">d8a994ef24 (diff-2)</a>")
  169. // render other commit URLs
  170. tmp = "https://external-link.gogs.io/gogs/gogs/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2"
  171. test(tmp, "<a href=\""+tmp+"\">d8a994ef24 (diff-2)</a>")
  172. }
  173. func TestRender_FullIssueURLs(t *testing.T) {
  174. setting.AppURL = AppURL
  175. setting.AppSubURL = AppSubURL
  176. test := func(input, expected string) {
  177. ctx := new(postProcessCtx)
  178. ctx.procs = []processor{fullIssuePatternProcessor}
  179. if ctx.urlPrefix == "" {
  180. ctx.urlPrefix = AppSubURL
  181. }
  182. result, err := ctx.postProcess([]byte(input))
  183. assert.NoError(t, err)
  184. assert.Equal(t, expected, string(result))
  185. }
  186. test("Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6",
  187. "Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6")
  188. test("Look here http://localhost:3000/person/repo/issues/4",
  189. `Look here <a href="http://localhost:3000/person/repo/issues/4">#4</a>`)
  190. test("http://localhost:3000/person/repo/issues/4#issuecomment-1234",
  191. `<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234">#4</a>`)
  192. }
  193. func TestRegExp_issueNumericPattern(t *testing.T) {
  194. trueTestCases := []string{
  195. "#1234",
  196. "#0",
  197. "#1234567890987654321",
  198. " #12",
  199. }
  200. falseTestCases := []string{
  201. "# 1234",
  202. "# 0",
  203. "# ",
  204. "#",
  205. "#ABC",
  206. "#1A2B",
  207. "",
  208. "ABC",
  209. }
  210. for _, testCase := range trueTestCases {
  211. assert.True(t, issueNumericPattern.MatchString(testCase))
  212. }
  213. for _, testCase := range falseTestCases {
  214. assert.False(t, issueNumericPattern.MatchString(testCase))
  215. }
  216. }
  217. func TestRegExp_sha1CurrentPattern(t *testing.T) {
  218. trueTestCases := []string{
  219. "d8a994ef243349f321568f9e36d5c3f444b99cae",
  220. "abcdefabcdefabcdefabcdefabcdefabcdefabcd",
  221. }
  222. falseTestCases := []string{
  223. "test",
  224. "abcdefg",
  225. "abcdefghijklmnopqrstuvwxyzabcdefghijklmn",
  226. "abcdefghijklmnopqrstuvwxyzabcdefghijklmO",
  227. }
  228. for _, testCase := range trueTestCases {
  229. assert.True(t, sha1CurrentPattern.MatchString(testCase))
  230. }
  231. for _, testCase := range falseTestCases {
  232. assert.False(t, sha1CurrentPattern.MatchString(testCase))
  233. }
  234. }
  235. func TestRegExp_anySHA1Pattern(t *testing.T) {
  236. testCases := map[string][]string{
  237. "https://github.com/jquery/jquery/blob/a644101ed04d0beacea864ce805e0c4f86ba1cd1/test/unit/event.js#L2703": {
  238. "a644101ed04d0beacea864ce805e0c4f86ba1cd1",
  239. "test/unit/event.js",
  240. "L2703",
  241. },
  242. "https://github.com/jquery/jquery/blob/a644101ed04d0beacea864ce805e0c4f86ba1cd1/test/unit/event.js": {
  243. "a644101ed04d0beacea864ce805e0c4f86ba1cd1",
  244. "test/unit/event.js",
  245. "",
  246. },
  247. "https://github.com/jquery/jquery/commit/0705be475092aede1eddae01319ec931fb9c65fc": {
  248. "0705be475092aede1eddae01319ec931fb9c65fc",
  249. "",
  250. "",
  251. },
  252. "https://github.com/jquery/jquery/tree/0705be475092aede1eddae01319ec931fb9c65fc/src": {
  253. "0705be475092aede1eddae01319ec931fb9c65fc",
  254. "src",
  255. "",
  256. },
  257. "https://try.gogs.io/gogs/gogs/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2": {
  258. "d8a994ef243349f321568f9e36d5c3f444b99cae",
  259. "",
  260. "diff-2",
  261. },
  262. }
  263. for k, v := range testCases {
  264. assert.Equal(t, anySHA1Pattern.FindStringSubmatch(k)[1:], v)
  265. }
  266. }
  267. func TestRegExp_mentionPattern(t *testing.T) {
  268. trueTestCases := []string{
  269. "@Unknwon",
  270. "@ANT_123",
  271. "@xxx-DiN0-z-A..uru..s-xxx",
  272. " @lol ",
  273. " @Te/st",
  274. }
  275. falseTestCases := []string{
  276. "@ 0",
  277. "@ ",
  278. "@",
  279. "",
  280. "ABC",
  281. }
  282. for _, testCase := range trueTestCases {
  283. res := mentionPattern.MatchString(testCase)
  284. assert.True(t, res)
  285. }
  286. for _, testCase := range falseTestCases {
  287. res := mentionPattern.MatchString(testCase)
  288. assert.False(t, res)
  289. }
  290. }
  291. func TestRegExp_issueAlphanumericPattern(t *testing.T) {
  292. trueTestCases := []string{
  293. "ABC-1234",
  294. "A-1",
  295. "RC-80",
  296. "ABCDEFGHIJ-1234567890987654321234567890",
  297. }
  298. falseTestCases := []string{
  299. "RC-08",
  300. "PR-0",
  301. "ABCDEFGHIJK-1",
  302. "PR_1",
  303. "",
  304. "#ABC",
  305. "",
  306. "ABC",
  307. "GG-",
  308. "rm-1",
  309. }
  310. for _, testCase := range trueTestCases {
  311. assert.True(t, issueAlphanumericPattern.MatchString(testCase))
  312. }
  313. for _, testCase := range falseTestCases {
  314. assert.False(t, issueAlphanumericPattern.MatchString(testCase))
  315. }
  316. }
  317. func TestRegExp_shortLinkPattern(t *testing.T) {
  318. trueTestCases := []string{
  319. "[[stuff]]",
  320. "[[]]",
  321. "[[stuff|title=Difficult name with spaces*!]]",
  322. }
  323. falseTestCases := []string{
  324. "test",
  325. "abcdefg",
  326. "[[]",
  327. "[[",
  328. "[]",
  329. "]]",
  330. "abcdefghijklmnopqrstuvwxyz",
  331. }
  332. for _, testCase := range trueTestCases {
  333. assert.True(t, shortLinkPattern.MatchString(testCase))
  334. }
  335. for _, testCase := range falseTestCases {
  336. assert.False(t, shortLinkPattern.MatchString(testCase))
  337. }
  338. }