Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions apps/api/src/app.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
jest.mock('puppeteer-extra', () => ({
use: jest.fn(),
launch: jest.fn(),
}));

jest.mock('puppeteer-extra-plugin-stealth', () => () => ({}));

jest.mock('puppeteer-extra-plugin-adblocker', () => () => ({}));

jest.mock('puppeteer', () => ({
DEFAULT_INTERCEPT_RESOLUTION_PRIORITY: 0,
}));

jest.mock('./config/db', () => ({
isDbConnected: jest.fn(() => false),
}));

jest.mock('./config/logger', () => ({
__esModule: true,
default: {
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
},
setupErrorHandlers: jest.fn(),
}));

jest.mock('./client/Instagram', () => ({
getIgClient: jest.fn(),
closeIgClient: jest.fn(),
scrapeFollowersHandler: jest.fn(),
getIgClientStatus: jest.fn(() => ({ connected: false })),
getIgClientsSnapshot: jest.fn(() => ({})),
}));

jest.mock('./services/actionLog', () => ({
logAction: jest.fn().mockResolvedValue(undefined),
getActionSummary: jest.fn().mockResolvedValue({}),
listActionLogs: jest.fn().mockResolvedValue([]),
}));

jest.mock('./services/metrics', () => ({
metricsMiddleware: jest.fn((_req, _res, next) => next()),
getMetrics: jest.fn(() => ({
uptime: 120,
uptimeFormatted: '2m 0s',
requests: 0,
})),
}));

jest.mock('./config/accounts', () => ({
getAccount: jest.fn(),
getAccountsMap: jest.fn(() => ({})),
}));

import request from 'supertest';
import app from './app';

describe('Root App Routes', () => {
test('GET /hello returns { ok: true }', async () => {
const res = await request(app).get('/hello');
expect(res.status).toBe(200);
expect(res.body).toEqual({ ok: true });
});
});
5 changes: 5 additions & 0 deletions apps/api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ app.use(express.static('frontend/dist'));
// API Routes
app.use('/api', apiRoutes);

// Hello world test endpoint for bot detection verification
app.get('/hello', (_req, res) => {
res.status(200).json({ ok: true });
});

// Admin dashboard
app.get('/dashboard', (_req, res) => {
res.type('html').send(dashboardHtml);
Expand Down
6 changes: 6 additions & 0 deletions apps/api/src/routes/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ app.use('/api', apiRoutes);

describe('API routes', () => {
describe('public endpoints', () => {
test('GET /api/hello returns { ok: true }', async () => {
const res = await request(app).get('/api/hello');
expect(res.status).toBe(200);
expect(res.body).toEqual({ ok: true });
});

test('GET /api/ping returns pong', async () => {
const res = await request(app).get('/api/ping');
expect(res.status).toBe(200);
Expand Down
11 changes: 11 additions & 0 deletions apps/api/src/routes/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ router.use(generalLimiter);
// API Documentation endpoint - lists all available endpoints
const apiEndpoints = [
// Public endpoints
{
method: 'GET',
path: '/api/hello',
auth: false,
description: 'Hello world test endpoint for bot detection verification (returns { ok: true })',
},
{
method: 'GET',
path: '/api/ping',
Expand Down Expand Up @@ -268,6 +274,11 @@ const apiEndpoints = [
// Track server start time for uptime calculation
const serverStartTime = Date.now();

// Hello world test endpoint for bot detection verification
router.get('/hello', (_req: Request, res: Response) => {
return res.json({ ok: true });
});

// Simple ping endpoint for load balancers and uptime monitors
router.get('/ping', (_req: Request, res: Response) => {
return res.send('pong');
Expand Down