549 lines
16 KiB
JavaScript
549 lines
16 KiB
JavaScript
|
|
import { expect } from "@esm-bundle/chai";
|
||
|
|
import sinon from "sinon";
|
||
|
|
// Import to register custom element
|
||
|
|
import "../../src/ui/screens/marketplace-screen.js";
|
||
|
|
|
||
|
|
describe("UI: MarketplaceScreen", () => {
|
||
|
|
let element;
|
||
|
|
let container;
|
||
|
|
let mockMarketManager;
|
||
|
|
let mockInventoryManager;
|
||
|
|
let mockHubStash;
|
||
|
|
|
||
|
|
beforeEach(async () => {
|
||
|
|
container = document.createElement("div");
|
||
|
|
document.body.appendChild(container);
|
||
|
|
element = document.createElement("marketplace-screen");
|
||
|
|
container.appendChild(element);
|
||
|
|
|
||
|
|
// Wait for element to be defined
|
||
|
|
await element.updateComplete;
|
||
|
|
|
||
|
|
// Create mock hub stash
|
||
|
|
mockHubStash = {
|
||
|
|
currency: {
|
||
|
|
aetherShards: 1000,
|
||
|
|
ancientCores: 0,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
// Create mock inventory manager
|
||
|
|
mockInventoryManager = {
|
||
|
|
hubStash: mockHubStash,
|
||
|
|
};
|
||
|
|
|
||
|
|
// Create mock item registry
|
||
|
|
const mockItemRegistry = {
|
||
|
|
get: (defId) => {
|
||
|
|
const items = {
|
||
|
|
"ITEM_RUSTY_BLADE": {
|
||
|
|
id: "ITEM_RUSTY_BLADE",
|
||
|
|
name: "Rusty Infantry Blade",
|
||
|
|
type: "WEAPON",
|
||
|
|
rarity: "COMMON",
|
||
|
|
},
|
||
|
|
"ITEM_SCRAP_PLATE": {
|
||
|
|
id: "ITEM_SCRAP_PLATE",
|
||
|
|
name: "Scrap Plate Armor",
|
||
|
|
type: "ARMOR",
|
||
|
|
rarity: "COMMON",
|
||
|
|
},
|
||
|
|
};
|
||
|
|
return items[defId] || null;
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
// Create mock market manager
|
||
|
|
mockMarketManager = {
|
||
|
|
inventoryManager: mockInventoryManager,
|
||
|
|
itemRegistry: mockItemRegistry,
|
||
|
|
getStockForMerchant: sinon.stub().returns([]),
|
||
|
|
buyItem: sinon.stub().resolves(true),
|
||
|
|
getState: sinon.stub().returns({
|
||
|
|
generationId: "TEST_123",
|
||
|
|
stock: [],
|
||
|
|
buyback: [],
|
||
|
|
}),
|
||
|
|
};
|
||
|
|
});
|
||
|
|
|
||
|
|
afterEach(() => {
|
||
|
|
if (container && container.parentNode) {
|
||
|
|
container.parentNode.removeChild(container);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Helper to wait for LitElement update
|
||
|
|
async function waitForUpdate() {
|
||
|
|
await element.updateComplete;
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper to query shadow DOM
|
||
|
|
function queryShadow(selector) {
|
||
|
|
return element.shadowRoot?.querySelector(selector);
|
||
|
|
}
|
||
|
|
|
||
|
|
function queryShadowAll(selector) {
|
||
|
|
return element.shadowRoot?.querySelectorAll(selector) || [];
|
||
|
|
}
|
||
|
|
|
||
|
|
describe("CoA 1: Basic Rendering", () => {
|
||
|
|
it("should render marketplace screen with header", async () => {
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const header = queryShadow(".header");
|
||
|
|
expect(header).to.exist;
|
||
|
|
expect(header.textContent).to.include("The Gilded Bazaar");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should display wallet currency", async () => {
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const walletDisplay = queryShadow(".wallet-display");
|
||
|
|
expect(walletDisplay).to.exist;
|
||
|
|
expect(walletDisplay.textContent).to.include("1000");
|
||
|
|
expect(walletDisplay.textContent).to.include("Shards");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should render merchant tabs", async () => {
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const merchantTabs = queryShadowAll(".merchant-tab");
|
||
|
|
expect(merchantTabs.length).to.equal(4); // Smith, Tailor, Alchemist, Buyback
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should render filter buttons", async () => {
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const filterButtons = queryShadowAll(".filter-button");
|
||
|
|
expect(filterButtons.length).to.be.greaterThan(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("CoA 2: Merchant Tab Switching", () => {
|
||
|
|
it("should switch active merchant when tab is clicked", async () => {
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const tailorTab = queryShadowAll(".merchant-tab")[1]; // Tailor
|
||
|
|
tailorTab.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
expect(element.activeMerchant).to.equal("TAILOR");
|
||
|
|
expect(tailorTab.classList.contains("active")).to.be.true;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should call getStockForMerchant with correct merchant type", async () => {
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
mockMarketManager.getStockForMerchant.reset();
|
||
|
|
mockMarketManager.getStockForMerchant.returns([]);
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const smithTab = queryShadowAll(".merchant-tab")[0];
|
||
|
|
smithTab.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
expect(mockMarketManager.getStockForMerchant.calledWith("SMITH")).to.be
|
||
|
|
.true;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should reset filter to ALL when switching merchants", async () => {
|
||
|
|
element.activeFilter = "WEAPON";
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const tailorTab = queryShadowAll(".merchant-tab")[1];
|
||
|
|
tailorTab.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
expect(element.activeFilter).to.equal("ALL");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("CoA 3: Item Display", () => {
|
||
|
|
beforeEach(async () => {
|
||
|
|
// Reset stub
|
||
|
|
mockMarketManager.getStockForMerchant.reset();
|
||
|
|
// Set up mock to return items
|
||
|
|
mockMarketManager.getStockForMerchant.returns([
|
||
|
|
{
|
||
|
|
id: "STOCK_001",
|
||
|
|
defId: "ITEM_RUSTY_BLADE",
|
||
|
|
type: "WEAPON",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 50,
|
||
|
|
purchased: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: "STOCK_002",
|
||
|
|
defId: "ITEM_SCRAP_PLATE",
|
||
|
|
type: "ARMOR",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 75,
|
||
|
|
purchased: false,
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
await waitForUpdate();
|
||
|
|
await waitForUpdate(); // Extra update to ensure render completes
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should display items in grid", async () => {
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const itemCards = queryShadowAll(".item-card");
|
||
|
|
expect(itemCards.length).to.equal(2);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should display item names", async () => {
|
||
|
|
const itemNames = queryShadowAll(".item-name");
|
||
|
|
expect(itemNames.length).to.equal(2);
|
||
|
|
expect(itemNames[0].textContent).to.include("Rusty Infantry Blade");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should display item prices", async () => {
|
||
|
|
const prices = queryShadowAll(".item-price");
|
||
|
|
expect(prices.length).to.equal(2);
|
||
|
|
expect(prices[0].textContent).to.include("50");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should apply rarity classes to item cards", async () => {
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const itemCards = queryShadowAll(".item-card");
|
||
|
|
itemCards.forEach((card) => {
|
||
|
|
expect(card.classList.contains("rarity-common")).to.be.true;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("CoA 4: Purchase Flow", () => {
|
||
|
|
beforeEach(async () => {
|
||
|
|
// Reset stub
|
||
|
|
mockMarketManager.getStockForMerchant.reset();
|
||
|
|
// Set up mock to return items
|
||
|
|
mockMarketManager.getStockForMerchant.returns([
|
||
|
|
{
|
||
|
|
id: "STOCK_001",
|
||
|
|
defId: "ITEM_RUSTY_BLADE",
|
||
|
|
type: "WEAPON",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 50,
|
||
|
|
purchased: false,
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
await waitForUpdate();
|
||
|
|
await waitForUpdate(); // Extra update to ensure render completes
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should open modal when item is clicked", async () => {
|
||
|
|
|
||
|
|
const itemCard = queryShadow(".item-card");
|
||
|
|
itemCard.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const modal = queryShadow(".modal");
|
||
|
|
expect(modal).to.exist;
|
||
|
|
expect(element.showModal).to.be.true;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should display purchase confirmation in modal", async () => {
|
||
|
|
const itemCard = queryShadow(".item-card");
|
||
|
|
expect(itemCard).to.exist;
|
||
|
|
itemCard.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const modalTitle = queryShadow(".modal-title");
|
||
|
|
expect(modalTitle).to.exist;
|
||
|
|
expect(modalTitle.textContent).to.include("Confirm Purchase");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should call buyItem when confirmed", async () => {
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const itemCard = queryShadow(".item-card");
|
||
|
|
itemCard.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const confirmButton = queryShadow(".btn-primary");
|
||
|
|
confirmButton.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
expect(mockMarketManager.buyItem.calledWith("STOCK_001")).to.be.true;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should close modal after successful purchase", async () => {
|
||
|
|
const itemCard = queryShadow(".item-card");
|
||
|
|
expect(itemCard).to.exist;
|
||
|
|
itemCard.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const confirmButton = queryShadow(".btn-primary");
|
||
|
|
expect(confirmButton).to.exist;
|
||
|
|
confirmButton.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 50)); // Wait for async
|
||
|
|
|
||
|
|
expect(element.showModal).to.be.false;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should close modal when cancel is clicked", async () => {
|
||
|
|
const itemCard = queryShadow(".item-card");
|
||
|
|
expect(itemCard).to.exist;
|
||
|
|
itemCard.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const cancelButton = queryShadowAll(".btn")[1]; // Cancel button
|
||
|
|
expect(cancelButton).to.exist;
|
||
|
|
cancelButton.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 10)); // Wait for async
|
||
|
|
|
||
|
|
expect(element.showModal).to.be.false;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("CoA 5: Affordability States", () => {
|
||
|
|
beforeEach(async () => {
|
||
|
|
// Reset stub
|
||
|
|
mockMarketManager.getStockForMerchant.reset();
|
||
|
|
// Set up mock to return items
|
||
|
|
mockMarketManager.getStockForMerchant.returns([
|
||
|
|
{
|
||
|
|
id: "STOCK_AFFORDABLE",
|
||
|
|
defId: "ITEM_RUSTY_BLADE",
|
||
|
|
type: "WEAPON",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 50,
|
||
|
|
purchased: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: "STOCK_UNAFFORDABLE",
|
||
|
|
defId: "ITEM_SCRAP_PLATE",
|
||
|
|
type: "ARMOR",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 2000,
|
||
|
|
purchased: false,
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
await waitForUpdate();
|
||
|
|
await waitForUpdate(); // Extra update to ensure render completes
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should mark affordable items correctly", async () => {
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
mockHubStash.currency.aetherShards = 1000;
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const itemCards = queryShadowAll(".item-card");
|
||
|
|
const affordableCard = Array.from(itemCards).find((card) =>
|
||
|
|
card.textContent.includes("Rusty Infantry Blade")
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(affordableCard).to.exist;
|
||
|
|
expect(affordableCard.classList.contains("unaffordable")).to.be.false;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should mark unaffordable items correctly", async () => {
|
||
|
|
mockHubStash.currency.aetherShards = 100;
|
||
|
|
element._updateWallet();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const itemCards = queryShadowAll(".item-card");
|
||
|
|
expect(itemCards.length).to.be.greaterThan(0);
|
||
|
|
const unaffordableCard = Array.from(itemCards).find((card) =>
|
||
|
|
card.textContent.includes("Scrap Plate")
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(unaffordableCard).to.exist;
|
||
|
|
expect(unaffordableCard.classList.contains("unaffordable")).to.be.true;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should disable buy button for unaffordable items", async () => {
|
||
|
|
mockHubStash.currency.aetherShards = 100;
|
||
|
|
element._updateWallet();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const itemCards = queryShadowAll(".item-card");
|
||
|
|
expect(itemCards.length).to.be.greaterThan(0);
|
||
|
|
const itemCard = itemCards[1]; // Unaffordable item
|
||
|
|
expect(itemCard).to.exist;
|
||
|
|
itemCard.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const confirmButton = queryShadow(".btn-primary");
|
||
|
|
expect(confirmButton).to.exist;
|
||
|
|
expect(confirmButton.disabled).to.be.true;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("CoA 6: Sold Out State", () => {
|
||
|
|
beforeEach(async () => {
|
||
|
|
// Reset stub
|
||
|
|
mockMarketManager.getStockForMerchant.reset();
|
||
|
|
// Set up mock to return sold item
|
||
|
|
mockMarketManager.getStockForMerchant.returns([
|
||
|
|
{
|
||
|
|
id: "STOCK_SOLD",
|
||
|
|
defId: "ITEM_RUSTY_BLADE",
|
||
|
|
type: "WEAPON",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 50,
|
||
|
|
purchased: true,
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
await waitForUpdate();
|
||
|
|
await waitForUpdate(); // Extra update to ensure render completes
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should display sold out overlay", async () => {
|
||
|
|
const itemCards = queryShadowAll(".item-card");
|
||
|
|
expect(itemCards.length).to.be.greaterThan(0);
|
||
|
|
|
||
|
|
const soldOverlay = queryShadow(".sold-overlay");
|
||
|
|
expect(soldOverlay).to.exist;
|
||
|
|
expect(soldOverlay.textContent).to.include("SOLD");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should apply sold-out class to card", async () => {
|
||
|
|
const itemCard = queryShadow(".item-card");
|
||
|
|
expect(itemCard).to.exist;
|
||
|
|
expect(itemCard.classList.contains("sold-out")).to.be.true;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should not open modal when sold item is clicked", async () => {
|
||
|
|
const itemCard = queryShadow(".item-card");
|
||
|
|
expect(itemCard).to.exist;
|
||
|
|
itemCard.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const modal = queryShadow(".modal");
|
||
|
|
expect(modal).to.be.null;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("CoA 7: Filter Functionality", () => {
|
||
|
|
beforeEach(async () => {
|
||
|
|
// Reset stub
|
||
|
|
mockMarketManager.getStockForMerchant.reset();
|
||
|
|
// Set up mock to return items
|
||
|
|
mockMarketManager.getStockForMerchant.returns([
|
||
|
|
{
|
||
|
|
id: "STOCK_WEAPON",
|
||
|
|
defId: "ITEM_RUSTY_BLADE",
|
||
|
|
type: "WEAPON",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 50,
|
||
|
|
purchased: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: "STOCK_ARMOR",
|
||
|
|
defId: "ITEM_SCRAP_PLATE",
|
||
|
|
type: "ARMOR",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 75,
|
||
|
|
purchased: false,
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
await waitForUpdate();
|
||
|
|
await waitForUpdate(); // Extra update to ensure render completes
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should filter items by type", async () => {
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const weaponFilter = Array.from(queryShadowAll(".filter-button")).find(
|
||
|
|
(btn) => btn.textContent.includes("Weapons")
|
||
|
|
);
|
||
|
|
weaponFilter.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
expect(element.activeFilter).to.equal("WEAPON");
|
||
|
|
const itemCards = queryShadowAll(".item-card");
|
||
|
|
expect(itemCards.length).to.equal(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should show all items when ALL filter is selected", async () => {
|
||
|
|
element.activeFilter = "WEAPON";
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const allFilter = Array.from(queryShadowAll(".filter-button")).find(
|
||
|
|
(btn) => btn.textContent.includes("All")
|
||
|
|
);
|
||
|
|
allFilter.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
expect(element.activeFilter).to.equal("ALL");
|
||
|
|
const itemCards = queryShadowAll(".item-card");
|
||
|
|
expect(itemCards.length).to.equal(2);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("CoA 8: Event Dispatching", () => {
|
||
|
|
it("should dispatch market-closed event when close button is clicked", async () => {
|
||
|
|
const closeSpy = sinon.spy();
|
||
|
|
element.addEventListener("market-closed", closeSpy);
|
||
|
|
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const closeButton = queryShadow(".btn-close");
|
||
|
|
closeButton.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
expect(closeSpy.called).to.be.true;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("Empty State", () => {
|
||
|
|
it("should display empty state when no items available", async () => {
|
||
|
|
mockMarketManager.getStockForMerchant.returns([]);
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
const emptyState = queryShadow(".empty-state");
|
||
|
|
expect(emptyState).to.exist;
|
||
|
|
expect(emptyState.textContent).to.include("No items available");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("Wallet Updates", () => {
|
||
|
|
it("should update wallet display after purchase", async () => {
|
||
|
|
element.marketManager = mockMarketManager;
|
||
|
|
mockMarketManager.getStockForMerchant.returns([
|
||
|
|
{
|
||
|
|
id: "STOCK_001",
|
||
|
|
defId: "ITEM_RUSTY_BLADE",
|
||
|
|
type: "WEAPON",
|
||
|
|
rarity: "COMMON",
|
||
|
|
price: 50,
|
||
|
|
purchased: false,
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
|
||
|
|
mockHubStash.currency.aetherShards = 1000;
|
||
|
|
await waitForUpdate();
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 10)); // Extra wait for wallet update
|
||
|
|
|
||
|
|
const itemCard = queryShadow(".item-card");
|
||
|
|
expect(itemCard).to.exist;
|
||
|
|
itemCard.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
|
||
|
|
// Simulate purchase - update currency before clicking
|
||
|
|
mockHubStash.currency.aetherShards = 950;
|
||
|
|
const confirmButton = queryShadow(".btn-primary");
|
||
|
|
expect(confirmButton).to.exist;
|
||
|
|
confirmButton.click();
|
||
|
|
await waitForUpdate();
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 50)); // Wait for async
|
||
|
|
|
||
|
|
// Wallet should be updated (component calls _updateWallet after purchase)
|
||
|
|
expect(element.wallet.aetherShards).to.equal(950);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|