/** * 积分兑换会员弹窗契约(参考主题 zibpay_get_vip_points_exchange_modal 1:1 对齐)。 * * 三条硬约束: * 1) 服务端静态输出参考主题 refresh_modal 同构壳(`modal flex jc fade` > * `modal-dialog modal-mini full-sm` > `modal-content` > `modal-body`), * 入口只保留在会员购买弹窗内——/user/vip/ 页底部的独立入口已移除。 * 2) 静止态必须被 vip-modal.css 显式隐藏(.flex 覆盖回归护栏),打开态为 * flex 而非 block,且层级高于 runtime 宿主(100050),以复现参考主题在 * 会员弹窗之上再叠一层兑换弹窗的行为。 * 3) 旧的客户端自实现弹窗(renderPointsModal / aksrt-vip-points-option / * catalog.vip_url)必须已彻底移除。 */ const test = require('node:test'); const assert = require('node:assert'); const fs = require('node:fs'); const path = require('node:path'); const root = path.join(__dirname, '..', '..'); const read = (...seg) => fs.readFileSync(path.join(root, ...seg), 'utf8'); const modal = read('src', 'Content', 'VipServiceModal.php'); const catalogSource = read('src', 'Content', 'VipServicePurchase.php'); const footer = read('inc', 'helpers', 'aksrt-vip.php'); const vipJs = read('assets', 'js', 'pay-vip.js'); const creditsJs = read('assets', 'js', 'credits.js'); const vipCss = read('assets', 'css', 'frontend', 'vip-modal.css'); const vipTab = read('inc', 'helpers', 'user-center-renderers', 'vip-tab.php'); const creditsCss = read('assets', 'css', 'routes', 'user-center', 'credits.css'); test('弹窗为参考主题 refresh_modal 同构静态壳并带 data 钩子', () => { assert.match(modal, /public function get_points_exchange_modal_html/); assert.match(modal, /class="modal flex jc fade"[^']*data-aksrt-vip-points-modal/); assert.match(modal, /class="modal-dialog modal-mini full-sm"/); assert.match(modal, /class="modal-content">