fix(vip): render points exchange description
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
0d51beeaad
commit
a120f61e13
7 files changed
+112
-4
No files matched your search
@@ -224,7 +224,8 @@ test('积分兑换说明按 post 级 HTML 放行并原样渲染', () => {
|
||||
assert.match(schemaPhp, /'key' => 'pay_vip_points_exchange_desc', 'label' => '兑换说明', 'type' => 'textarea', 'sanitize_type' => 'html'/);
|
||||
const vipSettings = slice(paymentRuntime, 'public static function get_payment_vip_settings', 'public static function get_payment_revenue_settings');
|
||||
assert.match(vipSettings, /'desc'\s+=> wp_kses_post\(\(string\) \(\$settings\['pay_vip_points_exchange_desc'\]/);
|
||||
// 弹窗渲染端不再 esc_html 剥标签。
|
||||
assert.match(modalSource, /<div class="muted-box muted-2-color padding-10 em09 mt20">' \. wp_kses_post\(\$desc_text\)/);
|
||||
// 弹窗从同一份 VIP 设置上下文读取说明,不经 catalog 投影遗漏;说明容器保留参考主题的 HTML 与定位类。
|
||||
assert.match(modalSource, /\$desc_text = trim\(\(string\) \(\$vip\['points_exchange'\]\['desc'\] \?\? ''\)\);/);
|
||||
assert.match(modalSource, /<div class="muted-box muted-2-color padding-10 em09 mt20 aksrt-vip-points-desc">' \. wp_kses_post\(\$desc_text\)/);
|
||||
assert.doesNotMatch(modalSource, /esc_html\(\$desc_text\)/);
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {
|
||||
define('ABSPATH', __DIR__ . '/');
|
||||
|
||||
function __(string $text, string $domain = ''): string { return $text; }
|
||||
function esc_html($value): string { return (string) $value; }
|
||||
function esc_html__($value, string $domain = ''): string { return (string) $value; }
|
||||
function esc_attr($value): string { return (string) $value; }
|
||||
function esc_attr__($value, string $domain = ''): string { return (string) $value; }
|
||||
function esc_url($value): string { return (string) $value; }
|
||||
function wp_kses_post($value): string { return (string) $value; }
|
||||
function aksrt_get_user_center_tab_url(string $tab): string { return '/user/' . $tab; }
|
||||
}
|
||||
|
||||
namespace AKSRT\Settings {
|
||||
final class Settings {
|
||||
public static function credits_enabled(): bool { return true; }
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
require dirname(__DIR__, 2) . '/src/Content/VipServiceModal.php';
|
||||
|
||||
final class VipPointsDescriptionProbe {
|
||||
use \AKSRT\Content\VipServiceModal;
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
private function get_vip_settings_context(): array {
|
||||
return [
|
||||
'enabled' => true,
|
||||
'levels' => [1 => ['enabled' => true, 'name' => 'VIP1']],
|
||||
'points_exchange' => [
|
||||
'enabled' => true,
|
||||
'desc' => '<p>后台配置的兑换说明</p>',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
public function get_catalog(int $user_id = 0): array {
|
||||
return [
|
||||
'points_exchange' => [
|
||||
'packages' => [[
|
||||
'package_id' => 6001,
|
||||
'level' => 1,
|
||||
'points' => 500,
|
||||
'time' => 30,
|
||||
'unit' => 'day',
|
||||
]],
|
||||
],
|
||||
'user_points' => 1000,
|
||||
'currency_name' => '积分',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
echo (new VipPointsDescriptionProbe())->get_points_exchange_modal_html(1);
|
||||
}
|
||||
@@ -22,6 +22,7 @@ const test = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { execFileSync } = require('node:child_process');
|
||||
|
||||
const root = path.join(__dirname, '..', '..');
|
||||
const read = (...seg) => fs.readFileSync(path.join(root, ...seg), 'utf8');
|
||||
@@ -80,6 +81,28 @@ test('弹窗壳随 wp_footer 全局输出且不进入 catalog 载荷', () => {
|
||||
assert.doesNotMatch(modal, /'vip_url'/);
|
||||
});
|
||||
|
||||
test('我的积分盒恢复参考主题 muted-box 的背景、圆角与内边距', () => {
|
||||
assert.match(vipCss, /\.modal\[data-aksrt-vip-points-modal\]\s+\.muted-box\.padding-h10\s*\{\s*background-color:\s*var\(--this-bg,\s*var\(--muted-border-color\)\);\s*border-radius:\s*var\(--main-radius\);\s*padding:\s*10px 15px;\s*\}/);
|
||||
assert.match(vipCss, /\.modal\[data-aksrt-vip-points-modal\]\s+\.muted-box\.padding-10,\s*\.modal\[data-aksrt-vip-points-modal\]\s+\.aksrt-vip-points-desc\s*\{\s*background-color:\s*var\(--this-bg,\s*var\(--muted-border-color\)\);\s*border-radius:\s*var\(--main-radius\);\s*padding:\s*10px;\s*\}/);
|
||||
});
|
||||
|
||||
test('后台兑换说明直接从 VIP 设置读取并作为富文本置于套餐与提交动作之间', () => {
|
||||
assert.match(modal, /\$desc_text = trim\(\(string\) \(\$vip\['points_exchange'\]\['desc'\] \?\? ''\)\);/);
|
||||
assert.match(modal, /aksrt-vip-points-desc/);
|
||||
assert.match(modal, /wp_kses_post\(\$desc_text\)/);
|
||||
assert.match(modal, /\. \$header\s*\. '<form class="" data-aksrt-vip-points-form>' \. \$user_box \. \$lists \. \$desc \. \$form/);
|
||||
assert.match(vipCss, /\.modal\[data-aksrt-vip-points-modal\]\s+\.aksrt-vip-points-desc\s*\{[^}]*display:\s*block;[^}]*margin-top:\s*20px;[^}]*color:\s*var\(--muted-2-color,\s*#999\);/s);
|
||||
assert.match(vipCss, /\.modal\[data-aksrt-vip-points-modal\]\s+\.muted-box\.padding-10,\s*\.modal\[data-aksrt-vip-points-modal\]\s+\.aksrt-vip-points-desc\s*\{[^}]*padding:\s*10px;/s);
|
||||
});
|
||||
|
||||
test('兑换说明从后台设置实际输出,保留 HTML 并显示在卡片与 CTA 之间', () => {
|
||||
const rendered = execFileSync(process.env.PHP_BINARY || 'php', [
|
||||
path.join(__dirname, 'vip-points-exchange-description-harness.php'),
|
||||
], { encoding: 'utf8' });
|
||||
assert.match(rendered, /class="muted-box muted-2-color padding-10 em09 mt20 aksrt-vip-points-desc"><p>后台配置的兑换说明<\/p><\/div>/);
|
||||
assert.ok(rendered.indexOf('aksrt-vip-points-desc') < rendered.indexOf('data-aksrt-vip-points-submit'));
|
||||
});
|
||||
|
||||
test('弹窗壳静止态必须被 vip-modal.css 显式隐藏(.flex 覆盖回归护栏)', () => {
|
||||
assert.match(vipCss, /\.modal\[data-aksrt-vip-points-modal\]\s*\{\s*display:\s*none;/);
|
||||
assert.match(vipCss, /\.modal\[data-aksrt-vip-points-modal\]\.in\s*\{\s*display:\s*flex;/);
|
||||
|
||||
@@ -371,6 +371,7 @@ test('运行时归一化:默认值、价格净化、零价与非法行剔除',
|
||||
assert.strictEqual(custom.upgrade.permanent_tag_class, 'jb-vip2');
|
||||
// 积分兑换:非法行(积分为 0 / 等级越界 / 时长为空)被剔除。
|
||||
assert.strictEqual(custom.points_exchange.packages.length, 3);
|
||||
assert.strictEqual(custom.points_exchange.desc, '<p>积分兑换说明</p>');
|
||||
assert.strictEqual(custom.points_exchange.packages[0].days, 30);
|
||||
assert.strictEqual(custom.points_exchange.packages[1].is_permanent, true);
|
||||
assert.strictEqual(custom.points_exchange.packages[2].days, 90);
|
||||
|
||||
@@ -155,6 +155,7 @@ namespace {
|
||||
],
|
||||
'vip_2_renew_product' => [],
|
||||
'pay_vip_points_exchange_s' => true,
|
||||
'pay_vip_points_exchange_desc' => '<p>积分兑换说明</p>',
|
||||
'pay_vip_points_exchange_product' => [
|
||||
['points' => 800, 'level' => 1, 'time' => 30, 'unit' => 'day'],
|
||||
['points' => 9000, 'level' => 2, 'time' => 'Permanent'],
|
||||
|
||||
Reference in new issue
Block a user