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 = (file) => fs.readFileSync(path.join(root, file), 'utf8'); test('modal and sign page use one renderer and one state machine', () => { const modal = read('templates/parts/modal-auth.php'); const page = read('templates/pages/page-sign.php'); const shared = read('templates/parts/auth-content.php'); const scripts = read('src/Core/ScriptsPart1c.php'); const runtime = read('assets/js/runtime/main.js') + read('assets/js/runtime/main.min.js'); const loader = read('assets/js/runtime/loader.js'); assert.match(modal, /templates\/parts\/auth-content\.php/); assert.match(page, /templates\/parts\/auth-content\.php/); assert.match(shared, /data-auth-panel="signin"/); assert.match(shared, /data-auth-panel="signup"/); assert.match(shared, /data-auth-panel="resetpassword"/); assert.match(shared, /data-auth-panel="bind"/); assert.match(shared, /data-auth-panel="oauth"/); assert.match(scripts, /assets\/js\/auth\.js/); assert.doesNotMatch(scripts, /modal-auth\.js|sign-register\.js/); assert.doesNotMatch(runtime, /signsubmit-loader|tbquire\(\['sign-register'\]\)|\.on\('click', '\.(?:signin|signup)-loader'/); assert.doesNotMatch(loader, /sign-register/); }); test('static Zibll authentication dimensions and responsive contract are retained', () => { const css = read('assets/css/routes/sign.css'); assert.match(css, /\.sign\s*\{[\s\S]*?max-width:\s*330px/); assert.match(css, /#u_sign\.has-sign-img \.modal-dialog\s*\{\s*width:\s*800px/); assert.match(css, /\.social-login-item\s*\{[\s\S]*?width:\s*32px;[\s\S]*?height:\s*32px/); assert.match(css, /\.auth-qrcode\s*\{[\s\S]*?width:\s*180px;[\s\S]*?min-height:\s*180px/); assert.match(css, /@media \(max-width:\s*767px\)[\s\S]*?\.sign-img\s*\{\s*display:\s*none/); }); test('authentication settings use reference defaults and canonical keys', () => { const js = read('assets/admin/src/schema/sections/users/auth.js'); const php = read('src/Admin/Schema/SchemaUsers.php'); const all = js + '\n' + php; assert.match(all, /user_sign_type['"]?\s*(?:=>|:)\s*['"]modal/); assert.match(all, /user_signup_captch['"]?\s*(?:=>|:)\s*false/); assert.match(all, /sign_card_position['"]?\s*(?:=>|:)\s*['"]right/); assert.match(all, /sign_show_logo['"]?\s*(?:=>|:)\s*false/); assert.match(all, /sign_modal_show_logo['"]?\s*(?:=>|:)\s*false/); assert.match(all, /invit_code_s/); assert.match(all, /only_nopas/); assert.match(all, /user_signup_no_repas[\s\S]*?dependsOn[\s\S]*?user_signup_captch/); assert.doesNotMatch(all, /user_close_login|user_close_signup|nopas_first|password_first|nopas_only|referral_registration_enabled|referral_register_field/); }); test('only the shared authentication REST routes and /sign/ renderer are registered', () => { const controller = read('src/Admin/UserController.php'); const router = read('src/Auth/Router.php'); const urls = read('inc/modules/user-parts/urls.php'); ['/auth/code', '/auth/login', '/auth/register', '/auth/reset-password'].forEach((route) => { assert.match(controller, new RegExp(route.replace('/', '\\/'))); }); assert.doesNotMatch(controller, /auth\/(?:modal-|phone-|send-sms-code|bind-phone)/); assert.match(router, /'sign'\s*=>\s*'index\.php\?aksrt_sign=1'/); assert.doesNotMatch(router, /'login'\s*=>|'register'\s*=>|'reset-password'\s*=>|'verify-email'\s*=>|'bind-account'\s*=>/); assert.match(router, /aksrt_bypass/); assert.match(router, /\$action === 'logout'[\s\S]*?aksrt_get_logout_url/); assert.doesNotMatch(router, /is_user_logged_in\(\) && current_user_can\('manage_options'\)|wp_doing_ajax\(\)/); assert.match(urls, /home_url\('\/sign\/'\)/); }); test('legacy authentication templates and scripts are removed', () => { [ 'assets/js/modal-auth.js', 'assets/js/sign-register.js', 'assets/js/runtime/sign-register.js', 'assets/js/runtime/sign-register.min.js', 'assets/css/routes/auth.css', 'assets/css/frontend/enhancements/modal-motion.css', 'templates/pages/page-login.php', 'templates/pages/page-register.php', 'templates/pages/page-reset-password.php', 'templates/pages/page-bind-account.php', 'templates/pages/page-verify-email.php', ].forEach((file) => assert.equal(fs.existsSync(path.join(root, file)), false, file)); }); test('unified handlers enforce nonce, captcha, rate limits, configured channels, and generic errors', () => { const handlers = read('src/Admin/UserControllerAuthPhoneOperations.php'); const service = read('src/Auth/Service.php'); assert.match(handlers, /auth_verify_rest_nonce/); assert.match(handlers, /aksrt_require_captcha/); assert.match(handlers, /auth_rate_limited/); assert.match(handlers, /auth_channel_allowed/); ['auth_code', 'auth_login', 'auth_register', 'auth_reset_password'].forEach((method) => { const start = handlers.indexOf(`public function ${method}(`); const end = handlers.indexOf('\n\tpublic function ', start + 1); const body = handlers.slice(start, end === -1 ? handlers.length : end); assert.match(body, /aksrt_require_captcha/, method); }); assert.match(handlers, /passwordless_login_type/); assert.match(handlers, /signup_verification_type/); assert.match(handlers, /reset_password_verification_type/); assert.match(handlers, /账号或密码错误/); assert.match(handlers, /账号或验证码错误/); assert.match(service, /signin_phone_enabled/); assert.doesNotMatch(service, /login_by_phone_password|login_by_phone_code/); }); test('OAuth bind and reset flows stay inside the shared page and four auth endpoints', () => { const shared = read('templates/parts/auth-content.php'); const page = read('templates/pages/page-sign.php'); const handlers = read('src/Admin/UserControllerAuthPhoneOperations.php'); const serviceA = read('src/Auth/ServicePart1a.php'); const serviceB = read('src/Auth/ServicePart1b.php'); assert.match(page, /'obk'\s*=>\s*\$obk/); assert.match(shared, /data-auth-panel="bind"[\s\S]*?data-auth-form="login"/); assert.match(shared, /name="obk"/); assert.match(handlers, /finalize_oauth_binding/); assert.match(serviceA, /finalize_oauth_binding/); assert.doesNotMatch(serviceA + serviceB, /bind_oauth_account|get_reset_context|request_password_reset|reset_password_with_token/); }); test('shared renderer contracts every configured authentication state', () => { const shared = read('templates/parts/auth-content.php'); const modal = read('templates/parts/modal-auth.php'); const client = read('assets/js/auth.js'); const settings = read('src/Settings/AuthReader.php'); assert.match(shared, /data-auth-password-fields/); assert.match(shared, /data-auth-code-fields/); assert.match(shared, /data-login-mode/); ['login', 'register', 'resetpassword'].forEach((scene) => { assert.match(shared, new RegExp(`data-send-code="${scene}"`)); }); assert.match(shared, /\$omit_confirm/); assert.match(shared, /\$ref_mode !== 'hidden'/); assert.match(shared, /\$ref_mode === 'required'/); assert.match(shared, /sign-agreement-implicit/); assert.match(shared, /name="agree_terms"[\s\S]*?required/); assert.match(shared, /oauth-button-lg/); assert.match(shared, /data-auth-qrcode/); assert.match(modal, /data-auto=/); assert.match(client, /aksrtAuthAutoUntil/); assert.match(client, /data-password-show/); assert.match(client, /pollQr/); assert.match(client, /window\.location\.assign\(authPageUrl/); assert.match(settings, /invitation_mode/); assert.match(settings, /\['close', 'open', 'must'\]/); });