Initial commit
This commit is contained in:
203
wechat-mini-program/components/mp-html/test/content.js
Normal file
203
wechat-mini-program/components/mp-html/test/content.js
Normal file
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* @fileoverview 用于测试的 html 内容
|
||||
*/
|
||||
module.exports = `<title>富文本示例</title>
|
||||
<div>
|
||||
<section style="text-align: center; margin: 0px auto;">
|
||||
<section style="border-radius: 4px; border: 1px solid #757576; display: inline-block; padding: 5px 20px;">
|
||||
<span style="font-size: 18px; color: #595959;">表格</span>
|
||||
</section>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em;">
|
||||
<table width="100%" cellspacing="0" cellpadding="5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>标题 1</th>
|
||||
<th>标题 2</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center">内容 1</td>
|
||||
<td align="center">内容 2</td>
|
||||
</tr>
|
||||
<tr style="background-color: #f6f8fa;">
|
||||
<td align="center">内容 3</td>
|
||||
<td align="center"><a>链接</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">内容 5</td>
|
||||
<td align="center">内容 6</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="font-size: 12px; color: gray; text-align: center; margin-top: 5px;">普通表格</div>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em;">
|
||||
<table width="500px" cellspacing="0" cellpadding="5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>标题 1</th>
|
||||
<th>标题 2</th>
|
||||
<th>标题 3</th>
|
||||
<th>标题 4</th>
|
||||
<th>标题 5</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center">内容 1</td>
|
||||
<td align="center">内容 2</td>
|
||||
<td align="center">内容 3</td>
|
||||
<td align="center">内容 4</td>
|
||||
<td align="center">内容 5</td>
|
||||
</tr>
|
||||
<tr style="background-color: #f6f8fa;">
|
||||
<td align="center"><a>链接</a></td>
|
||||
<td align="center">内容 7</td>
|
||||
<td align="center">内容 8</td>
|
||||
<td align="center">内容 9</td>
|
||||
<td align="center">内容 10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">内容 11</td>
|
||||
<td align="center">内容 12</td>
|
||||
<td align="center">内容 13</td>
|
||||
<td align="center">内容 14</td>
|
||||
<td align="center">内容 15</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="font-size: 12px; color: gray; text-align: center; margin-top: 5px;">长表格,可以单独横向滚动</div>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em;">
|
||||
<table width="100%" cellspacing="0" cellpadding="5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="center">标题 1</th>
|
||||
<th align="center">标题 2</th>
|
||||
<th align="center">标题 3</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" colspan="2">内容 1</td>
|
||||
<td align="center" rowspan="2">内容 2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" rowspan="2">内容 3</td>
|
||||
<td align="center">内容 4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" colspan="2">内容 5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">内容 6</td>
|
||||
<td align="center">内容 7</td>
|
||||
<td align="center"><a>链接</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="font-size: 12px; color: gray; text-align: center; margin-top: 5px;">含有合并单元格的表格</div>
|
||||
</section>
|
||||
<section id="list" style="text-align: center; margin: 0px auto; margin-top: 2em">
|
||||
<section style="border-radius: 4px; border: 1px solid #757576; display: inline-block; padding: 5px 20px;">
|
||||
<span style="font-size: 18px; color: #595959;">列表</span>
|
||||
</section>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em;">
|
||||
<ol style="margin-bottom: 1.5em;">
|
||||
<li>这是第一条列表项</li>
|
||||
<li>这是第二条列表项</li>
|
||||
<li>这是第三条 <a>链接</a></li>
|
||||
</ol>
|
||||
<ol type="A" style="margin-bottom: 1.5em;">
|
||||
<li>这是第一条列表项</li>
|
||||
<li>这是第二条列表项</li>
|
||||
<li>这是第三条 <a>链接</a></li>
|
||||
</ol>
|
||||
<ol type="I" style="margin-bottom: 1.5em;">
|
||||
<li>这是第一条列表项</li>
|
||||
<li>这是第二条列表项</li>
|
||||
<li>这是第三条 <a>链接</a></li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li>第一级无序列表</li>
|
||||
<li>第一级无序列表
|
||||
<ul>
|
||||
<li>第二级无序列表</li>
|
||||
<li>第二级无序列表
|
||||
<ul>
|
||||
<li>第三级无序列表</li>
|
||||
<li>第三级 <a>链接</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section style="text-align: center; margin: 0px auto; margin-top: 2em">
|
||||
<section style="border-radius: 4px; border: 1px solid #757576; display: inline-block; padding: 5px 20px;">
|
||||
<span style="font-size: 18px; color: #595959;">文本</span>
|
||||
</section>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em;">
|
||||
<p style="margin-bottom: 1em;">
|
||||
<ruby>
|
||||
拼<rp>(</rp><rt>pin</rt><rp>)</rp>
|
||||
音<rp>(</rp><rt>yin</rt><rp>)</rp>
|
||||
</ruby>
|
||||
<i>斜体</i>
|
||||
<b>粗体</b>
|
||||
上标<sup>1</sup>
|
||||
下标<sub>2</sub>
|
||||
</p>
|
||||
<p style="margin-bottom: 1em;">
|
||||
<span style="text-decoration: overline;">上划线</span>
|
||||
<s>中划线</s>
|
||||
<u>下划线</u>
|
||||
</p>
|
||||
<p>
|
||||
<big>大一号</big>
|
||||
<span>正常</span>
|
||||
<small>小一号</small>
|
||||
</p>
|
||||
<h2 style="margin-top: 0.5em;">大标题</h2>
|
||||
<h3 style="margin-top: 0.5em;">中标题</h3>
|
||||
<h4 style="margin-top: 0.5em;">小标题</h4>
|
||||
</section>
|
||||
<section style="text-align: center; margin: 0px auto; margin-top: 2em">
|
||||
<section style="border-radius: 4px; border: 1px solid #757576; display: inline-block; padding: 5px 20px;">
|
||||
<span style="font-size: 18px; color: #595959;">链接</span>
|
||||
</section>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em; text-align: center;">
|
||||
<a href="#">跳转到顶部</a> <a href="#list">跳转到列表</a>
|
||||
<div style="font-size: 12px; color: gray; margin-top: 5px;">锚点链接,将滚动到对应位置</div>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em; text-align: center;">
|
||||
<a href="https://github.com/jin-yufeng/mp-html">外部链接</a>
|
||||
<div style="font-size: 12px; color: gray; margin-top: 5px;">外部链接,将复制链接</div>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em; text-align: center;">
|
||||
<a href="/pages/jump/jump">内部链接</a>
|
||||
<div style="font-size: 12px; color: gray; margin-top: 5px;">内部链接,将跳转页面</div>
|
||||
</section>
|
||||
<section style="text-align: center; margin: 0px auto; margin-top: 2em">
|
||||
<section style="border-radius: 4px; border: 1px solid #757576; display: inline-block; padding: 5px 20px;">
|
||||
<span style="font-size: 18px; color: #595959;">图片</span>
|
||||
</section>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em; text-align: center;">
|
||||
<img src="demo.jpg">
|
||||
<div style="font-size: 12px; color: gray; margin-top: 5px;">点击预览</div>
|
||||
</section>
|
||||
<section style="margin-top: 1.5em; text-align: center;">
|
||||
<svg width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;">
|
||||
<path fill="#000" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z">
|
||||
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
</svg>
|
||||
<div style="font-size: 12px; color: gray; margin-top: 5px;">svg 动画</div>
|
||||
</section>
|
||||
</div>`
|
||||
373
wechat-mini-program/components/mp-html/test/test.js
Normal file
373
wechat-mini-program/components/mp-html/test/test.js
Normal file
@@ -0,0 +1,373 @@
|
||||
/**
|
||||
* @fileoverview 单元测试
|
||||
*/
|
||||
const path = require('path')
|
||||
const simulate = require('miniprogram-simulate')
|
||||
|
||||
const html = require('./content') // 测试 html
|
||||
const dist = '../dev/mp-weixin/components/mp-html/index' // 组件目录
|
||||
|
||||
// 新 api 模拟
|
||||
wx.getWindowInfo = function () {
|
||||
return {
|
||||
windowWidth: 414
|
||||
}
|
||||
}
|
||||
wx.getDeviceInfo = function () {
|
||||
return {
|
||||
system: 'iOS 10.0.1'
|
||||
}
|
||||
}
|
||||
const mpHtml = simulate.load(path.resolve(__dirname, dist), 'mp-html')
|
||||
|
||||
// 渲染测试
|
||||
test('render', async () => {
|
||||
// 创建和渲染页面
|
||||
const id = simulate.load({
|
||||
data: {
|
||||
containerStyle: '',
|
||||
copyLink: true,
|
||||
lazyLoad: true,
|
||||
pauseVideo: true,
|
||||
previewImg: true,
|
||||
useAnchor: true
|
||||
},
|
||||
template:
|
||||
`<scroll-view id="scroll" style="height:100px" scroll-y scroll-top="{{top}}">
|
||||
<mp-html id="article" container-style="{{containerStyle}}" content="{{html}}" domain="https://mp-html.oss-cn-hangzhou.aliyuncs.com" copy-link="{{copyLink}}" loading-img="xxx" error-img="xxx" lazy-load="{{lazyLoad}}" pause-video="{{pauseVideo}}" preview-img="{{previewImg}}" scroll-table use-anchor="{{useAnchor}}">加载中...</mp-html>
|
||||
</scroll-view>`,
|
||||
usingComponents: {
|
||||
'mp-html': mpHtml
|
||||
}
|
||||
})
|
||||
const page = simulate.render(id)
|
||||
|
||||
// 设置数据
|
||||
page.setData({
|
||||
html
|
||||
})
|
||||
await simulate.sleep(1000)
|
||||
|
||||
const comp = page.querySelector('#article')
|
||||
expect(comp.dom.tagName).toBe('MP-HTML')
|
||||
|
||||
await simulate.sleep(50)
|
||||
|
||||
// api 测试
|
||||
comp.instance.setContent(
|
||||
`<!-- 测试 base 标签 -->
|
||||
<base href="https://xxx.com">
|
||||
<!-- 测试 script 标签 -->
|
||||
<script>
|
||||
console.log('11')
|
||||
</script>
|
||||
<!-- 测试 embed 标签 -->
|
||||
<embed src="xxx.mp4" />
|
||||
<embed autostart src="xxx.m4a" />
|
||||
<!-- 测试 source 标签 -->
|
||||
<video src="xxx.mp4" style="height:auto" loop ></video>
|
||||
<!-- 测试 table 标签 -->
|
||||
<table align="center"></table>
|
||||
<table align="left" border="1">
|
||||
<td>
|
||||
<a>xxx</a>
|
||||
</td>
|
||||
</table>
|
||||
<table width="100%" border="1" style="border-collapse: collapse;">
|
||||
<colgroup><col style="width: 40%;"><col style="width: 60%;"></colgroup>
|
||||
<tr>
|
||||
<th style="vertical-align: bottom;" width="20%">标题1</th>
|
||||
<th width="80%">标题2</th>
|
||||
</tr>
|
||||
<tr style="color:gray">
|
||||
<td colspan="2" style="vertical-align:middle;text-align:right"><a>内容1</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="xxx.jpg" style="display:block">图片<td>
|
||||
<td><img src="xxx.jpg">图片<td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- 测试 font 标签、不同属性写法、实体 -->
|
||||
<font color='red' face = "宋体" size=8 >更多</font >
|
||||
<font size=0>1 < 2</font>
|
||||
<font>&#aaa;&aaa;&</FONT>
|
||||
<!-- 测试 rpx 单位处理 -->
|
||||
<span id="anchor" style="font-size:30rpx">11</span>
|
||||
<!-- 测试 pre 标签处理(保留空白符) -->
|
||||
<div style="white-space:pre">
|
||||
<pre>var i = 0</pre>
|
||||
</div>
|
||||
<!-- 测试不同情况中的图片处理 -->
|
||||
<img src="xxx" style="width:100px;height:100px;object-fit:contain">
|
||||
<img src="xxx" style="width:100px;object-fit:cover;height:100px;">
|
||||
<a data-test="test">
|
||||
<img src="//xxx.jpg">
|
||||
</a>
|
||||
<div style="display:inline-block !important;display:block">
|
||||
<img style="width:100%;" src="xxx.jpg">
|
||||
</p>
|
||||
</div>
|
||||
<div style="display:flex">
|
||||
<div style="flex:1">
|
||||
<img src="//xxx.jpg" style="display:inline">
|
||||
</div>
|
||||
</div>
|
||||
<img style="width:auto" src="data:image/png;base64,xxxx">
|
||||
<img src="xxx" style="width:20px" height="10">
|
||||
<img src="yyy.webp" style="width:1000px" ignore>
|
||||
<svg />
|
||||
<svg viewbox="0 0 1 1"><text>123</text><svg></svg></svg>
|
||||
<svg><foreignobject><div>123</div></foreignobject></svg>
|
||||
<div class="ql-align-center" style="background-image:url("/xxx.jpg?a=2&b=3")"></div>
|
||||
<![CDATA[<]]>
|
||||
<!-- 测试 flex 布局、未闭合标签、data- 属性处理 -->
|
||||
<div style="display:flex;width:1000px">
|
||||
<div style="flex:1" dir="rtl">123</div>
|
||||
</div>
|
||||
</br><div data-test="xxx" style="display:flex;display:-webkit-flex;"><div>
|
||||
<img data-src="/xxx.jpg" style="width:100%;height:100px"> `, true) // 补充测试
|
||||
expect(comp.instance.getText().includes('更多')).toBe(true) // 检查上方的实体是否被解码
|
||||
await comp.instance.getRect()
|
||||
|
||||
await comp.instance.navigateTo('anchor') // 基于页面跳转
|
||||
comp.instance.in(page.instance) // 错误设置
|
||||
comp.instance.in(page.instance, '#scroll', 'top')
|
||||
await comp.instance.navigateTo('anchor') // 基于 scroll-view 滚动
|
||||
|
||||
page.setData({
|
||||
useAnchor: false
|
||||
})
|
||||
await simulate.sleep(50)
|
||||
comp.instance.setContent('<span id="test">123</span>', true)
|
||||
try {
|
||||
await comp.instance.navigateTo('anchor') // 禁用锚点的情况下跳转
|
||||
} catch (e) { }
|
||||
|
||||
page.setData({
|
||||
containerStyle: 'white-space:pre-wrap'
|
||||
})
|
||||
await simulate.sleep(50)
|
||||
comp.instance.setContent(' 空格\n换行')
|
||||
expect(comp.instance.getText().includes('\n')).toBe(true) // 检查换行是否被保留
|
||||
|
||||
// 无图测试
|
||||
page.setData({
|
||||
lazyLoad: false
|
||||
})
|
||||
await simulate.sleep(50)
|
||||
comp.instance.setContent('<div>Hello world!</div>')
|
||||
simulate.sleep(50)
|
||||
|
||||
// 长内容测试
|
||||
let content = '<div>1</div>'.repeat(50) + '<div>'
|
||||
for (let i = 0; i < 50; i++) {
|
||||
content += '<div>' + i + '</div>'
|
||||
}
|
||||
content += '<a>xxx</a>'
|
||||
for (let i = 0; i < 3; i++) {
|
||||
content += '<div>' + i + '</div>'
|
||||
}
|
||||
comp.instance.setContent(content)
|
||||
simulate.sleep(50)
|
||||
expect(comp.data.nodes.length).toBe(2) // 应该切分为 2 块
|
||||
expect(comp.data.nodes[1].children.length).toBe(5) // 应该切分为 5 块
|
||||
|
||||
await simulate.sleep(50) // 等待异步 api 执行完毕
|
||||
|
||||
// 移除节点
|
||||
comp.triggerLifeTime('detached')
|
||||
})
|
||||
|
||||
// 事件测试
|
||||
test('event', async () => {
|
||||
// 模拟 api
|
||||
wx.createVideoContext = function () {
|
||||
// 模拟视频 context
|
||||
return {
|
||||
pause: function () { },
|
||||
playbackRate: function () { }
|
||||
}
|
||||
}
|
||||
// 测试失败回调
|
||||
wx.navigateTo = function (obj) {
|
||||
setTimeout(() => {
|
||||
if (typeof obj.fail === 'function') {
|
||||
obj.fail()
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
wx.switchTab = function (obj) {
|
||||
setTimeout(() => {
|
||||
if (typeof obj.fail === 'function') {
|
||||
obj.fail()
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
|
||||
const comp = simulate.render(mpHtml)
|
||||
comp.setData({
|
||||
selectable: 'force',
|
||||
loadingImg: 'xxx'
|
||||
})
|
||||
await simulate.sleep(50)
|
||||
|
||||
comp.instance.setContent(
|
||||
`<img src="xxx">
|
||||
<img src="yyy" width="100" height="50" ignore>
|
||||
<a href="#aaa"><img src="xxx"></a>
|
||||
<a href="https://github.com/jin-yufeng/mp-html">链接2</a>
|
||||
<a href="pages/test/test">链接3</a>
|
||||
<video src="xxx"></video>
|
||||
<video>
|
||||
<source src="/xxx">
|
||||
<source src="//yyy">
|
||||
</video>
|
||||
<base href="https://xxx.com">`)
|
||||
|
||||
await simulate.sleep(100)
|
||||
|
||||
const node = comp.querySelector('#_root')
|
||||
node.triggerLifeTime('attached')
|
||||
comp.instance._add({
|
||||
detail: node.instance
|
||||
})
|
||||
// 模拟图片加载完毕
|
||||
for (let i = 0; i <= 1; i++) {
|
||||
node.instance.imgLoad({
|
||||
target: {
|
||||
dataset: {
|
||||
i: i.toString()
|
||||
}
|
||||
},
|
||||
detail: {
|
||||
width: 100,
|
||||
height: 100
|
||||
}
|
||||
})
|
||||
// 模拟图片被点击
|
||||
node.instance.imgTap({
|
||||
target: {
|
||||
dataset: {
|
||||
i: i.toString()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
comp.setData({
|
||||
loadingImg: ''
|
||||
})
|
||||
await simulate.sleep(350)
|
||||
node.instance.imgLoad({
|
||||
target: {
|
||||
dataset: {
|
||||
i: '1'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 模拟图片链接被点击
|
||||
node.instance.imgTap({
|
||||
target: {
|
||||
dataset: {
|
||||
i: '2_0'
|
||||
}
|
||||
}
|
||||
})
|
||||
node.instance.noop()
|
||||
// 模拟图片出错
|
||||
const imgError = () => node.instance.mediaError({
|
||||
target: {
|
||||
dataset: {
|
||||
i: '0'
|
||||
}
|
||||
},
|
||||
detail: {
|
||||
errMsg: 'test'
|
||||
}
|
||||
})
|
||||
imgError()
|
||||
comp.setData({
|
||||
errorImg: 'xxx'
|
||||
}, imgError)
|
||||
// 模拟链接被点击
|
||||
for (let i = 2; i <= 4; i++) {
|
||||
node.instance.linkTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
i: i.toString()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 模拟视频播放
|
||||
for (let i = 0; i < 3; i++) {
|
||||
node.instance.play({
|
||||
target: {
|
||||
id: 'v' + (i % 2),
|
||||
dataset: {
|
||||
i: (5 + (i % 2)).toString()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 视频倍速播放
|
||||
comp.instance.setPlaybackRate(1.5)
|
||||
node.instance.play({
|
||||
target: {
|
||||
id: 'v2',
|
||||
dataset: {
|
||||
i: '6'
|
||||
}
|
||||
}
|
||||
})
|
||||
// 暂停视频播放
|
||||
comp.instance.pauseMedia()
|
||||
// 模拟视频出错
|
||||
node.instance.mediaError({
|
||||
target: {
|
||||
dataset: {
|
||||
i: '6'
|
||||
}
|
||||
},
|
||||
detail: {
|
||||
errMsg: 'test'
|
||||
}
|
||||
})
|
||||
|
||||
// 禁用一些功能
|
||||
comp.setData({
|
||||
copyLink: false,
|
||||
pauseVideo: false,
|
||||
previewImg: false
|
||||
}, () => {
|
||||
// 禁用自动拷贝后点击外部链接
|
||||
node.instance.linkTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
i: '3'
|
||||
}
|
||||
}
|
||||
})
|
||||
// 禁用自动暂停后播放视频
|
||||
node.instance.play({
|
||||
target: {
|
||||
id: 'v0',
|
||||
dataset: {
|
||||
i: '5'
|
||||
}
|
||||
}
|
||||
})
|
||||
// 禁用预览后点击图片
|
||||
node.instance.imgTap({
|
||||
target: {
|
||||
dataset: {
|
||||
i: '0'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
await simulate.sleep(100)
|
||||
})
|
||||
Reference in New Issue
Block a user