Files
wownerogue/test/commerceDisclosurePolicy.test.js
T

281 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const {
buildCommerceDisclosure,
safeContactUrl,
validatePaidAcknowledgement
} = require('../src/config/commerceDisclosurePolicy');
const PaymentHandlers = require('../src/network/paymentHandlers');
function manager(overrides = {}) {
return {
cryptoType: 'XMR',
currencyLabel: 'sXMR',
network: 'stagenet',
isTestNetwork: true,
gameName: 'Monerogue',
paymentsEnabled: true,
freePlayEnabled: true,
directModeEnabled: true,
creditsModeEnabled: true,
payoutsEnabled: true,
isPayoutEnabledForMode: mode => mode === 'PAID_SINGLE',
...overrides
};
}
function env(overrides = {}) {
return {
NODE_ENV: 'production',
LEGAL_POLICY_VERSION: '2026-07-21-v1',
TERMS_EFFECTIVE_DATE: '2026-07-21',
MINIMUM_AGE: '21',
PAID_ACKNOWLEDGEMENT_REQUIRED: 'true',
OPERATOR_NAME: 'Test Operator',
OPERATOR_CONTACT_URL: 'mailto:support@example.invalid',
MATCH_ENABLED: 'false',
...overrides
};
}
describe('commerce disclosure and paid-action policy', () => {
test('describes active test-network payout mode without conflating it with mainnet', () => {
const disclosure = buildCommerceDisclosure(manager(), env());
expect(disclosure).toEqual(expect.objectContaining({
policyVersion: '2026-07-21-v1',
minimumAge: 21,
paidAcknowledgementRequired: true
}));
expect(disclosure.service).toEqual(expect.objectContaining({
network: 'stagenet',
isTestNetwork: true,
paidPrestigeOnly: false,
soloPayoutsEnabled: true
}));
});
test('publishes the immutable play.wowne.ro scope and Such Software identity', () => {
const disclosure = buildCommerceDisclosure(manager({
cryptoType: 'WOW',
currencyLabel: 'WOW',
network: 'mainnet',
isTestNetwork: false,
directModeEnabled: false,
creditsModeEnabled: true,
payoutsEnabled: false,
isPayoutEnabledForMode: () => false
}), env({
OPERATED_PRODUCT_PROFILE: 'such-play-wow-prestige',
OPERATOR_NAME: 'untrusted override',
OPERATOR_CONTACT_URL: 'mailto:untrusted@example.invalid'
}));
expect(disclosure.operator).toEqual({
name: 'Such Software',
contactUrl: 'mailto:apps@such.software',
contactLabel: 'apps@such.software'
});
expect(disclosure.operatedProduct).toEqual(expect.objectContaining({
id: 'such-play-wow-prestige',
hostname: 'play.wowne.ro',
noRealValueNotice: null
}));
expect(disclosure.operatedProduct.scopeNotice).toContain('pay-for-credits leaderboard/prestige');
expect(disclosure.operatedProduct.scopeNotice).toContain('offers no prizes, winnings, cash-out, or payouts');
expect(disclosure.operatedProduct.scopeNotice).toContain('not offered or marketed as gambling');
expect(disclosure.operatedProduct.scopeNotice).toContain('legal classification depends on applicable law');
});
test('publishes conspicuous no-real-value monerogue.app scope and MIT operator boundary', () => {
const disclosure = buildCommerceDisclosure(manager({
creditsModeEnabled: false
}), env({
OPERATED_PRODUCT_PROFILE: 'such-monerogue-stagenet'
}));
expect(disclosure.operatedProduct.scopeNotice).toContain('single-player 2×/3× outcomes are test gambling mechanics');
expect(disclosure.operatedProduct.noRealValueNotice).toContain('NO REAL VALUE');
expect(disclosure.operatedProduct.commerceSummary).toMatch(/never send mainnet XMR/i);
expect(disclosure.operatedProduct.commerceSummary).toContain('Purchased-credit entry');
expect(disclosure.service.paidCreditsEnabled).toBe(false);
expect(disclosure.service.cryptoMatchPayoutsEnabled).toBe(false);
expect(disclosure.software).toEqual(expect.objectContaining({
license: 'MIT',
publisherName: 'Such Software'
}));
expect(disclosure.software.rightsNotice).toContain('copyright and permission notice');
expect(disclosure.software.warrantyNotice).toContain('AS IS');
expect(disclosure.software.legalAdviceNotice).toContain('not legal advice');
expect(disclosure.software.thirdPartyNotice).toContain('solely responsible');
expect(disclosure.software.thirdPartyNotice).toContain('does not make that deployment a Such Software service');
expect(disclosure.software.thirdPartyNotice).toContain('does not operate, supervise, endorse, or accept responsibility');
});
test('an unprofiled deployment remains generic and is not represented as Such-operated', () => {
const disclosure = buildCommerceDisclosure(manager(), env());
expect(disclosure.operatedProduct).toBeNull();
expect(disclosure.operator.name).toBe('Test Operator');
expect(disclosure.software.operatedBoundaryNotice).toContain('operates only play.wowne.ro and monerogue.app');
});
test('describes paid prestige separately when every payout path is off', () => {
const disclosure = buildCommerceDisclosure(manager({
cryptoType: 'WOW', currencyLabel: 'WOW', network: 'mainnet', isTestNetwork: false,
payoutsEnabled: false, isPayoutEnabledForMode: () => false
}), env());
expect(disclosure.service.paidPrestigeOnly).toBe(true);
expect(disclosure.service.anyPayoutsEnabled).toBe(false);
});
test('does not advertise a stale solo payout flag when that paid mode is disabled', () => {
const disclosure = buildCommerceDisclosure(manager({
directModeEnabled: false,
creditsModeEnabled: true,
isPayoutEnabledForMode: mode => mode === 'PAID_SINGLE'
}), env());
expect(disclosure.service.directPaidEntryEnabled).toBe(false);
expect(disclosure.service.paidCreditsEnabled).toBe(true);
expect(disclosure.service.soloPayoutsEnabled).toBe(false);
const activeCreditsPayout = buildCommerceDisclosure(manager({
directModeEnabled: false,
creditsModeEnabled: true,
isPayoutEnabledForMode: mode => mode === 'PAID_CREDITS'
}), env());
expect(activeCreditsPayout.service.soloPayoutsEnabled).toBe(true);
const noPaidModes = buildCommerceDisclosure(manager({
directModeEnabled: false,
creditsModeEnabled: false,
isPayoutEnabledForMode: () => true
}), env());
expect(noPaidModes.service.soloPayoutsEnabled).toBe(false);
expect(noPaidModes.service.anyPayoutsEnabled).toBe(false);
});
test('fails closed on missing, stale, incomplete, or testnet-unaware acknowledgement', () => {
const disclosure = buildCommerceDisclosure(manager(), env());
const good = {
policyVersion: disclosure.policyVersion,
ageEligible: true,
termsRead: true,
riskAccepted: true,
testnetUnderstood: true
};
expect(validatePaidAcknowledgement(null, disclosure).ok).toBe(false);
expect(validatePaidAcknowledgement({ ...good, policyVersion: 'old' }, disclosure).code).toBe('PAID_ACK_VERSION');
expect(validatePaidAcknowledgement({ ...good, riskAccepted: false }, disclosure).code).toBe('PAID_ACK_INCOMPLETE');
expect(validatePaidAcknowledgement({ ...good, testnetUnderstood: false }, disclosure).code).toBe('PAID_ACK_TESTNET');
expect(validatePaidAcknowledgement({ ...good, extra: true }, disclosure).code).toBe('PAID_ACK_MALFORMED');
expect(validatePaidAcknowledgement({
policyVersion: disclosure.policyVersion,
ageEligible: true,
termsRead: true,
riskAccepted: true
}, disclosure).code).toBe('PAID_ACK_MALFORMED');
expect(validatePaidAcknowledgement(good, disclosure)).toEqual({
ok: true,
code: 'ACKNOWLEDGED',
acknowledgement: Object.freeze(good)
});
});
test('mainnet acknowledgement is canonical and carries an explicit false testnet flag', () => {
const disclosure = buildCommerceDisclosure(manager({
cryptoType: 'WOW',
currencyLabel: 'WOW',
network: 'mainnet',
isTestNetwork: false
}), env());
const good = {
policyVersion: disclosure.policyVersion,
ageEligible: true,
termsRead: true,
riskAccepted: true,
testnetUnderstood: false
};
expect(validatePaidAcknowledgement(good, disclosure)).toEqual({
ok: true,
code: 'ACKNOWLEDGED',
acknowledgement: Object.freeze(good)
});
expect(validatePaidAcknowledgement({ ...good, testnetUnderstood: true }, disclosure).code)
.toBe('PAID_ACK_MALFORMED');
});
test('keeps acknowledgement UI enabled for paid match entitlements while invoice intake is off', () => {
const disclosure = buildCommerceDisclosure(manager({
paymentsEnabled: false,
directModeEnabled: false,
creditsModeEnabled: false,
freePlayEnabled: true,
_getMatchEconomies: () => ({ free: true, credits_prestige: true })
}), env({ PAID_ACKNOWLEDGEMENT_REQUIRED: 'false', MATCH_ENABLED: 'true' }));
expect(disclosure.service.paymentsEnabled).toBe(false);
expect(disclosure.paidAcknowledgementRequired).toBe(true);
});
test('allows no acknowledgement only where the policy is actually disabled', () => {
const disclosure = buildCommerceDisclosure(manager({
paymentsEnabled: false,
directModeEnabled: false,
creditsModeEnabled: false,
freePlayEnabled: false
}), {
NODE_ENV: 'test', PAID_ACKNOWLEDGEMENT_REQUIRED: 'false'
});
expect(validatePaidAcknowledgement(null, disclosure)).toEqual({
ok: true, code: 'NOT_REQUIRED', acknowledgement: null
});
});
test('contact URLs reject executable and unrelated schemes', () => {
expect(safeContactUrl('javascript:alert(1)')).toBeNull();
expect(safeContactUrl('data:text/html,boom')).toBeNull();
expect(safeContactUrl('mailto:support@example.invalid')).toBe('mailto:support@example.invalid');
expect(safeContactUrl('https://example.invalid/support')).toBe('https://example.invalid/support');
});
test('payment handler refuses an invoice before wallet or database work when acknowledgement is absent', async () => {
const previousNodeEnv = process.env.NODE_ENV;
const previousVersion = process.env.LEGAL_POLICY_VERSION;
process.env.NODE_ENV = 'production';
process.env.LEGAL_POLICY_VERSION = 'server-enforcement-v1';
const emit = jest.fn();
const createPaymentRequest = jest.fn();
const handler = new PaymentHandlers({
io: { to: () => ({ emit }) },
gameModeManager: {
...manager({ isTestNetwork: false, network: 'mainnet' }),
createPaymentRequest,
isPayoutEnabledForMode: () => false
},
walletService: {},
debugManager: { CONSOLE_LOGGING: false },
queueManager: {},
broadcastManager: { sendStatusUpdate: jest.fn() },
sessionManager: null
});
try {
await handler.handlePaymentRequest({ id: 'socket-1' }, { type: 'single_game' });
expect(createPaymentRequest).not.toHaveBeenCalled();
expect(emit).toHaveBeenCalledWith('commerce_ack_required', expect.objectContaining({
code: 'PAID_ACK_REQUIRED', policyVersion: 'server-enforcement-v1'
}));
expect(emit).toHaveBeenCalledWith('payment_error', expect.objectContaining({
code: 'PAID_ACK_REQUIRED'
}));
} finally {
handler.dispose();
if (previousNodeEnv === undefined) delete process.env.NODE_ENV;
else process.env.NODE_ENV = previousNodeEnv;
if (previousVersion === undefined) delete process.env.LEGAL_POLICY_VERSION;
else process.env.LEGAL_POLICY_VERSION = previousVersion;
}
});
});