forked from syntaxbullet/AuroraBot-discord
136 lines
5.9 KiB
TypeScript
136 lines
5.9 KiB
TypeScript
|
|
import { DrizzleClient } from "@/lib/DrizzleClient";
|
|
import { userService } from "@/modules/user/user.service";
|
|
import { questService } from "@/modules/quest/quest.service";
|
|
import { inventoryService } from "@/modules/inventory/inventory.service";
|
|
import { economyService } from "@/modules/economy/economy.service";
|
|
import { classService } from "@/modules/class/class.service";
|
|
import { levelingService } from "@/modules/leveling/leveling.service";
|
|
import { quests, items, classes, users, inventory } from "@/db/schema";
|
|
import { eq } from "drizzle-orm";
|
|
|
|
const TEST_ID = "999999999";
|
|
const TEST_USERNAME = "verification_bot";
|
|
const RANDOM_SUFFIX = Math.floor(Math.random() * 10000);
|
|
const TEST_CLASS_NAME = `Test Class ${RANDOM_SUFFIX}`;
|
|
const TEST_QUEST_NAME = `Test Quest ${RANDOM_SUFFIX}`;
|
|
const TEST_ITEM_NAME = `Test Potion ${RANDOM_SUFFIX}`;
|
|
const TEST_CLASS_ID = BigInt(10000 + RANDOM_SUFFIX);
|
|
const TEST_QUEST_ID = 10000 + RANDOM_SUFFIX;
|
|
const TEST_ITEM_ID = 10000 + RANDOM_SUFFIX;
|
|
|
|
|
|
async function verify() {
|
|
console.log("Starting verification...");
|
|
|
|
try {
|
|
// Cleanup previous run if checking same ID
|
|
try { await userService.deleteUser(TEST_ID); } catch { }
|
|
|
|
// 1. Setup Data (Class, Quest, Item)
|
|
// Ensure we have a class
|
|
let [cls] = await DrizzleClient.insert(classes).values({
|
|
id: TEST_CLASS_ID,
|
|
name: TEST_CLASS_NAME,
|
|
balance: 1000n
|
|
}).returning();
|
|
|
|
// Ensure we have a quest
|
|
let [quest] = await DrizzleClient.insert(quests).values({
|
|
id: TEST_QUEST_ID,
|
|
name: TEST_QUEST_NAME,
|
|
triggerEvent: "manual",
|
|
rewards: { xp: 500, balance: 100 }
|
|
}).returning();
|
|
|
|
// Ensure we have an item
|
|
let [item] = await DrizzleClient.insert(items).values({
|
|
id: TEST_ITEM_ID,
|
|
name: TEST_ITEM_NAME,
|
|
price: 50n,
|
|
iconUrl: "x",
|
|
imageUrl: "x"
|
|
}).returning();
|
|
|
|
// 2. Create User
|
|
console.log("Creating user...");
|
|
await userService.createUser(TEST_ID, TEST_USERNAME);
|
|
let user = await userService.getUserById(TEST_ID);
|
|
if (!user) throw new Error("User create failed");
|
|
console.log("User created:", user.username);
|
|
|
|
// 3. Assign Class & Modify Class Balance
|
|
console.log("Assigning class...");
|
|
await classService.assignClass(TEST_ID, cls!.id);
|
|
|
|
console.log("Modifying class balance...");
|
|
const clsBalBefore = (await DrizzleClient.query.classes.findFirst({ where: eq(classes.id, cls!.id) }))!.balance ?? 0n;
|
|
await classService.modifyClassBalance(cls!.id, 50n);
|
|
const clsBalAfter = (await DrizzleClient.query.classes.findFirst({ where: eq(classes.id, cls!.id) }))!.balance ?? 0n;
|
|
|
|
if (clsBalAfter !== clsBalBefore + 50n) throw new Error(`Class balance mismatch: ${clsBalAfter} vs ${clsBalBefore + 50n}`);
|
|
console.log("Class balance verified.");
|
|
|
|
// 4. Assign & Complete Quest (Check Logic)
|
|
console.log("Assigning quest...");
|
|
await questService.assignQuest(TEST_ID, quest!.id);
|
|
|
|
console.log("Completing quest...");
|
|
// Initial state
|
|
const initialXp = user.xp ?? 0n;
|
|
const initialBal = user.balance ?? 0n;
|
|
|
|
const result = await questService.completeQuest(TEST_ID, quest!.id);
|
|
if (!result.success) throw new Error("Quest completion failed");
|
|
|
|
// Refresh User
|
|
user = await userService.getUserById(TEST_ID);
|
|
if (!user) throw new Error("User lost");
|
|
|
|
console.log("Quest Rewards:", result.rewards);
|
|
console.log("User State:", { xp: user.xp, balance: user.balance, level: user.level });
|
|
|
|
if (user.balance !== initialBal + BigInt(result.rewards.balance)) throw new Error("Balance reward logic failed");
|
|
if (user.xp !== initialXp + BigInt(result.rewards.xp)) throw new Error("XP reward logic failed");
|
|
|
|
// 5. Buy Item (Check Atomic Logic)
|
|
console.log("Buying item...");
|
|
const buyResult = await inventoryService.buyItem(TEST_ID, item!.id, 2n);
|
|
if (!buyResult.success) throw new Error("Buy item failed");
|
|
|
|
// Refresh User
|
|
user = await userService.getUserById(TEST_ID);
|
|
|
|
const expectedBal = initialBal + BigInt(result.rewards.balance) - (item!.price! * 2n);
|
|
if (user!.balance !== expectedBal) throw new Error(`Buy logic balance mismatch: ${user!.balance} vs ${expectedBal}`);
|
|
|
|
const inv = await inventoryService.getInventory(TEST_ID);
|
|
const invItem = inv.find(i => i.itemId === item!.id);
|
|
if (!invItem || invItem.quantity !== 2n) throw new Error("Inventory item mismatch");
|
|
|
|
console.log("Buy Verification Successful.");
|
|
|
|
// Cleanup
|
|
await userService.deleteUser(TEST_ID);
|
|
// Also clean up metadata
|
|
await DrizzleClient.delete(inventory).where(eq(inventory.itemId, TEST_ITEM_ID)); // Cascade should handle user link, but manually cleaning item/quest/class
|
|
await DrizzleClient.delete(items).where(eq(items.id, TEST_ITEM_ID));
|
|
await DrizzleClient.delete(quests).where(eq(quests.id, TEST_QUEST_ID));
|
|
await DrizzleClient.delete(classes).where(eq(classes.id, TEST_CLASS_ID));
|
|
|
|
console.log("Cleanup done. Verification PASSED.");
|
|
|
|
} catch (e) {
|
|
console.error("Verification FAILED:", e);
|
|
// Attempt cleanup
|
|
try { await userService.deleteUser(TEST_ID); } catch { }
|
|
try { if (TEST_ITEM_ID) await DrizzleClient.delete(inventory).where(eq(inventory.itemId, TEST_ITEM_ID)); } catch { }
|
|
try { if (TEST_ITEM_ID) await DrizzleClient.delete(items).where(eq(items.id, TEST_ITEM_ID)); } catch { }
|
|
try { if (TEST_QUEST_ID) await DrizzleClient.delete(quests).where(eq(quests.id, TEST_QUEST_ID)); } catch { }
|
|
try { if (TEST_CLASS_ID) await DrizzleClient.delete(classes).where(eq(classes.id, TEST_CLASS_ID)); } catch { }
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
verify();
|