'use strict'; /** AI 连接配置页已移除:主题只走 WordPress AI Connectors,生成能力与入口保留。 */ 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 read = (rel) => fs.readFileSync(path.join(root, rel), 'utf8'); const ai = read('src/Ai/AI.php'); const controller = read('src/Admin/AIController.php'); const seoSchema = read('assets/admin/src/schema/sections/global/seo.js'); const extensionsMenu = read('assets/admin/src/constants/sections/extensions.js'); const apiModule = read('assets/admin/src/api/modules/extensions.js'); const frontSubmit = read('assets/js/front-submit.js'); const submitContext = read('templates/parts/submit/context.php'); const submitPage = read('templates/pages/page-submit.php'); const removed = [ 'aksrt_ai_settings', 'AI 连接配置', 'AI连接配置', 'ExtensionAI', 'extensions-ai', '/ai/settings', '/ai/status', 'ai-assist-btn', '扩展 → AI', ]; const walk = (dir) => fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => { const full = path.join(dir, entry.name); if (entry.isDirectory()) { return ['node_modules', 'build', 'dist'].includes(entry.name) ? [] : walk(full); } return [full]; }); const sources = ['src', 'assets/admin/src', 'templates', 'assets/js', 'inc'] .flatMap((dir) => walk(path.join(root, dir))); test('后台菜单、路由与 API 中不再有 AI 连接配置页', () => { assert.doesNotMatch(extensionsMenu, /extensions-ai|ExtensionAI|AI 连接配置/); assert.doesNotMatch(apiModule, /getAiStatus|updateAiSettings|generateSeo|suggestSummary|suggestTags/); assert.ok(!fs.existsSync(path.join(root, 'assets/admin/src/pages/extensions/ExtensionAI.vue'))); assert.ok(!fs.existsSync(path.join(root, 'assets/admin/src/router/component-loaders/extensions.js'))); }); test('AI.php 只保留 WP AI Client 单路出口', () => { assert.doesNotMatch(ai, /PROVIDER_OPENAI|PROVIDER_NONE/); assert.doesNotMatch(ai, /get_config|update_config/); assert.doesNotMatch(ai, /generate_via_theme|normalize_api_base/); assert.doesNotMatch(ai, /is_theme_provider_available|resolve_backend/); assert.doesNotMatch(ai, /check_rate_limit|record_call/); assert.match(ai, /wp_ai_client_prompt/); assert.match(ai, /function is_wp_ai_available/); assert.match(ai, /function is_available/); }); test('生成路由保留,连接配置与旧草稿兼容路由移除', () => { assert.match(controller, /\/ai\/seo-generate/); assert.match(controller, /\/ai\/summary-suggest/); assert.match(controller, /\/ai\/tags-suggest/); assert.doesNotMatch(controller, /\/ai\/seo-suggest/); assert.doesNotMatch(controller, /function get_status|function update_settings|function seo_suggest/); }); test('残留文案不再指向已删除的配置页', () => { for (const [name, source] of [['AI.php', ai], ['AIController.php', controller], ['seo.js', seoSchema]]) { assert.doesNotMatch(source, /AI 连接配置/, `${name} 仍引用 AI 连接配置页`); assert.doesNotMatch(source, /扩展 → AI/, `${name} 仍引导到扩展菜单`); } }); test('前台投稿 AI 辅助死代码已清理', () => { assert.doesNotMatch(frontSubmit, /bindAi|ai-assist-btn|cfg\.ai/); assert.doesNotMatch(submitContext, /ai_available/); assert.doesNotMatch(submitPage, /'ai'\s*=>|aiGenerating|aiFailed|aiFilled|needContent/); }); test('全仓源码不再引用已删除的 AI 连接配置', () => { const offenders = sources.filter((file) => { const text = fs.readFileSync(file, 'utf8'); return removed.some((pattern) => text.includes(pattern)); }); assert.deepEqual(offenders.map((file) => path.relative(root, file)), []); });