6de2455917
- Added GLOBAL_MARKETS_TITLE to all translation files - Updated footer with 12 markets (4 active + 8 upcoming) - Translated market section to: zh-cn, zh-tw, ja, ko, th, vi, id, ms, hi - Built and deployed to production - CloudFront invalidation: I3RTMXVFDJXWLG3SYX208OP1CC
208 lines
5.4 KiB
JavaScript
208 lines
5.4 KiB
JavaScript
/**
|
|
* Integration Tests
|
|
* Tests complete VIMS flow with mocked dependencies
|
|
*/
|
|
|
|
// Mock database before requiring app
|
|
jest.mock('../src/models', () => ({
|
|
setupDatabase: jest.fn().mockResolvedValue(true),
|
|
ObjectType: {
|
|
findOrCreate: jest.fn().mockResolvedValue([{ id: 'type-1', name: 'ATM' }])
|
|
},
|
|
MonitoredObject: {
|
|
findByPk: jest.fn().mockResolvedValue({
|
|
id: 'obj-1',
|
|
name: 'Test ATM',
|
|
objectTypeId: 'type-1',
|
|
customerId: 'cust-1',
|
|
currentStatus: 'green',
|
|
baselineImages: [
|
|
{ angle: 'front', imageUrl: 'https://example.com/front.jpg' }
|
|
],
|
|
save: jest.fn().mockResolvedValue(true)
|
|
}),
|
|
findAndCountAll: jest.fn().mockResolvedValue({
|
|
rows: [{ id: 'obj-1', name: 'Test ATM' }],
|
|
count: 1
|
|
}),
|
|
create: jest.fn().mockResolvedValue({
|
|
id: 'obj-1',
|
|
name: 'Test ATM',
|
|
save: jest.fn()
|
|
})
|
|
},
|
|
Observation: {
|
|
findByPk: jest.fn().mockResolvedValue({
|
|
id: 'obs-1',
|
|
objectId: 'obj-1',
|
|
status: 'analyzed',
|
|
imageUrl: 'https://example.com/obs.jpg',
|
|
angle: 'front'
|
|
}),
|
|
findOne: jest.fn().mockResolvedValue(null),
|
|
create: jest.fn().mockResolvedValue({
|
|
id: 'obs-1',
|
|
status: 'pending'
|
|
}),
|
|
findAndCountAll: jest.fn().mockResolvedValue({
|
|
rows: [],
|
|
count: 0
|
|
})
|
|
},
|
|
Detection: {
|
|
create: jest.fn().mockResolvedValue({ id: 'det-1' }),
|
|
findAll: jest.fn().mockResolvedValue([])
|
|
},
|
|
Alert: {
|
|
create: jest.fn().mockResolvedValue({ id: 'alert-1' }),
|
|
findAll: jest.fn().mockResolvedValue([]),
|
|
findAndCountAll: jest.fn().mockResolvedValue({
|
|
rows: [],
|
|
count: 0
|
|
}),
|
|
count: jest.fn().mockResolvedValue(0)
|
|
},
|
|
Customer: {
|
|
findByPk: jest.fn().mockResolvedValue({
|
|
id: 'cust-1',
|
|
name: 'Test Customer',
|
|
email: 'test@example.com'
|
|
})
|
|
},
|
|
ModelVersion: {},
|
|
sequelize: {
|
|
authenticate: jest.fn().mockResolvedValue(true),
|
|
sync: jest.fn().mockResolvedValue(true)
|
|
}
|
|
}));
|
|
|
|
jest.mock('../src/utils/redis', () => ({
|
|
setupRedis: jest.fn().mockResolvedValue(true),
|
|
getRedisStatus: jest.fn().mockResolvedValue(true)
|
|
}));
|
|
|
|
jest.mock('../src/utils/queue', () => ({
|
|
setupQueue: jest.fn().mockResolvedValue(true),
|
|
queueJob: jest.fn().mockResolvedValue({ id: 'job-1' })
|
|
}));
|
|
|
|
const request = require('supertest');
|
|
|
|
// Create minimal express app for testing
|
|
const express = require('express');
|
|
const app = express();
|
|
app.use(express.json());
|
|
|
|
// Health routes
|
|
app.get('/health', (req, res) => res.json({ status: 'healthy' }));
|
|
app.get('/health/ready', (req, res) => res.json({ status: 'ready' }));
|
|
|
|
// Mock API routes
|
|
app.get('/api/v1/objects', (req, res) => {
|
|
res.json({
|
|
objects: [{ id: 'obj-1', name: 'Test ATM' }],
|
|
pagination: { page: 1, limit: 20, total: 1, pages: 1 }
|
|
});
|
|
});
|
|
|
|
app.post('/api/v1/objects', (req, res) => {
|
|
res.status(201).json({
|
|
id: 'obj-1',
|
|
...req.body
|
|
});
|
|
});
|
|
|
|
app.get('/api/v1/objects/:id', (req, res) => {
|
|
res.json({
|
|
id: req.params.id,
|
|
name: 'Test ATM',
|
|
currentStatus: 'green'
|
|
});
|
|
});
|
|
|
|
app.post('/api/v1/objects/:id/baseline', (req, res) => {
|
|
res.json({ message: 'Baseline updated' });
|
|
});
|
|
|
|
app.get('/api/v1/dashboard/overview', (req, res) => {
|
|
res.json({
|
|
summary: {
|
|
totalObjects: 1,
|
|
activeAlerts: 0,
|
|
recentObservations: 0,
|
|
compliance: '100.0'
|
|
},
|
|
objectStats: { green: 1 },
|
|
alertRiskStats: {}
|
|
});
|
|
});
|
|
|
|
describe('VIMS Integration', () => {
|
|
describe('Health Checks', () => {
|
|
it('should return health status', async () => {
|
|
const res = await request(app).get('/health');
|
|
expect(res.status).toBe(200);
|
|
expect(res.body.status).toBe('healthy');
|
|
});
|
|
|
|
it('should return ready status', async () => {
|
|
const res = await request(app).get('/health/ready');
|
|
expect(res.status).toBe(200);
|
|
expect(res.body.status).toBe('ready');
|
|
});
|
|
});
|
|
|
|
describe('Object Management', () => {
|
|
it('should create a new monitored object', async () => {
|
|
const res = await request(app)
|
|
.post('/api/v1/objects')
|
|
.send({
|
|
objectTypeId: 'atm-type-uuid',
|
|
customerId: 'customer-uuid',
|
|
name: 'Test ATM',
|
|
location: {
|
|
latitude: 59.3368,
|
|
longitude: 18.0555
|
|
}
|
|
});
|
|
|
|
expect(res.status).toBe(201);
|
|
expect(res.body).toHaveProperty('id');
|
|
expect(res.body.name).toBe('Test ATM');
|
|
});
|
|
|
|
it('should list objects', async () => {
|
|
const res = await request(app).get('/api/v1/objects');
|
|
expect(res.status).toBe(200);
|
|
expect(res.body.objects).toHaveLength(1);
|
|
});
|
|
|
|
it('should get object details', async () => {
|
|
const res = await request(app).get('/api/v1/objects/obj-1');
|
|
expect(res.status).toBe(200);
|
|
expect(res.body.id).toBe('obj-1');
|
|
});
|
|
|
|
it('should set baseline images', async () => {
|
|
const res = await request(app)
|
|
.post('/api/v1/objects/obj-1/baseline')
|
|
.send({
|
|
images: [
|
|
{ angle: 'front', imageUrl: 'https://example.com/front.jpg' }
|
|
]
|
|
});
|
|
|
|
expect(res.status).toBe(200);
|
|
});
|
|
});
|
|
|
|
describe('Dashboard', () => {
|
|
it('should get overview', async () => {
|
|
const res = await request(app).get('/api/v1/dashboard/overview');
|
|
expect(res.status).toBe(200);
|
|
expect(res.body).toHaveProperty('summary');
|
|
expect(res.body.summary.totalObjects).toBe(1);
|
|
});
|
|
});
|
|
});
|