SwiftyMarkdownLinkTests.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. //
  2. // SwiftyMarkdownCharacterTests.swift
  3. // SwiftyMarkdownTests
  4. //
  5. // Created by Simon Fairbairn on 17/12/2019.
  6. // Copyright © 2019 Voyage Travel Apps. All rights reserved.
  7. //
  8. @testable import SwiftyMarkdown
  9. import XCTest
  10. class SwiftyMarkdownLinkTests: SwiftyMarkdownCharacterTests {
  11. func testForLinks() {
  12. challenge = TokenTest(input: "[Link at start](http://voyagetravelapps.com/)", output: "Link at start", tokens: [
  13. Token(type: .string, inputString: "Link at start", characterStyles: [CharacterStyle.link])
  14. ])
  15. results = self.attempt(challenge)
  16. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  17. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  18. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  19. XCTAssertEqual(results.attributedString.string, challenge.output)
  20. if let existentOpen = results.tokens.filter({ $0.type == .string && (($0.characterStyles as? [CharacterStyle])?.contains(.link) ?? false) }).first {
  21. XCTAssertEqual(existentOpen.metadataString, "http://voyagetravelapps.com/")
  22. } else {
  23. XCTFail("Failed to find an open link tag")
  24. }
  25. challenge = TokenTest(input: "A [Link](http://voyagetravelapps.com/)", output: "A Link", tokens: [
  26. Token(type: .string, inputString: "A ", characterStyles: []),
  27. Token(type: .string, inputString: "Link", characterStyles: [CharacterStyle.link])
  28. ])
  29. results = self.attempt(challenge)
  30. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  31. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  32. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  33. XCTAssertEqual(results.attributedString.string, challenge.output)
  34. challenge = TokenTest(input: "[Link 1](http://voyagetravelapps.com/), [Link 2](https://www.neverendingvoyage.com/)", output: "Link 1, Link 2", tokens: [
  35. Token(type: .string, inputString: "Link 1", characterStyles: [CharacterStyle.link]),
  36. Token(type: .string, inputString: ", ", characterStyles: []),
  37. Token(type: .string, inputString: "Link 2", characterStyles: [CharacterStyle.link])
  38. ])
  39. results = self.attempt(challenge)
  40. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  41. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  42. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  43. XCTAssertEqual(results.attributedString.string, challenge.output)
  44. var links = results.tokens.filter({ $0.type == .string && (($0.characterStyles as? [CharacterStyle])?.contains(.link) ?? false) })
  45. if links.count == 2 {
  46. XCTAssertEqual(links[0].metadataString, "http://voyagetravelapps.com/")
  47. XCTAssertEqual(links[1].metadataString, "https://www.neverendingvoyage.com/")
  48. } else {
  49. XCTFail("Incorrect number of links found. Expecting 2, found \(links.count)")
  50. }
  51. challenge = TokenTest(input: "Email us at [simon@voyagetravelapps.com](mailto:simon@voyagetravelapps.com) Twitter [@VoyageTravelApp](twitter://user?screen_name=VoyageTravelApp)", output: "Email us at simon@voyagetravelapps.com Twitter @VoyageTravelApp", tokens: [
  52. Token(type: .string, inputString: "Email us at ", characterStyles: []),
  53. Token(type: .string, inputString: "simon@voyagetravelapps.com", characterStyles: [CharacterStyle.link]),
  54. Token(type: .string, inputString: " Twitter", characterStyles: []),
  55. Token(type: .string, inputString: "@VoyageTravelApp", characterStyles: [CharacterStyle.link])
  56. ])
  57. results = self.attempt(challenge)
  58. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  59. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  60. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  61. XCTAssertEqual(results.attributedString.string, challenge.output)
  62. links = results.tokens.filter({ $0.type == .string && (($0.characterStyles as? [CharacterStyle])?.contains(.link) ?? false) })
  63. if links.count == 2 {
  64. XCTAssertEqual(links[0].metadataString, "mailto:simon@voyagetravelapps.com")
  65. XCTAssertEqual(links[1].metadataString, "twitter://user?screen_name=VoyageTravelApp")
  66. } else {
  67. XCTFail("Incorrect number of links found. Expecting 2, found \(links.count)")
  68. }
  69. }
  70. func testMalformedLinks() {
  71. challenge = TokenTest(input: "[Link with missing parenthesis](http://voyagetravelapps.com/", output: "[Link with missing parenthesis](http://voyagetravelapps.com/", tokens: [
  72. Token(type: .string, inputString: "[Link with missing parenthesis](", characterStyles: []),
  73. Token(type: .string, inputString: "http://voyagetravelapps.com/", characterStyles: [])
  74. ])
  75. results = self.attempt(challenge)
  76. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  77. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  78. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  79. XCTAssertEqual(results.attributedString.string, challenge.output)
  80. challenge = TokenTest(input: "A [Link](http://voyagetravelapps.com/", output: "A [Link](http://voyagetravelapps.com/", tokens: [
  81. Token(type: .string, inputString: "A ", characterStyles: []),
  82. Token(type: .string, inputString: "[Link](", characterStyles: []),
  83. Token(type: .string, inputString: "http://voyagetravelapps.com/", characterStyles: [])
  84. ])
  85. results = self.attempt(challenge)
  86. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  87. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  88. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  89. XCTAssertEqual(results.attributedString.string, challenge.output)
  90. challenge = TokenTest(input: "[A link](((url)", output: "A link", tokens: [
  91. Token(type: .string, inputString: "A link", characterStyles: [CharacterStyle.link])
  92. ])
  93. rules = [
  94. CharacterRule(openTag: "![", intermediateTag: "](", closingTag: ")", escapeCharacter: "\\", styles: [1 : [CharacterStyle.image]]),
  95. CharacterRule(openTag: "[", intermediateTag: "](", closingTag: ")", escapeCharacter: "\\", styles: [1 : [CharacterStyle.link]]),
  96. ]
  97. results = self.attempt(challenge, rules: rules)
  98. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  99. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  100. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  101. XCTAssertEqual(results.attributedString.string, challenge.output)
  102. XCTAssertEqual(results.links.count, 1)
  103. if results.links.count == 1 {
  104. XCTAssertEqual(results.links[0].metadataString, "((url")
  105. } else {
  106. XCTFail("Incorrect link count. Expecting 1, found \(results.links.count)")
  107. }
  108. challenge = TokenTest(input: "[Link with missing square(http://voyagetravelapps.com/)", output: "[Link with missing square(http://voyagetravelapps.com/)", tokens: [
  109. Token(type: .string, inputString: "Link with missing square(http://voyagetravelapps.com/)", characterStyles: [])
  110. ])
  111. results = self.attempt(challenge)
  112. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  113. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  114. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  115. XCTAssertEqual(results.attributedString.string, challenge.output)
  116. challenge = TokenTest(input: "[Link with [second opening](http://voyagetravelapps.com/)", output: "[Link with second opening", tokens: [
  117. Token(type: .string, inputString: "Link with ", characterStyles: []),
  118. Token(type: .string, inputString: "second opening", characterStyles: [CharacterStyle.link])
  119. ])
  120. results = self.attempt(challenge)
  121. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  122. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  123. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  124. XCTAssertEqual(results.attributedString.string, challenge.output)
  125. XCTAssertEqual(results.links.count, 1)
  126. if results.links.count == 1 {
  127. XCTAssertEqual(results.links[0].metadataString, "http://voyagetravelapps.com/")
  128. } else {
  129. XCTFail("Incorrect link count. Expecting 1, found \(results.links.count)")
  130. }
  131. challenge = TokenTest(input: "A [Link(http://voyagetravelapps.com/)", output: "A [Link(http://voyagetravelapps.com/)", tokens: [
  132. Token(type: .string, inputString: "A [Link(http://voyagetravelapps.com/)", characterStyles: [])
  133. ])
  134. results = self.attempt(challenge)
  135. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  136. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  137. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  138. XCTAssertEqual(results.attributedString.string, challenge.output)
  139. }
  140. func testLinksWithOtherStyles() {
  141. var challenge = TokenTest(input: "A **Bold [Link](http://voyagetravelapps.com/)**", output: "A Bold Link", tokens: [
  142. Token(type: .string, inputString: "A ", characterStyles: []),
  143. Token(type: .string, inputString: "Bold ", characterStyles: [CharacterStyle.bold]),
  144. Token(type: .string, inputString: "Link", characterStyles: [CharacterStyle.link, CharacterStyle.bold])
  145. ])
  146. var results = self.attempt(challenge)
  147. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  148. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  149. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  150. // XCTAssertEqual(results.attributedString.string, challenge.output)
  151. var links = results.tokens.filter({ $0.type == .string && (($0.characterStyles as? [CharacterStyle])?.contains(.link) ?? false) })
  152. XCTAssertEqual(links.count, 1)
  153. if links.count == 1 {
  154. XCTAssertEqual(links[0].metadataString, "http://voyagetravelapps.com/")
  155. } else {
  156. XCTFail("Incorrect link count. Expecting 1, found \(links.count)")
  157. }
  158. challenge = TokenTest(input: "A Bold [**Link**](http://voyagetravelapps.com/)", output: "A Bold Link", tokens: [
  159. Token(type: .string, inputString: "A Bold ", characterStyles: []),
  160. Token(type: .string, inputString: "Link", characterStyles: [CharacterStyle.bold, CharacterStyle.link])
  161. ])
  162. results = self.attempt(challenge)
  163. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  164. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  165. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  166. XCTAssertEqual(results.attributedString.string, challenge.output)
  167. links = results.tokens.filter({ $0.type == .string && (($0.characterStyles as? [CharacterStyle])?.contains(.link) ?? false) })
  168. XCTAssertEqual(links.count, 1)
  169. if links.count == 1 {
  170. XCTAssertEqual(links[0].metadataString, "http://voyagetravelapps.com/")
  171. } else {
  172. XCTFail("Incorrect link count. Expecting 1, found \(links.count)")
  173. }
  174. challenge = TokenTest(input: "[Link1](http://voyagetravelapps.com/) **bold** [Link2](http://voyagetravelapps.com/)", output: "Link1 bold Link2", tokens: [
  175. Token(type: .string, inputString: "Link1", characterStyles: [CharacterStyle.link]),
  176. Token(type: .string, inputString: " ", characterStyles: []),
  177. Token(type: .string, inputString: "bold", characterStyles: [CharacterStyle.bold]),
  178. Token(type: .string, inputString: " ", characterStyles: []),
  179. Token(type: .string, inputString: "Link2", characterStyles: [CharacterStyle.link])
  180. ])
  181. results = self.attempt(challenge)
  182. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  183. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  184. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  185. XCTAssertEqual(results.attributedString.string, challenge.output)
  186. }
  187. func testForImages() {
  188. let challenge = TokenTest(input: "An ![Image](imageName)", output: "An Image", tokens: [
  189. Token(type: .string, inputString: "An Image", characterStyles: []),
  190. Token(type: .string, inputString: "", characterStyles: [CharacterStyle.image])
  191. ])
  192. let results = self.attempt(challenge)
  193. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  194. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  195. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  196. let links = results.tokens.filter({ $0.type == .string && (($0.characterStyles as? [CharacterStyle])?.contains(.image) ?? false) })
  197. XCTAssertEqual(links.count, 1)
  198. if links.count == 1 {
  199. XCTAssertEqual(links[0].metadataString, "imageName")
  200. } else {
  201. XCTFail("Incorrect link count. Expecting 1, found \(links.count)")
  202. }
  203. }
  204. func testForReferencedLinks() {
  205. var challenge = TokenTest(input: "A [referenced link][link]\n[link]: https://www.neverendingvoyage.com/", output: "A referenced link", tokens: [
  206. Token(type: .string, inputString: "A ", characterStyles: []),
  207. Token(type: .string, inputString: "referenced link", characterStyles: [CharacterStyle.link])
  208. ])
  209. var results = self.attempt(challenge)
  210. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  211. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  212. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  213. var links = results.tokens.filter({ $0.type == .string && (($0.characterStyles as? [CharacterStyle])?.contains(.link) ?? false) })
  214. if links.count == 1 {
  215. XCTAssertEqual(links[0].metadataString, "https://www.neverendingvoyage.com/")
  216. } else {
  217. XCTFail("Incorrect link count. Expecting 1, found \(links.count)")
  218. }
  219. challenge = TokenTest(input: "A [referenced link][link]\n [link]: https://www.neverendingvoyage.com/", output: "A referenced link", tokens: [
  220. Token(type: .string, inputString: "A ", characterStyles: []),
  221. Token(type: .string, inputString: "referenced link", characterStyles: [CharacterStyle.link])
  222. ])
  223. results = self.attempt(challenge)
  224. XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
  225. XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
  226. XCTAssertEqual(results.foundStyles, results.expectedStyles)
  227. links = results.tokens.filter({ $0.type == .string && (($0.characterStyles as? [CharacterStyle])?.contains(.link) ?? false) })
  228. if links.count == 1 {
  229. XCTAssertEqual(links[0].metadataString, "https://www.neverendingvoyage.com/")
  230. } else {
  231. XCTFail("Incorrect link count. Expecting 1, found \(links.count)")
  232. }
  233. }
  234. }