diff --git a/.eslintignore b/.eslintignore
index bbc3713a42b7b7ab3256c47b0f37f2ae6763e552..e67b549817ca173753194a06038ece64e4b37286 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -6,3 +6,5 @@ packages/*/template/**/*
packages/uni-h5/src
packages/uni-stat
node_modules
+automator.js
+uni.automator.js
diff --git a/packages/uni-automator/LICENSE b/packages/uni-automator/LICENSE
new file mode 100755
index 0000000000000000000000000000000000000000..7a4a3ea2424c09fbe48d455aed1eaa94d9124835
--- /dev/null
+++ b/packages/uni-automator/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/packages/uni-automator/dist/environment.js b/packages/uni-automator/dist/environment.js
new file mode 100644
index 0000000000000000000000000000000000000000..bfb22b651c28fb436f4cbed24524cbafee2a42a3
--- /dev/null
+++ b/packages/uni-automator/dist/environment.js
@@ -0,0 +1 @@
+"use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t.default:t}var e=t(require("jest-environment-node"));const o=new(t(require("./index.js")));module.exports=class extends e{constructor(t,e){super(t),this.launchOptions=t.testEnvironmentOptions}async setup(){await super.setup();const t=global;t.program||(this.launchOptions.platform=this.launchOptions.platform||process.env.UNI_PLATFORM,t.program=await o.launch(this.launchOptions),this.launchOptions.devtools&&this.launchOptions.devtools.remote&&await t.program.remote(!0)),this.global.program=t.program}async teardown(){await super.teardown()}};
diff --git a/packages/uni-automator/dist/index.js b/packages/uni-automator/dist/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..1148b250fbb8cbe5dd373db5e6e9de23ed84a6e7
--- /dev/null
+++ b/packages/uni-automator/dist/index.js
@@ -0,0 +1,15 @@
+"use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t.default:t}var e=t(require("fs")),n=t(require("path")),s=t(require("debug")),o=require("child_process"),i=t(o),r=t(require("licia/getPort")),a=t(require("licia/toStr")),c=t(require("licia/waitUntil")),l=t(require("licia/concat")),p=t(require("licia/sleep")),u=t(require("licia/isRelative")),h=t(require("licia/dateFormat")),d=t(require("ws")),m=require("events"),y=t(require("licia/uuid")),g=t(require("licia/stringify")),v=t(require("licia/fs")),w=t(require("licia/isFn")),f=t(require("licia/trim")),P=t(require("licia/isStr")),M=t(require("licia/startWith")),E=t(require("licia/isNum")),k=t(require("licia/isUndef"));require("jimp");class C extends m.EventEmitter{constructor(t){super(),this.ws=t,this.ws.addEventListener("message",t=>{this.emit("message",t.data)}),this.ws.addEventListener("close",()=>{this.emit("close")})}send(t){this.ws.send(t)}close(){this.ws.close()}}class b extends m.EventEmitter{constructor(t,e,n){super(),this.puppet=e,this.namespace=n,this.callbacks=new Map,this.transport=t,this.debug=s("automator:protocol:"+this.namespace),this.onMessage=t=>{this.debug(`${h("yyyy-mm-dd HH:MM:ss:l")} ◀ RECV ${t}`);const{id:e,method:n,error:s,result:o,params:i}=JSON.parse(t);if(!e)return this.puppet.emit(n,i);const{callbacks:r}=this;if(e&&r.has(e)){const t=r.get(e);r.delete(e),s?t.reject(Error(s.message)):t.resolve(o)}},this.onClose=()=>{this.callbacks.forEach(t=>{t.reject(Error("Connection closed"))})},this.transport.on("message",this.onMessage),this.transport.on("close",this.onClose)}send(t,e={},n=!0){if(n&&"devtool"===this.namespace&&this.puppet.adapter.has(t))return this.puppet.adapter.send(this,t,e);const s=y(),o=g({id:s,method:t,params:e});return this.debug(`${h("yyyy-mm-dd HH:MM:ss:l")} SEND ► ${o}`),new Promise((t,e)=>{try{this.transport.send(o)}catch(t){e(Error("Connection closed"))}this.callbacks.set(s,{resolve:t,reject:e})})}dispose(){this.transport.close()}static createDevtoolConnection(t,e){return new Promise((n,s)=>{const o=new d(t);o.addEventListener("open",()=>{n(new b(new C(o),e,"devtool"))}),o.addEventListener("error",s)})}static createRuntimeConnection(t,e,n){return new Promise((o,i)=>{s("automator:runtime")(`${h("yyyy-mm-dd HH:MM:ss:l")} port=${t}`);const r=new d.Server({port:t});c(async()=>{if(e.runtimeConnection)return!0},n,1e3).catch(t=>{throw Error("Failed to connect to runtime, please make sure the project is running")}),r.on("connection",(function(t){s("automator:runtime")(h("yyyy-mm-dd HH:MM:ss:l")+" connected");const n=new b(new C(t),e,"runtime");e.setRuntimeConnection(n),o(n)})),e.setRuntimeServer(r)})}}const T=require("qrcode-terminal");require("qrcode-reader");async function D(t,e){const[n,s]=function(t){return P(t)?[!0,[t]]:[!1,t]}(e),o=await t(s);return n?o[0]:o}
+/*! *****************************************************************************
+Copyright (c) Microsoft Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License. You may obtain a copy of the
+License at http://www.apache.org/licenses/LICENSE-2.0
+
+THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
+WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+MERCHANTABLITY OR NON-INFRINGEMENT.
+
+See the Apache Version 2.0 License for specific language governing permissions
+and limitations under the License.
+***************************************************************************** */function I(t,e,n,s){var o,i=arguments.length,r=i<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,n):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(t,e,n,s);else for(var a=t.length-1;a>=0;a--)(o=t[a])&&(r=(i<3?o(r):i>3?o(e,n,r):o(e,n))||r);return i>3&&r&&Object.defineProperty(e,n,r),r}var A,x;function R(t,e){const n=e.value;return e.value=async function(e){return(await(null==n?void 0:n.call(this,e)))(t)},e}function S(t,e,n){return R(A.RUNTIME,n)}function j(t,e,n){return R(A.DEVTOOL,n)}!function(t){t.RUNTIME="runtime",t.DEVTOOL="devtool"}(A||(A={}));class q{constructor(t){this.puppet=t}invoke(t,e){return async n=>this.puppet.devtoolConnection?(n===A.DEVTOOL?this.puppet.devtoolConnection:this.puppet.runtimeConnection).send(t,e):this.puppet.runtimeConnection.send(t,e)}on(t,e){this.puppet.on(t,e)}}class $ extends q{constructor(t,e){super(t),this.id=e.elementId,this.pageId=e.pageId,this.nodeId=e.nodeId,this.videoId=e.videoId}async getData(t){return this.invokeMethod("Element.getData",t)}async setData(t){return this.invokeMethod("Element.setData",t)}async callMethod(t){return this.invokeMethod("Element.callMethod",t)}async getElement(t){return this.invokeMethod("Element.getElement",t)}async getElements(t){return this.invokeMethod("Element.getElements",t)}async getOffset(){return this.invokeMethod("Element.getOffset")}async getHTML(t){return this.invokeMethod("Element.getHTML",t)}async getAttributes(t){return this.invokeMethod("Element.getAttributes",t)}async getStyles(t){return this.invokeMethod("Element.getStyles",t)}async getDOMProperties(t){return this.invokeMethod("Element.getDOMProperties",t)}async getProperties(t){return this.invokeMethod("Element.getProperties",t)}async tap(){return this.invokeMethod("Element.tap")}async touchstart(t){return this.invokeMethod("Element.touchstart",t)}async touchmove(t){return this.invokeMethod("Element.touchmove",t)}async touchend(t){return this.invokeMethod("Element.touchend",t)}async triggerEvent(t){return this.invokeMethod("Element.triggerEvent",t)}async callFunction(t){return this.invokeMethod("Element.callFunction",t)}async callContextMethod(t){return this.invokeMethod("Element.callContextMethod",t)}invokeMethod(t,e={}){return e.elementId=this.id,e.pageId=this.pageId,this.nodeId&&(e.nodeId=this.nodeId),this.videoId&&(e.videoId=this.videoId),this.invoke(t,e)}}I([S],$.prototype,"getData",null),I([S],$.prototype,"setData",null),I([S],$.prototype,"callMethod",null),I([j],$.prototype,"getElement",null),I([j],$.prototype,"getElements",null),I([j],$.prototype,"getOffset",null),I([j],$.prototype,"getHTML",null),I([j],$.prototype,"getAttributes",null),I([j],$.prototype,"getStyles",null),I([j],$.prototype,"getDOMProperties",null),I([j],$.prototype,"getProperties",null),I([j],$.prototype,"tap",null),I([j],$.prototype,"touchstart",null),I([j],$.prototype,"touchmove",null),I([j],$.prototype,"touchend",null),I([j],$.prototype,"triggerEvent",null),I([j],$.prototype,"callFunction",null),I([j],$.prototype,"callContextMethod",null);class O{constructor(t,e,n){this.puppet=t,this.id=e.elementId,this.pageId=e.pageId,this.nodeId=e.nodeId||null,this.videoId=e.videoId||null,this.tagName=e.tagName,this.elementMap=n,"body"===this.tagName&&(this.tagName="page"),this.api=new $(t,e)}async $(t){try{const e=await this.api.getElement({selector:t});return O.create(this.puppet,Object.assign({},e,{pageId:this.pageId}),this.elementMap)}catch(t){return null}}async $$(t){const{elements:e}=await this.api.getElements({selector:t});return e.map(t=>O.create(this.puppet,Object.assign({},t,{pageId:this.pageId}),this.elementMap))}async size(){const[t,e]=await this.domProperty(["offsetWidth","offsetHeight"]);return{width:t,height:e}}async offset(){return this.api.getOffset()}async text(){return this.domProperty("innerText")}async attribute(t){if(!P(t))throw Error("name must be a string");return(await this.api.getAttributes({names:[t]})).attributes[0]}async value(){return this.property("value")}async property(t){if(!P(t))throw Error("name must be a string");if(this.puppet.checkProperty){let e=this.publicProps;if(e||(this.publicProps=e=await this._property("__propPublic")),!e[t])throw Error(`${this.tagName}.${t} not exists`)}return this._property(t)}async html(){return(await this.api.getHTML({type:"inner"})).html}async outerHtml(){return(await this.api.getHTML({type:"outer"})).html}async style(t){if(!P(t))throw Error("name must be a string");return(await this.api.getStyles({names:[t]})).styles[0]}async tap(){return this.api.tap()}async longpress(){return await this.touchstart(),await p(350),this.touchend()}async trigger(t,e){const n={type:t};return k(e)||(n.detail=e),this.api.triggerEvent(n)}async touchstart(t){return this.api.touchstart(t)}async touchmove(t){return this.api.touchmove(t)}async touchend(t){return this.api.touchend(t)}async domProperty(t){return D(async t=>(await this.api.getDOMProperties({names:t})).properties,t)}_property(t){return D(async t=>(await this.api.getProperties({names:t})).properties,t)}send(t,e){return e.elementId=this.id,e.pageId=this.pageId,this.nodeId&&(e.nodeId=this.nodeId),this.videoId&&(e.videoId=this.videoId),this.puppet.send(t,e)}async callFunction(t,...e){return(await this.api.callFunction({functionName:t,args:e})).result}static create(t,e,n){let s,o=n.get(e.elementId);if(o)return o;if(e.nodeId)s=F;else switch(e.tagName){case"input":s=N;break;case"textarea":s=L;break;case"scroll-view":s=U;break;case"swiper":s=H;break;case"movable-view":s=B;break;case"switch":s=_;break;case"slider":s=W;break;case"video":s=V;break;default:s=O}return o=new s(t,e,n),n.set(e.elementId,o),o}}class F extends O{async setData(t){return this.api.setData({data:t})}async data(t){const e={};return t&&(e.path=t),(await this.api.getData(e)).data}async callMethod(t,...e){return(await this.api.callMethod({method:t,args:e})).result}}class N extends O{async input(t){return this.callFunction("input.input",t)}}class L extends O{async input(t){return this.callFunction("textarea.input",t)}}class U extends O{async scrollTo(t,e){return this.callFunction("scroll-view.scrollTo",t,e)}async property(t){return"scrollTop"===t?this.callFunction("scroll-view.scrollTop"):"scrollLeft"===t?this.callFunction("scroll-view.scrollLeft"):super.property(t)}async scrollWidth(){return this.callFunction("scroll-view.scrollWidth")}async scrollHeight(){return this.callFunction("scroll-view.scrollHeight")}}class H extends O{async swipeTo(t){return this.callFunction("swiper.swipeTo",t)}}class B extends O{async moveTo(t,e){return this.callFunction("movable-view.moveTo",t,e)}async property(t){return"x"===t?this._property("_translateX"):"y"===t?this._property("_translateY"):super.property(t)}}class _ extends O{async tap(){return this.callFunction("switch.tap")}}class W extends O{async slideTo(t){return this.callFunction("slider.slideTo",t)}}class V extends O{async callContextMethod(t,...e){return this.api.callContextMethod({method:t,args:e})}}class z extends q{constructor(t,e){super(t),this.id=e.id}async getData(t){return this.invokeMethod("Page.getData",t)}async setData(t){return this.invokeMethod("Page.setData",t)}async callMethod(t){return this.invokeMethod("Page.callMethod",t)}async getElement(t){return this.invokeMethod("Page.getElement",t)}async getElements(t){return this.invokeMethod("Page.getElements",t)}async getWindowProperties(t){return this.invokeMethod("Page.getWindowProperties",t)}invokeMethod(t,e={}){return e.pageId=this.id,this.invoke(t,e)}}I([S],z.prototype,"getData",null),I([S],z.prototype,"setData",null),I([S],z.prototype,"callMethod",null),I([j],z.prototype,"getElement",null),I([j],z.prototype,"getElements",null),I([j],z.prototype,"getWindowProperties",null);class G{constructor(t,e){this.puppet=t,this.id=e.id,this.path=e.path,this.query=e.query,this.elementMap=new Map,this.api=new z(t,e)}async waitFor(t){return E(t)?await p(t):w(t)?c(t):P(t)?c(async()=>(await this.$$(t)).length>0):void 0}async $(t){try{const e=await this.api.getElement({selector:t});return O.create(this.puppet,Object.assign({selector:t},e,{pageId:this.id}),this.elementMap)}catch(t){return null}}async $$(t){const{elements:e}=await this.api.getElements({selector:t});return e.map(e=>O.create(this.puppet,Object.assign({selector:t},e,{pageId:this.id}),this.elementMap))}async data(t){const e={};return t&&(e.path=t),(await this.api.getData(e)).data}async setData(t){return this.api.setData({data:t})}async size(){const[t,e]=await this.windowProperty(["document.documentElement.scrollWidth","document.documentElement.scrollHeight"]);return{width:t,height:e}}async callMethod(t,...e){return(await this.api.callMethod({method:t,args:e})).result}async scrollTop(){return this.windowProperty("document.documentElement.scrollTop")}async windowProperty(t){const e=P(t);e&&(t=[t]);const{properties:n}=await this.api.getWindowProperties({names:t});return e?n[0]:n}static create(t,e,n){let s=n.get(e.id);return s||(s=new G(t,e),n.set(e.id,s),s)}}class J extends q{async getPageStack(){return this.invoke("App.getPageStack")}async callUniMethod(t){return this.invoke("App.callUniMethod",t)}async getCurrentPage(){return this.invoke("App.getCurrentPage")}async mockUniMethod(t){return this.invoke("App.mockUniMethod",t)}async callFunction(t){return this.invoke("App.callFunction",t)}async captureScreenshot(){return this.invoke("App.captureScreenshot")}async exit(){return this.invoke("App.exit")}async addBinding(t){return this.invoke("App.addBinding",t)}async enableLog(){return this.invoke("App.enableLog")}onLogAdded(t){return this.on("App.logAdded",t)}onBindingCalled(t){return this.on("App.bindingCalled",t)}onExceptionThrown(t){return this.on("App.exceptionThrown",t)}}I([S],J.prototype,"getPageStack",null),I([S],J.prototype,"callUniMethod",null),I([S],J.prototype,"getCurrentPage",null),I([j],J.prototype,"mockUniMethod",null),I([j],J.prototype,"callFunction",null),I([j],J.prototype,"captureScreenshot",null),I([j],J.prototype,"exit",null),I([j],J.prototype,"addBinding",null),I([j],J.prototype,"enableLog",null);class X extends q{async getInfo(){return this.invoke("Tool.getInfo")}async enableRemoteDebug(t){return this.invoke("Tool.enableRemoteDebug")}async close(){return this.invoke("Tool.close")}async getTestAccounts(){return this.invoke("Tool.getTestAccounts")}onRemoteDebugConnected(t){this.puppet.once("Tool.onRemoteDebugConnected",t),this.puppet.once("Tool.onPreviewConnected",t)}}function Y(t){return new Promise(e=>setTimeout(e,t))}I([j],X.prototype,"getInfo",null),I([j],X.prototype,"enableRemoteDebug",null),I([j],X.prototype,"close",null),I([j],X.prototype,"getTestAccounts",null),function(t){t.CLOSE="close",t.DISCONNECT="disconnect"}(x||(x={}));class K extends m.EventEmitter{constructor(t,e){super(),this.puppet=t,this.options=e,this.pageMap=new Map,this.appBindings=new Map,this.appApi=new J(t),this.toolApi=new X(t),this.appApi.onLogAdded(t=>{this.emit("console",t)}),this.appApi.onBindingCalled(({name:t,args:e})=>{try{const n=this.appBindings.get(t);n&&n(...e)}catch(t){}}),this.appApi.onExceptionThrown(t=>{this.emit("exception",t)})}async pageStack(){return(await this.appApi.getPageStack()).pageStack.map(t=>G.create(this.puppet,t,this.pageMap))}async navigateTo(t){return this.changeRoute("navigateTo",t)}async redirectTo(t){return this.changeRoute("redirectTo",t)}async navigateBack(){return this.changeRoute("navigateBack")}async reLaunch(t){return this.changeRoute("reLaunch",t)}async switchTab(t){return this.changeRoute("switchTab",t)}async currentPage(){const{id:t,path:e,query:n}=await this.appApi.getCurrentPage();return G.create(this.puppet,{id:t,path:e,query:n},this.pageMap)}async systemInfo(){return this.callUniMethod("getSystemInfoSync")}async callUniMethod(t,...e){return(await this.appApi.callUniMethod({method:t,args:e})).result}async mockUniMethod(t,e,...n){return w(e)||P(s=e)&&(s=f(s),M(s,"function")||M(s,"() =>"))?this.appApi.mockUniMethod({method:t,functionDeclaration:e.toString(),args:n}):this.appApi.mockUniMethod({method:t,result:e});var s}async restoreUniMethod(t){return this.appApi.mockUniMethod({method:t})}async evaluate(t,...e){return(await this.appApi.callFunction({functionDeclaration:t.toString(),args:e})).result}async pageScrollTo(t){await this.callUniMethod("pageScrollTo",{scrollTop:t,duration:0})}async close(){try{await this.appApi.exit()}catch(t){}await Y(1e3),this.puppet.disposeRuntimeServer(),await this.toolApi.close(),this.disconnect()}async teardown(){return this[this.options.teardown===x.DISCONNECT?x.DISCONNECT:x.CLOSE]()}async remote(t){if(!this.puppet.devtools.remote)return console.warn(`Failed to enable remote, ${this.puppet.devtools.name} is unimplemented`);const{qrCode:e}=await this.toolApi.enableRemoteDebug({auto:t});var n;e&&await(n=e,new Promise(t=>{T.generate(n,{small:!0},e=>{process.stdout.write(e),t()})}));const s=new Promise(t=>{this.toolApi.onRemoteDebugConnected(async()=>{await Y(1e3),t()})}),o=new Promise(t=>{this.puppet.setRemoteRuntimeConnectionCallback(()=>{t()})});return Promise.all([s,o])}disconnect(){this.puppet.dispose()}on(t,e){return"console"===t&&this.appApi.enableLog(),super.on(t,e),this}async exposeFunction(t,e){if(this.appBindings.has(t))throw Error(`Failed to expose function with name ${t}: already exists!`);this.appBindings.set(t,e),await this.appApi.addBinding({name:t})}async checkVersion(){}async screenshot(t){const{data:e}=await this.appApi.captureScreenshot();if(!(null==t?void 0:t.path))return e;await v.writeFile(t.path,e,"base64")}async testAccounts(){return(await this.toolApi.getTestAccounts()).accounts}async changeRoute(t,e){return await this.callUniMethod(t,{url:e}),await Y(3e3),this.currentPage()}}class Q{constructor(t){this.options=t}has(t){return!!this.options[t]}send(t,e,n){const s=this.options[e];if(!s)return Promise.reject(Error(`adapter for ${e} not found`));const o=s.reflect;return o?(s.params&&(n=s.params(n)),"function"==typeof o?o(t.send.bind(t),n):(e=o,t.send(e,n))):Promise.reject(Error(e+"'s reflect is required"))}}class Z extends m.EventEmitter{constructor(t,e){if(super(),this.target=e||require(`@dcloudio/uni-${t}/lib/uni.automator.js`),!this.target)throw Error("puppet is not provided");this.platform=t,this.adapter=new Q(this.target.adapter||{})}setRuntimeServer(t){this.wss=t}setRemoteRuntimeConnectionCallback(t){this.remoteRuntimeConnectionCallback=t}setRuntimeConnection(t){this.runtimeConnection=t,this.remoteRuntimeConnectionCallback&&(this.remoteRuntimeConnectionCallback(),this.remoteRuntimeConnectionCallback=null)}setDevtoolConnection(t){this.devtoolConnection=t}disposeRuntimeServer(){this.wss&&this.wss.close()}disposeRuntime(){this.runtimeConnection.dispose()}disposeDevtool(){this.devtoolConnection&&this.devtoolConnection.dispose()}dispose(){this.disposeRuntime(),this.disposeDevtool(),this.disposeRuntimeServer()}send(t,e){return this.runtimeConnection.send(t,e)}validateProject(t){const s=this.target.devtools.required;return!s||!s.find(s=>!e.existsSync(n.join(t,s)))}get checkProperty(){return"mp-weixin"===this.platform}get defaultPort(){return this.target.devtools.defaultPort}get devtools(){return this.target.devtools}get mode(){const t=this.target.mode;return t||("production"===process.env.NODE_ENV?"build":"dev")}}const tt=s("automator:compiler"),et=/The\s+(.*)\s+directory is ready/;class nt{constructor(t){this.puppet=t}compile(t){const e=this.puppet.mode,s=this.puppet.platform;let i=t.silent;const r=t.port,c=t.host,l=process.env.UNI_NPM_PATH||"npm",p=`${e}:${s}`,u=t.projectPath,h=["run",p,"--","--auto-port",a(r)];c&&(h.push("--auto-host"),h.push(c));const d={cwd:t.cliPath||t.projectPath,env:process.env};return new Promise((t,r)=>{const a=function(o){const r=o.toString().trim();if(!i&&console.log(r),r.includes("App running at:"))t({path:""});else if(r.includes("DONE Build complete")){let o=`unpackage/dist/${e}/${s}`;const a=r.match(et);a&&a.length>1&&(o=a[1]),i=!0,c.kill("SIGTERM"),t({path:n.join(u,o)})}};tt(`${l} ${h.join(" ")}`);const c=o.spawn(l,h,d);c.on("error",(function(t){r(t)})),c.stdout.on("data",a),c.stderr.on("data",a)})}}const st=s("automator:devtool"),ot=1e5;function it(t){throw Error(t)}class rt{async launch(t){const e=t.devtools||{};this.puppet=new Z(t.platform,t.puppet);const{port:n,cliPath:o,projectPath:i}=await this.validate(t);let r;this.puppet.devtools.automator&&(r=await this.validateDevtools(e));let a=i;if(!1!==t.compile){this.compiler=new nt(this.puppet);const e=await this.compiler.compile({host:r&&r.host,port:n,cliPath:o,projectPath:i,silent:!!t.silent});e.path&&(a=e.path)}const c=[];return c.push(this.createRuntimeConnection(n,e)),r&&c.push(this.createDevtoolConnection(a,r)),new Promise((t,n)=>{Promise.all(c).then(([n,o])=>{this.puppet.setRuntimeConnection(n),this.puppet.setDevtoolConnection(o),s("automator:program")("ready");const i=e.teardown||x.DISCONNECT;t(new K(this.puppet,{teardown:i}))}).catch(t=>n(t))})}async connectTool(t){let e;try{e=await b.createDevtoolConnection(t.wsEndpoint,this.puppet)}catch(e){throw Error(`Failed connecting to ${t.wsEndpoint}, check if target project window is opened with automation enabled`)}return e}validateCliPath(t){try{const e=require(n.join(t,"package.json"));if(e.devDependencies&&e.devDependencies["@dcloudio/vue-cli-plugin-uni"])return!0}catch(t){}}resolveCliPath(t){return t?this.validateCliPath(t)?t:void it(`Cli ${t} doesn't exist`):t}resolveProjectPath(t,s){if(t||(t=process.cwd()),u(t)&&(t=n.resolve(t)),e.existsSync(t)||it(`Project path ${t} doesn't exist`),!1===s.compile&&!this.puppet.validateProject(t)){const e=n.join(t,"dist/"+this.puppet.mode+"/"+this.puppet.platform);if(this.puppet.validateProject(e))return e;s.compile=!0}return t}async resolvePort(t,e){const n=await r(t||e);return t&&n!==t&&it(`Port ${t} is in use, please specify another port`),n}async validate(t){const e=this.resolveProjectPath(t.projectPath,t);let n=t.cliPath;return!1!==t.compile&&(n=this.resolveCliPath(t.cliPath||""),!n&&(n=this.resolveCliPath(e))),{port:await this.resolvePort(t.port||9520),cliPath:n,projectPath:e,platform:t.platform}}resolveDevtoolsPath(t){const n=this.puppet.devtools.paths.slice(0);t&&n.unshift(t);for(const t of n)if(e.existsSync(t))return t;it(this.puppet.devtools.name+" not found, please specify devtools.cliPath option")}async validateDevtools(t={}){const e=this.resolveDevtoolsPath(t.cliPath);let n=t.port||this.puppet.defaultPort;if(!1!==t.launch)try{n=await this.resolvePort(n)}catch(e){t.launch=!1}else{n===await r(n)&&(t.launch=!0)}return Object.assign(Object.assign({},t),{port:n,cliPath:e})}async createRuntimeConnection(t,e){return b.createRuntimeConnection(t,this.puppet,e.timeout||ot)}async createDevtoolConnection(t,e){const{port:n,cliPath:s,timeout:o=ot,cwd:r="",account:u="",args:d=[],launch:m=!0}=e;let y=!1,g=!1;if(!1!==m){const e={detached:!0,stdio:"ignore"};r&&(e.cwd=r);let o=l(d,["--auto",t,"--auto-port",a(n)]);u&&(o=l(o,["--auto-account",u]));try{st("%s %o %o",s,o,e);const t=i.spawn(s,o,e);t.on("error",t=>{y=!0}),t.on("exit",()=>{setTimeout(()=>{g=!0},15e3)}),t.unref()}catch(t){y=!1}}else setTimeout(()=>{g=!0},15e3);const v=await c(async()=>{try{if(y||g)return!0;return await this.connectTool({wsEndpoint:"ws://127.0.0.1:"+n})}catch(t){}},o,1e3);return y&&it(`Failed to launch ${this.puppet.devtools.name}, please make sure cliPath is correctly specified`),g&&it(`Failed to launch ${this.puppet.devtools.name} , please make sure http port is open`),await p(5e3),st(h("yyyy-mm-dd HH:MM:ss:l")+" connected"),!1===m&&this.initRuntimeAutomator(v),v}async initRuntimeAutomator(t){return st("initRuntimeAutomator"),t.send("App.callUniMethod",{method:"$$initRuntimeAutomator",args:[]})}}module.exports=class{constructor(){this.launcher=new rt}async launch(t){return this.launcher.launch(t)}};
diff --git a/packages/uni-automator/dist/teardown.js b/packages/uni-automator/dist/teardown.js
new file mode 100644
index 0000000000000000000000000000000000000000..f9c5fc96a2ceb07897bdeb4efc4a03de212b9714
--- /dev/null
+++ b/packages/uni-automator/dist/teardown.js
@@ -0,0 +1 @@
+"use strict";module.exports=async function(){const e=global.program;e&&e.teardown(),await new Promise(e=>{setTimeout(()=>{e()},3e3)})};
diff --git a/packages/uni-automator/package.json b/packages/uni-automator/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..06bdc58140525d2ffdf55832235fbc366a2e44ef
--- /dev/null
+++ b/packages/uni-automator/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@dcloudio/uni-automator",
+ "version": "2.0.0-alpha-26920200407011",
+ "description": "uni-app automator",
+ "main": "dist/index.js",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/dcloudio/uni-app.git",
+ "directory": "packages/uni-automator"
+ },
+ "files": [
+ "dist"
+ ],
+ "author": "fxy060608",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "jimp": "^0.10.1",
+ "licia": "^1.21.0",
+ "qrcode-reader": "^1.0.4",
+ "qrcode-terminal": "^0.12.0",
+ "ws": "^7.2.3"
+ }
+}
diff --git a/packages/uni-h5/dist/automator.js b/packages/uni-h5/dist/automator.js
new file mode 100644
index 0000000000000000000000000000000000000000..2f1be0528c19bcdf2cb03f031c09cd026a6b6f74
--- /dev/null
+++ b/packages/uni-h5/dist/automator.js
@@ -0,0 +1 @@
+var n,t=Object.prototype.hasOwnProperty,e=Array.isArray;function r(n){return n.__wxWebviewId__?n.__wxWebviewId__:n.privateProperties?n.privateProperties.slaveId:void 0}function o(n){return n.route||n.uri}function u(n){return{id:r(n),path:o(n),query:n.options}}function i(n){var t=function(n){return getCurrentPages().find((function(t){return r(t)===n}))}(n);return t&&t.$vm}function a(n,t){var e=i(n);return e&&function n(t,e){var r,o;return t&&(t.$scope&&((o=t.$scope).__wxExparserNodeId__||o.nodeId||o.id)===e?r=t:t.$children.find((function(t){return r=n(t,e)}))),r}(e,t)}function c(n,r){var o;return n&&(o=r?function(n,r){var o,u=function(n,r){if(e(n))return n;if(r&&(o=r,u=n,t.call(o,u)))return[n];var o,u;var i=[];return n.replace(l,(function(n,t,e,r){return i.push(e?r.replace(/\\(\\)?/g,"$1"):t||n),r})),i}(r,n);for(o=u.shift();i=o,null!=i;){if(null==(n=n[o]))return;o=u.shift()}var i;return n}(n.$data,r):Object.assign({},n.$data)),Promise.resolve({data:o})}function s(n,t){return n&&Object.keys(t).forEach((function(e){n[e]=t[e]})),Promise.resolve()}function f(t,e,r){return new Promise((function(o,u){if(!t)return u(n.VM_NOT_EXISTS);if(!t[e])return u(n.VM_NOT_EXISTS);var i,a=t[e].apply(t,r);!(i=a)||"object"!=typeof i&&"function"!=typeof i||"function"!=typeof i.then?o({result:a}):a.then((function(n){o({result:n})}))}))}!function(n){n.VM_NOT_EXISTS="VM_NOT_EXISTS",n.METHOD_NOT_EXISTS="METHOD_NOT_EXISTS"}(n||(n={}));var l=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;var p=/Sync$/;var d={getPageStack:function(){return Promise.resolve({pageStack:getCurrentPages().map((function(n){return u(n)}))})},getCurrentPage:function(){var n=getCurrentPages(),t=n.length;return new Promise((function(e,r){t?e(u(n[t-1])):r(Error("getCurrentPages().length=0"))}))},callUniMethod:function(n){var t=n.method,e=n.args;return new Promise((function(n,r){if(!uni[t])return r(Error("uni."+t+" not exists"));if(function(n){return p.test(n)}(t))return n({result:uni[t].apply(uni,e)});var o=[Object.assign({},e[0]||{},{success:function(e){setTimeout((function(){n({result:e})}),"pageScrollTo"===t?350:0)},fail:function(n){r(Error(n.errMsg.replace(t+":fail ","")))}})];uni[t].apply(uni,o)}))}},g={getData:function(n){return c(i(n.pageId),n.path)},setData:function(n){return s(i(n.pageId),n.data)},callMethod:function(t){var e,r=((e={})[n.VM_NOT_EXISTS]="Page["+t.pageId+"] not exists",e[n.METHOD_NOT_EXISTS]="page."+t.method+" not exists",e);return new Promise((function(n,e){f(i(t.pageId),t.method,t.args).then((function(t){return n(t)})).catch((function(n){e(Error(r[n]))}))}))}};function _(n){return n.nodeId||n.elementId}var v={getData:function(n){return c(a(n.pageId,_(n)),n.path)},setData:function(n){return s(a(n.pageId,_(n)),n.data)},callMethod:function(t){var e,r=_(t),o=((e={})[n.VM_NOT_EXISTS]="Component["+t.pageId+":"+r+"] not exists",e[n.METHOD_NOT_EXISTS]="component."+t.method+" not exists",e);return new Promise((function(n,e){f(a(t.pageId,r),t.method,t.args).then((function(t){return n(t)})).catch((function(n){e(Error(o[n]))}))}))}},m={};Object.keys(d).forEach((function(n){m["App."+n]=d[n]})),Object.keys(g).forEach((function(n){m["Page."+n]=g[n]})),Object.keys(v).forEach((function(n){m["Element."+n]=v[n]}));var h=process.env.UNI_AUTOMATOR_WS_ENDPOINT;setTimeout((function(){!function(n){void 0===n&&(n={});var t=uni.connectSocket({url:h,complete:function(){}}),e=function(n){return t.send({data:JSON.stringify(n)})};t.onOpen((function(t){n.success&&n.success(),console.log("自动化测试已开启...")})),t.onMessage((function(n){var t=JSON.parse(n.data),r=t.id,o=t.method,u=t.params,i={id:r},a=m[o];if(!a)return i.error={message:o+" unimplemented"},e(i);a(u).then((function(n){n&&(i.result=n)})).catch((function(n){i.error={message:n.message}})).finally((function(){e(i)}))})),t.onError((function(n){console.log("automator.onError",n)})),t.onClose((function(){n.fail&&n.fail({errMsg:"$$initRuntimeAutomator:fail"}),console.log("automator.onClose")}))}()}),500);
diff --git a/packages/uni-mp-baidu/dist/automator.js b/packages/uni-mp-baidu/dist/automator.js
new file mode 100644
index 0000000000000000000000000000000000000000..53434b706c7366f007da1552f709bc470a859901
--- /dev/null
+++ b/packages/uni-mp-baidu/dist/automator.js
@@ -0,0 +1 @@
+var n,t=Object.prototype.hasOwnProperty,e=Array.isArray;function r(n){return n.__wxWebviewId__?n.__wxWebviewId__:n.privateProperties?n.privateProperties.slaveId:void 0}function o(n){return n.route||n.uri}function u(n){return{id:r(n),path:o(n),query:n.options}}function i(n){var t=function(n){return getCurrentPages().find((function(t){return r(t)===n}))}(n);return t&&t.$vm}function a(n,t){var e=i(n);return e&&function n(t,e){var r,o;return t&&(t.$scope&&((o=t.$scope).__wxExparserNodeId__||o.nodeId||o.id)===e?r=t:t.$children.find((function(t){return r=n(t,e)}))),r}(e,t)}function c(n,r){var o;return n&&(o=r?function(n,r){var o,u=function(n,r){if(e(n))return n;if(r&&(o=r,u=n,t.call(o,u)))return[n];var o,u;var i=[];return n.replace(l,(function(n,t,e,r){return i.push(e?r.replace(/\\(\\)?/g,"$1"):t||n),r})),i}(r,n);for(o=u.shift();i=o,null!=i;){if(null==(n=n[o]))return;o=u.shift()}var i;return n}(n.$data,r):Object.assign({},n.$data)),Promise.resolve({data:o})}function s(n,t){return n&&Object.keys(t).forEach((function(e){n[e]=t[e]})),Promise.resolve()}function f(t,e,r){return new Promise((function(o,u){if(!t)return u(n.VM_NOT_EXISTS);if(!t[e])return u(n.VM_NOT_EXISTS);var i,a=t[e].apply(t,r);!(i=a)||"object"!=typeof i&&"function"!=typeof i||"function"!=typeof i.then?o({result:a}):a.then((function(n){o({result:n})}))}))}!function(n){n.VM_NOT_EXISTS="VM_NOT_EXISTS",n.METHOD_NOT_EXISTS="METHOD_NOT_EXISTS"}(n||(n={}));var l=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;var p=/Sync$/;var d={getPageStack:function(){return Promise.resolve({pageStack:getCurrentPages().map((function(n){return u(n)}))})},getCurrentPage:function(){var n=getCurrentPages(),t=n.length;return new Promise((function(e,r){t?e(u(n[t-1])):r(Error("getCurrentPages().length=0"))}))},callUniMethod:function(n){var t=n.method,e=n.args;return new Promise((function(n,r){if(!uni[t])return r(Error("uni."+t+" not exists"));if(function(n){return p.test(n)}(t))return n({result:uni[t].apply(uni,e)});var o=[Object.assign({},e[0]||{},{success:function(e){setTimeout((function(){n({result:e})}),"pageScrollTo"===t?350:0)},fail:function(n){r(Error(n.errMsg.replace(t+":fail ","")))}})];uni[t].apply(uni,o)}))}},g={getData:function(n){return c(i(n.pageId),n.path)},setData:function(n){return s(i(n.pageId),n.data)},callMethod:function(t){var e,r=((e={})[n.VM_NOT_EXISTS]="Page["+t.pageId+"] not exists",e[n.METHOD_NOT_EXISTS]="page."+t.method+" not exists",e);return new Promise((function(n,e){f(i(t.pageId),t.method,t.args).then((function(t){return n(t)})).catch((function(n){e(Error(r[n]))}))}))}};function m(n){return n.nodeId||n.elementId}var _={getData:function(n){return c(a(n.pageId,m(n)),n.path)},setData:function(n){return s(a(n.pageId,m(n)),n.data)},callMethod:function(t){var e,r=m(t),o=((e={})[n.VM_NOT_EXISTS]="Component["+t.pageId+":"+r+"] not exists",e[n.METHOD_NOT_EXISTS]="component."+t.method+" not exists",e);return new Promise((function(n,e){f(a(t.pageId,r),t.method,t.args).then((function(t){return n(t)})).catch((function(n){e(Error(o[n]))}))}))}},v={};Object.keys(d).forEach((function(n){v["App."+n]=d[n]})),Object.keys(g).forEach((function(n){v["Page."+n]=g[n]})),Object.keys(_).forEach((function(n){v["Element."+n]=_[n]}));var h=process.env.UNI_AUTOMATOR_WS_ENDPOINT;swan.$$initRuntimeAutomator=function(n){void 0===n&&(n={});var t=uni.connectSocket({url:h,complete:function(){}}),e=function(n){return t.send({data:JSON.stringify(n)})};t.onOpen((function(t){n.success&&n.success(),console.log("自动化测试已开启...")})),t.onMessage((function(n){var t=JSON.parse(n.data),r=t.id,o=t.method,u=t.params,i={id:r},a=v[o];if(!a)return i.error={message:o+" unimplemented"},e(i);a(u).then((function(n){n&&(i.result=n)})).catch((function(n){i.error={message:n.message}})).finally((function(){e(i)}))})),t.onError((function(n){console.log("automator.onError",n)})),t.onClose((function(){n.fail&&n.fail({errMsg:"$$initRuntimeAutomator:fail"}),console.log("automator.onClose")}))},setTimeout((function(){swan.$$initRuntimeAutomator()}),500);
diff --git a/packages/uni-mp-baidu/lib/uni.automator.js b/packages/uni-mp-baidu/lib/uni.automator.js
new file mode 100644
index 0000000000000000000000000000000000000000..1c9ac051fe9932463770d789eb9b71188ec14403
--- /dev/null
+++ b/packages/uni-mp-baidu/lib/uni.automator.js
@@ -0,0 +1 @@
+'use strict'; function e (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e } var t = e(require('os')); var a = e(require('path')); var s = e(require('licia/isWindows')); const r = /(^[a-z][a-z0-9-]*)/i; const n = /^navigator/i; const o = /^swan-nav$/i; var p; !(function (e) { e.SELECTOR = 'selector', e.TAGNAME = 'tagName' }(p || (p = {}))); const c = { [p.SELECTOR]: [{ test: n, processor: e => e.replace(n, 'nav') }, { test: r, processor: e => 'swan-' + e }], [p.TAGNAME]: [{ test: o, processor: e => e.replace(o, 'swan-navigator') }, { test: r, processor: e => e.toLocaleLowerCase().replace('swan-', '') }] }; const l = e => t => { const a = (c[e] || []).filter(e => e.test.test(t)); for (const e of a)t = e.processor(t); return t }; const i = l(p.SELECTOR); const m = l(p.TAGNAME); const g = e => Object.assign({}, e, { type: 'id', info: { id: e.elementId } }); const f = []; ['', '-rc'].forEach(e => { s ? (f.push(a.join(t.homedir(), `AppData/Local/Programs/swan-ide-gui${e}/cli.bat`)), f.push(`C:/Program Files/swan-ide-gui${e}/cli.bat`)) : f.push(`/Applications/百度开发者工具${e}.app/Contents/MacOS/cli`) }); const u = { devtools: { name: 'Baidu DevTools', remote: !0, automator: !0, paths: f, required: ['project.swan.json', 'app.json', 'app.js'], defaultPort: 9430 }, adapter: { 'Tool.enableRemoteDebug': { reflect: async e => ({ qrCode: (await e('Tool.enablePreview')).url }) }, 'App.exit': { reflect: async () => Promise.resolve() }, 'App.callUniMethod': { reflect: 'smartapp.swan', params: e => Object.assign({ api: e.method, params: e.args }, e) }, 'Page.getElement': { reflect: async (e, t) => (await e('Page.getElements', t)).elements[0] }, 'Page.getElements': { reflect: async (e, t) => { return { elements: (await e('smartapp.element.getBySelector', Object.assign(Object.assign({}, t), { properties: ['id', 'tagName'], selector: (a = t.selector, a.split(' ').map(e => i(e)).join(' ')) }))).map(e => { const t = e.properties; return { elementId: t.id, nodeId: t.id, tagName: m(t.tagName) } }) }; var a } }, 'Element.getHTML': { reflect: async (e, t) => { const a = [t.type + 'HTML']; return { html: (await e('Element.getDOMProperties', Object.assign(Object.assign({}, t), { names: a }))).properties[0] } } }, 'Element.getElement': { reflect: async (e, t) => (await e('Element.getElements', t)).elements[0] }, 'Element.getElements': { reflect: async (e, t) => { const { elements: a } = await e('Page.getElements', Object.assign(Object.assign({}, t), { selector: `#${t.elementId} ${t.selector}` })); return a.forEach(e => { e.nodeId = e.id }), { elements: a } } }, 'Element.getAttributes': { reflect: async (e, t) => { const a = []; for (const s of t.names)a.push(await e('smartapp.element.getAttribute', Object.assign({ attribute: s }, t))); return { attributes: a } }, params: g }, 'Element.getStyles': { reflect: async (e, t) => { const a = []; for (const s of t.names)a.push(await e('smartapp.element.getComputedStyle', Object.assign({ style: s }, t))); return { styles: a } }, params: g }, 'Element.getDOMProperties': { reflect: async (e, t) => { const a = []; for (const s of t.names)a.push(await e('smartapp.element.getProperty', Object.assign({ property: s }, t))); return { properties: a } }, params: g }, 'Element.getProperties': { reflect: async (e, t) => { const a = []; for (const s of t.names)a.push(await e('smartapp.element.getAttribute', Object.assign({ attribute: s }, t))); return { properties: a } }, params: g }, 'Element.getOffset': { reflect: async (e, t) => ({ left: await e('smartapp.element.getProperty', Object.assign({ property: 'offsetLeft' }, t)), top: await e('smartapp.element.getProperty', Object.assign({ property: 'offsetTop' }, t)) }), params: g }, 'Element.tap': { reflect: 'smartapp.element.touch', params: g } } }; module.exports = u
diff --git a/packages/uni-mp-weixin/dist/automator.js b/packages/uni-mp-weixin/dist/automator.js
new file mode 100644
index 0000000000000000000000000000000000000000..4a735cd71423163ba9c28c881d5b6a81db31b46a
--- /dev/null
+++ b/packages/uni-mp-weixin/dist/automator.js
@@ -0,0 +1 @@
+var n,t=Object.prototype.hasOwnProperty,e=Array.isArray;function r(n){return n.__wxWebviewId__?n.__wxWebviewId__:n.privateProperties?n.privateProperties.slaveId:void 0}function o(n){return n.route||n.uri}function u(n){return{id:r(n),path:o(n),query:n.options}}function i(n){var t=function(n){return getCurrentPages().find((function(t){return r(t)===n}))}(n);return t&&t.$vm}function a(n,t){var e=i(n);return e&&function n(t,e){var r,o;return t&&(t.$scope&&((o=t.$scope).__wxExparserNodeId__||o.nodeId||o.id)===e?r=t:t.$children.find((function(t){return r=n(t,e)}))),r}(e,t)}function c(n,r){var o;return n&&(o=r?function(n,r){var o,u=function(n,r){if(e(n))return n;if(r&&(o=r,u=n,t.call(o,u)))return[n];var o,u;var i=[];return n.replace(l,(function(n,t,e,r){return i.push(e?r.replace(/\\(\\)?/g,"$1"):t||n),r})),i}(r,n);for(o=u.shift();i=o,null!=i;){if(null==(n=n[o]))return;o=u.shift()}var i;return n}(n.$data,r):Object.assign({},n.$data)),Promise.resolve({data:o})}function s(n,t){return n&&Object.keys(t).forEach((function(e){n[e]=t[e]})),Promise.resolve()}function f(t,e,r){return new Promise((function(o,u){if(!t)return u(n.VM_NOT_EXISTS);if(!t[e])return u(n.VM_NOT_EXISTS);var i,a=t[e].apply(t,r);!(i=a)||"object"!=typeof i&&"function"!=typeof i||"function"!=typeof i.then?o({result:a}):a.then((function(n){o({result:n})}))}))}!function(n){n.VM_NOT_EXISTS="VM_NOT_EXISTS",n.METHOD_NOT_EXISTS="METHOD_NOT_EXISTS"}(n||(n={}));var l=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;var p=/Sync$/;var d={getPageStack:function(){return Promise.resolve({pageStack:getCurrentPages().map((function(n){return u(n)}))})},getCurrentPage:function(){var n=getCurrentPages(),t=n.length;return new Promise((function(e,r){t?e(u(n[t-1])):r(Error("getCurrentPages().length=0"))}))},callUniMethod:function(n){var t=n.method,e=n.args;return new Promise((function(n,r){if(!uni[t])return r(Error("uni."+t+" not exists"));if(function(n){return p.test(n)}(t))return n({result:uni[t].apply(uni,e)});var o=[Object.assign({},e[0]||{},{success:function(e){setTimeout((function(){n({result:e})}),"pageScrollTo"===t?350:0)},fail:function(n){r(Error(n.errMsg.replace(t+":fail ","")))}})];uni[t].apply(uni,o)}))}},g={getData:function(n){return c(i(n.pageId),n.path)},setData:function(n){return s(i(n.pageId),n.data)},callMethod:function(t){var e,r=((e={})[n.VM_NOT_EXISTS]="Page["+t.pageId+"] not exists",e[n.METHOD_NOT_EXISTS]="page."+t.method+" not exists",e);return new Promise((function(n,e){f(i(t.pageId),t.method,t.args).then((function(t){return n(t)})).catch((function(n){e(Error(r[n]))}))}))}};function m(n){return n.nodeId||n.elementId}var _={getData:function(n){return c(a(n.pageId,m(n)),n.path)},setData:function(n){return s(a(n.pageId,m(n)),n.data)},callMethod:function(t){var e,r=m(t),o=((e={})[n.VM_NOT_EXISTS]="Component["+t.pageId+":"+r+"] not exists",e[n.METHOD_NOT_EXISTS]="component."+t.method+" not exists",e);return new Promise((function(n,e){f(a(t.pageId,r),t.method,t.args).then((function(t){return n(t)})).catch((function(n){e(Error(o[n]))}))}))}},v={};Object.keys(d).forEach((function(n){v["App."+n]=d[n]})),Object.keys(g).forEach((function(n){v["Page."+n]=g[n]})),Object.keys(_).forEach((function(n){v["Element."+n]=_[n]}));var h=process.env.UNI_AUTOMATOR_WS_ENDPOINT;wx.$$initRuntimeAutomator=function(n){void 0===n&&(n={});var t=uni.connectSocket({url:h,complete:function(){}}),e=function(n){return t.send({data:JSON.stringify(n)})};t.onOpen((function(t){n.success&&n.success(),console.log("自动化测试已开启...")})),t.onMessage((function(n){var t=JSON.parse(n.data),r=t.id,o=t.method,u=t.params,i={id:r},a=v[o];if(!a)return i.error={message:o+" unimplemented"},e(i);a(u).then((function(n){n&&(i.result=n)})).catch((function(n){i.error={message:n.message}})).finally((function(){e(i)}))})),t.onError((function(n){console.log("automator.onError",n)})),t.onClose((function(){n.fail&&n.fail({errMsg:"$$initRuntimeAutomator:fail"}),console.log("automator.onClose")}))},setTimeout((function(){wx.$$initRuntimeAutomator()}),500);
diff --git a/packages/uni-mp-weixin/lib/uni.automator.js b/packages/uni-mp-weixin/lib/uni.automator.js
new file mode 100644
index 0000000000000000000000000000000000000000..4eaba7a6fad0c0e3907b143cb41f131ec70818fc
--- /dev/null
+++ b/packages/uni-mp-weixin/lib/uni.automator.js
@@ -0,0 +1 @@
+'use strict'; function e (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e } var t = e(require('licia/isWindows')); var n = e(require('jimp')); require('licia/isStr'); require('qrcode-terminal'); const a = require('qrcode-reader'); const r = { devtools: { name: 'Wechat web devTools', remote: !0, automator: !0, paths: [t ? 'C:/Program Files (x86)/Tencent/微信web开发者工具/cli.bat' : '/Applications/wechatwebdevtools.app/Contents/MacOS/cli'], required: ['project.config.json', 'app.json', 'app.js'], defaultPort: 9420 }, adapter: { 'Tool.enableRemoteDebug': { reflect: async (e, t) => { let{ qrCode: r } = await e('Tool.enableRemoteDebug', t, !1); return r && (r = await (function (e) { const t = new Buffer(e, 'base64'); return new Promise(async (e, r) => { const o = await n.read(t); const c = new a(); c.callback = function (t, n) { if (t) return r(t); e(n.result) }, c.decode(o.bitmap) }) }(r))), { qrCode: r } } }, 'App.callUniMethod': { reflect: 'App.callWxMethod' }, 'App.callFunction': { reflect: async (e, t) => { return e('App.callFunction', Object.assign(Object.assign({}, t), { functionDeclaration: (n = t.functionDeclaration, n[n.length - 1] === '}' ? n.replace('{', '{\nvar uni = wx;\n') : n.replace('=>', '=>{\nvar uni = wx;\nreturn ') + '}') }), !1); var n } }, 'Element.getHTML': { reflect: async (e, t) => ({ html: (await e('Element.getWXML', t, !1)).wxml }) } } }; module.exports = r
diff --git a/packages/uni-template-compiler/__tests__/demo.js b/packages/uni-template-compiler/__tests__/demo.js
index a98c54828c27e51bd75fd0139d70d2c25d9f2edd..39d59d4f82c9aa7f9c56e0fe3838de4091cf8e48 100644
--- a/packages/uni-template-compiler/__tests__/demo.js
+++ b/packages/uni-template-compiler/__tests__/demo.js
@@ -19,7 +19,12 @@ const scopedPath = path.resolve(__dirname, '../../')
const compiler = require('../lib')
const res = compiler.compile(
`
-
+
+
+123
+456
+
+
`, {
miniprogram: true,
resourcePath: '/User/fxy/Documents/test.wxml',
diff --git a/packages/vue-cli-plugin-uni/commands/build.js b/packages/vue-cli-plugin-uni/commands/build.js
index d9a28a74b2c5cb938e0271bf3862873125afb545..dc3f298b3dafa82291f5d04ffe9d44965492cbfa 100644
--- a/packages/vue-cli-plugin-uni/commands/build.js
+++ b/packages/vue-cli-plugin-uni/commands/build.js
@@ -24,7 +24,9 @@ module.exports = (api, options) => {
usage: 'vue-cli-service uni-build [options]',
options: {
'--watch': 'watch for changes',
- '--minimize': 'Tell webpack to minimize the bundle using the TerserPlugin.'
+ '--minimize': 'Tell webpack to minimize the bundle using the TerserPlugin.',
+ '--auto-host': 'specify automator host',
+ '--auto-port': 'specify automator port'
}
}, async (args) => {
for (const key in defaults) {
@@ -33,6 +35,18 @@ module.exports = (api, options) => {
}
}
+ const port = args['auto-port'] || process.env.UNI_AUTOMATOR_PORT
+ if (port) {
+ const host = args['auto-host'] || process.env.UNI_AUTOMATOR_HOST || '0.0.0.0'
+ const prepareURLs = require('@vue/cli-service/lib/util/prepareURLs')
+ const urls = prepareURLs('ws', host, port, '')
+ if (urls.lanUrlForConfig) {
+ process.env.UNI_AUTOMATOR_WS_ENDPOINT = 'ws://' + urls.lanUrlForConfig + ':' + port
+ } else {
+ process.env.UNI_AUTOMATOR_WS_ENDPOINT = urls.localUrlForBrowser
+ }
+ }
+
args.entry = args.entry || args._[0]
process.env.VUE_CLI_BUILD_TARGET = args.target
diff --git a/packages/vue-cli-plugin-uni/generator.js b/packages/vue-cli-plugin-uni/generator.js
index 144d93b10ba7371e632a09b2208aa838d80432eb..187d277d1c8035715e8c050aee4b189fa2517d79 100644
--- a/packages/vue-cli-plugin-uni/generator.js
+++ b/packages/vue-cli-plugin-uni/generator.js
@@ -27,7 +27,9 @@ module.exports = (api, options, rootOptions) => {
'build:quickapp-vue': 'cross-env NODE_ENV=production UNI_PLATFORM=quickapp-vue vue-cli-service uni-build',
'build:quickapp-light': 'cross-env NODE_ENV=production UNI_PLATFORM=quickapp-light vue-cli-service uni-build',
'dev:custom': 'cross-env NODE_ENV=development uniapp-cli custom',
- 'build:custom': 'cross-env NODE_ENV=production uniapp-cli custom'
+ 'build:custom': 'cross-env NODE_ENV=production uniapp-cli custom',
+ 'test:mp-weixin': 'cross-env UNI_PLATFORM=mp-weixin jest -i',
+ 'test:mp-baidu': 'cross-env UNI_PLATFORM=mp-baidu jest -i'
},
'uni-app': {
scripts: {}
@@ -56,7 +58,8 @@ module.exports = (api, options, rootOptions) => {
'@dcloudio/webpack-uni-mp-loader': version,
'@dcloudio/webpack-uni-pages-loader': version,
'babel-plugin-import': '^1.11.0',
- 'cross-env': '^7.0.2'
+ 'cross-env': '^7.0.2',
+ jest: '^25.4.0'
},
browserslist: [
'Android >= 4',
diff --git a/packages/vue-cli-plugin-uni/lib/chain-webpack.js b/packages/vue-cli-plugin-uni/lib/chain-webpack.js
index ede789c34adb11e6e8fc803cd645a53d5f5bb8e3..1ff13f2417b20007ce09152f715e6a551a54c960 100644
--- a/packages/vue-cli-plugin-uni/lib/chain-webpack.js
+++ b/packages/vue-cli-plugin-uni/lib/chain-webpack.js
@@ -90,13 +90,16 @@ module.exports = function chainWebpack (platformOptions, vueOptions, api) {
platformOptions.chainWebpack(webpackConfig, vueOptions, api)
// define
+ const defines = {
+ 'process.env.UNI_ENV': JSON.stringify(process.env.UNI_PLATFORM),
+ 'process.env.UNI_CLOUD_PROVIDER': process.env.UNI_CLOUD_PROVIDER,
+ 'process.env.HBX_USER_TOKEN': JSON.stringify(process.env.HBX_USER_TOKEN || ''),
+ 'process.env.UNI_AUTOMATOR_WS_ENDPOINT': JSON.stringify(process.env.UNI_AUTOMATOR_WS_ENDPOINT)
+ }
+
webpackConfig
.plugin('uni-define')
- .use(require.resolve('webpack/lib/DefinePlugin'), [{
- 'process.env.UNI_ENV': JSON.stringify(process.env.UNI_PLATFORM),
- 'process.env.UNI_CLOUD_PROVIDER': process.env.UNI_CLOUD_PROVIDER,
- 'process.env.HBX_USER_TOKEN': JSON.stringify(process.env.HBX_USER_TOKEN || '')
- }])
+ .use(require.resolve('webpack/lib/DefinePlugin'), [defines])
if (runByHBuilderX) { // 由 HBuilderX 运行时,移除进度,错误
webpackConfig.plugins.delete('progress')
@@ -106,4 +109,4 @@ module.exports = function chainWebpack (platformOptions, vueOptions, api) {
webpackConfig.plugins.delete('progress')
}
}
-}
+}
diff --git a/packages/vue-cli-plugin-uni/lib/mp/index.js b/packages/vue-cli-plugin-uni/lib/mp/index.js
index f3a3efcd836b67bc5154596630feaf6a8a8961fc..cf11d0b183e40e80123e11a464c646b387103722 100644
--- a/packages/vue-cli-plugin-uni/lib/mp/index.js
+++ b/packages/vue-cli-plugin-uni/lib/mp/index.js
@@ -81,6 +81,9 @@ module.exports = {
const beforeCode = 'import \'uni-pages\';'
+ const automator = `@dcloudio/uni-${process.env.UNI_SUB_PLATFORM || process.env.UNI_PLATFORM}/dist/automator`
+ const automatorCode = process.env.UNI_AUTOMATOR_WS_ENDPOINT ? `import '${automator}';` : ''
+
return {
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
entry () {
@@ -109,7 +112,7 @@ module.exports = {
loader: path.resolve(__dirname, '../../packages/wrap-loader'),
options: {
before: [
- beforeCode + statCode
+ beforeCode + automatorCode + statCode
]
}
}, {
@@ -197,4 +200,4 @@ module.exports = {
webpackConfig.plugins.delete('preload')
webpackConfig.plugins.delete('prefetch')
}
-}
+}
diff --git a/packages/webpack-uni-pages-loader/lib/platforms/mp.js b/packages/webpack-uni-pages-loader/lib/platforms/mp.js
index 2e138319c754aeeee5befde45347ff335208c4ac..1eb16d01242a56e41381c8895811e51b629f52e8 100644
--- a/packages/webpack-uni-pages-loader/lib/platforms/mp.js
+++ b/packages/webpack-uni-pages-loader/lib/platforms/mp.js
@@ -249,8 +249,8 @@ module.exports = function (pagesJson, manifestJson, project = {}) {
content: require(projectPath)
}
}
- } else {
- parseCondition(project, pagesJson)
+ } else {
+ parseCondition(project, pagesJson)
copyToJson(project, pagesJson, pagesJson2ProjectJson)
@@ -286,6 +286,14 @@ module.exports = function (pagesJson, manifestJson, project = {}) {
}
}
+ if (process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
+ if (!project.setting) {
+ project.setting = {}
+ }
+ // automator时,强制不检测域名
+ project.setting.urlCheck = false
+ }
+
if (!project.appid) {
project.appid = 'touristappid'
}
@@ -301,4 +309,4 @@ module.exports = function (pagesJson, manifestJson, project = {}) {
}
}
}
-}
+}
diff --git a/src/core/service/api/ui/keyboard.js b/src/core/service/api/ui/keyboard.js
index e01c473139553537933c2baf50874385d7667c2b..d4f17e42e93483eef58e3a9d973a8f57f738761f 100644
--- a/src/core/service/api/ui/keyboard.js
+++ b/src/core/service/api/ui/keyboard.js
@@ -4,16 +4,16 @@ import {
import {
onMethod
-} from '../../platform'
-
-const callbacks = []
-
+} from '../../platform'
+
+let callback
+
onMethod('onKeyboardHeightChange', res => {
- callbacks.forEach(callbackId => {
- invoke(callbackId, res)
- })
-})
+ if (callback) {
+ invoke(callback, res)
+ }
+})
export function onKeyboardHeightChange (callbackId) {
- callbacks.push(callbackId)
-}
+ callback = callbackId
+}
diff --git a/src/platforms/app-plus/service/api/route/navigate-to.js b/src/platforms/app-plus/service/api/route/navigate-to.js
index 1ff60f4dc77eb2dd792fe9cbf46931ec57c5f102..e4d3e1f0b5e61136553b1f784874bf7192154e18 100644
--- a/src/platforms/app-plus/service/api/route/navigate-to.js
+++ b/src/platforms/app-plus/service/api/route/navigate-to.js
@@ -63,7 +63,7 @@ export function navigateTo ({
const urls = url.split('?')
const path = urls[0]
const routeStyles = __uniRoutes.find(route => route.path === path).window
- const globalStyle = __uniConfig.window
+ const globalStyle = __uniConfig.window || {}
if (!animationType) {
animationType = routeStyles.animationType || globalStyle.animationType || ANI_SHOW
}
@@ -80,4 +80,4 @@ export function navigateTo ({
animationDuration
}, callbackId)
}, openType === 'appLaunch')
-}
+}
diff --git a/src/platforms/app-plus/view/components/picker/index.vue b/src/platforms/app-plus/view/components/picker/index.vue
index ca09ce6d68cfaad19170bc592c7090858d4da59c..d5e21e1b2380d97a2ced540e0d66e4b1f9963ffa 100644
--- a/src/platforms/app-plus/view/components/picker/index.vue
+++ b/src/platforms/app-plus/view/components/picker/index.vue
@@ -55,7 +55,7 @@ function getDefaultStartValue () {
return year
case fields.MONTH:
return year + '-01'
- case fields.DAY:
+ default:
return year + '-01-01'
}
}
@@ -73,7 +73,7 @@ function getDefaultEndValue () {
return year
case fields.MONTH:
return year + '-12'
- case fields.DAY:
+ default:
return year + '-12-31'
}
}
diff --git a/src/platforms/h5/view/components/picker/index.vue b/src/platforms/h5/view/components/picker/index.vue
index 8c702426e7f63a2e840a9cf7a7c9697016cf247d..05e5bc2f617cebfebc084faf79d6a3a7e3f0ae5b 100644
--- a/src/platforms/h5/view/components/picker/index.vue
+++ b/src/platforms/h5/view/components/picker/index.vue
@@ -385,7 +385,9 @@ export default {
for (let index = 0; index < length; index++) {
const val0 = Number(val[index])
const val1 = Number(this.valueSync[index])
- this.valueSync.splice(index, 1, isNaN(val0) ? (isNaN(val1) ? 0 : val1) : val0)
+ const val2 = isNaN(val0) ? (isNaN(val1) ? 0 : val1) : val0
+ const maxVal = this.range[index] ? this.range[index].length - 1 : 0
+ this.valueSync.splice(index, 1, val2 > maxVal ? 0 : val2)
}
}
break
diff --git a/src/platforms/mp-alipay/runtime/api/protocols.js b/src/platforms/mp-alipay/runtime/api/protocols.js
index f52c2897eb4ca05e51b1ccee46af9302f6231b84..838ab1d74934be49787580ff1695ea4ab84f4f51 100644
--- a/src/platforms/mp-alipay/runtime/api/protocols.js
+++ b/src/platforms/mp-alipay/runtime/api/protocols.js
@@ -211,11 +211,11 @@ const protocols = { // 需要做转换的 API 列表
returnValue: {
apFilePath: 'tempFilePath'
}
- },
- getFileInfo: {
- args: {
- filePath: 'apFilePath'
- }
+ },
+ getFileInfo: {
+ args: {
+ filePath: 'apFilePath'
+ }
},
chooseVideo: {
// 支付宝小程序文档中未找到(仅在getSetting处提及),但实际可用
@@ -306,22 +306,19 @@ const protocols = { // 需要做转换的 API 列表
scanCode: {
name: 'scan',
args (fromArgs) {
- if (fromArgs.scanType === 'qrCode') {
- fromArgs.type = 'qr'
- return {
- onlyFromCamera: 'hideAlbum'
- }
- } else if (fromArgs.scanType === 'barCode') {
- fromArgs.type = 'bar'
- return {
- onlyFromCamera: 'hideAlbum'
- }
- } else {
- return {
- scanType: false,
- onlyFromCamera: 'hideAlbum'
+ if (fromArgs.scanType) {
+ switch (fromArgs.scanType[0]) {
+ case 'qrCode':
+ fromArgs.type = 'qr'
+ break
+ case 'barCode':
+ fromArgs.type = 'bar'
+ break
}
}
+ return {
+ onlyFromCamera: 'hideAlbum'
+ }
},
returnValue: {
code: 'result'