Initial SMM panel implementation
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const http = require('node:http');
|
||||
const test = require('node:test');
|
||||
|
||||
const { createApp } = require('../src/app');
|
||||
const { closeDbPool, getDb } = require('../src/config/db');
|
||||
|
||||
const createdUserIds = [];
|
||||
const createdServiceIds = [];
|
||||
let providerMock;
|
||||
|
||||
function unique(prefix) {
|
||||
return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
||||
}
|
||||
|
||||
function startFailingProviderMock() {
|
||||
const server = http.createServer(async (_req, res) => {
|
||||
res.setHeader('content-type', 'application/json');
|
||||
res.end(JSON.stringify({ error: 'forced provider failure' }));
|
||||
});
|
||||
|
||||
return new Promise((resolve) => {
|
||||
server.listen(0, '127.0.0.1', () => {
|
||||
resolve({
|
||||
url: `http://127.0.0.1:${server.address().port}`,
|
||||
close: () => new Promise((done) => server.close(done))
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function listen(app) {
|
||||
return new Promise((resolve) => {
|
||||
const server = app.listen(0, '127.0.0.1', () => {
|
||||
resolve({
|
||||
baseUrl: `http://127.0.0.1:${server.address().port}`,
|
||||
close: () => new Promise((done) => server.close(done))
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function request(baseUrl, path, options = {}) {
|
||||
const response = await fetch(`${baseUrl}${path}`, {
|
||||
...options,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
...(options.headers || {})
|
||||
}
|
||||
});
|
||||
const body = await response.json().catch(() => ({}));
|
||||
|
||||
return { response, body };
|
||||
}
|
||||
|
||||
async function register(baseUrl, prefix) {
|
||||
const account = {
|
||||
username: unique(prefix),
|
||||
email: `${unique(prefix)}@example.com`,
|
||||
password: 'StrongPass123'
|
||||
};
|
||||
const result = await request(baseUrl, '/auth/register', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(account)
|
||||
});
|
||||
|
||||
assert.equal(result.response.status, 201);
|
||||
createdUserIds.push(result.body.user.id);
|
||||
|
||||
return {
|
||||
...account,
|
||||
id: result.body.user.id
|
||||
};
|
||||
}
|
||||
|
||||
async function login(baseUrl, account) {
|
||||
const result = await request(baseUrl, '/auth/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
email: account.email,
|
||||
password: account.password
|
||||
})
|
||||
});
|
||||
|
||||
assert.equal(result.response.status, 200);
|
||||
return result.body.accessToken;
|
||||
}
|
||||
|
||||
test.before(async () => {
|
||||
providerMock = await startFailingProviderMock();
|
||||
process.env.PROVIDER_API_URL = providerMock.url;
|
||||
process.env.PROVIDER_API_KEY = 'mock-key';
|
||||
});
|
||||
|
||||
test.after(async () => {
|
||||
const db = getDb();
|
||||
|
||||
if (createdUserIds.length > 0) {
|
||||
await db('orders').whereIn('user_id', createdUserIds).del();
|
||||
await db('deposits').whereIn('user_id', createdUserIds).orWhereIn('reviewed_by', createdUserIds).del();
|
||||
await db('transactions').whereIn('user_id', createdUserIds).del();
|
||||
await db('refresh_tokens').whereIn('user_id', createdUserIds).del();
|
||||
await db('password_reset_tokens').whereIn('user_id', createdUserIds).del();
|
||||
await db('users').whereIn('id', createdUserIds).del();
|
||||
}
|
||||
|
||||
if (createdServiceIds.length > 0) {
|
||||
await db('services').whereIn('id', createdServiceIds).del();
|
||||
}
|
||||
|
||||
await closeDbPool();
|
||||
await providerMock.close();
|
||||
});
|
||||
|
||||
test('full flow refunds wallet when provider order fails', async () => {
|
||||
process.env.JWT_SECRET = process.env.JWT_SECRET || 'test_secret';
|
||||
const api = await listen(createApp());
|
||||
|
||||
try {
|
||||
const db = getDb();
|
||||
const user = await register(api.baseUrl, 'e2e_user');
|
||||
const admin = await register(api.baseUrl, 'e2e_admin');
|
||||
await db('users').where({ id: admin.id }).update({ role: 'admin' });
|
||||
|
||||
const userToken = await login(api.baseUrl, user);
|
||||
const adminToken = await login(api.baseUrl, admin);
|
||||
const userAuth = { authorization: `Bearer ${userToken}` };
|
||||
const adminAuth = { authorization: `Bearer ${adminToken}` };
|
||||
|
||||
const deposit = await request(api.baseUrl, '/deposits', {
|
||||
method: 'POST',
|
||||
headers: userAuth,
|
||||
body: JSON.stringify({
|
||||
amount: '10.0000',
|
||||
method: 'paypal',
|
||||
tx_ref: unique('e2e_tx')
|
||||
})
|
||||
});
|
||||
assert.equal(deposit.response.status, 201);
|
||||
|
||||
const approved = await request(api.baseUrl, `/admin/deposits/${deposit.body.deposit.id}`, {
|
||||
method: 'PATCH',
|
||||
headers: adminAuth,
|
||||
body: JSON.stringify({ action: 'approve' })
|
||||
});
|
||||
assert.equal(approved.response.status, 200);
|
||||
|
||||
const [serviceId] = await db('services').insert({
|
||||
provider_service_id: unique('e2e_provider_service'),
|
||||
name: 'E2E Failure Service',
|
||||
category: 'E2E',
|
||||
provider_price: '2.0000',
|
||||
markup_percent: '25.0000',
|
||||
sell_price: '2.5000',
|
||||
min: 100,
|
||||
max: 10000,
|
||||
is_active: true
|
||||
});
|
||||
createdServiceIds.push(serviceId);
|
||||
|
||||
const failedOrder = await request(api.baseUrl, '/orders', {
|
||||
method: 'POST',
|
||||
headers: userAuth,
|
||||
body: JSON.stringify({
|
||||
service_id: serviceId,
|
||||
link: 'https://example.com/e2e-failure',
|
||||
quantity: 1000
|
||||
})
|
||||
});
|
||||
assert.equal(failedOrder.response.status, 502);
|
||||
|
||||
const me = await request(api.baseUrl, '/me', { headers: userAuth });
|
||||
const orders = await request(api.baseUrl, '/orders', { headers: userAuth });
|
||||
const transactions = await request(api.baseUrl, '/transactions', { headers: userAuth });
|
||||
|
||||
assert.equal(me.body.user.balance, '10.0000');
|
||||
assert.equal(orders.body.orders.some((order) => order.status === 'failed' && order.charge === '2.5000'), true);
|
||||
assert.equal(transactions.body.transactions.some((transaction) => transaction.type === 'refund' && transaction.amount === '2.5000'), true);
|
||||
} finally {
|
||||
await api.close();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user