選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

html_internal_test.go 12KB

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