'use strict'; /** * 「卡密管理」后台页契约: * 1) 标题右侧按钮(page-title-action)由页面头部唯一输出,列表渲染不得再输出一次; * 2) 表头排序箭头宿主(.orderby-but)必须保持 inline,不能改成零高度 inline-block, * 否则绝对定位箭头的静态位置会落到文字基线上,整组箭头下沉一行字高。 */ const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const test = require('node:test'); const root = path.resolve(__dirname, '..', '..'); const page = fs.readFileSync(path.join(root, 'src/Admin/Native/PayChargeCards.php'), 'utf8'); const count = (src, pattern) => (src.match(pattern) || []).length; const header = page.slice( page.indexOf('public function render_charge_cards_page('), page.indexOf('private function render_list(') ); const list = page.slice( page.indexOf('private function render_list('), page.indexOf('private function render_add_form(') ); test('标题右侧按钮只在页面头部输出一次', () => { assert.ok(header.length > 0 && list.length > 0); // 添加/导出两个 tab 的「返回列表」各一次,列表页的「添加卡密 / 导出卡密」各一次。 assert.equal(count(header, /class="page-title-action"/g), 4); assert.doesNotMatch(list, /class="page-title-action"/); assert.equal(count(page, /class="page-title-action"/g), count(header, /class="page-title-action"/g)); // 列表页的两个入口按钮各自只有一处定义。 assert.equal(count(page, /add_query_arg\('tab', 'add'/g), 1); assert.equal(count(page, /add_query_arg\('tab', 'export'/g), 1); assert.match(header, /esc_html__\('添加卡密', 'aksrt'\)/); assert.match(header, /esc_html__\('导出卡密', 'aksrt'\)/); }); test('搜索提示仍由页面头部输出且列表不再自建头部', () => { assert.equal(count(header, /update-nag/g), 1); assert.match(header, /搜索 “%s” 的内容/); assert.doesNotMatch(list, /update-nag/); assert.doesNotMatch(list, /\$head_but/); // 搜索词在页面头部解析后传入列表,避免两处各解析一次。 assert.match(page, /render_list\(\$s\)/); assert.match(list, /private function render_list\(string \$s\): void/); }); test('排序箭头宿主保持 inline,不使用零高度 inline-block 定位', () => { const host = page.match(/\.orderby-but \{[^}]*\}/); assert.ok(host, '.orderby-but 规则缺失'); assert.match(host[0], /position:\s*relative/); assert.doesNotMatch(host[0], /display\s*:/); assert.doesNotMatch(host[0], /margin-left/); const arrow = page.match(/\.orderby-but > a \{[^}]*\}/); assert.ok(arrow, '.orderby-but > a 规则缺失'); assert.match(arrow[0], /position:\s*absolute/); assert.match(arrow[0], /padding-right:\s*1em/); assert.match(page, /\.orderby-but > a \+ a \{ transform: translateY\(6px\); \}/); assert.match(header + list, //); }); test('类型列链接每种类型只生成一次', () => { assert.equal(count(page, /\$type_html = '