Files
miaojingAI/scripts/test-admin-password-and-video-reuse.mjs
2026-06-06 22:26:01 +08:00

68 lines
3.1 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
const repoRoot = path.resolve(import.meta.dirname, '..');
function read(relativePath) {
return fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
}
async function runTest(name, fn) {
try {
await fn();
console.log(`PASS ${name}`);
} catch (error) {
console.error(`FAIL ${name}`);
console.error(error);
process.exitCode = 1;
}
}
await runTest('admin user management exposes reset password without hiding it behind edit modal', () => {
const source = read('src/components/admin/user-management-tab.tsx');
assert.match(source, /const startResetPassword = \(user: ManagedUser\) => \{/);
assert.match(source, /setResetPwUser\(user\)/);
assert.match(source, /setNewPassword\(''\)/);
assert.match(source, /setEditingUser\(null\)/);
assert.match(source, /onClick=\{\(\) => startResetPassword\(user\)\}/);
assert.match(source, /<KeyRound className="h-3\.5 w-3\.5" \/>重置密码/);
assert.match(source, /onClick=\{\(\) => startResetPassword\(editingUser\)\}/);
});
await runTest('admin reset password form is rendered as an overlay dialog', () => {
const source = read('src/components/admin/user-management-tab.tsx');
const resetSection = source.slice(source.indexOf('{resetPwUser && ('), source.indexOf('{editingUser && ('));
assert.match(resetSection, /fixed inset-0 z-50/);
assert.match(resetSection, /max-h-\[90vh\] overflow-y-auto/);
assert.doesNotMatch(resetSection, /\{resetPwUser && \(\s*<Card className="border-primary\/30">/);
assert.match(source, /setRechargeUser\(null\)/);
assert.match(source, /setShowAddForm\(false\)/);
});
await runTest('admin password reset upserts auth credentials instead of silently updating zero rows', () => {
const source = read('src/lib/admin-users-service.ts');
assert.match(source, /INSERT INTO auth\.users \(id, email, password_hash, created_at\)/);
assert.match(source, /VALUES \(\$1, \$2, crypt\(\$3, gen_salt\('bf'\)\), NOW\(\)\)/);
assert.match(source, /ON CONFLICT \(id\) DO UPDATE SET password_hash = crypt\(\$3, gen_salt\('bf'\)\)/);
assert.match(source, /\[userId,\s*currentResult\.rows\[0\]\.email,\s*newPassword\]/);
});
await runTest('creation detail reuse supports text-to-video and image-to-video history records', () => {
const source = read('src/components/creation-detail-dialog.tsx');
assert.match(source, /buildCreationReuseDraft,\s*writeCreationReuseDraft/);
assert.match(source, /function getReuseTarget\(record: CreationRecord\)/);
assert.match(source, /return mode === 'img2video' \? 'img2video' : 'text2video'/);
assert.match(source, /const target = getReuseTarget\(record\)/);
assert.match(source, /writeCreationReuseDraft\(target,\s*draft\)/);
assert.match(source, /router\.push\(`\/create\?type=\$\{target\}&reuse=\$\{encodeURIComponent\(record\.id\)\}`\)/);
assert.doesNotMatch(source, /disabled=\{record\.type !== 'image'\}/);
assert.doesNotMatch(source, /当前仅支持将图片创作配置复用到文生图/);
});
if (process.exitCode) process.exit(process.exitCode);