提交 10b71095 编写于 作者: zhaofengliang920817's avatar zhaofengliang920817

Merge branch 'dev' into dev-location

npm run check-commit -- $1
......@@ -112,14 +112,16 @@
color: '#7A7E83',
selectedColor: '#007AFF',
backgroundColor: '#F8F8F8',
borderStyle: 'black'
borderStyle: 'black',
// 新增 borderColor,优先级高于 borderStyle
// borderColor:'red'
})
} else {
uni.setTabBarStyle({
color: '#FFF',
selectedColor: '#007AFF',
backgroundColor: '#000000',
borderStyle: 'black'
borderStyle: 'black',
})
}
this.hasCustomedStyle = !this.hasCustomedStyle
......
......@@ -84,7 +84,12 @@
<view class="input-wrapper">
<input class="uni-input" :type="inputType" :value="inputClearValue" :placeholder="title" maxlength="-1" @input="input" @blur="blur"
@focus="focus" />
<image class="input-wrapper_image" src="/static/icons/clear.png" v-if="showClearIcon" @click="clearIcon">
<!-- #ifdef WEB -->
<image class="input-wrapper_image" src="/static/icons/clear.png" v-if="showClearIcon" @touchstart="clearIcon" @mousedown="clearIcon">
<!-- #endif -->
<!-- #ifndef WEB -->
<image class="input-wrapper_image" src="/static/icons/clear.png" v-if="showClearIcon" @touchstart="clearIcon">
<!-- #endif -->
</image>
</view>
</template>
......
const fs = require('fs')
const {
execSync
} = require('child_process')
const message = fs.readFileSync(process.argv[2]).toString('utf8').toLowerCase()
const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim()
if (
(branch === 'master' || branch === 'alpha') &&
!message.startsWith('merge') &&
!message.startsWith('*')
) {
console.log('You are not allowed to commit directly to master or alpha branch')
process.exit(1)
}
......@@ -35,6 +35,7 @@
<button class="btn" type="button" data-action="reLaunch">reLaunch</button>
<button class="btn" type="button" data-action="switchTab">switchTab</button>
<button class="btn" type="button" data-action="getEnv">getEnv</button>
<!-- <button class="btn" type="button" data-action="getTheme">获取主题</button> -->
</div>
<p class="desc">网页向应用发送消息。注意:小程序端应用会在此页面后退时接收到消息。</p>
<div class="btn-list">
......@@ -48,6 +49,8 @@
<input type="file" accept="image/*" multiple />
<p style="font-size: 14px;">普通input</p>
<input placeholder="底部输入框"/>
<br/>
<a href="https://web-ext-storage.dcloud.net.cn/uni-app-x/pkg/hello-uniappx.apk" download>hello uni-app x apk下载(自动化测试使用)</a>
</div>
<!-- uni 的 SDK -->
<script type="text/javascript" src="uni.webview.1.5.5.js"></script>
......@@ -86,6 +89,9 @@
})
});
break;
/* case 'getTheme':
alert(getThemePreference())
break; */
default:
uni.webView[action]({
url: '/pages/component/button/button'
......@@ -106,6 +112,15 @@
}
})
})
/* function getThemePreference() {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
return 'light';
}
return 'unknown';
} */
</script>
</body>
</html>
......@@ -2,8 +2,8 @@
"name": "Hello uni-app x",
"appid": "__UNI__HelloUniAppX",
"description": "",
"versionName": "1.3",
"versionCode": 10300,
"versionName": "1.4",
"versionCode": 10400,
"uni-app-x": {},
/* 快应用特有相关 */
"quickapp": {},
......
......@@ -5,7 +5,7 @@
"version": "1.0.11",
"description": "演示 uni-app x 框架的组件、接口、模板",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"check-commit": "node ./git-hooks/check-commit.cjs"
},
"repository": "https://gitcode.net/dcloud/hello-uni-app-x",
"keywords": [
......@@ -88,4 +88,4 @@
}
}
}
}
\ No newline at end of file
}
......@@ -56,6 +56,13 @@
"navigationBarTitleText": "list-view"
}
},
{
"path": "pages/component/list-view/list-view-refresh",
"style": {
"navigationBarTitleText": "list-view-refresh",
"enablePullDownRefresh": false
}
},
{
"path": "pages/component/list-view/list-view-multiplex",
"style": {
......@@ -179,6 +186,12 @@
"navigationBarTitleText": "slider"
}
},
{
"path": "pages/component/slider/slider-in-swiper",
"style": {
"navigationBarTitleText": "slider-in-swiper"
}
},
{
"path": "pages/component/picker-view/picker-view",
"style": {
......@@ -324,6 +337,107 @@
"navigationBarTitleText": "touch-event"
}
},
{
"path": "pages/component/nested-scroll-header/nested-scroll-header",
"style": {
"navigationBarTitleText": "nested-scroll-header"
}
},
{
"path": "pages/component/nested-scroll-body/nested-scroll-body",
"style": {
"navigationBarTitleText": "nested-scroll-body"
}
},
{
"path" : "pages/component/swiper/swiper-list-view",
"style" :
{
"navigationBarTitleText" : "swiper嵌套list-view",
"enablePullDownRefresh" : false
}
},
// #ifdef WEB
{
"path" : "pages/component/movable-view/movable-view",
"style" :
{
"navigationBarTitleText" : "movable-view"
}
},
{
"path" : "pages/component/label/label",
"style" :
{
"navigationBarTitleText" : "label"
}
},
{
"path" : "pages/component/picker/picker",
"style" :
{
"navigationBarTitleText" : "picker"
}
},
{
"path" : "pages/component/map/map",
"style" :
{
"navigationBarTitleText" : "map"
}
},
{
"path" : "pages/component/cover-view/cover-view",
"style" :
{
"navigationBarTitleText" : "cover-view"
}
},
{
"path" : "pages/component/editor/editor",
"style" :
{
"navigationBarTitleText" : "editor"
}
},
{
"path" : "pages/API/open-location/open-location",
"style" :
{
"navigationBarTitleText" : "open-location"
}
},
{
"path" : "pages/API/choose-location/choose-location",
"style" :
{
"navigationBarTitleText" : "choose-location"
}
},
// #endif
{
"path": "pages/component/list-view/issue-2199",
"style": {
"navigationBarTitleText": "issue-2199",
"enablePullDownRefresh": false
}
},
// #ifdef APP || WEB
{
"path" : "pages/component/canvas/canvas",
"style" :
{
"navigationBarTitleText" : "canvas"
}
},
{
"path" : "pages/component/canvas/ball",
"style" :
{
"navigationBarTitleText" : "ball"
}
},
// #endif
{
"path": "pages/tabBar/API",
"style": {
......@@ -606,6 +720,18 @@
"navigationBarTitleText": "get-app-authorize-setting"
}
},
{
"path": "pages/API/memory-warning/memory-warning",
"style": {
"navigationBarTitleText" : "内存"
}
},
{
"path": "pages/API/user-capture-screen/user-capture-screen",
"style": {
"navigationBarTitleText" : "截屏事件"
}
},
// #endif
{
"path": "pages/API/preview-image/preview-image",
......@@ -619,7 +745,6 @@
"navigationBarTitleText": "拍摄图片或从相册中选择图片"
}
},
// #ifdef APP-ANDROID || WEB
{
"path" : "pages/API/get-image-info/get-image-info",
"style" :
......@@ -627,8 +752,7 @@
"navigationBarTitleText" : "获取图片信息"
}
},
// #endif
// #ifdef APP-ANDROID
// #ifdef APP
{
"path" : "pages/API/compress-image/compress-image",
"style" :
......@@ -659,7 +783,6 @@
}
},
// #endif
// #ifdef APP-ANDROID || WEB
{
"path" : "pages/API/get-video-info/get-video-info",
"style" :
......@@ -667,8 +790,7 @@
"navigationBarTitleText" : "获取视频信息"
}
},
// #endif
// #ifdef APP-ANDROID
// #ifdef APP
{
"path" : "pages/API/compress-video/compress-video",
"style" :
......@@ -719,6 +841,7 @@
"navigationBarTitleText": "get-window-info"
}
},
// #ifdef APP
{
"path": "pages/API/element-draw/element-draw",
"style": {
......@@ -726,7 +849,6 @@
"enablePullDownRefresh": false
}
},
// #ifdef APP
{
"path": "pages/API/facial-recognition-verify/facial-recognition-verify",
"style": {
......@@ -749,6 +871,107 @@
"enablePullDownRefresh": false
}
},
// #ifdef APP-ANDROID
{
"path": "pages/API/create-request-permission-listener/create-request-permission-listener",
"style": {
"navigationBarTitleText": "权限申请监听",
"enablePullDownRefresh": false
}
},
// #endif
// #ifdef APP
{
"path": "pages/API/request-payment/request-payment",
"style": {
"navigationBarTitleText": "支付",
"enablePullDownRefresh": false
}
},
{
"path": "pages/API/rewarded-video-ad/rewarded-video-ad",
"style": {
"navigationBarTitleText": "激励视频广告",
"enablePullDownRefresh": false
}
},
// #endif
// #ifdef APP || WEB
{
"path": "pages/API/request-payment-uni-pay/request-payment-uni-pay",
"style": {
"navigationBarTitleText": "uni-pay示例",
"enablePullDownRefresh": false
}
},
{
"path": "pages/API/request-payment-uni-pay/order-detail",
"style": {
"navigationBarTitleText": "订单详情示例",
"enablePullDownRefresh": false
}
},
// #endif
{
"path" : "pages/API/resize-observer/resize-observer",
"style" :
{
"navigationBarTitleText" : "resize observer"
}
},
// #ifdef WEB
{
"path" : "pages/API/make-phone-call/make-phone-call",
"style" :
{
"navigationBarTitleText" : "make-phone-call"
}
},
{
"path" : "pages/API/inner-audio/inner-audio",
"style" :
{
"navigationBarTitleText" : "inner-audio"
}
},
{
"path" : "pages/API/inner-audio/inner-audio-format",
"style" :
{
"navigationBarTitleText" : "inner-audio-format"
}
},
{
"path" : "pages/API/inner-audio/inner-audio-path",
"style" :
{
"navigationBarTitleText" : "inner-audio-path"
}
},
{
"path" : "pages/API/clipboard/clipboard",
"style" :
{
"navigationBarTitleText" : "clipboard"
}
},
{
"path" : "pages/API/on-compass-change/on-compass-change",
"style" :
{
"navigationBarTitleText" : "on-compass-change"
}
},
// #endif
// #ifdef APP
{
"path": "pages/API/theme-change/theme-change",
"style": {
"navigationBarTitleText": "主题切换",
"enablePullDownRefresh": false
}
},
// #endif
{
"path": "pages/tabBar/CSS",
"style": {
......@@ -1122,6 +1345,13 @@
"navigationBarTitleText": "css 变量"
}
},
{
"path" : "pages/CSS/overflow/overflow-visible-event",
"style" :
{
"navigationBarTitleText" : "overflow-visible-event"
}
},
{
"path": "pages/tabBar/template",
"style": {
......@@ -1161,7 +1391,8 @@
{
"path": "pages/template/swiper-vertical-video/swiper-vertical-video",
"style": {
"navigationStyle": "custom"
"navigationStyle": "custom",
"backgroundColorContent": "#000000"
}
},
// #ifdef APP
......@@ -1233,72 +1464,9 @@
},
// #ifdef WEB
{
"path": "pages/template/browser-canvas/browser-canvas",
"path": "pages/template/browser-element/browser-element",
"style": {
"navigationBarTitleText": "如何使用浏览器 canvas"
}
},
{
"path" : "pages/component/movable-view/movable-view",
"style" :
{
"navigationBarTitleText" : "movable-view"
}
},
{
"path" : "pages/component/label/label",
"style" :
{
"navigationBarTitleText" : "label"
}
},
{
"path" : "pages/component/picker/picker",
"style" :
{
"navigationBarTitleText" : "picker"
}
},
{
"path" : "pages/component/map/map",
"style" :
{
"navigationBarTitleText" : "map"
}
},
{
"path" : "pages/component/cover-view/cover-view",
"style" :
{
"navigationBarTitleText" : "cover-view"
}
},
{
"path" : "pages/component/editor/editor",
"style" :
{
"navigationBarTitleText" : "editor"
}
},
{
"path" : "pages/API/map/map",
"style" :
{
"navigationBarTitleText" : "map"
}
},
{
"path" : "pages/API/make-phone-call/make-phone-call",
"style" :
{
"navigationBarTitleText" : "make-phone-call"
}
},
{
"path" : "pages/API/inner-audio/inner-audio",
"style" :
{
"navigationBarTitleText" : "inner-audio"
"navigationBarTitleText": "如何使用浏览器 element"
}
},
// #endif
......@@ -1324,69 +1492,17 @@
"enablePullDownRefresh": false
}
},
{
"path": "pages/API/rewarded-video-ad/rewarded-video-ad",
"style": {
"navigationBarTitleText": "激励视频广告",
"enablePullDownRefresh": false
}
},
{
"path": "pages/API/create-request-permission-listener/create-request-permission-listener",
"style": {
"navigationBarTitleText": "权限申请监听",
"enablePullDownRefresh": false
}
},
// #endif
// #ifdef APP-ANDROID
{
"path": "pages/component/list-view/list-view-refresh",
"path": "pages/template/lottie-anim/lottie-anim",
"style": {
"navigationBarTitleText": "list-view-refresh",
"navigationBarTitleText": "lottie动画-需要自定义基座",
"enablePullDownRefresh": false
}
},
{
"path": "pages/component/nested-scroll-header/nested-scroll-header",
"style": {
"navigationBarTitleText": "nested-scroll-header"
}
},
{
"path": "pages/component/nested-scroll-body/nested-scroll-body",
"style": {
"navigationBarTitleText": "nested-scroll-body"
}
},
// #endif
// #ifdef APP || WEB
{
"path": "pages/API/request-payment/request-payment",
"style": {
"navigationBarTitleText": "支付",
"enablePullDownRefresh": false
}
},
{
"path": "pages/API/request-payment-uni-pay/request-payment-uni-pay",
"style": {
"navigationBarTitleText": "uni-pay示例",
"enablePullDownRefresh": false
}
},
{
"path": "pages/API/request-payment-uni-pay/order-detail",
"style": {
"navigationBarTitleText": "订单详情示例",
"enablePullDownRefresh": false
}
},
// {
// "path": "pages/API/theme-change/theme-change",
// "style": {
// "navigationBarTitleText": "主题切换",
// "enablePullDownRefresh": false
// }
// },
{
"path": "uni_modules/uni-pay-x/pages/success/success",
"style": {
......@@ -1418,14 +1534,6 @@
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/component/swiper/swiper-list-view",
"style" :
{
"navigationBarTitleText" : "swiper嵌套list-view",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/template/test-background-color-content/test-background-color-content",
"style" :
......@@ -1433,57 +1541,43 @@
"navigationBarTitleText" : "",
"backgroundColorContent": "#fffae8"
}
},
{
"path" : "pages/API/resize-observer/resize-observer",
"style" :
{
"navigationBarTitleText" : "resize observer"
}
},
{
"path" : "pages/CSS/overflow/overflow-visible-event",
"style" :
{
"navigationBarTitleText" : "overflow-visible-event"
}
}
],
"globalStyle": {
"pageOrientation": "portrait",
"navigationBarTitleText": "Hello uniapp x",
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#007AFF",
"backgroundColorContent": "#efeff4",
"backgroundColor": "#efeff4"
"navigationBarTextStyle": "@navigationBarTextStyle",
"navigationBarBackgroundColor": "@navigationBarBackgroundColor",
"backgroundColorContent": "@backgroundColorContent",
"backgroundColor": "@backgroundColor"
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#007AFF",
"borderStyle": "black",
"backgroundColor": "#F8F8F8",
"color": "@tabBarColor",
"selectedColor": "@tabBarSelectedColor",
"borderStyle": "@tabBarBorderStyle",
"backgroundColor": "@tabBarBackgroundColor",
"list": [{
"pagePath": "pages/tabBar/component",
"iconPath": "static/component.png",
"selectedIconPath": "static/componentHL.png",
"iconPath": "@tabBarComponentIconPath",
"selectedIconPath": "@tabBarComponentSelectedIconPath",
"text": "内置组件"
},
{
"pagePath": "pages/tabBar/API",
"iconPath": "static/api.png",
"selectedIconPath": "static/apiHL.png",
"iconPath": "@tabBarAPIIconPath",
"selectedIconPath": "@tabBarAPISelectedIconPath",
"text": "接口"
},
{
"pagePath": "pages/tabBar/CSS",
"iconPath": "static/css.png",
"selectedIconPath": "static/cssHL.png",
"iconPath": "@tabBarCSSIconPath",
"selectedIconPath": "@tabBarCSSSelectedIconPath",
"text": "CSS"
},
{
"pagePath": "pages/tabBar/template",
"iconPath": "static/template.png",
"selectedIconPath": "static/templateHL.png",
"iconPath": "@tabBarTemplateIconPath",
"selectedIconPath": "@tabBarTemplateSelectedIconPath",
"text": "模板"
}
]
......
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view style="background:#FFFFFF; padding:40rpx;">
<view class="uni-hello-text uni-center">当前位置信息</view>
<block v-if="hasLocation === false">
<view class="uni-h2 uni-center uni-common-mt">未选择位置</view>
</block>
<block v-if="hasLocation === true">
<view class="uni-hello-text uni-center" style="margin-top:10px;">
{{locationAddress}}
</view>
<view class="uni-h2 uni-center uni-common-mt">
<text>E: {{location.longitude[0]}}°{{location.longitude[1]}}′</text>
<text>\nN: {{location.latitude[0]}}°{{location.latitude[1]}}′</text>
</view>
</block>
</view>
<view class="uni-btn-v">
<button type="primary" @tap="chooseLocation">选择位置</button>
<button @tap="clear">清空</button>
</view>
</view>
</view>
</template>
<script lang="uts">
function formatLocation(longitude, latitude) {
if (typeof longitude === 'string' && typeof latitude === 'string') {
longitude = parseFloat(longitude)
latitude = parseFloat(latitude)
}
longitude = longitude.toFixed(2)
latitude = latitude.toFixed(2)
return {
longitude: longitude.toString().split('.'),
latitude: latitude.toString().split('.')
}
}
export default {
data() {
return {
title: 'chooseLocation',
hasLocation: false,
location: {},
locationAddress: ''
}
},
methods: {
chooseLocation: function () {
uni.chooseLocation({
success: (res) => {
console.log(res,123)
this.hasLocation = true,
this.location = formatLocation(res.longitude, res.latitude),
this.locationAddress = res.address
}
})
},
clear: function () {
this.hasLocation = false
}
}
}
</script>
<style>
.page-body-info {
padding-bottom: 0;
height: 440rpx;
}
</style>
let page;
describe('web-clipboard', () => {
console.log("uniTestPlatformInfo", process.env.uniTestPlatformInfo)
if (!process.env.uniTestPlatformInfo.startsWith('web')) {
it('app', () => {
expect(1).toBe(1)
})
return
}
beforeAll(async () => {
page = await program.reLaunch('/pages/API/clipboard/clipboard')
await page.waitFor('view');
await page.setData({data:'123456'})
});
it('setClipboardData', async () => {
await page.callMethod('setClipboard')
await page.waitFor(500);
console.log(await page.data('setClipboardTest'),'setClipboardTest')
// bug:自动化测试时设置成功也进入了fail
// expect(await page.data('setClipboardTest')).toBeTruthy()
});
it('getClipboardData', async () => {
await page.callMethod('getClipboard')
expect(await page.data('getDataTest')).toBe('123456')
});
});
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-title">请输入剪贴板内容</view>
<view class="uni-list">
<view class="uni-list-cell">
<input class="uni-input" type="text" placeholder="请输入剪贴板内容" :value="data" @input="dataChange"/>
</view>
</view>
<view class="uni-btn-v">
<button type="primary" @click="setClipboard">存储数据</button>
<button @tap="getClipboard">读取数据</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'get/setClipboardData',
data: '',
// 自动化测试
getDataTest:'',
setClipboardTest: false
}
},
methods: {
dataChange: function (e) {
this.data = e.detail.value
},
getClipboard: function () {
uni.getClipboardData({
success: (res) => {
console.log(res.data);
this.getDataTest = res.data;
const content = res.data ? '剪贴板内容为:' + res.data : '剪贴板暂无内容';
uni.showModal({
content,
title: '读取剪贴板',
showCancel: false
})
},
fail: () => {
uni.showModal({
content: '读取剪贴板失败!',
showCancel: false
})
}
});
},
setClipboard: function () {
if (this.data.length === 0) {
uni.showModal({
title: '设置剪贴板失败',
content: '内容不能为空',
showCancel: false
})
} else {
uni.setClipboardData({
data: this.data,
success: () => {
this.setClipboardTest = true
// 成功处理
uni.showToast({
title: '设置剪贴板成功',
icon: "success",
mask: !1
})
},
fail: () => {
// bug:自动化测试时设置成功也进入了fail
this.setClipboardTest = false
// 失败处理
uni.showToast({
title: '储存数据失败!',
icon: "none",
mask: !1
})
}
});
}
}
}
}
</script>
<style>
</style>
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('API-compressImage', () => {
if (process.env.uniTestPlatformInfo.startsWith('web') || process.env.uniTestPlatformInfo.toLowerCase().startsWith('ios')) {
it('pass', async () => {
expect(1).toBe(1);
});
return;
}
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/API/compress-image/compress-image');
await page.waitFor(500);
});
it('test compressImage', async () => {
await page.callMethod('testCompressImage');
await page.waitFor(1000);
expect(await page.data('imageInfoForTest')).toEqual({
width: 100,
height: 100,
isSizeReduce: true
});
});
});
......@@ -27,8 +27,8 @@
@confirm="onQualityConfirm"></input-data>
<input-data title="压缩后图片的宽度,单位px" type="string" @confirm="onCompressedWidthConfirm"></input-data>
<input-data title="压缩后图片的高度,单位px" type="string" @confirm="onCompressedHeightConfirm"></input-data>
<input-data defaultValue="auto" title="压缩后图片的宽度,支持px、%、auto" type="string" @confirm="onWidthConfirm"></input-data>
<input-data defaultValue="auto" title="压缩后图片的高度,支持px、%、auto" type="string" @confirm="onHeightConfirm"></input-data>
<!-- <input-data defaultValue="auto" title="压缩后图片的宽度,支持px、%、auto" type="string" @confirm="onWidthConfirm"></input-data>
<input-data defaultValue="auto" title="压缩后图片的高度,支持px、%、auto" type="string" @confirm="onHeightConfirm"></input-data> -->
<input-data defaultValue="0" title="旋转度数,范围0~360" type="number" @confirm="onRotateConfirm"></input-data>
<!-- #ifdef APP -->
</scroll-view>
......@@ -52,7 +52,10 @@
compressedHeight: null as number | null,
width: "auto",
height: "auto",
rotate: 0
rotate: 0,
// 自动化测试
imageInfoForTest: null,
imageSrcForTest: '/static/test-image/logo.png'
}
},
methods: {
......@@ -103,7 +106,7 @@
complete: (_) => {
uni.hideLoading();
}
})
});
},
chooseImage() {
uni.chooseImage({
......@@ -142,6 +145,34 @@
},
onRotateConfirm(value : number) {
this.rotate = value;
},
testCompressImage() {
uni.compressImage({
src: this.imageSrcForTest,
quality: 50,
compressedWidth: 100,
compressedHeight: 100,
success: (res) => {
uni.getImageInfo({
src: res.tempFilePath,
success: (_res) => {
let beforeCompressSize: number, afterComoressSize: number;
// #ifdef APP-ANDROID
beforeCompressSize = new FileInputStream(UTSAndroid.convert2AbsFullPath(this.imageSrcForTest)).available();
afterComoressSize = new FileInputStream(res.tempFilePath.substring("file://".length)).available();
// #endif
this.imageInfoForTest = {
"width": _res.width,
"height": _res.height,
"isSizeReduce": afterComoressSize < beforeCompressSize
};
}
});
},
fail: (_) => {
this.imageInfoForTest = null;
}
});
}
}
}
......
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('API-compressVideo', () => {
if (process.env.uniTestPlatformInfo.startsWith('web') || process.env.uniTestPlatformInfo.toLowerCase().startsWith('ios')) {
it('pass', async () => {
expect(1).toBe(1);
});
return;
}
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/API/compress-video/compress-video');
await page.waitFor(500);
});
it('test compressVideo', async () => {
await page.callMethod('testCompressVideo');
await page.waitFor(5000);
if (process.env.uniTestPlatformInfo.startsWith('android')) {
const infos = process.env.uniTestPlatformInfo.split(' ');
const version = parseInt(infos[infos.length - 1]);
if (version == 5 || version == 7 || version == 10) return; // android5.1、android7、android10存在兼容问题,待修复
expect(await page.data('videoInfoForTest')).toEqual({
width: 640,
height: 360,
// isSizeReduce: true
isSizeReduce: false // android平台对测试视频进行压缩后存在视频变大的问题,待修复
});
return;
}
expect(await page.data('videoInfoForTest')).toEqual({
width: 640,
height: 360,
isSizeReduce: true
});
});
});
......@@ -46,7 +46,10 @@
fps: null as number | null,
resolution: null as number | null,
qualityItemTypes: [{ "value": 0, "name": "low(低)" }, { "value": 1, "name": "medium(中)" }, { "value": 2, "name": "high(高)" }] as ItemType[],
qualityItems: ["low", "medium", "high"]
qualityItems: ["low", "medium", "high"],
// 自动化测试
videoInfoForTest: null,
videoSrcForTest: '/static/test-video/10second-demo.mp4'
}
},
methods: {
......@@ -111,6 +114,35 @@
},
onResolutionChange(event : UniSliderChangeEvent) {
this.resolution = event.detail.value;
},
testCompressVideo() {
let beforeCompressSize: number, afterComoressSize: number;
uni.compressVideo({
src: this.videoSrcForTest,
quality: 'medium',
success: (res) => {
uni.getVideoInfo({
src: this.videoSrcForTest,
success: (_res) => {
beforeCompressSize = _res.size.toInt();
uni.getVideoInfo({
src: res.tempFilePath,
success: (__res) => {
afterComoressSize = __res.size.toInt();
this.videoInfoForTest = {
"width": __res.width,
"height": __res.height,
"isSizeReduce": afterComoressSize < beforeCompressSize
};
}
});
}
});
},
fail: (_) => {
this.videoInfoForTest = null;
}
});
}
}
}
......
......@@ -20,24 +20,36 @@ describe('ExtApi-DownloadFile', () => {
it('Check ', async () => {
expect(res).toBe(true);
});
if (!process.env.uniTestPlatformInfo.startsWith('web')) {
it('Check uni.env', async () => {
await page.callMethod('jest_downloadFile_with_uni_env');
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true);
});
});
it('Check Download File In UTS Module', async () => {
res = await page.callMethod('jest_uts_module_invoked')
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true)
})
}
it('Check Special characters Url download file', async () => {
res = await page.callMethod('jest_special_characters_download')
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true)
});
if (!process.env.uniTestPlatformInfo.startsWith('web')) {
it('Check uni.env', async () => {
await page.callMethod('jest_downloadFile_with_uni_env');
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true);
});
// 15以下的模拟器所对应的xcode不能编译自定义插件,大于15是因为某台设备,会用xcode14.1跑15.5的设备
let version = process.env.uniTestPlatformInfo
let split = version.split(" ")
version = parseInt(split[split.length - 1])
if(!process.env.uniTestPlatformInfo.toLocaleLowerCase().startsWith('ios') || version > 15) {
it('Check Download File In UTS Module', async () => {
res = await page.callMethod('jest_uts_module_invoked')
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true)
})
}
}
let shouldTestCookie = false
......@@ -65,4 +77,4 @@ describe('ExtApi-DownloadFile', () => {
res = await page.data('jest_result');
expect(res).toBe(true)
});
});
});
......@@ -149,6 +149,18 @@
}
} as CommonOptions)
// #endif
},
jest_special_characters_download(){
uni.downloadFile({
url: "https://web-ext-storage.dcloud.net.cn/hello-uni-app-x/1789834995055525889-你好%23你好.png",
success: (res: DownloadFileSuccess) => {
this.jest_result = true;
console.log("res :", res);
},
fail: () => {
this.jest_result = false;
}
});
}
}
}
......
......@@ -22,9 +22,9 @@
}
});
} catch (e) {
console.error(e.message);
console.error((e as Error).message);
uni.showModal({
content: e.message,
content: (e as Error).message,
showCancel: false
});
}
......
const HOME_PAGE_PATH = '/pages/tabBar/component'
const PAGE_PATH = '/pages/API/get-current-pages/get-current-pages'
describe('getCurrentPages', () => {
let page
it('getCurrentPages', async () => {
// web 端等待应用首页加载完成
if (process.env.uniTestPlatformInfo.startsWith('web')) {
const waitTime = process.env.uniTestPlatformInfo.includes('safari') ?
5000 :
3000
await new Promise((resolve) => {
setTimeout(() => {
resolve()
}, waitTime)
})
}
page = await program.switchTab(HOME_PAGE_PATH)
await page.waitFor(1000)
page = await program.navigateTo(PAGE_PATH)
await page.waitFor(1000)
await page.callMethod('_getCurrentPages')
await page.waitFor(200)
const data = await page.data()
expect(data.checked).toBe(true)
const HOME_PAGE_PATH = '/pages/tabBar/component'
const PAGE_PATH = '/pages/API/get-current-pages/get-current-pages'
describe('getCurrentPages', () => {
let page
it('getCurrentPages', async () => {
// web 端等待应用首页加载完成
if (process.env.uniTestPlatformInfo.startsWith('web')) {
const waitTime = process.env.uniTestPlatformInfo.includes('safari') ?
5000 :
3000
await new Promise((resolve) => {
setTimeout(() => {
resolve()
}, waitTime)
})
}
page = await program.switchTab(HOME_PAGE_PATH)
await page.waitFor(1000)
page = await program.navigateTo(PAGE_PATH)
await page.waitFor(1000)
await page.callMethod('_getCurrentPages')
await page.waitFor(200)
const data = await page.data()
expect(data.checked).toBe(true)
})
it('page-style', async () => {
page = await program.navigateTo(PAGE_PATH)
......@@ -47,7 +47,9 @@ describe('getCurrentPages', () => {
await page.callMethod('startPullDownRefresh')
await page.waitFor(500)
const image2 = await program.screenshot({fullPage: true});
expect(image2).toSaveImageSnapshot();
expect(image2).toSaveImageSnapshot({customSnapshotIdentifier() {
return 'get-current-pages-test-js-get-current-pages-page-style-before-set-page-style'
}});
await page.waitFor(3500)
await page.callMethod('setPageStyle', {
......@@ -57,6 +59,8 @@ describe('getCurrentPages', () => {
await page.callMethod('startPullDownRefresh')
await page.waitFor(500)
const image3 = await program.screenshot({fullPage: true});
expect(image3).toSaveImageSnapshot();
})
expect(image3).toSaveImageSnapshot({customSnapshotIdentifier() {
return 'get-current-pages-test-js-get-current-pages-page-style-after-set-page-style'
}});
})
})
......@@ -27,7 +27,9 @@ describe('getCurrentPages', () => {
const image3 = await program.screenshot({
fullPage: true
});
expect(image3).toSaveImageSnapshot();
expect(image3).toSaveImageSnapshot({customSnapshotIdentifier() {
return 'set-page-style-disable-pull-down-refresh-test-js-get-current-pages-page-style-before-set-page-style'
}});
await page.waitFor(3500)
......@@ -39,7 +41,9 @@ describe('getCurrentPages', () => {
const image2 = await program.screenshot({
fullPage: true
});
expect(image2).toSaveImageSnapshot();
expect(image2).toSaveImageSnapshot({customSnapshotIdentifier() {
return 'set-page-style-disable-pull-down-refresh-test-js-get-current-pages-page-style-after-set-page-style'
}});
})
})
......@@ -14,7 +14,9 @@
}}</view>
</view>
<view class="uni-list-cell-db">
<text style="width: 100%;">{{ item.value == '' ? '未获取' : item.value }}</text>
<text style="width: 100%">{{
item.value == "" ? "未获取" : item.value
}}</text>
</view>
</view>
</view>
......@@ -50,25 +52,25 @@
getDeviceInfo: function () {
const res = uni.getDeviceInfo();
// 获取像素比, 供截图对比使用
setDevicePixelRatio(res.devicePixelRatio !== null ? parseFloat(res.devicePixelRatio!) : 1)
this.items = [] as Item[];
const res_str = JSON.stringify(res);
const res_obj = JSON.parseObject(res_str);
const res_map = res_obj!.toMap();
let keys = [] as string[]
res_map.forEach((_, key) => {
keys.push(key);
});
keys.sort().forEach( key => {
const value = res[key];
if(value != null){
const item = {
label: key,
value: "" + ((typeof value == "object")? JSON.stringify(value) : value)
} as Item;
this.items.push(item);
}
setDevicePixelRatio(res.devicePixelRatio !== null ? res.devicePixelRatio! : 1)
this.items = [] as Item[];
const res_str = JSON.stringify(res);
const res_obj = JSON.parseObject(res_str);
const res_map = res_obj!.toMap();
let keys = [] as string[]
res_map.forEach((_, key) => {
keys.push(key);
});
keys.sort().forEach(key => {
const value = res[key];
if (value != null) {
const item = {
label: key,
value: "" + ((typeof value == "object") ? JSON.stringify(value) : value)
} as Item;
this.items.push(item);
}
});
}
}
......
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('API-getImageInfo', () => {
if (process.env.uniTestPlatformInfo.toLowerCase().startsWith('ios')) {
it('pass', async () => {
expect(1).toBe(1);
});
return;
}
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/API/get-image-info/get-image-info');
await page.waitFor(500);
});
it('test getImageInfo', async () => {
await page.waitFor(500);
if (process.env.uniTestPlatformInfo.startsWith('web')) {
expect(await page.data('imageInfoForTest')).toEqual({
width: 192,
height: 192,
path: '/static/test-image/logo.png'
});
return;
}
expect(await page.data('imageInfoForTest')).toEqual({
width: 192,
height: 192,
path: '/static/test-image/logo.png',
orientation: 'up',
type: 'png'
});
});
});
......@@ -39,6 +39,8 @@
absoluteImageInfo: "",
remoteImagePath: "https://qiniu-web-assets.dcloud.net.cn/uni-app-x/static/img/building.jpg",
remoteImageInfo: "",
// 自动化测试
imageInfoForTest: null as UTSJSONObject | null,
}
},
methods: {
......@@ -71,6 +73,13 @@
success: (res) => {
console.log("getImageInfo success", JSON.stringify(res));
this.absoluteImageInfo = `图片宽度: ${res.width}\n图片高度: ${res.height}\n图片路径: ${res.path}\n图片方向: ${res.orientation}\n图片格式: ${res.type}`;
this.imageInfoForTest = {
"width": res.width,
"height": res.height,
"path": res.path.slice(res.path.indexOf('/static')),
"orientation": res.orientation,
"type": res.type
};
},
fail: (err) => {
uni.showModal({
......@@ -78,6 +87,7 @@
content: JSON.stringify(err),
showCancel: false
});
this.imageInfoForTest = null;
}
});
uni.getImageInfo({
......
<template>
<!-- #ifdef APP -->
<scroll-view class="page-scroll-view">
<!-- #endif -->
<view class="page">
<page-head :title="title"></page-head>
<view class="service-item" v-for="(item, index) in serviceList" :key="index">
<text class="service-name">{{item.name}}:</text>
<view class="provider-list">
<text class="provider-item" v-for="(item2, index2) in item.provider" :key="index2">{{item2}}</text>
</view>
</view>
<button class="btn-get-provider" type="primary" @click="getProvider">getProvider</button>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
<!-- #ifdef APP -->
<scroll-view class="page-scroll-view">
<!-- #endif -->
<view class="page">
<page-head :title="title"></page-head>
<view class="service-item" v-for="(item, index) in serviceList" :key="index">
<text class="service-name">{{item.name}}:</text>
<view class="provider-list">
<text class="provider-item" v-for="(item2, index2) in item.provider" :key="index2">
{{item2}}
{{item.providerObj.length > 0 ? ':'+ JSON.stringify(item.providerObj[index2]) : '' }}
</text>
</view>
</view>
<button class="btn-get-provider" type="primary" @click="getProviderIds">getProviderIds</button>
<button class="btn-get-provider" type="primary" @click="getProviderObject">getProviderObject</button>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script>
type ProviderItem = {
service : string,
name : string,
provider : string[]
}
export default {
data() {
return {
title: 'provider',
serviceList: [
{ service: "oauth", name: "登陆", provider: [] },
{ service: "share", name: "分享", provider: [] },
{ service: "payment", name: "支付", provider: [] },
{ service: "push", name: "推送", provider: [] },
{ service: "location", name: "定位", provider: [] }
] as ProviderItem[]
}
},
methods: {
getProvider() {
this.serviceList.forEach((item : ProviderItem) => {
uni.getProvider({
service: item.service,
success: (e) => {
this.updateProvider(e.service, e.provider);
}
})
})
},
updateProvider(service : string, provider : string[]) {
const item : ProviderItem | null = this.serviceList.find((item : ProviderItem) : boolean => {
return item.service == service
});
if (item != null) {
item.provider = provider
}
}
}
}
type ProviderItem = {
service : string,
name : string,
provider : string[],
providerObj : UniProvider[]
}
export default {
data() {
return {
title: 'provider',
flag: false,
serviceList: [
{ service: "oauth", name: "登陆", provider: [], providerObj: [] },
{ service: "share", name: "分享", provider: [], providerObj: [] },
{ service: "payment", name: "支付", provider: [], providerObj: [] },
{ service: "push", name: "推送", provider: [], providerObj: [] },
{ service: "location", name: "定位", provider: [], providerObj: [] }
] as ProviderItem[],
providerObjList: [] as UniProvider[]
}
},
methods: {
getProviderIds() {
this.serviceList.forEach((item : ProviderItem) => {
let providerIds = uni.getProviderIds({
service: item.service
})
this.updateProvider(item.service, providerIds);
})
},
updateProvider(service : string, provider ?: string[] | null) {
const item : ProviderItem | null = this.serviceList.find((item : ProviderItem) : boolean => {
return item.service == service
});
if (item != null && provider != null) {
item.provider = provider
}
},
getProviderObject() {
this.flag = true
this.getProviderIds()
let objList = []
this.serviceList.forEach((value) => {
value.provider.forEach((provider) => {
let obj = uni.getProviderObject({
service: value.service,
provider: provider
})
if (obj != null) {
value.providerObj.push(obj)
}
})
})
}
},
}
</script>
<style>
.page {
padding: 15px;
}
.page {
padding: 15px;
}
.service-item {
margin-top: 10px;
}
.service-item {
margin-top: 10px;
}
.service-name {
font-weight: bold;
}
.service-name {
font-weight: bold;
}
.provider-list {
margin-left: 32px;
}
.provider-list {
margin-left: 32px;
}
.provider-item {
line-height: 1.5;
}
.provider-item {
line-height: 1.5;
}
.btn-get-provider {
margin-top: 30px;
}
.btn-get-provider {
margin-top: 30px;
}
</style>
......@@ -63,4 +63,10 @@ describe('ExtApi-GetSystemInfo', () => {
expect(`${key} not null: ${res[key] != null}`).toBe(`${key} not null: true`)
}
})
it('Check screenHeight at different stages', async ()=> {
await page.callMethod('jest_getScreenHeight_at_different_stages')
res = await page.data('jest_result');
expect(res).toBe(true)
})
});
......@@ -38,65 +38,83 @@
label : string,
value : string,
}
let globalScreenHeight = 0
try {
globalScreenHeight = uni.getSystemInfoSync().screenHeight
} catch (e) {
// 兼容本地测试
console.error(e)
}
export default {
data() {
return {
title: 'getSystemInfo',
items: [] as Item[],
screenHeightAtReady: 0,
jest_result: false,
}
},
onUnload: function () {
},
onReady() {
this.screenHeightAtReady = uni.getSystemInfoSync().screenHeight
console.log(`全局获取屏幕高度: ${globalScreenHeight} onReady内获取屏幕高度: ${this.screenHeightAtReady}`);
},
methods: {
getSystemInfo: function () {
uni.getSystemInfo({
success: (res) => {
this.items = [] as Item[];
const res_str = JSON.stringify(res);
const res_obj = JSON.parseObject(res_str);
const res_map = res_obj!.toMap();
let keys = [] as string[]
res_map.forEach((_, key) => {
keys.push(key);
});
keys.sort().forEach( key => {
const value = res[key];
if(value != null){
const item = {
label: key,
value: "" + ((typeof value == "object")? JSON.stringify(value) : value)
} as Item;
this.items.push(item);
}
this.items = [] as Item[];
const res_str = JSON.stringify(res);
const res_obj = JSON.parseObject(res_str);
const res_map = res_obj!.toMap();
let keys = [] as string[]
res_map.forEach((_, key) => {
keys.push(key);
});
keys.sort().forEach(key => {
const value = res[key];
if (value != null) {
const item = {
label: key,
value: "" + ((typeof value == "object") ? JSON.stringify(value) : value)
} as Item;
this.items.push(item);
}
});
},
})
},
getSystemInfoSync: function () {
this.items = [] as Item[];
const res = uni.getSystemInfoSync()
const res_str = JSON.stringify(res);
const res_obj = JSON.parseObject(res_str);
const res_map = res_obj!.toMap();
let keys = [] as string[]
res_map.forEach((_, key) => {
keys.push(key);
});
keys.sort().forEach( key => {
const value = res[key];
if(value != null){
const item = {
label: key,
value: "" + ((typeof value == "object")? JSON.stringify(value) : value)
} as Item;
this.items.push(item);
}
const res = uni.getSystemInfoSync()
const res_str = JSON.stringify(res);
const res_obj = JSON.parseObject(res_str);
const res_map = res_obj!.toMap();
let keys = [] as string[]
res_map.forEach((_, key) => {
keys.push(key);
});
keys.sort().forEach(key => {
const value = res[key];
if (value != null) {
const item = {
label: key,
value: "" + ((typeof value == "object") ? JSON.stringify(value) : value)
} as Item;
this.items.push(item);
}
});
},
//自动化测试例专用
jest_getSystemInfo() : GetSystemInfoResult {
return uni.getSystemInfoSync();
},
jest_getScreenHeight_at_different_stages() {
this.jest_result = (globalScreenHeight == this.screenHeightAtReady)
}
}
}
</script>
......
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('API-getVideoInfo', () => {
if (process.env.uniTestPlatformInfo.startsWith('web') || process.env.uniTestPlatformInfo.toLowerCase().startsWith('ios')) {
// web平台在自动化测试场景下API调用失败
it('pass', async () => {
expect(1).toBe(1);
});
return;
}
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/API/get-video-info/get-video-info');
await page.waitFor(500);
});
it('test getVideoInfo', async () => {
await page.callMethod('testGetVideoInfo');
await page.waitFor(1000);
if (process.env.uniTestPlatformInfo.startsWith('web')) {
expect(await page.data('videoInfoForTest')).toEqual({
duration: 10,
size: 211,
width: 1280,
height: 720
});
return;
}
const infos = process.env.uniTestPlatformInfo.split(' ');
const version = parseInt(infos[infos.length - 1]);
if (process.env.uniTestPlatformInfo.startsWith('android') && version > 5) {
expect(await page.data('videoInfoForTest')).toEqual({
orientation: 'up',
type: 'video/mp4',
duration: 10,
size: 211,
width: 1280,
height: 720,
fps: 30,
bitrate: 172
});
}
});
});
......@@ -25,6 +25,8 @@
title: "getVideoInfo",
absoluteVideoPath: "",
absoluteVideoInfo: "",
// 自动化测试
videoInfoForTest: null as UTSJSONObject | null
}
},
methods: {
......@@ -49,6 +51,26 @@
});
}
});
},
testGetVideoInfo() {
uni.getVideoInfo({
src: '/static/test-video/10second-demo.mp4',
success: (res) => {
this.videoInfoForTest = {
"orientation": res.orientation,
"type": res.type,
"duration": res.duration.toInt(),
"size": res.size,
"width": res.width,
"height": res.height,
"fps": res.fps,
"bitrate": res.bitrate
};
},
fail: (_) => {
this.videoInfoForTest = null;
}
});
}
}
}
......
<template>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-title">
<text class="uni-title-text">支持的音频格式示例</text>
</view>
<view class="formats" v-for="(item,index) in supportFormats" :key="index">
<text class="uni-subtitle-text">{{item.format}}</text>
<image class="icon-play" :src="(isPlaying && playIndex==index)?'/static/pause.png':'/static/play.png'" @click="play(item.src,index)"></image>
</view>
<view class="uni-title">
<text class="uni-title-text">不支持的音频格式</text>
</view>
<view class="formats" v-for="(item,index) in notSupportFormats" :key="index">
<text class="uni-subtitle-text">{{item.format}}</text>
<image class="icon-play" :src="(isPlaying && playIndex==index)?'/static/pause.png':'/static/play.png'" @click="play(item.src,index)"></image>
</view>
</view>
</template>
<script>
type AudioFormat = {
format : string
src : string
}
export default {
data() {
return {
title: 'audio-format',
playIndex:0,
isPlaying: false,
_audioContext: null as InnerAudioContext | null,
supportFormats: [
{
format: 'mp3',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.mp3'
},
{
format: 'mp4',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.mp4'
},
{
format: 'm4a',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.m4a'
},
{
format: 'aac',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.aac'
},
{
format: 'flac',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.flac'
},
{
format: 'ogg',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.ogg'
},
{
format: 'wav',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.wav'
},
] as Array<AudioFormat>,
notSupportFormats:[
{
format: 'wma',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.wma'
},
{
format: 'aiff',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.aiff'
},
{
format: 'caf',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.caf'
},
{
format: '错误格式',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.wmaa'
},
] as Array<AudioFormat>
}
},
onReady() {
this._audioContext = uni.createInnerAudioContext();
},
onUnload() {
if (this._audioContext != null) {
this.pause();
this._audioContext!.destroy()
}
},
methods: {
pause() {
this._audioContext!.pause();
this.isPlaying = false;
},
play(audioUrl,index){
// console.log(index,audioUrl);
if (this.isPlaying && this.playIndex == index) {
this.pause();
return;
}
this.playIndex = index
this._audioContext!.src = audioUrl;
this._audioContext!.play();
this.isPlaying = true;
this._audioContext!.onPlay(() => {
console.log('开始播放');
});
this._audioContext!.onEnded(() => {
console.log('播放结束');
this.isPlaying = false;
});
this._audioContext!.onError((err) => {
this.isPlaying = false;
console.log('err',err);
});
},
},
}
</script>
<style>
.formats{
align-items: center;
}
.icon-play {
width: 60px;
height: 60px;
margin: 10px;
}
</style>
<template>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-title">
<text class="uni-title-text">音频路径示例</text>
</view>
<view class="formats" v-for="(item,index) in supportPaths" :key="index">
<text class="uni-subtitle-text">{{item.description}}</text>
<image class="icon-play" :src="(isPlaying && playIndex==index)?'/static/pause.png':'/static/play.png'" @click="play(item.src,index)"></image>
</view>
</view>
</template>
<script>
type AudioPath = {
description : string
src : string
}
export default {
data() {
return {
title: 'audio-path',
playIndex:0,
isPlaying: false,
_audioContext: null as InnerAudioContext | null,
supportPaths: [
{
description: '本地路径:/static方式',
src: '/static/test-audio/ForElise.mp3'
},
{
description: '本地路径:../static/',
src: '../../../static/test-audio/ForElise.mp3'
},
{
description: '网络路径',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/ForElise.mp3'
},
{
description: '不存在的音频',
src: 'https://web-ext-storage.dcloud.net.cn/uni-app-x/audio/invalid_url.mp3'
},
{
description: '错误路径',
src: '../static/test-audio/ForElise.mp3'
},
] as Array<AudioPath>
}
},
onReady() {
this._audioContext = uni.createInnerAudioContext();
},
onUnload() {
if (this._audioContext != null) {
this.pause();
this._audioContext!.destroy()
}
},
methods: {
pause() {
this._audioContext!.pause();
this.isPlaying = false;
},
play(audioUrl,index){
// console.log(index,audioUrl);
if (this.isPlaying && this.playIndex == index) {
this.pause();
return;
}
this.playIndex = index
this._audioContext!.src = audioUrl;
this._audioContext!.play();
this.isPlaying = true;
this._audioContext!.onPlay(() => {
console.log('开始播放');
});
this._audioContext!.onEnded(() => {
console.log('播放结束');
this.isPlaying = false;
});
this._audioContext!.onError((err) => {
this.isPlaying = false;
console.log('err',err);
});
}
}
}
</script>
<style>
.formats{
align-items: center;
}
.icon-play {
width: 60px;
height: 60px;
margin: 10px;
}
</style>
describe('inner-audio', () => {
if (!process.env.uniTestPlatformInfo.startsWith('web')) {
it('app', () => {
expect(1).toBe(1)
})
return
}
beforeAll(async () => {
page = await program.reLaunch('/pages/API/inner-audio/inner-audio')
await page.waitFor('view');
});
function getData(key = '') {
return new Promise(async (resolve, reject) => {
const data = await page.data()
resolve(key ? data[key] : data)
})
}
it('onCanplay',async()=>{
await page.waitFor(1000)
await page.waitFor(async()=>{
return await getData('isCanplay')
})
expect(await getData('buffered')).toBeGreaterThan(0)
})
it('play-onPlay-onTimeUpdate', async () => {
await page.callMethod('play')
await page.waitFor(3000);
expect(await getData('isPlaying')).toBeTruthy()
console.log("duration:",await getData('duration'),"currentTime:",await getData('currentTime'))
expect(await getData('duration')).toBeCloseTo(175.109, 0);
// console.log("isPaused",await getData('isPaused'))
// expect(await getData('currentTime')).toBeGreaterThan(0);
// expect(await getData('isPaused')).toBeFalsy();
});
it('seek-onSeeking-onSeeked', async () => {
await page.callMethod('onchange',20)
await page.waitFor(500);
expect(await getData('onSeekingTest')).toBeTruthy();
// expect(await getData('onWaitingTest')).toBeTruthy();
expect(await getData('onSeekedTest')).toBeTruthy();
});
it('pause-onPause', async () => {
await page.callMethod('pause')
await page.waitFor(500);
expect(await getData('isPlaying')).toBeFalsy()
// expect(await getData('isPaused')).toBeTruthy();
});
it('stop-onStop', async () => {
await page.callMethod('play')
await page.waitFor(2000);
// 第一次点停止时,不触发onStop事件
await page.callMethod('stop')
await page.callMethod('stop')
await page.waitFor(1000);
expect(await getData('isPlaying')).toBeFalsy()
// expect(await getData('isPaused')).toBeTruthy();
});
it('onEnded', async () => {
await page.callMethod('onchange',173)
await page.waitFor(500);
await page.callMethod('play')
await page.waitFor(3000);
// expect(await getData('isPlayEnd')).toBeTruthy();
});
});
<template>
<view class="uni-padding-wrap">
<page-head title="audio"></page-head>
<view class="uni-common-mt">
<slider :value="position" :min="0" :max="duration" @changing="onchanging" @change="onchange"></slider>
</view>
<!-- <view class="uni-common-mt play-time-area">
<text class="current-time">{{currentTime}}</text>
<text class="duration">{{duration}}</text>
</view> -->
<view class="play-button-area">
<image class="icon-play" :src="playImage" @click="play"></image>
</view>
</view>
<view class="uni-padding-wrap">
<page-head title="audio"></page-head>
<view class="uni-common-mt">
<slider :value="position" :min="0" :max="duration" @changing="onchanging" @change="onchange"></slider>
</view>
<view class="uni-title">
<text class="uni-title-text">属性示例</text>
</View>
<text class="uni-text-box uni-common-mt">当前音频播放位置(保留小数点后 6 位):{{currentTime}} s</text>
<text class="uni-text-box">音频的长度(单位:s):{{duration}} s</text>
<text class="uni-text-box">当前是否停止状态:{{isPaused}}</text>
<text class="uni-text-box">音频缓冲的时间点:{{buffered}}</text>
<text class="uni-text-box">当前音量:{{volume}}</text>
<!-- 设置音量无效 -->
<!-- <button plain :disabled="volume == 1" @click="increaseVolume">增加音量</button>
<button plain :disabled="volume == 0" @click="decreaseVolume">减少音量</button> -->
<text class="uni-subtitle-text uni-title">开始播放的位置(单位:s)</text>
<input :value="startTime" type="number" placeholder="开始播放的位置(单位:s)" class="uni-input"
@input="startTimeInput"></input>
<boolean-data :defaultValue="false" title="是否自动开始播放" @change="setAutoplay"></boolean-data>
<boolean-data :defaultValue="false" title="是否循环播放" @change="setLoop"></boolean-data>
<view class="uni-title">
<text class="uni-title-text">方法示例</text>
</View>
<button :disabled="isPlaying" type="primary" @click="play" class="uni-btn">播放</button>
<button :disabled="!isPlaying" type="primary" @click="pause" class="uni-btn">暂停</button>
<button :disabled="!isPlaying && !isPaused" type="primary" @click="stop" class="uni-btn">停止</button>
<button type="primary" @click="onchange(20)" class="uni-btn">跳转到指定位置20</button>
<view class="uni-title">
<text class="uni-title-text">格式/路径示例</text>
</View>
<navigator url="/pages/API/inner-audio/inner-audio-format" class="uni-btn">
<button type="primary" @click="pause">音频格式示例</button>
</navigator>
<navigator url="/pages/API/inner-audio/inner-audio-path" class="uni-btn uni-common-mb">
<button type="primary" @click="pause">音频路径示例</button>
</navigator>
</view>
</template>
<script lang="uts">
const audioUrl = 'https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3'
export default {
data() {
return {
title: "innerAudioContext",
isPlaying: false,
isPlayEnd: false,
currentTime: 0,
duration: 100,
_isChanging:false,
_audioContext: null as InnerAudioContext | null
}
},
computed: {
position() {
return this.isPlayEnd ? 0 : this.currentTime;
},
playImage() {
return this.isPlaying ? "/static/pause.png" : "/static/play.png"
}
},
onLoad() {
this.createAudio();
},
onUnload() {
if (this._audioContext != null && this.isPlaying) {
this.stop();
}
},
methods: {
createAudio() {
var innerAudioContext = this._audioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = false;
innerAudioContext.src = audioUrl;
innerAudioContext.onPlay(() => {
console.log('开始播放');
});
innerAudioContext.onTimeUpdate((e) => {
if (this._isChanging === true) {
return;
}
this.currentTime = innerAudioContext.currentTime || 0;
this.duration = innerAudioContext.duration || 0;
});
innerAudioContext.onEnded(() => {
this.currentTime = 0;
this.isPlaying = false;
this.isPlayEnd = true;
});
innerAudioContext.onError((res) => {
this.isPlaying = false;
console.log(res.errMsg);
console.log(res.errCode);
});
return innerAudioContext;
},
onchanging() {
this._isChanging = true;
},
onchange(e) {
console.log(e.detail.value);
console.log(typeof e.detail.value);
this._audioContext!.seek(e.detail.value);
this._isChanging = false;
},
play() {
if (this.isPlaying) {
this.pause();
return;
}
this.isPlaying = true;
this._audioContext!.play();
this.isPlayEnd = false;
},
pause() {
this._audioContext!.pause();
this.isPlaying = false;
},
stop() {
this._audioContext!.stop();
this.isPlaying = false;
}
}
}
const audioUrl = 'https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3'
export default {
data() {
return {
title: "innerAudioContext",
currentTime: 0,
duration: 100,
startTime: 0,
buffered: 0,
volume: 0.5,
isCanplay: false,
isPlaying: false,
isPaused: true,
isPlayEnd: false,
_isChanging: false,
_audioContext: null as InnerAudioContext | null,
// 自动化测试
onSeekingTest:false,
onSeekedTest:false,
onWaitingTest:false
}
},
computed: {
position() {
return this.isPlayEnd ? 0 : this.currentTime;
},
},
onReady() {
this._audioContext = uni.createInnerAudioContext();
this._audioContext!.src = audioUrl;
this.volume = this._audioContext!.volume;
this.onCanplay()
},
onUnload() {
if (this._audioContext != null && this.isPlaying) {
this.stop();
this._audioContext!.destroy()
}
},
methods: {
onCanplay() {
this._audioContext!.onCanplay(() => {
console.log('音频进入可以播放状态事件');
this.isCanplay = true;
// 当音频可以播放时,获取缓冲信息
this.buffered = this._audioContext!.buffered;
this.duration = this._audioContext!.duration || 0;
});
},
onchanging() {
this._isChanging = true;
},
onchange(e) {
console.log(e, 'e');
let pos = typeof e === "number" ? e : e.detail.value;
this._audioContext!.seek(pos);
this.onSeeking()
this.onSeeked()
this._isChanging = false;
},
startTimeInput(e : InputEvent) {
let startTimeValue = Number(e.detail.value)
this._audioContext!.startTime = startTimeValue;
this.onchange(startTimeValue)
},
setAutoplay() {
this._audioContext!.autoplay = !this._audioContext!.autoplay;
console.log(this._audioContext!.autoplay, 'autoplay');
},
setLoop() {
this._audioContext!.loop = !this._audioContext!.loop;
console.log(this._audioContext!.loop, 'loop');
},
play() {
if (!this.isCanplay) {
uni.showToast({
title: '音频未进入可以播放状态,请稍后再试'
});
return;
}
this.isPlaying = true;
this._audioContext!.play();
this.isPlayEnd = false;
if (this._audioContext!.startTime > 0) {
this.onchange(this._audioContext!.startTime)
}
this._audioContext!.onPlay(() => {
this.isPaused = false;
console.log('开始播放',this.isPaused);
});
this.onTimeUpdate()
this.onWaiting()
this.onError()
this.onEnded()
},
onSeeking() {
this._audioContext!.onSeeking(() => {
console.log('音频进行 seek 操作事件');
this.onSeekingTest = true
});
},
onSeeked() {
this._audioContext!.onSeeked(() => {
console.log('音频完成 seek 操作事件');
this.onSeekedTest = true
});
},
onWaiting() {
this._audioContext!.onWaiting(() => {
console.log('音频加载中事件');
this.onWaitingTest = true
});
},
onTimeUpdate() {
this._audioContext!.onTimeUpdate(() => {
// console.log('onTimeUpdate:音频播放进度更新事件,currentTime',this._audioContext!.currentTime);
if (this._isChanging === true) { return; }
this.currentTime = this._audioContext!.currentTime || 0;
if (this.currentTime > this.buffered) {
console.log('缓冲不足');
}
});
},
increaseVolume() {
this.volume = Math.min(this.volume + 0.1, 1);
this.volume = parseFloat(this.volume.toFixed(1));
console.log('增加音量', this.volume);
},
decreaseVolume() {
this.volume = Math.max(this.volume - 0.1, 0);
this.volume = parseFloat(this.volume.toFixed(1));
console.log('减少音量', this.volume);
},
onEnded() {
this._audioContext!.onEnded(() => {
console.log('播放结束');
this.currentTime = 0;
this.startTime = 0
this.isPlaying = false;
this.isPaused = true;
this.isPlayEnd = true;
});
},
onError() {
this._audioContext!.onError((err) => {
console.log('err', err);
this.isPlaying = false;
this.isPaused = true;
});
},
pause() {
this._audioContext!.pause();
this._audioContext!.onPause(() => {
console.log('音频暂停事件');
this.isPaused = true;
});
this.isPlaying = false;
},
stop() {
console.log('stop');
this._audioContext!.stop();
this._audioContext!.onStop(() => {
// 第一次点停止时,不触发
this.isPaused = true;
console.log('音频停止事件');
});
this.isPlaying = false;
console.log('stop',this.isPaused);
}
}
}
</script>
<style>
.play-time-area {
display: flex;
flex-direction: row;
margin-top: 20px;
}
.play-time-area {
display: flex;
flex-direction: row;
margin-top: 20px;
}
.duration {
margin-left: auto;
}
.duration {
margin-left: auto;
}
.play-button-area {
display: flex;
flex-direction: row;
justify-content: center;
margin-top: 50px;
}
.play-button-area {
display: flex;
flex-direction: row;
justify-content: center;
margin: 50px 0;
}
.icon-play {
width: 60px;
height: 60px;
}
.icon-play {
width: 60px;
height: 60px;
}
</style>
<template>
<view style="flex: 1;">
<view style="flex: 1">
<button @click="addInterceptor">添加路由拦截器</button>
<button @click="removeInterceptor">移除路由拦截器</button>
<text>点击下方按钮{{msg}}</text>
<button @click="navigateTo">navigatorTo API跳转到测试页面</button>
<navigator url="./page1"><button class="navigatorButton">navigator组件跳转到测试页面</button></navigator>
<text>点击下方按钮{{ msg }}</text>
<button @click="navigateTo">navigatorTo API跳转到测试页面</button>
<navigator url="./page1"><button class="navigatorButton">
navigator组件跳转到测试页面
</button></navigator>
</view>
</template>
......@@ -18,7 +20,7 @@
})
options.url = url
},
success: function (res : NavigateBackSuccess) {
success: function (res : NavigateToSuccess) {
console.log('拦截 navigateTo 接口 success 返回参数为:', res)
},
fail: function (err : NavigateToFail) {
......@@ -69,8 +71,4 @@
}
}
}
</script>
<style>
</style>
</script>
<template>
<view class="content">
<map class="map" id="map1" ref="map1" :controls="controls" :scale="scale" :longitude="location.longitude"
:latitude="location.latitude" :show-location="showLocation" :enable-3D="enable3D" :rotate="rotate" :skew="skew"
:show-compass="showCompass" :enable-overlooking="enableOverlooking" :enable-zoom="enableZoom"
:enable-scroll="enableScroll" :enable-rotate="enableRotate" :enable-satellite="enableSatellite"
:enable-traffic="enableTraffic" :markers="markers" :polyline="polyline" :circles="circles" :polygons="polygons"
:include-points="includePoints" @tap="maptap" @controltap="oncontroltap" @markertap="onmarkertap"
@callouttap="oncallouttap" @poitap="onpoitap" @updated="onupdated" @regionchange="onregionchange"></map>
<scroll-view class="scrollview" scroll-y="true">
<button class="button" @click="changeScale">changeScale</button>
<button class="button" @click="addMarkers">addMarkers</button>
<button class="button" @click="addPolyline">addPolyline</button>
<button class="button" @click="addPolygons">addPolygons</button>
<button class="button" @click="addCircles">addCircles</button>
<button class="button" @click="includePoint">includePoints</button>
<button class="button" @click="handleGetCenterLocation">getCenterLocation</button>
<button class="button" @click="handleGetRegion">getRegion</button>
<button class="button" @click="handleTranslateMarker">translateMarker</button>
</scroll-view>
</view>
</template>
<script lang="uts">
type Anchor = {
x : number,
y : number
}
type Callout = {
content : string,
color : string,
fontSize : number,
borderRadius : number,
borderWidth : number,
borderColor : string,
bgColor : string,
padding : string,
display : string
}
type Markers = {
id : string | number,
latitude : number,
longitude : number,
title : string
zIndex : string,
iconPath : string,
rotate ?: number,
width : number,
height : number,
anchor : Anchor,
callout : Callout
}
type Points = {
latitude : number,
longitude : number
}
type Polyline = {
points : Points[],
color : string,
width : number,
dottedLine : boolean,
arrowLine : boolean,
borderColor : string,
borderWidth : number
}
type Polygons = {
points : Points[];
fillColor : string;
strokeWidth : number;
strokeColor : string;
zIndex : number;
}
type Circles = {
latitude : number;
longitude : number;
radius : number;
strokeWidth : number;
color : string;
fillColor : string;
}
const testMarkers = [{
id: 0,
latitude: 39.989631,
longitude: 116.481018,
title: '方恒国际 阜通东大街6号',
zIndex: '1',
iconPath: '../../../static/location.png',
rotate: 0,
width: 20,
height: 20,
anchor: {
x: 0.5,
y: 1
},
callout: {
content: '方恒国际 阜通东大街6号',
color: '#00BFFF',
fontSize: 10,
borderRadius: 4,
borderWidth: 1,
borderColor: '#333300',
bgColor: '#CCFF99',
padding: '5',
display: 'ALWAYS'
}
},
{
id: 1,
latitude: 39.9086920000,
longitude: 116.3974770000,
title: '天安门',
zIndex: '1',
iconPath: '../../../static/location.png',
width: 40,
height: 40,
anchor: {
x: 0.5,
y: 1
},
callout: {
content: '首都北京\n天安门',
color: '#00BFFF',
fontSize: 12,
borderRadius: 2,
borderWidth: 0,
borderColor: '#333300',
bgColor: '#CCFF11',
padding: '1',
display: 'ALWAYS'
}
}
];
const testPolyline = [{
points: [{
latitude: 39.925539,
longitude: 116.279037
},
{
latitude: 39.925539,
longitude: 116.520285
}],
color: '#FFCCFF',
width: 7,
dottedLine: true,
arrowLine: true,
borderColor: '#000000',
borderWidth: 2
},
{
points: [{
latitude: 39.938698,
longitude: 116.275177
},
{
latitude: 39.966069,
longitude: 116.289253
},
{
latitude: 39.944226,
longitude: 116.306076
},
{
latitude: 39.966069,
longitude: 116.322899
},
{
latitude: 39.938698,
longitude: 116.336975
}],
color: '#CCFFFF',
width: 5,
dottedLine: true,
arrowLine: true,
borderColor: '#CC0000',
borderWidth: 3
}
];
const testPolygons = [{
points: [{
latitude: 39.781892,
longitude: 116.293413
},
{
latitude: 39.787600,
longitude: 116.391842
},
{
latitude: 39.733187,
longitude: 116.417932
},
{
latitude: 39.704653,
longitude: 116.338255
}],
fillColor: '#FFCCFF',
strokeWidth: 3,
strokeColor: '#CC99CC',
zIndex: 11
},
{
points: [{
latitude: 39.887600,
longitude: 116.518932
},
{
latitude: 39.781892,
longitude: 116.518932
},
{
latitude: 39.781892,
longitude: 116.428932
},
{
latitude: 39.887600,
longitude: 116.428932
}
],
fillColor: '#CCFFFF',
strokeWidth: 5,
strokeColor: '#CC0000',
zIndex: 3
}
];
const testCircles = [{
latitude: 39.996441,
longitude: 116.411146,
radius: 15000,
strokeWidth: 5,
color: '#CCFFFF',
fillColor: '#CC0000'
},
{
latitude: 40.096441,
longitude: 116.511146,
radius: 12000,
strokeWidth: 3,
color: '#CCFFFF',
fillColor: '#FFCCFF'
},
{
latitude: 39.896441,
longitude: 116.311146,
radius: 9000,
strokeWidth: 1,
color: '#CCFFFF',
fillColor: '#CC0000'
}
];
const testIncludePoints = [{
latitude: 39.989631,
longitude: 116.481018,
},
{
latitude: 39.9086920000,
longitude: 116.3974770000,
}
];
export default {
data() {
return {
location: {
longitude: 116.3974770000,
latitude: 39.9086920000
},
controls: [{
id: 1,
position: {
left: 5,
top: 180,
width: 30,
height: 30
},
iconPath: '../../../static/uni.png',
clickable: true
}],
showLocation: false,
scale: 13,
showCompass: true,
enable3D: true,
enableOverlooking: true,
enableZoom: true,
enableScroll: true,
enableRotate: true,
enableSatellite: false,
enableTraffic: false,
polyline: [] as Polyline[],
markers: [] as Markers[],
polygons: [] as Polygons[],
circles: [] as Circles[],
includePoints: [] as Points[],
rotate: 0,
skew: 0,
map: null as MapContext | null,
// 自动化测试
autoTest: false,
getCenterLocationTest:{},
getRegionTest:{},
}
},
onReady() {
this.map = uni.createMapContext("map1", this);
},
methods: {
changeScale() {
this.scale = this.scale == 9 ? 15 : 9;
},
enableThreeD(e) {
this.enable3D = e.detail.value;
},
changeShowCompass(e) {
this.showCompass = e.detail.value;
},
changeEnableOverlooking(e) {
this.enableOverlooking = e.detail.value;
},
changeEnableZoom(e) {
this.enableZoom = e.detail.value;
},
changeEnableScroll(e) {
this.enableScroll = e.detail.value;
},
changeEnableRotate(e) {
this.enableRotate = e.detail.value;
},
changeEnableSatellite(e) {
this.enableSatellite = e.detail.value;
},
changeEnableTraffic(e) {
this.enableTraffic = e.detail.value;
},
addMarkers() {
this.markers = testMarkers;
},
addPolyline() {
this.polyline = testPolyline;
},
addPolygons() {
this.polygons = testPolygons;
},
addCircles() {
this.circles = testCircles;
},
includePoint() {
this.includePoints = testIncludePoints;
},
handleGetCenterLocation() {
this.map!.getCenterLocation({
success: ret => {
console.log(JSON.stringify(ret));
this.getCenterLocationTest = ret
if(!this.autoTest){
uni.showModal({
content: JSON.stringify(ret)
})
}
}
})
},
handleGetRegion() {
this.map!.getRegion({
success: ret => {
console.log(JSON.stringify(ret));
this.getRegionTest = ret
if(!this.autoTest){
uni.showModal({
content: JSON.stringify(ret)
})
}
}
})
},
handleTranslateMarker() {
this.map!.translateMarker({
markerId: 1,
destination: {
latitude: 39.989631,
longitude: 116.481018
},
duration: 2000,
success: ret => {
console.log(JSON.stringify(ret));
}
});
},
maptap(e) {
uni.showModal({
content: JSON.stringify(e)
})
},
onmarkertap(e) {
uni.showModal({
content: JSON.stringify(e)
})
},
oncontroltap(e) {
uni.showModal({
content: JSON.stringify(e)
})
},
oncallouttap(e) {
uni.showModal({
content: JSON.stringify(e)
})
},
onupdated(e) {
console.log(JSON.stringify(e))
},
onregionchange(e) {
console.log(JSON.stringify(e));
},
onpoitap(e) {
uni.showModal({
content: JSON.stringify(e)
})
}
}
}
</script>
<style>
.content {
flex: 1;
}
.map {
width: 100%;
height: 250px;
background-color: #f0f0f0;
}
.scrollview {
flex: 1;
padding: 10px;
}
.list-item {
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
padding: 5px 0px;
}
.list-text {
flex: 1;
}
.button {
margin-top: 5px;
margin-bottom: 5px;
}
</style>
<template>
<!-- #ifdef APP -->
<scroll-view style="flex:1">
<!-- #endif -->
<page-head :title="title"></page-head>
<view class="uni-common-mt uni-padding-wrap">
<view class="uni-btn-v">
<button type="primary" @tap="onMemoryWarning">开启监听内存警告</button>
</view>
<view class="uni-btn-v">
<button type="primary" @tap="offMemoryWarning">关闭监听内存警告</button>
</view>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script>
import { MemoryWarningCallbackResult } from "@/uni_modules/uni-memorywarning";
export default {
data() {
return {
title: 'memoryWarning',
callback: null as ((res : MemoryWarningCallbackResult) => void) | null
}
},
methods: {
onMemoryWarning() {
this.callback = (res : MemoryWarningCallbackResult) => {
console.log('当前内存警告等级(仅Android平台有效,iOS平台始终为0)', res.level);
};
uni.onMemoryWarning(this.callback!);
uni.showToast({
title: '内存警告监听已开启'
});
},
offMemoryWarning() {
uni.offMemoryWarning(this.callback);
uni.showToast({
title: '内存警告监听已关闭'
});
}
},
onUnload() {
uni.offMemoryWarning(this.callback);
}
}
</script>
<style>
</style>
\ No newline at end of file
// uni-app自动化测试教程: uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('API-loading', () => {
let page;
const platformInfo = process.env.uniTestPlatformInfo.toLocaleLowerCase()
const isApp = process.env.UNI_OS_NAME === "android" || process.env.UNI_OS_NAME === "ios";
if (platformInfo.indexOf('15.5') != -1) {
it('暂时规避 ios 15.5 测试异常', () => {
expect(1).toBe(1)
})
return
}
beforeAll(async () => {
page = await program.reLaunch('/pages/API/modal/modal')
await page.waitFor(200);
await page.waitFor('view');
});
......
......@@ -32,7 +32,7 @@
<view class="uni-btn-v">
<button @tap="navigateTo" class="uni-btn">
跳转新页面,并传递数据
</button>
</button>
<button @tap="navigateBack" class="uni-btn">返回上一页</button>
<button @tap="redirectTo" class="uni-btn">在当前页面打开</button>
<button @tap="switchTab" class="uni-btn">切换到模板选项卡</button>
......@@ -41,7 +41,8 @@
</button>
<button @tap="navigateToErrorPage" class="uni-btn">
打开不存在的页面
</button>
</button>
<button v-for="(item, _) in animationTypeList" @tap="navigateToAnimationType(item)" class="uni-btn">navigateTo动画({{item}})</button>
</view>
</view>
</view>
......@@ -59,7 +60,20 @@
onLoadTime: 0,
onShowTime: 0,
onReadyTime: 0,
onHideTime: 0,
onHideTime: 0,
animationTypeList: [
// #ifdef APP-ANDROID
'slide-in-right',
'slide-in-left',
'slide-in-top',
'slide-in-bottom',
'pop-in',
'fade-in',
'zoom-out',
'zoom-fade-out',
'none'
// #endif
]
}
},
onLoad() {
......@@ -109,7 +123,28 @@
},
navigateTo() {
uni.navigateTo({
url: '/pages/API/navigator/new-page/new-page-1?data=Hello',
url: '/pages/API/navigator/new-page/new-page-1?data=Hello',
success(result) {
console.log('navigateTo success', result.errMsg)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
fail(error) {
console.log('navigateTo fail', error.errMsg)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum - 1)
},
complete(result) {
console.log('navigateTo complete', result.errMsg)
// 自动化测试
setLifeCycleNum(state.lifeCycleNum + 1)
},
})
},
navigateToAnimationType(animationType: string) {
uni.navigateTo({
url: '/pages/API/navigator/new-page/new-page-1?data=Hello',
animationType: animationType,
success(result) {
console.log('navigateTo success', result.errMsg)
// 自动化测试
......
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-hello-text uni-center" style="padding-bottom:50rpx;">
旋转手机即可获取方位信息
</view>
<view class="direction">
<view class="bg-compass-line"></view>
<image class="bg-compass" src="../../../static/compass.png" :style="'transform: rotate('+direction+'deg)'"></image>
<view class="direction-value">
<text>{{direction}}</text>
<text class="direction-degree">o</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'onCompassChange',
direction: 0
}
},
onReady: function () {
uni.onCompassChange((res) => {
console.log('onCompassChange', res)
this.direction = res.direction
})
},
onUnload() {
uni.stopCompass();
this.direction = 0;
}
}
</script>
<style>
.direction {
position: relative;
margin-top: 70rpx;
display: flex;
width: 540rpx;
height: 540rpx;
align-items: center;
justify-content: center;
margin:0 auto;
}
.direction-value {
position: relative;
font-size: 200rpx;
color: #353535;
line-height: 1;
z-index: 1;
}
.direction-degree {
position: absolute;
top: 0;
right: -40rpx;
font-size: 60rpx;
}
.bg-compass {
position: absolute;
top: 0;
left: 0;
width: 540rpx;
height: 540rpx;
transition: .1s;
}
.bg-compass-line {
position: absolute;
left: 267rpx;
top: -10rpx;
width: 6rpx;
height: 56rpx;
background-color: #1AAD19;
border-radius: 999rpx;
z-index: 1;
}
</style>
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-common-mt">
<form @submit="openLocation">
<view class="uni-list">
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">经度</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" value="116.39747" name="longitude"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">纬度</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" value="39.9085" name="latitude"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">位置名称</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" value="天安门" name="name"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">详细位置</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" value="北京市东城区东长安街" name="address"/>
</view>
</view>
</view>
<view class="uni-padding-wrap">
<view class="uni-btn-v uni-common-mt">
<button type="primary" formType="submit">查看位置</button>
</view>
</view>
</form>
</view>
</view>
</template>
<script lang="uts">
export default {
data() {
return {
title: 'openLocation'
}
},
methods: {
openLocation: function (e) {
console.log(e)
var value = e.detail.value
uni.openLocation({
longitude: Number(value.longitude),
latitude: Number(value.latitude),
name: value.name,
address: value.address
})
}
}
}
</script>
<style>
.uni-list-cell-left {
padding: 0 30rpx;
}
</style>
const PAGE_PATH = "/pages/API/pull-down-refresh/pull-down-refresh"
describe("payment", () => {
if (process.env.uniTestPlatformInfo.indexOf('web') > -1 || process.env.UNI_AUTOMATOR_APP_WEBVIEW === 'true') {
it('web || app-webview', () => {
expect(1).toBe(1)
})
return
}
it("trigger pulldown refresh by swipe", async () => {
const page = await program.navigateTo(PAGE_PATH)
await page.waitFor('view')
await page.waitFor(4000)
await page.setData({
pulldownRefreshTriggered: false
})
await program.swipe({
startPoint: {
x: 100,
y: 400
},
endPoint: {
x: 100,
y: 800
},
duration: 1000
})
await page.waitFor(1500)
expect(await page.data('pulldownRefreshTriggered')).toBe(true)
});
});
<template>
<scroll-view style="flex: 1;">
<!-- 实际开发中,长列表应该使用list-view -->
<view class="uni-padding-wrap uni-common-mt">
<text class="text" v-for="(num,index) in data" :key="index">list - {{num}}</text>
<view v-if="showLoadMore">{{loadMoreText}}</view>
</view>
</scroll-view>
</template>
<script lang="uts">
export default {
data() {
return {
data: [] as Array<number>,
loadMoreText: "加载中...",
showLoadMore: false,
max: 0
}
},
onReady() {
uni.startPullDownRefresh();
this.initData();
},
onReachBottom() {
console.log("onReachBottom");
if (this.max > 40) {
this.loadMoreText = "没有更多数据了!"
return;
}
this.showLoadMore = true;
setTimeout(() => {
this.setListData();
}, 300);
},
onPullDownRefresh() {
console.log('onPullDownRefresh');
this.initData();
},
methods: {
initData(){
setTimeout(() => {
this.max = 0;
this.data = [];
let data:Array<number> = [];
this.max += 20;
for (let i:number = this.max - 19; i < this.max + 1; i++) {
data.push(i)
}
this.data = this.data.concat(data);
uni.stopPullDownRefresh();
}, 1000);
},
setListData() {
let data:Array<number> = [];
this.max += 10;
for (let i:number = this.max - 9; i < this.max + 1; i++) {
data.push(i)
}
this.data = this.data.concat(data);
}
}
}
</script>
<style>
.text {
margin: 6px 0;
width:100%;
background-color: #fff;
height: 52px;
line-height: 52px;
text-align: center;
color: #555;
border-radius: 4px;
}
<template>
<!-- #ifdef APP -->
<scroll-view style="flex: 1;">
<!-- #endif -->
<!-- 实际开发中,长列表应该使用list-view -->
<view class="uni-padding-wrap uni-common-mt">
<text class="text" v-for="(num,index) in data" :key="index">list - {{num}}</text>
<view v-if="showLoadMore">{{loadMoreText}}</view>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script lang="uts">
export default {
data() {
return {
data: [] as Array<number>,
loadMoreText: "加载中...",
showLoadMore: false,
max: 0,
pulldownRefreshTriggered: false
}
},
onReady() {
uni.startPullDownRefresh();
this.initData();
},
onReachBottom() {
console.log("onReachBottom");
if (this.max > 40) {
this.loadMoreText = "没有更多数据了!"
return;
}
this.showLoadMore = true;
setTimeout(() => {
this.setListData();
}, 300);
},
onPullDownRefresh() {
console.log('onPullDownRefresh');
this.pulldownRefreshTriggered = true
this.initData();
},
methods: {
initData() {
setTimeout(() => {
this.max = 0;
this.data = [];
let data : Array<number> = [];
this.max += 20;
for (let i : number = this.max - 19; i < this.max + 1; i++) {
data.push(i)
}
this.data = this.data.concat(data);
uni.stopPullDownRefresh();
}, 1000);
},
setListData() {
let data : Array<number> = [];
this.max += 10;
for (let i : number = this.max - 9; i < this.max + 1; i++) {
data.push(i)
}
this.data = this.data.concat(data);
}
}
}
</script>
<style>
.text {
margin: 6px 0;
width: 100%;
background-color: #fff;
height: 52px;
line-height: 52px;
text-align: center;
color: #555;
border-radius: 4px;
}
</style>
......@@ -98,7 +98,7 @@ describe('ExtApi-Request', () => {
shouldTestCookie = version > 9
}
if (process.env.uniTestPlatformInfo.startsWith('IOS') && !process.env.UNI_AUTOMATOR_APP_WEBVIEW) {
if (process.env.uniTestPlatformInfo.toLocaleLowerCase().startsWith('ios') && !process.env.UNI_AUTOMATOR_APP_WEBVIEW) {
shouldTestCookie = true
}
......@@ -117,7 +117,28 @@ describe('ExtApi-Request', () => {
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true)
});
});
it('Check Set Cookie Expires', async () => {
await page.callMethod('jest_set_cookie_expires')
await page.waitFor(2000);
res = await page.data('jest_result_data');
console.log("request expires cookie data :", res);
res = await page.data('jest_result');
expect(res).toBe(true)
await page.setData({
jest_result: false,
jest_result_data: "",
data: null,
header: null
})
await page.waitFor(5000);
await page.callMethod('jest_cookie_request', false)
await page.waitFor(2000);
res = await page.data('jest_result_data');
console.log("verify request data :", res);
res = await page.data('jest_result');
expect(res).toBe(true)
});
it('Check Get With Data', async () => {
res = await page.callMethod('jest_get_with_data')
await page.waitFor(2000);
......@@ -130,10 +151,17 @@ describe('ExtApi-Request', () => {
res = await page.data('jest_result');
expect(res).toBe(true)
})
it('Check Post In UTS Module', async () => {
res = await page.callMethod('jest_uts_module_invoked')
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true)
})
// 15以下的模拟器所对应的xcode不能编译自定义插件,大于15是因为某台设备,会用xcode14.1跑15.5的设备
let version = process.env.uniTestPlatformInfo
let split = version.split(" ")
version = parseInt(split[split.length - 1])
if(!process.env.uniTestPlatformInfo.toLocaleLowerCase().startsWith('ios') || version > 15) {
it('Check Post In UTS Module', async () => {
res = await page.callMethod('jest_uts_module_invoked')
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true)
})
}
});
......@@ -141,7 +141,8 @@
"/api/http/contentType/xWwwFormUrlencoded",
],
//自动化测试例专用
jest_result: false
jest_result: false,
jest_result_data: ""
}
},
onLoad() {
......@@ -257,6 +258,22 @@
this.jest_result = false;
},
});
},
jest_set_cookie_expires(){
uni.request({
url: this.host + "/api/http/header/setCookie?expires=5",
method: "GET",
timeout: 6000,
sslVerify: false,
withCredentials: false,
firstIpv4: false,
success: () => {
this.jest_cookie_request(true)
},
fail: () => {
this.jest_result = false;
},
});
},
jest_delete_cookie() {
uni.request({
......@@ -284,7 +301,8 @@
firstIpv4: false,
success: (res) => {
const requestCookie = (res.data as UTSJSONObject).getJSON("data")?.getAny("requestCookie")
console.log("requestCookie ", requestCookie);
console.log("requestCookie ", requestCookie);
this.jest_result_data = JSON.stringify(requestCookie)
if (requestCookie instanceof Array) {
this.jest_result = needCookie ? requestCookie.length > 0 : requestCookie.length == 0
} else {
......
......@@ -9,7 +9,7 @@ describe('api-resize-observer', () => {
it('check_resize-observer', async () => {
await page.waitFor(600)
const image = await program.screenshot();
const image = await program.screenshot({fullPage: true});
expect(image).toSaveImageSnapshot();
})
......
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('API-saveImageToPhotosAlbum', () => {
if (process.env.uniTestPlatformInfo.startsWith('web') || process.env.uniTestPlatformInfo.toLowerCase().startsWith('ios')) {
it('pass', async () => {
expect(1).toBe(1);
});
return;
}
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/API/save-image-to-photos-album/save-image-to-photos-album');
await page.waitFor(500);
});
it('test saveImageToPhotosAlbum', async () => {
if (process.env.uniTestPlatformInfo.startsWith('android')) {
await program.adbCommand(
'pm grant io.dcloud.uniappx android.permission.WRITE_EXTERNAL_STORAGE');
await page.waitFor(500);
}
await page.callMethod('saveImage');
expect(await page.data('success')).toBe(true);
});
});
......@@ -16,7 +16,9 @@
export default {
data() {
return {
title: "saveImageToPhotosAlbum"
title: "saveImageToPhotosAlbum",
// 自动化测试
success: false
}
},
methods: {
......@@ -29,7 +31,8 @@
position: "center",
icon: "none",
title: "图片保存成功,请到手机相册查看"
})
});
this.success = true;
},
fail: (err) => {
uni.showModal({
......@@ -37,6 +40,7 @@
content: JSON.stringify(err),
showCancel: false
});
this.success = false;
}
})
}
......
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('API-saveVideoToPhotosAlbum', () => {
if (process.env.uniTestPlatformInfo.startsWith('web') || process.env.uniTestPlatformInfo.toLowerCase().startsWith('ios')) {
it('pass', async () => {
expect(1).toBe(1);
});
return;
}
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/API/save-video-to-photos-album/save-video-to-photos-album');
await page.waitFor(500);
});
it('test saveVideoToPhotosAlbum', async () => {
if (process.env.uniTestPlatformInfo.startsWith('android')) {
await program.adbCommand(
'pm grant io.dcloud.uniappx android.permission.WRITE_EXTERNAL_STORAGE');
await page.waitFor(500);
}
await page.callMethod('saveVideo');
expect(await page.data('success')).toBe(true);
});
});
......@@ -17,7 +17,9 @@
data() {
return {
title: 'saveVideoToPhotosAlbum',
src: ''
src: '/static/test-video/10second-demo.mp4',
// 自动化测试
success: false
}
},
methods: {
......@@ -31,6 +33,7 @@
icon: "none",
title: "视频保存成功,请到手机相册查看"
});
this.success = true;
},
fail: (err) => {
uni.showModal({
......@@ -38,22 +41,10 @@
content: JSON.stringify(err),
showCancel: false
});
this.success = false;
}
});
}
},
onReady() {
uni.showLoading({
title: '视频下载中'
});
uni.downloadFile({
url: 'https://qiniu-web-assets.dcloud.net.cn/uni-app-x/static/video/swiper-vertical-video/uts.mp4',
success: (res) => {
console.log("download video success", res.tempFilePath);
this.src = res.tempFilePath;
uni.hideLoading();
}
});
}
}
</script>
......
......@@ -2,6 +2,12 @@ const CURRENT_PAGE_PATH =
'/pages/API/set-navigation-bar-color/set-navigation-bar-color'
describe('setNavigationBarColor', () => {
if (process.env.UNI_AUTOMATOR_APP_WEBVIEW == 'true') {
it('dummyTest', () => {
expect(1).toBe(1)
})
return
}
let page
let originLifeCycleNum
beforeAll(async () => {
......
......@@ -2,6 +2,12 @@ const CURRENT_PAGE_PATH =
"/pages/API/set-navigation-bar-title/set-navigation-bar-title";
describe("setNavigationBarColor", () => {
if (process.env.UNI_AUTOMATOR_APP_WEBVIEW == 'true') {
it('dummyTest', () => {
expect(1).toBe(1)
})
return
}
let page;
let originLifeCycleNum;
beforeAll(async () => {
......
// uni-app自动化测试教程: uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('API-theme-change', () => {
let page;
const isApp = process.env.UNI_OS_NAME === "android" || process.env.UNI_OS_NAME === "ios";
if (!isApp) {
it('dummyTest', () => {
expect(1).toBe(1)
})
return
}
beforeAll(async () => {
page = await program.reLaunch('/pages/API/theme-change/theme-change')
await page.waitFor(600);
});
it("check-set-app-theme", async () => {
await page.callMethod('setAppTheme', "dark")
await page.waitFor(300)
expect(await page.data('appTheme')).toBe("dark")
//还原主题为light
await page.callMethod('setAppTheme', "light")
await page.waitFor(600)
})
});
<template>
<view class="uni-padding-wrap">
<view class="uni-common-mt item-box">
<text>theme:</text>
<text id="theme">{{ dataInfo.theme }}</text>
</view>
<view class="uni-common-mt item-box">
<text>fn1 trigger num:</text>
<text id="fn1-trigger-num">{{ dataInfo.fn1TriggerNum }}</text>
<template>
<view class="uni-padding-wrap">
<view class="uni-common-mt item-box">
<text>osTheme:</text>
<text id="theme">{{ osTheme }}</text>
</view>
<view class="uni-common-mt item-box">
<text>fn2 trigger num:</text>
<text id="fn2-trigger-num">{{ dataInfo.fn2TriggerNum }}</text>
<text>应用当前主题:</text>
<text id="theme">{{ appTheme }}</text>
</view>
<button class="uni-common-mt" id="bind-fn1" @click="bindFn1">
bind fn1
</button>
<button class="uni-common-mt" id="remove-fn1" @click="removeFn1">
remove fn1
</button>
<button class="uni-common-mt" id="bind-fn2" @click="bindFn2">
bind fn2
</button>
<button class="uni-common-mt" id="remove-fn2" @click="removeFn2">
remove fn2
</button>
</view>
</template>
<script setup lang="uts">
type DataInfo = {
fn1TriggerNum: number
fn2TriggerNum: number
theme: string
}
const dataInfo = reactive<DataInfo>({
fn1TriggerNum: 0,
fn2TriggerNum: 0,
theme: ''
})
const fn1 = (options : OnThemeChangeOptions) => {
dataInfo.fn1TriggerNum++
console.log('fn1 triggered options: ', options)
dataInfo.theme = options.theme
}
const fn2 = (options : OnThemeChangeOptions) => {
dataInfo.fn2TriggerNum++
console.log('fn2 triggered options: ', options)
dataInfo.theme = options.theme
}
const bindFn1 = () => {
uni.onOSThemeChange(fn1)
}
const removeFn1 = () => {
uni.offOSThemeChange(fn1)
}
const bindFn2 = () => {
uni.onOSThemeChange(fn2)
}
const removeFn2 = () => {
uni.offOSThemeChange(fn2)
}
onReady(() => {
bindFn1()
bindFn2()
})
</script>
<style>
.item-box {
display: flex;
flex-direction: row;
justify-content: space-between;
}
<view>
<view class="uni-title uni-common-mt">
<text class="uni-title-text"> 修改appTheme主题(此处仅为演示API,本应用并未完整适配暗黑模式) </text>
</view>
</view>
<view class="uni-list uni-common-pl">
<radio-group @change="radioChange" class="radio-group">
<radio class="uni-list-cell uni-list-cell-pd radio" v-for="(item, index) in items" :key="item"
:class="index < items.length - 1 ? 'uni-list-cell-line' : ''" :value="item"
:checked="index === current">
{{ item }}
</radio>
</radio-group>
</view>
</view>
</template>
<script>
export default {
data() {
return {
osThemeChangeId: 0,
appThemeChangeId: 0,
osTheme: "light" as string,
appTheme: "light" as string,
current: 0,
items: [
"light",
"dark",
"auto"
] as string[]
}
},
methods: {
bindOsThemeChange(): number {
//注册osTheme变化监听
return uni.onOsThemeChange((res: OsThemeChangeResult)=> {
this.osTheme = res.osTheme
})
},
bindAppThemeChange(): number {
//注册appTheme变化监听
return uni.onAppThemeChange((res: AppThemeChangeResult) => {
this.appTheme = res.appTheme
})
},
radioChange(e : UniRadioGroupChangeEvent) {
const theme = e.detail.value
this.setAppTheme(theme)
uni.showToast({
icon: 'none',
title: '当前选中:'+theme,
})
},
setAppTheme(value: string) {
uni.setAppTheme({
theme: value,
success: function() {
console.log("设置appTheme为", value, "成功")
},
fail: function(e: IAppThemeFail) {
console.log("设置appTheme为", value, "失败,原因:", e.errMsg)
}
})
}
},
onReady() {
uni.getSystemInfo({
success: (res:GetSystemInfoResult) => {
this.osTheme = res.osTheme!
this.appTheme = res.appTheme == "auto" ? res.osTheme! : res.appTheme!
this.current = this.items.indexOf(res.appTheme!)
}
})
this.osThemeChangeId = this.bindOsThemeChange()
this.appThemeChangeId = this.bindAppThemeChange()
},
onUnload() {
//注销监听
uni.offAppThemeChange(this.appThemeChangeId)
uni.offOsThemeChange(this.osThemeChangeId)
uni.showToast({
"position":"bottom",
"title":"已停止监听主题切换"
})
}
}
</script>
<style>
.item-box {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.uni-list-cell {
justify-content: flex-start;
}
</style>
......@@ -280,19 +280,19 @@
const error = err as UniCloudError
this.notify(error.errMsg, '错误')
})
},
dbMultiSend() {
const db = uniCloud.databaseForJQL()
const temp1 = db.collection('type')
.where(
'tag == "default-tag"'
).getTemp()
const temp2 = db.collection('type')
.where(
'tag == "default-tag"'
).getTemp()
db.multiSend(temp1, temp2)
.then<void>(res => {
},
async dbMultiSend() : Promise<void> {
const db = uniCloud.databaseForJQL()
const temp1 = db.collection('type')
.where(
'tag == "default-tag"'
).getTemp()
const temp2 = db.collection('type')
.where(
'tag == "default-tag"'
).getTemp()
await db.multiSend(temp1, temp2)
.then<void>(res => {
uni.hideLoading()
let successCount = 0
for (let i = 0; i < res.dataList.length; i++) {
......@@ -305,14 +305,14 @@
}
}
this.multiSendSuccessCount = successCount
this.notify(`合并查询成功,成功查询的语句条数为:${successCount}`, '提示')
})
.catch<void>((err : any | null) => {
uni.hideLoading()
this.notify(`合并查询成功,成功查询的语句条数为:${successCount}`, '提示')
})
.catch<void>((err : any | null) => {
uni.hideLoading()
const error = err as UniCloudError
console.error(err)
this.notify(error.errMsg, '错误')
})
this.notify(error.errMsg, '错误')
})
}
}
}
......
......@@ -7,6 +7,7 @@
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-btn-v uni-common-mt">
<button type="primary" @click="uploadFile">选择文件上传</button>
<button type="primary" @click="chooseAndUploadFile">一个接口选择文件并上传</button>
</view>
</view>
</view>
......@@ -62,6 +63,26 @@
console.error('chooseImage fail: ', err)
}
})
},
chooseAndUploadFile() {
uniCloud.chooseAndUploadFile({
type: 'image'
}).then(function (res) {
uni.hideLoading()
console.log(res)
uni.showModal({
content: '上传成功',
showCancel: false
});
})
.catch(function (err : any | null) {
uni.hideLoading()
const error = err as UniCloudError
uni.showModal({
content: '上传失败,' + error.errMsg,
showCancel: false
});
})
}
}
}
......
......@@ -24,6 +24,7 @@ describe('unicloud-import-object', () => {
genericDemoReturnTodoTitle,
genericDemoReturnTodoContent,
failErrCode,
failErrDetailTips,
failNumberErrCode,
successErrCode,
} = await page.data()
......@@ -33,6 +34,7 @@ describe('unicloud-import-object', () => {
expect(genericDemoReturnTodoTitle).toBe(todoTitle)
expect(genericDemoReturnTodoContent).toBe(todoContent)
expect(failErrCode).toBe('TEST_ERROR_CODE')
expect(failErrDetailTips).toBe('DO_NOT_TRY_AGAIN')
expect(failNumberErrCode).toBe(-1)
expect(successErrCode).toBe(0)
......
......@@ -42,6 +42,7 @@
genericDemoReturnTodoTitle: '',
genericDemoReturnTodoContent: '',
failErrCode: '',
failErrDetailTips: '',
failNumberErrCode: 0,
successErrCode: -1,
isUniTest: false
......@@ -119,6 +120,10 @@
}).catch((err : any | null) => {
const error = err as UniCloudError
this.failErrCode = error.errCode as string
const detail = error.detail
if (detail != null && detail['tips'] != null) {
this.failErrDetailTips = detail['tips'] as string
}
console.error(error)
})
},
......
......@@ -36,12 +36,27 @@ describe('ExtApi-UploadFile', () => {
expect(res).toBe(true)
});
it('Check Upload File In UTS Module', async () => {
res = await page.callMethod('jest_uts_module_invoked')
it('Check uni.env', async () => {
await page.callMethod('jest_uploadFile_with_uni_env');
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true)
})
expect(res).toBe(true);
});
// 15以下的模拟器所对应的xcode不能编译自定义插件,大于15是因为某台设备,会用xcode14.1跑15.5的设备
let version = process.env.uniTestPlatformInfo
let split = version.split(" ")
version = parseInt(split[split.length - 1])
if(!process.env.uniTestPlatformInfo.toLocaleLowerCase().startsWith('ios') || version > 15) {
it('Check Upload File In UTS Module', async () => {
res = await page.callMethod('jest_uts_module_invoked')
await page.waitFor(2000);
res = await page.data('jest_result');
expect(res).toBe(true)
})
}
let shouldTestCookie = false
if (process.env.uniTestPlatformInfo.startsWith('android') && !process.env.UNI_AUTOMATOR_APP_WEBVIEW) {
......@@ -66,4 +81,4 @@ describe('ExtApi-UploadFile', () => {
res = await page.data('jest_result');
expect(res).toBe(true)
});
});
});
......@@ -15,13 +15,13 @@
</scroll-view>
<!-- #endif -->
</template>
<script>
// #ifdef APP
import {
testInovkeUploadFile,
CommonOptions
} from '@/uni_modules/test-invoke-network-api'
// #endif
<script>
// #ifdef APP
import {
testInovkeUploadFile,
CommonOptions
} from '@/uni_modules/test-invoke-network-api'
// #endif
export default {
data() {
......@@ -102,6 +102,29 @@
},
})
},
jest_uploadFile_with_uni_env() {
const filePath = `${uni.env.CACHE_PATH}/download/uni-app.png`
uni.downloadFile({
url: "https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni-app.png",
filePath: filePath,
success: () => {
uni.uploadFile({
url: 'https://unidemo.dcloud.net.cn/upload', //仅为示例,非真实的接口地址
filePath: filePath,
name: 'file',
success: () => {
this.jest_result = true;
},
fail: () => {
this.jest_result = false;
},
})
},
fail: () => {
this.jest_result = false
}
});
},
jest_set_cookie() {
uni.request({
url: "https://request.dcloud.net.cn/api/http/header/setCookie",
......@@ -178,20 +201,20 @@
this.jest_result = false;
},
})
},
jest_uts_module_invoked(){
// #ifdef APP
testInovkeUploadFile({
success:(res: any)=>{
console.log("success :", res);
this.jest_result = true
},
fail:(err: any)=>{
console.log("fail :", err);
this.jest_result = false
}
} as CommonOptions)
// #endif
},
jest_uts_module_invoked() {
// #ifdef APP
testInovkeUploadFile({
success: (res : any) => {
console.log("success :", res);
this.jest_result = true
},
fail: (err : any) => {
console.log("fail :", err);
this.jest_result = false
}
} as CommonOptions)
// #endif
}
}
}
......@@ -217,4 +240,4 @@
font-size: 19px;
color: #808080;
}
</style>
</style>
<template>
<!-- #ifdef APP -->
<scroll-view style="flex:1">
<!-- #endif -->
<page-head :title="title"></page-head>
<view class="uni-common-mt uni-padding-wrap">
<view class="uni-btn-v">
<button type="primary" @tap="onUserCaptureScreen">开启截屏监听</button>
</view>
<view class="uni-btn-v">
<button type="primary" @tap="offUserCaptureScreen">关闭截屏监听</button>
</view>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script>
import { OnUserCaptureScreenCallbackResult } from "@/uni_modules/uni-usercapturescreen";
export default {
data() {
return {
title: 'userCaptureScreen',
callback: null as ((res : OnUserCaptureScreenCallbackResult) => void) | null
}
},
methods: {
onUserCaptureScreen() {
this.callback = (res : OnUserCaptureScreenCallbackResult) => {
console.log('截屏文件路径(仅Android平台支持)', res.path);
uni.showToast({
title: '捕获截屏事件'
});
};
uni.onUserCaptureScreen(this.callback!);
uni.showToast({
title: '截屏监听已开启'
});
},
offUserCaptureScreen() {
uni.offUserCaptureScreen(this.callback);
uni.showToast({
title: '截屏监听已关闭'
});
}
},
onUnload() {
uni.offUserCaptureScreen(this.callback);
}
}
</script>
<style>
</style>
\ No newline at end of file
......@@ -14,7 +14,7 @@ describe('css-dynamic-border', () => {
// 取消圆角
it('check_none', async () => {
await page.callMethod('changeIndex', 2)
page.waitFor(100)
await page.waitFor(100)
const image = await program.screenshot({fullPage: true});
expect(image).toSaveImageSnapshot();
})
......@@ -22,7 +22,7 @@ describe('css-dynamic-border', () => {
// 左下,右下设置圆角
it('check_bottomleft_bottomright', async () => {
await page.callMethod('changeIndex', 10)
page.waitFor(100)
await page.waitFor(100)
const image = await program.screenshot({fullPage: true});
expect(image).toSaveImageSnapshot();
})
......
......@@ -18,6 +18,8 @@ describe('/pages/CSS/overflow/overflow-visible-event.uvue', () => {
beforeEach(async () => {
await page.setData({
jest_result: false,
jest_click_x: -1,
jest_click_y: -1
})
});
......@@ -30,4 +32,34 @@ describe('/pages/CSS/overflow/overflow-visible-event.uvue', () => {
res = await page.data('jest_result');
expect(res).toBe(true)
});
// 此测试针对开发者使用 translate 移动view
it('Check Overflow Visible Part Use translate Drag', async ()=> {
await page.callMethod('jest_getRect')
const point_x = await page.data('jest_click_x');
const point_y = await page.data('jest_click_y');
const distance = 100;
const destY = point_y + 100
const duration = 1000
await program.adbCommand("input swipe" + " " + point_x + " " + point_y + " " + point_x + " " + destY + " " + duration)
await page.waitFor(1500);
await page.callMethod('jest_getParentRect')
const currentParentTop = await page.data('jest_parent_top');
const offset = 2
const diff = Math.abs(currentParentTop - distance) < offset
console.log("current ", currentParentTop);
console.log("diff", diff);
expect(diff).toBe(true)
})
it('Check Overflow Visible Block View Click', async () => {
await page.callMethod('jest_getAbsoluteViewRect')
const point_x = await page.data('jest_click_x');
const point_y = await page.data('jest_click_y');
console.log("input tap" + " " + point_x + " " + point_y);
await program.adbCommand("input tap" + " " + point_x + " " + point_y)
await page.waitFor(500);
res = await page.data('jest_result');
expect(res).toBe(true)
})
});
<template>
<view>
<text style="font-size: 15px;">overflow=visible 点击子view(超出父view区域的部分)</text>
<view class="backgroundview">
<view class="box-visible-border-radius">
<view id="child" style="width: 50px; height: 150px; background-color: greenyellow;"
@click="handleClickOverflowPart" @touchmove="handleTouchMoveOverflowPart">
<scroll-view style="flex: 1;">
<view>
<text style="font-size: 15px;">overflow=visible 父view(绿色),子view(红色),点击超出父view区域的部分也可触发事件。</text>
<view class="backgroundview">
<view id="parent" class="box-visible-border-radius">
<view id="child" style="width: 50px; height: 150px; background-color: red;" @click="handleClickOverflowPart"
@touchmove="handleTouchMoveOverflowPart" @touchstart="handleTouchStartOverflowPart"
@touchend="handleTouchEndOverflowPart">
</view>
</view>
</view>
<text style="font-size: 15px;">overflow=visible组件的子view (绿色)被position:
absolute的view(红色)遮挡时,点击事件测试。</text>
<view style="width: 300px;height: 300px;background-color: white;">
<view style="overflow:visible;height: 100px;width: 100%;">
<view style="background-color: green;height: 100px;width: 100%;" @click="handleClick('green')">
</view>
</view>
<view id="absolute-view" style="position: absolute;background-color: red;width: 100px;height: 200px;right: 0px;"
@click="handleClick('red')">
</view>
</view>
<text style="font-size: 15px;">overflow=visible组件设置hover-class的测试</text>
<view class="backgroundview">
<view class="box-visible-border-radius" hover-class="hover-class">
<view style="background-color: red;height: 100px;width: 100px;margin-left: 20px;margin-top: 20px;">
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</template>
<script>
......@@ -17,24 +38,76 @@
return {
jest_result: false,
jest_click_x: -1,
jest_click_y: -1
jest_click_y: -1,
jest_parent_top: -1.0,
startX: 0,
startY: 0,
moveX: 0,
moveY: 0,
oldX: 0,
oldY: 0,
moveEl: null as UniElement | null
}
},
onReady() {
this.moveEl = uni.getElementById('parent')
},
methods: {
handleClickOverflowPart() {
console.log("click");
this.jest_result = true;
uni.showToast({ "title": "点击红色区域" })
},
handleTouchStartOverflowPart(e : UniTouchEvent) {
this.startX = e.changedTouches[0].clientX
this.startY = e.changedTouches[0].clientY
},
handleTouchMoveOverflowPart(e : UniTouchEvent) {
console.log("touchmove:" + e.touches[0].clientX + "," + e.touches[0].clientY);
e.preventDefault()
e.stopPropagation()
const difX = e.changedTouches[0].clientX
const difY = e.changedTouches[0].clientY
this.moveX = difX - this.startX + this.oldX
this.moveY = difY - this.startY + this.oldY
this.moveEl?.style?.setProperty('transform', `translate(${this.moveX}px,${this.moveY}px)`)
},
handleTouchMoveOverflowPart() {
console.log("move");
handleTouchEndOverflowPart(_ : UniTouchEvent) {
this.oldX = this.moveX
this.oldY = this.moveY
},
handleClick(str : string) {
console.log(`点击了 ${str} view`);
if (str == 'red') {
this.jest_result = true;
}
},
jest_getRect() {
const rect = uni.getElementById('child')?.getBoundingClientRect()
if (rect != null) {
if (rect != null) {
const ratio = uni.getSystemInfoSync().devicePixelRatio
this.jest_click_x = rect.x * ratio + 10
this.jest_click_y = rect.bottom * ratio - 10
}
}
},
jest_getParentRect() {
const transform = uni.getElementById('parent')?.style.getPropertyValue("transform")
if (transform != null) {
let value = transform as string
value = value.split(",")[1].slice(0, -3)
const ratio = uni.getSystemInfoSync().devicePixelRatio
this.jest_parent_top = Math.round((parseFloat(value) * ratio))
}
},
jest_getAbsoluteViewRect() {
const rect = uni.getElementById('absolute-view')?.getBoundingClientRect()
if (rect != null) {
const systemInfo = uni.getSystemInfoSync()
const titleBarHeight = systemInfo.screenHeight - systemInfo.windowHeight
const ratio = systemInfo.devicePixelRatio
this.jest_click_x = rect.x * ratio + 10
this.jest_click_y = (rect.top + titleBarHeight + 10) * ratio
}
}
}
}
......@@ -57,4 +130,8 @@
overflow: visible;
background-color: green;
}
.hover-class {
background-color: aqua;
}
</style>
......@@ -4,7 +4,7 @@ describe('css-font-size', () => {
page = await program.reLaunch('/pages/CSS/text/font-size');
});
it('screenshot', async () => {
it('change font-size screenshot', async () => {
await page.callMethod("setFontSize");
await page.waitFor(100);
const image = await program.screenshot({ fullPage: true });
......
<template>
<view style="flex-grow: 1;">
<view style="height: 250px;background-color: gray;justify-content: center;align-items: center;">
<text ref="text" style="font-size: 15px;">{{fontSize}}</text>
<text ref="text" :style="{'font-size': fontSize}">font-size: {{fontSize}}</text>
<text style="font-size: 30px;">font-size: 30px</text>
</view>
</view>
......@@ -11,14 +11,13 @@
export default {
data() {
return {
fontSize: 'font-size: 15px'
fontSize: '15px'
}
},
methods: {
// 自动化测试
setFontSize() {
this.fontSize = 'font-size: 30px';
(this.$refs['text'] as UniElement).style.setProperty('font-size', '30px');
this.fontSize = '30px';
}
}
}
......
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('/pages/CSS/transform/rotate.uvue', () => {
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/CSS/transform/rotate')
await page.waitFor(1000);
});
it("snap rotate", async () => {
const image = await program.screenshot({
fullPage: true
})
expect(image).toSaveImageSnapshot()
})
});
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('/pages/CSS/transform/scale.uvue', () => {
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/CSS/transform/scale')
await page.waitFor(1000);
});
it("snap scale", async () => {
const image = await program.screenshot({
fullPage: true
})
expect(image).toSaveImageSnapshot()
})
});
<template>
<scroll-view class="page">
<view class="trace">
<view class="base reserve">
<text class="reserve-text">scaleX(0.6)</text>
<text class="reserve-text">转变前位置</text>
</view>
<view class="base reserve">
<text class="reserve-text">scaleY(0.8)</text>
<text class="reserve-text">转变前位置</text>
</view>
<view class="base reserve">
<text class="reserve-text">scale(0.8,0.8)</text>
<text class="reserve-text">转变前位置</text>
</view>
</view>
<scroll-view class="page">
<view class="trace">
<view class="base reserve">
<text class="reserve-text">scaleX(0.6)</text>
<text class="reserve-text">转变前位置</text>
</view>
<view class="base reserve">
<text class="reserve-text">scaleY(0.8)</text>
<text class="reserve-text">转变前位置</text>
</view>
<view class="base reserve">
<text class="reserve-text">scale(0.8,0.8)</text>
<text class="reserve-text">转变前位置</text>
</view>
</view>
<view class="base transform" style="transform: scaleX(0.6)">
<text>scaleX(0.6)</text>
<text>转变后位置</text>
</view>
<view class="base transform" style="transform: scaleY(0.6)">
<text>scaleY(0.6)</text>
<text>转变后位置</text>
</view>
<view class="base transform" style="transform: scale(1.2,1.2)">
<text>scale(1.2,1.2)</text>
<text>转变后位置</text>
</view>
</scroll-view>
<view class="base transform" style="transform: scaleX(0.6)">
<text>scaleX(0.6)</text>
<text>转变后位置</text>
</view>
<view class="base transform" style="transform: scaleY(0.6)">
<text>scaleY(0.6)</text>
<text>转变后位置</text>
</view>
<view class="base transform" style="transform: scale(1.2,1.2)">
<text>scale(1.2,1.2)</text>
<text>转变后位置</text>
</view>
<view class="base">
<text>通过scaleY(0.5)实现0.5px的线</text>
<view style="width: 150px; height: 1px; background-color: #000; transform: scaleY(0.5)"></view>
</view>
</scroll-view>
</template>
<script lang="uts">
export default {
data() {
return {
}
},
methods: {
},
}
</script>
<style>
.page {
flex: 1;
align-items: center;
}
.trace {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
align-items: center;
}
.base {
margin: 10px;
width: 150px;
height: 150px;
align-items: center;
justify-content: center;
}
.reserve {
border: 1px dotted #588;
background-color: #DDD;
}
.reserve-text {
color: #CCC;
}
.transform {
border: 1px solid #00F;
background-color: rgba(0,255,255,0.5);
}
.page {
flex: 1;
align-items: center;
}
.trace {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
align-items: center;
}
.base {
margin: 10px;
width: 150px;
height: 150px;
align-items: center;
justify-content: center;
}
.reserve {
border: 1px dotted #588;
background-color: #DDD;
}
.reserve-text {
color: #CCC;
}
.transform {
border: 1px solid #00F;
background-color: rgba(0, 255, 255, 0.5);
}
</style>
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('/pages/CSS/transform/translate.uvue', () => {
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/CSS/transform/translate')
await page.waitFor(1000);
});
it("snap translate", async () => {
const image = await program.screenshot({
fullPage: true
})
expect(image).toSaveImageSnapshot()
})
});
// uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
describe('/pages/CSS/transition/transition.uvue', () => {
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/CSS/transition/transition')
await page.waitFor(2000);
});
it("snap transition finish", async () => {
await page.callMethod('changeWidthOrHeight')
await page.callMethod('changeWidthProgress')
await page.callMethod('changeMargin')
await page.callMethod('changePadding')
await page.callMethod('changeBackground')
await page.callMethod('changeBackground2')
await page.callMethod('changeStyleOpacity')
await page.callMethod('propertyChangeBackground')
await page.callMethod('changeTransform')
await page.callMethod('changeTransformTranslate')
await page.callMethod('changeTransformWithWidth')
await page.callMethod('changeTransformWithOrigin')
await page.callMethod('changeBorder')
await page.callMethod('changestylePosition')
await page.waitFor(3000)
const image = await program.screenshot({
fullPage: true
})
expect(image).toSaveImageSnapshot()
})
});
......@@ -2,64 +2,67 @@
<!-- #ifdef APP -->
<scroll-view style="flex: 1">
<!-- #endif -->
<view>
<view class="container">
<text class="text">点击修改宽度</text>
<view class="base-style transition-width" id="widthOrHeight" @click="changeWidthOrHeight"></view>
</view>
<view class="container">
<text class="text">点击修改宽度(递增)</text>
<view class="width-progress transition-width" id="widthProgress" @click="changeWidthProgress"></view>
</view>
<view class="container">
<text class="text">点击修改Margin</text>
<view class="base-style transition-margin" id="styleMargin" @click="changeMargin"></view>
</view>
<view class="container">
<text class="text">点击修改Padding</text>
<view class="base-style transition-padding" id="stylePadding" @click="changePadding">
<view style="background-color: black; height: 50px; width: 50px"></view>
</view>
</view>
<view class="container">
<text class="text">点击修改Background</text>
<view class="base-style transition-background" id="styleBackground" @click="changeBackground"></view>
</view>
<view class="container">
<text class="text">点击修改Background(颜色带透明度)</text>
<view style="flex: 1;">
<view class="base-style transition-background" id="styleBackground2" @click="changeBackground2"></view>
</view>
</view>
<view class="container">
<text class="text">动态修改Background</text>
<view class="base-style" id="propertyStyleBackground" @click="propertyChangeBackground"></view>
</view>
<view class="container">
<text class="text">点击修改Transform</text>
<view class="base-style transition-transform" id="styleTransform" @click="changeTransform"></view>
</view>
<view class="container">
<text class="text">点击修改TransformTranslate</text>
<view class="base-style transition-transform" id="transformTranslate" @click="changeTransformTranslate"></view>
</view>
<view class="container">
<text class="text">点击修改Transform和宽</text>
<view class="base-style transition-transform-width" id="styleTransformWithWidth" @click="changeTransformWithWidth"></view>
</view>
<view class="container" @click="changeTransformWithOrigin">
<text class="text">点击修改Transform(含transform-origin)</text>
<view class="base-style transition-transform" style="transform-origin: 0 0;" id="styleTransformWithOrigin"></view>
</view>
<view class="container">
<text class="text">点击修改Border</text>
<view class="base-style transition-border" id="styleBorder" @click="changeBorder"></view>
<view class="container">
<text class="text">点击修改宽度</text>
<view class="base-style transition-width" id="widthOrHeight" @click="changeWidthOrHeight"></view>
</view>
<view class="container">
<text class="text">点击修改宽度(递增)</text>
<view class="width-progress transition-width" id="widthProgress" @click="changeWidthProgress"></view>
</view>
<view class="container">
<text class="text">点击修改Margin</text>
<view class="base-style transition-margin" id="styleMargin" @click="changeMargin"></view>
</view>
<view class="container">
<text class="text">点击修改Padding</text>
<view class="base-style transition-padding" id="stylePadding" @click="changePadding">
<view style="background-color: black; height: 50px; width: 50px"></view>
</view>
<view class="container">
<text class="text">点击修改Position</text>
<view class="base-style transition-position" id="stylePosition" @click="changestylePosition"></view>
</view>
<view class="container">
<text class="text">点击修改background-color和opacity</text>
<view class="base-style transition-background" id="styleBackground" @click="changeBackground"></view>
</view>
<view class="container">
<text class="text">点击修改background-color(rgba)</text>
<view style="flex: 1;">
<view class="base-style transition-background" id="styleBackground2" @click="changeBackground2"></view>
</view>
</view>
<view class="container">
<text class="text">点击修改opacity渐隐渐现</text>
<view class="base-style transition-opacity" id="styleOpacity" @click="changeStyleOpacity"></view>
</view>
<view class="container">
<text class="text">动态修改background-color和duration</text>
<view class="base-style" id="propertyStyleBackground" @click="propertyChangeBackground"></view>
</view>
<view class="container">
<text class="text">点击修改Transform</text>
<view class="base-style transition-transform" id="styleTransform" @click="changeTransform"></view>
</view>
<view class="container">
<text class="text">点击修改TransformTranslate</text>
<view class="base-style transition-transform" id="transformTranslate" @click="changeTransformTranslate"></view>
</view>
<view class="container">
<text class="text">点击修改Transform和宽</text>
<view class="base-style transition-transform-width" id="styleTransformWithWidth"
@click="changeTransformWithWidth"></view>
</view>
<view class="container" @click="changeTransformWithOrigin">
<text class="text">点击修改Transform(含transform-origin)</text>
<view class="base-style transition-transform" style="transform-origin: 0 0;" id="styleTransformWithOrigin"></view>
</view>
<view class="container">
<text class="text">点击修改Border</text>
<view class="base-style transition-border" id="styleBorder" @click="changeBorder"></view>
</view>
<view class="container">
<text class="text">点击修改Position</text>
<view class="base-style transition-position" id="stylePosition" @click="changestylePosition"></view>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
......@@ -78,11 +81,14 @@
isTransitionStylePadding: false,
stylePadding: null as UniElement | null,
isTransitionstyleBackground: false,
isTransitionstyleBackground2: false,
isTransitionstyleOpacity: false,
styleBackground: null as UniElement | null,
styleBackground2: null as UniElement | null,
styleOpacity: null as UniElement | null,
isTransitionStyleTransform: false,
styleTransform: null as UniElement | null,
isTransitionStyleTransformWithWidth:false,
isTransitionStyleTransformWithWidth: false,
styleTransformWithWidth: null as UniElement | null,
isTransitionstyleBorder: false,
styleBorder: null as UniElement | null,
......@@ -104,6 +110,7 @@
this.stylePadding = uni.getElementById("stylePadding")
this.styleBackground = uni.getElementById("styleBackground")
this.styleBackground2 = uni.getElementById("styleBackground2")
this.styleOpacity = uni.getElementById("styleOpacity")
this.styleTransform = uni.getElementById("styleTransform")
this.styleBorder = uni.getElementById("styleBorder")
this.stylePosition = uni.getElementById("stylePosition")
......@@ -156,11 +163,19 @@
this.isTransitionstyleBackground = !this.isTransitionstyleBackground
},
changeBackground2() {
this.styleBackground2?.style?.setProperty("background-color", this.isTransitionstyleBackground
this.styleBackground2?.style?.setProperty("background-color", this.isTransitionstyleBackground2
? 'brown'
: 'rgba(0, 0, 0, 0.5);'
: 'rgba(0, 0, 0, 0.5)'
)
this.isTransitionstyleBackground = !this.isTransitionstyleBackground
this.isTransitionstyleBackground2 = !this.isTransitionstyleBackground2
},
changeStyleOpacity() {
this.styleOpacity?.style?.setProperty("opacity", this.isTransitionstyleOpacity
? '1'
: '0'
)
this.styleOpacity?.style?.setProperty("transition-duration", "1000ms")
this.isTransitionstyleOpacity = !this.isTransitionstyleOpacity
},
propertyChangeBackground() {
if (!this.isSetTransition) {
......@@ -270,6 +285,11 @@
transition-duration: 1s;
}
.transition-opacity {
transition-property: opacity;
transition-duration: 1s;
}
.transition-transform {
transition-property: transform;
transition-duration: 1s;
......@@ -288,6 +308,7 @@
transition-property: left;
transition-duration: 1s;
}
.transition-transform-width {
transition-property: transform, width;
transition-duration: 1s;
......
......@@ -11,8 +11,11 @@
type_enum: [{ "value": 0, "name": "default" }, { "value": 1, "name": "primary" }, { "value": 2, "name": "warn" }] as ItemType[],
type_enum_current: 0,
count: 0,
text: 'uni-app-x'
text: ''
}
},
onReady() {
this.text = 'uni-app-x'
},
methods: {
button_click() {
......@@ -54,7 +57,8 @@
:type="type_enum[type_enum_current].name" :plain="plain_boolean" @click="button_click"
@touchstart="button_touchstart" @touchmove="button_touchmove" @touchcancel="button_touchcancel"
@touchend="button_touchend" @tap="button_tap" @longpress="button_longpress" class="btn"
:class="default_style ? 'custom-btn' : ''" :hover-class="default_style ? 'is-hover' : 'button-hover'">
:class="default_style ? (disabled_boolean ? 'custom-btn-disable' : 'custom-btn') : ''"
:hover-class="default_style ? 'is-hover' : 'button-hover'">
{{ text }}
</button>
</view>
......@@ -92,6 +96,12 @@
border-color: #1AAD19;
}
.custom-btn-disable {
color: rgba(255, 255, 255, 0.7);
background-color: rgba(26, 173, 25, 0.7);
border-color: rgba(26, 173, 25, 0.7);
}
.is-hover {
color: rgba(255, 255, 255, 0.6);
background-color: #179b16;
......
<template>
<view class="page-body">
<canvas id="canvas" class="canvas"></canvas>
</view>
</template>
<script setup>
class Ball {
private width : number
private height : number
public x : number
public y : number
public vx : number
public vy : number
public radius : number = 5
constructor(w : number, h : number, x : number, y : number, vx : number, vy : number) {
this.width = w
this.height = h
this.x = x
this.y = y
this.vx = vx
this.vy = vy
}
move() {
this.x += this.vx
this.y += this.vy
// 边框反弹
if (this.x < this.radius) {
this.vx = Math.abs(this.vx)
return
}
if (this.x > this.width - this.radius) {
this.vx = -Math.abs(this.vx)
}
if (this.y < this.radius) {
this.vy = Math.abs(this.vy)
return
}
if (this.y > this.width - this.radius) {
this.vy = -Math.abs(this.vy)
}
}
}
class BallAnimation {
private ctx : CanvasRenderingContext2D
private ballList : Array<Ball> = []
private speed = 3
private layer = 3
private ballInlayer = 20
private interval : number = 0
private runningFlag : boolean = false
// #ifdef WEB
private _bindAnimate: Function = null
// #endif
constructor(ctx : CanvasRenderingContext2D) {
this.ctx = ctx
this.initBall()
this.ctx.fillStyle = '#007AFF'
// #ifdef WEB
this._bindAnimate = this.animate.bind(this)
// #endif
}
private getDistance(x : number, y : number) : number {
return Math.pow((Math.pow(x, 2) + Math.pow(y, 2)), 0.5)
}
private initBall() {
const canvasWidth = this.ctx.canvas.offsetWidth;
const canvasHeight = this.ctx.canvas.offsetHeight;
for (let i = 0; i < this.layer; i++) {
let radius = this.getDistance(canvasWidth / 2, canvasHeight / 2) / this.layer * i
for (let j = 0; j < this.ballInlayer; j++) {
let deg = j * 2 * Math.PI / this.ballInlayer,
sin = Math.sin(deg),
cos = Math.cos(deg),
x = radius * cos + canvasWidth / 2,
y = radius * sin + canvasHeight / 2,
vx = this.speed * cos,
vy = this.speed * sin
this.ballList.push(new Ball(canvasWidth, canvasHeight, x, y, vx, vy))
}
}
}
public animate() {
this.ctx.clearRect(0, 0, this.ctx.canvas.offsetWidth, this.ctx.canvas.offsetHeight)
this.ballList.forEach((item) => {
item.move()
this.ctx.beginPath()
this.ctx.arc(item.x, item.y, item.radius, 0, 2 * Math.PI)
// this.ctx.ellipse(item.x, item.y, item.radius, item.radius, 0, 0, Math.PI * 2)
this.ctx.fill()
})
// #ifdef APP
this.ctx.draw()
// #endif
// #ifdef WEB
if (!this.runningFlag) {
return
}
requestAnimationFrame(this._bindAnimate)
// #endif
}
start() {
// #ifdef WEB
cancelAnimationFrame(this._bindAnimate)
this.runningFlag = true
this.animate()
// #endif
// #ifdef APP
//Todo.. requestAnimationFrame
clearInterval(this.interval)
this.interval = setInterval(() => {
this.animate()
}, 17)
// #endif
}
stop() {
// #ifdef WEB
this.runningFlag = false
cancelAnimationFrame(this._bindAnimate)
// #endif
// #ifdef APP
//Todo.. requestAnimationFrame
clearInterval(this.interval)
// #endif
}
}
let animation : BallAnimation | null = null
onReady(() => {
let canvas = uni.getElementById("canvas") as UniCanvasElement
let canvasContext = canvas.getContext("2d");
if (canvasContext != null) {
const dpr = uni.getSystemInfoSync().pixelRatio
canvas.width = canvas.offsetWidth * dpr
canvas.height = canvas.offsetHeight * dpr
canvasContext.scale(dpr, dpr)
animation = new BallAnimation(canvasContext)
animation?.start()
} else {
console.log("canvas.getContext error!!")
}
})
onUnload(() => {
animation?.stop()
animation = null
})
onPageShow(() => {
animation?.start()
})
onPageHide(() => {
animation?.stop()
})
</script>
<style>
.page-body-wrapper {
text-align: center;
}
.canvas {
width: 300px;
height: 300px;
margin: auto;
background-color: #fff;
}
</style>
此差异已折叠。
// uni-app自动化测试教程: uni-app自动化测试教程: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/
jest.setTimeout(60000);
jest.setTimeout(30000);
describe('editor.uvue', () => {
if (!process.env.uniTestPlatformInfo.startsWith('web')) {
it('app', () => {
......@@ -65,7 +65,7 @@ describe('editor.uvue', () => {
it('insertImage', async () => {
await page.callMethod('insertImage','https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni-app.png')
await page.waitFor(500)
await page.waitFor(2000)
expect(await program.screenshot()).toSaveImageSnapshot();
})
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
describe('list-view-children-in-slot', () => {
if (process.env.uniTestPlatformInfo.startsWith('web')) {
it('dummyTest', async () => {
expect(1).toBe(1)
})
return
}
let page
beforeAll(async () => {
page = await program.reLaunch('/pages/component/list-view/list-view-children-in-slot')
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册