test.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /**
  2. * @fileoverview 单元测试
  3. */
  4. const path = require('path')
  5. const simulate = require('miniprogram-simulate')
  6. const html = require('./content') // 测试 html
  7. const dist = '../dev/mp-weixin/components/mp-html/index' // 组件目录
  8. const mpHtml = simulate.load(path.resolve(__dirname, dist), 'mp-html')
  9. // 渲染测试
  10. test('render', async () => {
  11. // 创建和渲染页面
  12. const id = simulate.load({
  13. data: {
  14. containerStyle: '',
  15. copyLink: true,
  16. pauseVideo: true,
  17. previewImg: true,
  18. useAnchor: true
  19. },
  20. template:
  21. `<scroll-view id="scroll" style="height:100px" scroll-y scroll-top="{{top}}">
  22. <mp-html id="article" container-style="{{containerStyle}}" content="{{html}}" domain="https://6874-html-foe72-1259071903.tcb.qcloud.la/demo" copy-link="{{copyLink}}" loading-img="xxx" error-img="xxx" lazy-load pause-video="{{pauseVideo}}" preview-img="{{previewImg}}" scroll-table use-anchor="{{useAnchor}}">加载中...</mp-html>
  23. </scroll-view>`,
  24. usingComponents: {
  25. 'mp-html': mpHtml
  26. }
  27. })
  28. const page = simulate.render(id)
  29. // 设置数据
  30. page.setData({
  31. html
  32. })
  33. await simulate.sleep(1000)
  34. // api 测试
  35. const comp = page.querySelector('#article')
  36. expect(comp.dom.tagName).toBe('MP-HTML')
  37. await simulate.sleep(50)
  38. comp.instance.setContent(
  39. `<!-- 测试 base 标签 -->
  40. <base href="https://xxx.com">
  41. <!-- 测试 script 标签 -->
  42. <script>
  43. console.log('11')
  44. </script>
  45. <!-- 测试 embed 标签 -->
  46. <embed src="xxx.mp4" />
  47. <embed autostart src="xxx.m4a" />
  48. <!-- 测试 source 标签 -->
  49. <video src="xxx.mp4" loop ></video>
  50. <!-- 测试 table 标签 -->
  51. <table align="center"></table>
  52. <table align="left" border="1">
  53. <td>
  54. <a>xxx</a>
  55. </td>
  56. </table>
  57. <table width="100%" border="1">
  58. <tr>
  59. <th width="20%">标题1</th>
  60. <th width="80%">标题2</th>
  61. </tr>
  62. <tr>
  63. <td colspan="2"><a>内容1</a></td>
  64. </tr>
  65. </table>
  66. <!-- 测试 font 标签、不同属性写法、实体 -->
  67. <font color='red' face = "宋体" size=8 >&#26356;&#x591a;</font >
  68. <font size=0>1 < 2</font>
  69. <font>&#aaa;&aaa;&</FONT>
  70. <!-- 测试 rpx 单位处理 -->
  71. <span id="anchor" style="font-size:30rpx">11</span>
  72. <!-- 测试 pre 标签处理(保留空白符) -->
  73. <div style="white-space:pre">
  74. <pre>var i = 0</pre>
  75. </div>
  76. <!-- 测试不同情况中的图片处理 -->
  77. <a data-test="test">
  78. <img src="//xxx.jpg">
  79. </a>
  80. <div style="display:inline-block !important;display:block">
  81. <img style="width:100%;" src="xxx.jpg">
  82. </p>
  83. </div>
  84. <div style="display:flex">
  85. <div style="flex:1">
  86. <img src="//xxx.jpg" style="display:inline">
  87. </div>
  88. </div>
  89. <img style="width:auto" src="data:image/png;base64,xxxx">
  90. <img src="xxx" style="width:20px" height="10">
  91. <img src="yyy.webp" style="width:1000px" ignore>
  92. <svg />
  93. <svg viewbox="0 0 1 1"><text>123</text><svg></svg></svg>
  94. <div class="ql-align-center" style="background-image:url(&quot;/xxx.jpg?a=2&amp;b=3&quot;)"></div>
  95. <![CDATA[<]]>
  96. <!-- 测试 flex 布局、未闭合标签、data- 属性处理 -->
  97. <div style="display:flex;width:1000px">
  98. <div style="flex:1" dir="rtl">123</div>
  99. </div>
  100. </br><div data-test="xxx" style="display:flex;display:-webkit-flex;"><div>
  101. <img data-src="/xxx.jpg" style="width:100%;height:100px"> `, true) // 补充测试
  102. expect(comp.instance.getText().includes('更多')).toBe(true) // 检查上方的实体是否被解码
  103. await comp.instance.getRect()
  104. await comp.instance.navigateTo('anchor') // 基于页面跳转
  105. comp.instance.in(page.instance) // 错误设置
  106. comp.instance.in(page.instance, '#scroll', 'top')
  107. await comp.instance.navigateTo('anchor') // 基于 scroll-view 滚动
  108. page.setData({
  109. useAnchor: false
  110. })
  111. await simulate.sleep(50)
  112. comp.instance.setContent('<span id="test">123</span>', true)
  113. try {
  114. await comp.instance.navigateTo('anchor') // 禁用锚点的情况下跳转
  115. } catch (e) { }
  116. page.setData({
  117. containerStyle: 'white-space:pre-wrap'
  118. })
  119. await simulate.sleep(50)
  120. comp.instance.setContent(' 空格\n换行')
  121. expect(comp.instance.getText().includes('\n')).toBe(true) // 检查换行是否被保留
  122. await simulate.sleep(50) // 等待异步 api 执行完毕
  123. // 移除节点
  124. comp.triggerLifeTime('detached')
  125. })
  126. // 事件测试
  127. test('event', async () => {
  128. // 模拟 api
  129. wx.createVideoContext = function () {
  130. // 模拟视频 context
  131. return {
  132. pause: function () { }
  133. }
  134. }
  135. // 测试失败回调
  136. wx.navigateTo = function (obj) {
  137. setTimeout(() => {
  138. if (typeof obj.fail === 'function') {
  139. obj.fail()
  140. }
  141. }, 0)
  142. }
  143. wx.switchTab = function (obj) {
  144. setTimeout(() => {
  145. if (typeof obj.fail === 'function') {
  146. obj.fail()
  147. }
  148. }, 0)
  149. }
  150. const comp = simulate.render(mpHtml)
  151. comp.setData({
  152. selectable: 'force',
  153. loadingImg: 'xxx'
  154. })
  155. await simulate.sleep(50)
  156. comp.instance.setContent(
  157. `<img src="xxx">
  158. <img src="yyy" width="100" height="50" ignore>
  159. <a href="#aaa"><img src="xxx"></a>
  160. <a href="https://github.com/jin-yufeng/mp-html">链接2</a>
  161. <a href="pages/test/test">链接3</a>
  162. <video src="xxx"></video>
  163. <video>
  164. <source src="/xxx">
  165. <source src="//yyy">
  166. </video>
  167. <base href="https://xxx.com">`)
  168. await simulate.sleep(100)
  169. const node = comp.querySelector('#_root')
  170. node.triggerLifeTime('attached')
  171. comp.instance._add({
  172. detail: node.instance
  173. })
  174. // 模拟图片加载完毕
  175. for (let i = 0; i <= 1; i++) {
  176. node.instance.imgLoad({
  177. target: {
  178. dataset: {
  179. i: i.toString()
  180. }
  181. },
  182. detail: {
  183. width: 100,
  184. height: 100
  185. }
  186. })
  187. // 模拟图片被点击
  188. node.instance.imgTap({
  189. target: {
  190. dataset: {
  191. i: i.toString()
  192. }
  193. }
  194. })
  195. }
  196. comp.setData({
  197. loadingImg: ''
  198. })
  199. await simulate.sleep(50)
  200. node.instance.imgLoad({
  201. target: {
  202. dataset: {
  203. i: '1'
  204. }
  205. }
  206. })
  207. // 模拟图片链接被点击
  208. node.instance.imgTap({
  209. target: {
  210. dataset: {
  211. i: '2_0'
  212. }
  213. }
  214. })
  215. node.instance.noop()
  216. // 模拟图片出错
  217. const imgError = () => node.instance.mediaError({
  218. target: {
  219. dataset: {
  220. i: '0'
  221. }
  222. },
  223. detail: {
  224. errMsg: 'test'
  225. }
  226. })
  227. imgError()
  228. comp.setData({
  229. errorImg: 'xxx'
  230. }, imgError)
  231. // 模拟链接被点击
  232. for (let i = 2; i <= 4; i++) {
  233. node.instance.linkTap({
  234. currentTarget: {
  235. dataset: {
  236. i: i.toString()
  237. }
  238. }
  239. })
  240. }
  241. // 模拟视频播放
  242. for (let i = 0; i < 3; i++) {
  243. node.instance.play({
  244. target: {
  245. id: 'v' + (i % 2)
  246. }
  247. })
  248. }
  249. // 模拟视频出错
  250. node.instance.mediaError({
  251. target: {
  252. dataset: {
  253. i: '6'
  254. }
  255. },
  256. detail: {
  257. errMsg: 'test'
  258. }
  259. })
  260. // 禁用一些功能
  261. comp.setData({
  262. copyLink: false,
  263. pauseVideo: false,
  264. previewImg: false
  265. }, () => {
  266. // 禁用自动拷贝后点击外部链接
  267. node.instance.linkTap({
  268. currentTarget: {
  269. dataset: {
  270. i: '3'
  271. }
  272. }
  273. })
  274. // 禁用自动暂停后播放视频
  275. node.instance.play({
  276. target: {
  277. id: 'v0'
  278. }
  279. })
  280. // 禁用预览后点击图片
  281. node.instance.imgTap({
  282. target: {
  283. dataset: {
  284. i: '0'
  285. }
  286. }
  287. })
  288. })
  289. await simulate.sleep(100)
  290. })