Files
wownerogue/test/paymentProviderWiring_ultra.test.js
jwinterm fad2a695bd Wownerogue
A browser-based roguelike synchronized with crypto block timing. A run is a race
against the next block: reach the exit before the block lands, or the house wins.
The same codebase runs the solo dungeon, the social Tavern, and operator-selected
PvP and race rulesets, with separate free and paid leaderboards.

Self-hostable under the MIT License. See README.md to run it, docs/ARCHITECTURE.md
for the design, and docs/DEPLOY.md to operate an instance.
2026-07-27 08:23:01 -04:00

69 lines
3.3 KiB
JavaScript

/**
* Proves GameModeManager.createPaymentRequest routes invoice creation through the payment-provider
* registry: a configured gateway is used, and with the default registry it delegates to the native
* walletService (byte-for-byte legacy path).
*/
const GameModeManager = require('../src/game/gameModeManager');
function mockDb() {
return {
query: jest.fn(async (sql) => {
const s = String(sql);
if (/FROM users WHERE id/i.test(s)) return { rows: [{ id: 7, credits: 0, total_credits_purchased: 0 }] };
if (/INSERT INTO payments/i.test(s)) return { rows: [{ id: 101, expires_at: null }] };
return { rows: [] }; // reuse lookup, expire-stale, everything else
}),
withTransaction: jest.fn(async (cb) => cb({ query: jest.fn().mockResolvedValue({ rows: [] }) }))
};
}
const mockDebug = { CONSOLE_LOGGING: false };
const mockConfig = {
getConfig: () => ({
paymentsEnabled: true,
currency: { symbol: 'WOW', decimals: 11 },
modes: { direct: { enabled: true, price: 100000000000n }, credits: { enabled: false, packages: [] } },
payouts: { rules: { direct: { multipliers: {} }, credits: { enabled: false, multipliers: {} } } },
preferences: {}
}),
getLegacyGameMode: () => 'PAID_SINGLE',
eventBus: { on: () => {} }
};
describe('createPaymentRequest routes through the provider registry', () => {
test('a configured gateway provider is used for invoice creation', async () => {
const gateway = {
id: 'xmrcheckout',
createInvoice: jest.fn(async () => ({ invoiceId: 'inv-uuid', address: 'GATEWAYADDR', addressIndex: null, expiresAt: null })),
getProvider() { return this; }
};
const registry = { getProvider: jest.fn(() => gateway) };
const walletService = { createPaymentRequest: jest.fn() };
const gmm = new GameModeManager(mockDb(), walletService, mockDebug, mockConfig, registry);
const res = await gmm.createPaymentRequest('sock1', 'single_game', { userId: 7 });
expect(registry.getProvider).toHaveBeenCalledWith(gmm.cryptoType);
expect(gateway.createInvoice).toHaveBeenCalledWith(
expect.objectContaining({ chain: gmm.cryptoType, userId: 7, orderId: 'sock1' })
);
expect(res.address).toBe('GATEWAYADDR');
expect(res.invoiceId).toBe('inv-uuid');
expect(walletService.createPaymentRequest).not.toHaveBeenCalled(); // routed away from native
});
test('the default registry delegates to the native walletService (legacy path preserved)', async () => {
const walletService = {
createPaymentRequest: jest.fn(async () => ({ address: 'NATIVEADDR', addressIndex: 3, expiresAt: null }))
};
// No injected registry -> constructor builds one whose only provider wraps this walletService.
const gmm = new GameModeManager(mockDb(), walletService, mockDebug, mockConfig);
const res = await gmm.createPaymentRequest('sock2', 'single_game', { userId: 7 });
expect(walletService.createPaymentRequest).toHaveBeenCalledWith(expect.anything(), expect.any(String), 7, 'sock2');
expect(res.address).toBe('NATIVEADDR');
expect(res.invoiceId).toBe('NATIVEADDR'); // native invoices keyed by subaddress
});
});