152 lines
4.8 KiB
TypeScript
152 lines
4.8 KiB
TypeScript
|
|
const BASE_URL = "http://localhost:5001";
|
|
const MAILHOG_API = "http://localhost:8025/api/v2";
|
|
|
|
let cookie = "";
|
|
|
|
async function request(method: string, path: string, body?: any) {
|
|
const headers: any = { "Content-Type": "application/json" };
|
|
if (cookie) headers["Cookie"] = cookie;
|
|
|
|
const res = await fetch(`${BASE_URL}${path}`, {
|
|
method,
|
|
headers,
|
|
body: body ? JSON.stringify(body) : undefined,
|
|
});
|
|
|
|
const setCookie = res.headers.get("set-cookie");
|
|
if (setCookie) {
|
|
cookie = setCookie.split(";")[0];
|
|
}
|
|
|
|
const text = await res.text();
|
|
try {
|
|
const data = JSON.parse(text);
|
|
return { status: res.status, data };
|
|
} catch {
|
|
return { status: res.status, data: text };
|
|
}
|
|
}
|
|
|
|
async function getLatestEmail(toEmail: string) {
|
|
try {
|
|
const res = await fetch(`${MAILHOG_API}/messages`);
|
|
const data = await res.json();
|
|
// MailHog returns { total: number, count: number, start: number, items: [...] }
|
|
// items are sorted newest first usually in MailHog UI, but API might vary.
|
|
// Let's filter by 'To' and take the first one.
|
|
const messages = data.items;
|
|
for (const msg of messages) {
|
|
// Headers is an object like { "To": ["<email>"], ... }
|
|
// Content.Headers.To
|
|
const toHeader = msg.Content.Headers.To?.[0];
|
|
if (toHeader && toHeader.includes(toEmail)) {
|
|
return msg;
|
|
}
|
|
}
|
|
return null;
|
|
} catch (e) {
|
|
console.error("Failed to fetch from MailHog:", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function run() {
|
|
console.log("📧 Testing Email Flow...");
|
|
|
|
const timestamp = Date.now();
|
|
const username = `email_user_${timestamp}`;
|
|
const email = `test_${timestamp}@example.com`;
|
|
const password = "password123";
|
|
const newPassword = "newpassword456";
|
|
|
|
// 1. Register User
|
|
console.log(`\n1. Registering user: ${username} (${email})`);
|
|
let res = await request("POST", "/api/register", { username, password, email });
|
|
if (res.status === 201 || res.status === 200) {
|
|
console.log("✅ Registration successful");
|
|
} else {
|
|
console.error("❌ Registration failed:", res.data);
|
|
process.exit(1);
|
|
}
|
|
|
|
// 2. Request Password Reset
|
|
console.log("\n2. Requesting Password Reset...");
|
|
// Logout first just in case
|
|
await request("POST", "/api/logout");
|
|
cookie = ""; // Clear cookie
|
|
|
|
res = await request("POST", "/api/auth/forgot-password", { email });
|
|
if (res.status === 200) {
|
|
console.log("✅ Reset request sent:", res.data.message);
|
|
} else {
|
|
console.error("❌ Reset request failed:", res.data);
|
|
process.exit(1);
|
|
}
|
|
|
|
// 3. Check MailHog
|
|
console.log("\n3. Checking MailHog for email...");
|
|
// Wait a bit for email to arrive
|
|
await new Promise(r => setTimeout(r, 2000));
|
|
|
|
const emailMsg = await getLatestEmail(email);
|
|
if (emailMsg) {
|
|
console.log("✅ Email found!", emailMsg.Content.Headers.Subject[0]);
|
|
} else {
|
|
console.error("❌ Email NOT found in MailHog!");
|
|
process.exit(1);
|
|
}
|
|
|
|
// 4. Extract Token
|
|
// We expect a link like: http://localhost:5001/reset-password?token=...
|
|
// In text body: msg.Content.Body
|
|
let body = emailMsg.Content.Body;
|
|
|
|
// Simple QP decoding for test
|
|
body = body.replace(/=\r\n/g, '').replace(/=\n/g, '').replace(/=3D/g, '=');
|
|
|
|
console.log("DEBUG BODY DECODED:", body);
|
|
|
|
const match = body.match(/token=([a-zA-Z0-9-]+)/);
|
|
if (!match) {
|
|
console.error("❌ Token not found in email body!");
|
|
console.log("Body:", body);
|
|
process.exit(1);
|
|
}
|
|
const token = match[1];
|
|
console.log("✅ Token extracted:", token);
|
|
|
|
// 5. Reset Password
|
|
console.log("\n5. Resetting Password...");
|
|
res = await request("POST", "/api/auth/reset-password", { token, newPassword });
|
|
if (res.status === 200) {
|
|
console.log("✅ Password reset successful");
|
|
} else {
|
|
console.error("❌ Password reset failed:", res.data);
|
|
process.exit(1);
|
|
}
|
|
|
|
// 6. Login with New Password
|
|
console.log("\n6. Logging in with NEW password...");
|
|
res = await request("POST", "/api/login", { username, password: newPassword });
|
|
if (res.status === 200) {
|
|
console.log("✅ Login successful with new password!");
|
|
} else {
|
|
console.error("❌ Login failed:", res.data);
|
|
process.exit(1);
|
|
}
|
|
|
|
// 7. Login with OLD Password (should fail)
|
|
console.log("\n7. Verifying OLD password fails...");
|
|
res = await request("POST", "/api/login", { username, password });
|
|
if (res.status === 401) {
|
|
console.log("✅ Old password rejected correctly.");
|
|
} else {
|
|
console.error("❌ Old password SHOULD fail but got:", res.status);
|
|
}
|
|
|
|
console.log("\n🎉 Full Email Flow Test Passed!");
|
|
}
|
|
|
|
run();
|