文件
Henglianshutong/tests/verify_wechat_quick_login_spec.js

238 行
10 KiB
JavaScript

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

const fs = require('fs');
const path = require('path');
let passed = 0;
let failed = 0;
function assert(condition, testName, detail = '') {
if (condition) {
console.log(` [PASS] ${testName}`);
passed++;
} else {
console.error(` [FAIL] ${testName} - ${detail}`);
failed++;
}
}
console.log("========================================================");
console.log(" 微信小程序默认登录采用手机号一键快捷登录规格测试");
console.log("========================================================\n");
// 1. 后端服务层: MiniProgram.php
const miniProgramPhpPath = path.resolve(__dirname, '../addons/shopro/service/third/wechat/MiniProgram.php');
assert(fs.existsSync(miniProgramPhpPath), 'MiniProgram.php 文件存在');
const miniProgramPhpContent = fs.readFileSync(miniProgramPhpPath, 'utf-8');
assert(
miniProgramPhpContent.includes('wxa/business/getuserphonenumber') && miniProgramPhpContent.includes("['code']"),
'MiniProgram.php 支持微信新版 code 获取手机号接口',
'未包含 wxa/business/getuserphonenumber 逻辑'
);
assert(
miniProgramPhpContent.includes('encryptor->decryptData') && miniProgramPhpContent.includes('purePhoneNumber'),
'MiniProgram.php 保留传统 iv + encryptedData 解密降级兼容',
'未包含 decryptData 解密兼容'
);
assert(
miniProgramPhpContent.includes('$mobile = $this->getUserPhoneNumber()') && miniProgramPhpContent.includes("'mobile' => $mobile"),
'MiniProgram.php 在 login() 方法中当传入手机号凭证时自动提取 mobile',
'login() 中未提取手机号'
);
// 2. 后端服务层: Wechat.php
const wechatServicePath = path.resolve(__dirname, '../addons/shopro/service/third/wechat/Wechat.php');
assert(fs.existsSync(wechatServicePath), 'Wechat.php (Service) 文件存在');
const wechatServiceContent = fs.readFileSync(wechatServicePath, 'utf-8');
assert(
wechatServiceContent.includes("UserModel::where('mobile', $extend['mobile'])->find()"),
'Wechat.php 在 registerOrBindUser 中检查已有手机号并直接绑定关联',
'未检测到已有手机号用户直接关联逻辑'
);
assert(
wechatServiceContent.includes('$user->mobile = $extend['),
'Wechat.php 为已绑定微信但尚无手机号的用户自动补充手机号',
'未检测到已绑定账号补充手机号逻辑'
);
// 3. 后端控制器层: Wechat.php
const wechatControllerPath = path.resolve(__dirname, '../addons/shopro/controller/third/Wechat.php');
assert(fs.existsSync(wechatControllerPath), 'Wechat.php (Controller) 文件存在');
const wechatControllerContent = fs.readFileSync(wechatControllerPath, 'utf-8');
assert(
wechatControllerContent.includes("'token' => $auth->isLogin() ? $auth->getToken() : ''"),
'Wechat.php (Controller) 在 login 成功响应数据中返回 token',
'响应未返回 token'
);
// 4. 前端平台驱动层: miniProgram.js
const miniProgramJsPath = path.resolve(__dirname, '../uniapp/sheep/platform/provider/wechat/miniProgram.js');
assert(fs.existsSync(miniProgramJsPath), 'miniProgram.js 文件存在');
const miniProgramJsContent = fs.readFileSync(miniProgramJsPath, 'utf-8');
assert(
miniProgramJsContent.includes('const mobileLogin = async (e) => {') && miniProgramJsContent.includes('third.wechat.login'),
'miniProgram.js 包含封装完善的 mobileLogin 方法',
'未包含 mobileLogin 方法'
);
assert(
miniProgramJsContent.includes('mobileLogin,') && miniProgramJsContent.includes('export default {'),
'miniProgram.js 在 export default 中导出了 mobileLogin',
'未导出 mobileLogin'
);
// 5. 前端弹窗状态控制: useModal.js
const useModalPath = path.resolve(__dirname, '../uniapp/sheep/hooks/useModal.js');
assert(fs.existsSync(useModalPath), 'useModal.js 文件存在');
const useModalContent = fs.readFileSync(useModalPath, 'utf-8');
assert(
useModalContent.includes('MP-WEIXIN') && useModalContent.includes("targetType = 'mpMobileLogin'"),
'useModal.js 微信小程序环境下默认弹窗类型为 mpMobileLogin',
'未设置微信小程序默认弹窗类型为 mpMobileLogin'
);
// 6. 新增组件: mp-mobile-login.vue
const mpMobileLoginPath = path.resolve(__dirname, '../uniapp/sheep/components/s-auth-modal/components/mp-mobile-login.vue');
assert(fs.existsSync(mpMobileLoginPath), 'mp-mobile-login.vue 文件存在');
const mpMobileLoginContent = fs.readFileSync(mpMobileLoginPath, 'utf-8');
assert(
mpMobileLoginContent.includes('open-type="getPhoneNumber"') && mpMobileLoginContent.includes('@getphonenumber="onGetPhoneNumber"'),
'mp-mobile-login.vue 包含 open-type="getPhoneNumber" 授权按钮',
'缺少 getPhoneNumber 授权按钮'
);
assert(
mpMobileLoginContent.includes("showAuthModal('smsLogin')") && mpMobileLoginContent.includes("showAuthModal('accountLogin')"),
'mp-mobile-login.vue 提供切换短信登录和账号登录的快速入口',
'缺少其他登录方式入口'
);
assert(
mpMobileLoginContent.includes('agreeStatus') && mpMobileLoginContent.includes('mobileLogin'),
'mp-mobile-login.vue 校验用户协议并调用 mobileLogin 登录',
'缺少协议校验或登录调用'
);
// 7. 弹窗容器: s-auth-modal.vue
const sAuthModalPath = path.resolve(__dirname, '../uniapp/sheep/components/s-auth-modal/s-auth-modal.vue');
assert(fs.existsSync(sAuthModalPath), 's-auth-modal.vue 文件存在');
const sAuthModalContent = fs.readFileSync(sAuthModalPath, 'utf-8');
assert(
sAuthModalContent.includes("import mpMobileLogin from './components/mp-mobile-login.vue'") && sAuthModalContent.includes("authType === 'mpMobileLogin'"),
's-auth-modal.vue 成功挂载 mp-mobile-login 组件',
'未挂载 mp-mobile-login'
);
assert(
sAuthModalContent.includes("'mpMobileLogin'") && sAuthModalContent.includes('agreement-box'),
's-auth-modal.vue 协议栏支持 mpMobileLogin 显示与勾选状态关联',
'协议栏未支持 mpMobileLogin'
);
// 8. 个人中心卡片组件: s-user-card.vue
const sUserCardPath = path.resolve(__dirname, '../uniapp/sheep/components/s-user-card/s-user-card.vue');
assert(fs.existsSync(sUserCardPath), 's-user-card.vue 文件存在');
const sUserCardContent = fs.readFileSync(sUserCardPath, 'utf-8');
assert(
sUserCardContent.includes('#ifdef MP-WEIXIN') && sUserCardContent.includes('open-type="getPhoneNumber"') && sUserCardContent.includes('@getphonenumber="onQuickLogin"'),
's-user-card.vue 在微信小程序端未登录时渲染 open-type="getPhoneNumber" 快捷登录按钮',
'未检测到微信小程序快捷登录按钮'
);
assert(
sUserCardContent.includes('async function onQuickLogin(e)') && sUserCardContent.includes("mobileLogin(e.detail)"),
's-user-card.vue 包含 onQuickLogin 处理函数调用 mobileLogin 完成快捷登录',
'未检测到 onQuickLogin 处理逻辑'
);
assert(
sUserCardContent.includes('hasBoundMobile') && sUserCardContent.includes('userInfo.value?.mobile || userInfo.value?.verification?.mobile'),
's-user-card.vue 使用 hasBoundMobile 判定:只要存在手机号则不展示绑定提示条',
'缺少 hasBoundMobile 判定逻辑'
);
assert(
sUserCardContent.includes('onBindPhoneNumber') && sUserCardContent.includes('bindUserPhoneNumber(e.detail)'),
's-user-card.vue 在微信小程序端去绑定支持 open-type="getPhoneNumber" 一键绑定',
'缺少一键去绑定逻辑'
);
assert(
sUserCardContent.includes('#ifndef MP-WEIXIN') && sUserCardContent.includes('showAuthModal()'),
's-user-card.vue 保留非微信小程序端正常点击弹窗唤醒逻辑',
'未保留非微信小程序端唤醒逻辑'
);
// 9. 用户模型与用户仓库:User.php & user.js
const userModelPath = path.resolve(__dirname, '../application/admin/model/shopro/user/User.php');
assert(fs.existsSync(userModelPath), 'User.php 模型存在');
const userModelContent = fs.readFileSync(userModelPath, 'utf-8');
assert(
userModelContent.includes("if (!empty($data['mobile']))") && userModelContent.includes("$value['mobile'] = 1"),
'User.php 模型 getVerificationAttr 当会员已有手机号时自动认定 mobile = 1',
'缺少 mobile 存在时自动认定 mobile = 1 逻辑'
);
assert(
userModelContent.includes('function setVerificationAttr'),
'User.php 模型定义了 setVerificationAttr 支持对象/数组自动 json 序列化',
'缺少 setVerificationAttr 方法'
);
const userStorePath = path.resolve(__dirname, '../uniapp/sheep/store/user.js');
assert(fs.existsSync(userStorePath), 'user.js Store 存在');
const userStoreContent = fs.readFileSync(userStorePath, 'utf-8');
assert(
userStoreContent.includes('if (merged.mobile)') && userStoreContent.includes('mobile: 1'),
'user.js getInfo() 当存在 mobile 时自动认定 verification.mobile = 1',
'缺少 getInfo() 补充 verification.mobile 逻辑'
);
// 10. 售后申请页编译修复: apply.vue
const applyVuePath = path.resolve(__dirname, '../uniapp/pages/order/aftersale/apply.vue');
assert(fs.existsSync(applyVuePath), 'apply.vue 存在');
const applyVueContent = fs.readFileSync(applyVuePath, 'utf-8');
assert(
applyVueContent.includes(':modelValue="formData"') && !applyVueContent.includes('v-model="formData"'),
'apply.vue 使用 :modelValue="formData" 消除 const 重赋值编译错误',
'仍包含 v-model="formData"'
);
assert(
applyVueContent.includes('let formData = reactive({'),
'apply.vue 中 formData 使用 let 声明提供双重防护',
'formData 不是 let 声明'
);
// 11. bindUserPhoneNumber 弹性支持与自动更新
assert(
miniProgramJsContent.includes('bindUserPhoneNumber') && miniProgramJsContent.includes("sheep.$store('user').getInfo()"),
'miniProgram.js bindUserPhoneNumber 成功后自动调用 getInfo() 刷新用户信息',
'bindUserPhoneNumber 未自动刷新用户信息'
);
// 12. 个人中心绑定横条受 showBindMobile 精确控制(微信小程序环境不冗余展示)
assert(
sUserCardContent.includes('v-if="showBindMobile"') && sUserCardContent.includes('#ifdef MP-WEIXIN'),
's-user-card.vue 使用 showBindMobile 精确控制,微信小程序端不显示冗余绑定提示条',
'未配置 showBindMobile 精确控制'
);
console.log("\n--------------------------------------------------------");
console.log(`测试执行结果: 通过 ${passed} 项, 失败 ${failed} 项`);
console.log("========================================================");
process.exit(failed === 0 ? 0 : 1);