'use strict' // Executes actual page data-loading methods with the local contract. No UI renderer or app startup. const fs=require('fs'),path=require('path'),vm=require('vm'),assert=require('assert') const repo=path.resolve(__dirname,'../..'), modules=path.resolve(repo,'../.local-acceptance/mp-build/node_modules') const babel=require(path.join(modules,'@babel/core')) const {createMock,ORIGIN}=require('./runtime');const cache={};const mock=createMock({get:k=>cache[k],set:(k,v)=>cache[k]=v}) const user=mock.request(ORIGIN+'/login','POST',{}).data const app={$wepy:{$options:{globalData:{systemInfo:{system:'Windows 10'}}}}} const storage={userInfo:{...user.user,is_base_profile:true,name:user.user.nickname},adv:user.adv} const wx=new Proxy({getStorageSync:k=>storage[k],setStorageSync:(k,v)=>storage[k]=v},{get:(o,k)=>o[k]||(()=>{})}) const errors=[] function page(file){ let definition const content=fs.readFileSync(path.join(repo,'src',file),'utf8').match(/]*>([\s\S]*?)<\/script>/)[1] const code=babel.transformSync(content,{babelrc:false,configFile:false,plugins:[require(path.join(modules,'@babel/plugin-transform-modules-commonjs'))]}).code const requireMock=id=>{ if(id==='@wepy/core')return {page:opts=>definition=opts} if(id.includes('config'))return {service:{host:ORIGIN,user:ORIGIN+'/user'}} if(id.includes('plugins'))return {commentTimeHandle:s=>s,formatRemainTimeData:()=>({d:0,h:0,m:0,s:0})} return {} } vm.runInNewContext(code,{require:requireMock,exports:{},module:{exports:{}},wx,getApp:()=>app,console:{log(...args){if(args.some(x=>x&&x.stack))errors.push('caught page exception')},error(){errors.push('page error')}},setTimeout(){},clearTimeout(){},setInterval(){},clearInterval(){}}) const instance=Object.assign({},JSON.parse(JSON.stringify(definition.data||{})),{$app:app.$wepy,$nextTick(){},$showLoading(){},$showToast(){},$signInVerify:()=>true}) for(const [key,fn] of Object.entries(definition.methods||{}))instance[key]=fn.bind(instance) for(const [key,method] of [['$get','GET'],['$post','POST'],['$put','PUT'],['$delete','DELETE']])instance[key]=({url,data})=>{const r=mock.request(url,method,data);if(r.code!==0){errors.push('unsupported page request: '+url.slice(ORIGIN.length));return Promise.reject(Error(r.message))}return Promise.resolve(r)} return instance } const tick=()=>new Promise(resolve=>setImmediate(resolve)) async function run(){ const home=page('pages/tabBar/home.wpy');for(const name of ['getTopUser','getArea','getEveryday','getSquare','applyTopUpState','getBannerList']){home[name]();await tick()} assert.equal(home.topList.length,3);assert.equal(home.squareList.length,3);assert.equal(home.referrals.length,4) const dynamic=page('pages/tabBar/dynamic.wpy');dynamic.getList();dynamic.getHotTopics();await tick();assert.equal(dynamic.dynamicList.length,1) const news=page('pages/tabBar/news.wpy');news.getList();news.getNewCount();await tick();assert.equal(news.menuList[0].count,0) const mine=page('pages/tabBar/user.wpy');mine.getIsBaseInfo();mine.initPageData();await tick();assert.equal(mine.user.id,900000001) const other=page('pages/home/information.wpy');other.id=900000002;other.getDetail();await tick() const editor=page('pages/users/selfTextarea.wpy');editor.text='自我描述';editor.getuser();await tick();assert.equal(editor.value,mock.snapshot().profile.introduction) const service=page('pages/users/upgradeVIP2.wpy');service.initPageData();await tick();assert.equal(service.rankList.length,0);assert.match(service.specialVIP.discount_desc,/暂无可展示/) for(const state of ['PENDING','FULFILLED'])assert.equal(mock.request(ORIGIN+'/order/virtual/LOCAL-ACCEPTANCE-'+state+'/confirm','POST',{}).data.state,state) assert.notEqual(mock.request(ORIGIN+'/order/virtual/REAL-ORDER/confirm','POST',{}).code,0) assert.deepEqual(errors,[]) console.log('PASS: actual home/dynamic/news/user/detail/editor data methods consume local mock contracts without recorded exceptions. Rendering not tested.') } run().catch(e=>{console.error(e);process.exitCode=1})