const test = require('node:test'); const assert = require('node:assert/strict'); const { pruneRetiredSidebarConfig, cleanupRetiredFeatureSettings, isRetiredDatabaseConfigName, isRetiredSystemConfigKey, } = require('../src/services/retiredFeatures'); test('retired sidebar cleanup is recursive and idempotent', () => { const saved = JSON.stringify({ entries: [ { key: 'agent' }, { key: 'store-management', children: [{ key: 'store-checkup' }] }, { key: 'operation-tools', children: [{ key: 'pricing-calculator' }] }, { key: 'marketing-management', children: [{ key: 'marketing-events' }] }, { key: 'product-management', children: [{ key: 'product-analysis' }] }, { key: 'product-monitoring' }, { key: 'ops-b-incentive' }, { key: 'manage', children: [{ key: 'ai-skill-tags' }, { key: 'desktop-client-releases' }, { key: 'settings', label: '管理设置' }] }, ] }); const clean = pruneRetiredSidebarConfig(saved); assert.deepEqual(JSON.parse(clean).entries, [{ key: 'manage', children: [{ key: 'settings', label: '管理设置' }] }]); assert.equal(pruneRetiredSidebarConfig(clean), clean); assert.equal(pruneRetiredSidebarConfig('{invalid'), '{invalid'); assert.equal(isRetiredSystemConfigKey('openclaw_chat_skill_tags'), true); assert.equal(isRetiredSystemConfigKey('cs_quality_ai_config'), true); assert.equal(isRetiredSystemConfigKey('product_tag_excluded_categories'), true); assert.equal(isRetiredDatabaseConfigName('ai_buyer_show_database'), true); assert.equal(isRetiredSystemConfigKey('site_name'), false); }); test('upgrade removes only retired settings and permission rows', async () => { const calls = []; await cleanupRetiredFeatureSettings({ query: async (sql, params) => { calls.push({ sql, params }); return sql.startsWith('SELECT') ? [{ config_value: '{"entries":[{"key":"agent"},{"key":"product-analysis"},{"key":"settings"}]}' }] : []; } }); const deletes = calls.filter((call) => call.sql.startsWith('DELETE')); assert.equal(deletes.length, 5); assert.ok(deletes.every((call) => call.sql.includes(' WHERE ') && call.params.length > 0)); assert.equal(calls.filter((call) => call.sql.startsWith('DROP TABLE IF EXISTS')).length, 11); const update = calls.find((call) => call.sql.startsWith('UPDATE')); assert.deepEqual(JSON.parse(update.params[0]).entries, [{ key: 'settings' }]); });