forked from syntaxbullet/AuroraBot-discord
feat: Introduce new modules for class, inventory, leveling, and quests with expanded schema, refactor user service, and add verification scripts.
This commit is contained in:
135
scripts/verify_logic.ts
Normal file
135
scripts/verify_logic.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
|
||||
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();
|
||||
Reference in New Issue
Block a user