const test = require('node:test') const assert = require('node:assert/strict') const fs = require('node:fs') const path = require('node:path') const root = path.resolve(__dirname, '..', '..') const read = (file) => fs.readFileSync(path.join(root, file), 'utf8') const templates = read('src/Settings/MailTemplates.php') const mail = read('src/Settings/Mail.php') const notifications = read('src/Settings/MailNotifications.php') const globalController = read('src/Admin/GlobalController.php') const userController = read('src/Admin/UserController.php') const settings = read('src/Settings/Settings.php') test('email catalog includes required non-forum and financial events', () => { const required = [ 'reg_verify_code', 'reg_success', 'login_code', 'password_reset', 'change_code', 'change_notice', 'order_paid', 'order_status', 'withdraw_submitted', 'withdraw_completed', 'affiliate_commission', 'creator_income', 'transfer_received', 'comment_approved', 'comment_reply', 'post_result', 'phone_changed', 'auth_apply_result', 'user_ban', 'report_result', 'order_paid_admin', 'withdraw_submitted_admin', ] for (const event of required) { assert.match(templates, new RegExp(`'${event}'\\s*=>\\s*self::event`), event) } }) test('forum-only events stay out of the email catalog', () => { for (const forbidden of ['bbs', 'moderator', 'answer_adopted', 'answer-adopted']) { assert.doesNotMatch(templates, new RegExp(forbidden, 'i')) assert.doesNotMatch(notifications, new RegExp(forbidden, 'i')) } }) test('email templates and SMTP use one aksrt_settings schema', () => { assert.match(templates, /'option_key'\s*=>\s*'aksrt_settings'/) assert.match(templates, /'mail_passwd'.*'secret'\s*=>\s*true/) assert.match(mail, /Settings::get_all\(\)/) assert.doesNotMatch(settings, /aksrt_mail_smtp/) assert.doesNotMatch(globalController, /aksrt_mail_config|\/settings\/mail'/) assert.doesNotMatch(userController, /aksrt_mail_templates|mail-templates/) }) test('only the canonical mail service calls wp_mail', () => { const phpFiles = [] const walk = (dir) => { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const full = path.join(dir, entry.name) if (entry.isDirectory()) walk(full) else if (entry.name.endsWith('.php')) phpFiles.push(full) } } walk(root) const callers = phpFiles.filter((file) => /wp_mail\s*\(/.test(fs.readFileSync(file, 'utf8'))) assert.deepEqual(callers.map((file) => path.relative(root, file).replaceAll('\\', '/')), ['src/Settings/Mail.php']) }) test('financial and account hooks are wired to the notification service', () => { for (const hook of [ 'aksrt_order_paid', 'aksrt_order_status_changed', 'aksrt_asset_transaction_committed', 'aksrt_withdrawal_submitted', 'aksrt_withdrawal_status_changed', 'aksrt_user_phone_changed', ]) { assert.match(notifications, new RegExp(`add_action\\('${hook}'`), hook) } })