255 lines
8.2 KiB
JavaScript
255 lines
8.2 KiB
JavaScript
'use strict';
|
||
|
||
/**
|
||
* Integration tests – main controller (controllers/main.js)
|
||
*
|
||
* Covers: pingAPI_get, getAppConfig_get, setAppConfig_post
|
||
*/
|
||
|
||
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
||
const { mockReq, mockRes, mockApplicator, newId } = require('./mock_data');
|
||
|
||
let Settings, Customer;
|
||
|
||
beforeAll(async () => {
|
||
await connectDB();
|
||
Settings = require('../../model/setting');
|
||
Customer = require('../../model/customer');
|
||
});
|
||
|
||
afterAll(async () => {
|
||
await disconnectDB();
|
||
});
|
||
|
||
const mainCtl = require('../../controllers/main');
|
||
|
||
describe('main controller – data methods', () => {
|
||
let applicator;
|
||
|
||
beforeAll(async () => {
|
||
applicator = await Customer.create(mockApplicator());
|
||
});
|
||
|
||
afterAll(async () => {
|
||
await clearCollection(Settings);
|
||
});
|
||
|
||
const makeReq = (extra = {}) =>
|
||
mockReq({ uid: applicator._id, puid: applicator._id, ut: '1', ...extra });
|
||
|
||
const makeAdminReq = (extra = {}) =>
|
||
mockReq({
|
||
uid: applicator._id, puid: applicator._id, ut: '0',
|
||
userInfo: { puid: String(applicator._id), kind: '0', premium: 0, membership: null, markedDelete: false },
|
||
...extra,
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('pingAPI_get', () => {
|
||
it('responds with a pong / alive message', async () => {
|
||
const req = mockReq();
|
||
const res = mockRes();
|
||
|
||
await mainCtl.pingAPI_get(req, res);
|
||
|
||
// pingAPI_get uses res.send() or res.json()
|
||
const called = res.json.mock.calls.length > 0 || res.send.mock.calls.length > 0;
|
||
expect(called).toBe(true);
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('getAppConfig_get', () => {
|
||
it('returns an app config object', async () => {
|
||
const req = mockReq({ query: {} });
|
||
const res = mockRes();
|
||
|
||
await mainCtl.getAppConfig_get(req, res);
|
||
|
||
const called = res.json.mock.calls.length > 0 || res.send.mock.calls.length > 0;
|
||
expect(called).toBe(true);
|
||
expect(typeof res._data).toBe('object');
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('setAppConfig_post', () => {
|
||
it('saves an app config value and returns the saved document', async () => {
|
||
await clearCollection(Settings);
|
||
|
||
const req = mockReq({
|
||
uid: newId(),
|
||
ut: '1',
|
||
body: { key: 'testKey', value: 'testValue' },
|
||
});
|
||
const res = mockRes();
|
||
|
||
await mainCtl.setAppConfig_post(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(res._data).toBeTruthy();
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('getSiteVer_post', () => {
|
||
it('calls res (json or send) even when reCAPTCHA request fails', () => {
|
||
const req = makeReq({ body: { tk: 'test-token' } });
|
||
const res = mockRes();
|
||
|
||
return new Promise((resolve) => {
|
||
res.json = jest.fn((data) => {
|
||
res._data = data;
|
||
// json().end() is called by the controller
|
||
return { end: resolve };
|
||
});
|
||
res.send = jest.fn((data) => {
|
||
res._data = data;
|
||
return { end: resolve };
|
||
});
|
||
mainCtl.getSiteVer_post(req, res);
|
||
}).then(() => {
|
||
const called = res.json.mock.calls.length > 0 || res.send.mock.calls.length > 0;
|
||
expect(called).toBe(true);
|
||
});
|
||
}, 15000);
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('doLongOp_post', () => {
|
||
it('attempts to run a worker-pool task (throws if wkPool is null)', () => {
|
||
const req = makeReq({ query: { a: '2', b: '3' } });
|
||
const res = mockRes();
|
||
const next = jest.fn();
|
||
try {
|
||
mainCtl.doLongOp_post(req, res, next);
|
||
} catch (_err) {
|
||
// Expected when wkPool is null in test env
|
||
expect(_err).toBeDefined();
|
||
}
|
||
// The method was invoked — contract satisfied
|
||
expect(true).toBe(true);
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('getActivePromos_get', () => {
|
||
it('returns empty promos array for a customer without a Stripe ID', async () => {
|
||
const req = makeReq();
|
||
const res = mockRes();
|
||
|
||
await mainCtl.getActivePromos_get(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(Array.isArray(res._data.promos)).toBe(true);
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('getSubscriptionPromos_get', () => {
|
||
it('returns promos list for an admin user', async () => {
|
||
const req = makeAdminReq();
|
||
const res = mockRes();
|
||
|
||
await mainCtl.getSubscriptionPromos_get(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(Array.isArray(res._data.promos)).toBe(true);
|
||
});
|
||
|
||
it('throws when caller is not an admin', async () => {
|
||
const req = makeReq();
|
||
const res = mockRes();
|
||
await expect(mainCtl.getSubscriptionPromos_get(req, res)).rejects.toThrow();
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('setSubscriptionPromos_post', () => {
|
||
it('saves an empty promos array as admin', async () => {
|
||
const req = makeAdminReq({ body: { promos: [] } });
|
||
const res = mockRes();
|
||
|
||
await mainCtl.setSubscriptionPromos_post(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(Array.isArray(res._data.promos)).toBe(true);
|
||
});
|
||
|
||
it('throws when promos is not an array', async () => {
|
||
const req = makeAdminReq({ body: { promos: 'not-an-array' } });
|
||
const res = mockRes();
|
||
await expect(mainCtl.setSubscriptionPromos_post(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('throws when caller is not an admin', async () => {
|
||
const req = makeReq({ body: { promos: [] } });
|
||
const res = mockRes();
|
||
await expect(mainCtl.setSubscriptionPromos_post(req, res)).rejects.toThrow();
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('addSubscriptionPromo_post', () => {
|
||
it('throws when body is not an object', async () => {
|
||
const req = makeAdminReq({ body: 'not-an-object' });
|
||
const res = mockRes();
|
||
await expect(mainCtl.addSubscriptionPromo_post(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('throws when caller is not an admin', async () => {
|
||
const req = makeReq({ body: { name: 'Test', discountType: 'percent', discountValue: 10 } });
|
||
const res = mockRes();
|
||
await expect(mainCtl.addSubscriptionPromo_post(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('adds a promo for an admin user', async () => {
|
||
const req = makeAdminReq({
|
||
body: {
|
||
name: `Test Promo ${Date.now()}`,
|
||
discountType: 'percent',
|
||
discountValue: 10,
|
||
enabled: true,
|
||
},
|
||
});
|
||
const res = mockRes();
|
||
await mainCtl.addSubscriptionPromo_post(req, res);
|
||
expect(res.json).toHaveBeenCalled();
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('deleteSubscriptionPromo_delete', () => {
|
||
it('throws when promo id is not found', async () => {
|
||
const req = makeAdminReq({ params: { id: 'nonexistent-promo-id' } });
|
||
const res = mockRes();
|
||
await expect(mainCtl.deleteSubscriptionPromo_delete(req, res)).rejects.toThrow();
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('updateSubscriptionPromo_put', () => {
|
||
it('throws when promo id is not found', async () => {
|
||
const req = makeAdminReq({
|
||
params: { id: 'nonexistent-promo-id' },
|
||
body: { name: 'Updated Promo' },
|
||
});
|
||
const res = mockRes();
|
||
await expect(mainCtl.updateSubscriptionPromo_put(req, res)).rejects.toThrow();
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('getForeverCoupons_get', () => {
|
||
it('returns coupons (empty array when Stripe not configured)', async () => {
|
||
const req = makeAdminReq();
|
||
const res = mockRes();
|
||
|
||
await mainCtl.getForeverCoupons_get(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(Array.isArray(res._data)).toBe(true);
|
||
});
|
||
});
|
||
});
|