test(api): update tests for knex
This commit is contained in:
166
backend/__tests__/api.test.js
Normal file
166
backend/__tests__/api.test.js
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||||
|
import request from 'supertest';
|
||||||
|
import express from 'express';
|
||||||
|
import cors from 'cors';
|
||||||
|
import knex from 'knex';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { dirname, join } from 'path';
|
||||||
|
import { Router } from 'express';
|
||||||
|
import { registerToken, authMiddleware } from '../middleware/auth.js';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
let app;
|
||||||
|
let db;
|
||||||
|
const TEST_TOKEN = 'test-token-12345';
|
||||||
|
|
||||||
|
function createCVRoutes(db) {
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.get('/', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const row = await db('cv_data').where({ id: 1 }).first();
|
||||||
|
if (!row) {
|
||||||
|
return res.status(404).json({ error: 'CV data not found' });
|
||||||
|
}
|
||||||
|
res.json(JSON.parse(row.data));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching CV:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to fetch CV data' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.put('/', authMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const data = req.body;
|
||||||
|
if (!data || typeof data !== 'object') {
|
||||||
|
return res.status(400).json({ error: 'Invalid CV data' });
|
||||||
|
}
|
||||||
|
if (!data.personal?.name) {
|
||||||
|
return res.status(400).json({ error: 'personal.name is required' });
|
||||||
|
}
|
||||||
|
await db('cv_data').where({ id: 1 }).update({
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
updated_at: db.fn.now()
|
||||||
|
});
|
||||||
|
res.json({ success: true, message: 'CV data updated' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating CV:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to update CV data' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/export', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const row = await db('cv_data').where({ id: 1 }).first();
|
||||||
|
if (!row) {
|
||||||
|
return res.status(404).json({ error: 'CV data not found' });
|
||||||
|
}
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
res.setHeader('Content-Disposition', 'attachment; filename="cv.json"');
|
||||||
|
res.send(row.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error exporting CV:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to export CV data' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const testDbPath = join(__dirname, 'test.db');
|
||||||
|
|
||||||
|
db = knex({
|
||||||
|
client: 'better-sqlite3',
|
||||||
|
connection: { filename: testDbPath },
|
||||||
|
useNullAsDefault: true
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.schema.dropTableIfExists('cv_data');
|
||||||
|
await db.schema.createTable('cv_data', (table) => {
|
||||||
|
table.increments('id').primary();
|
||||||
|
table.text('data').notNullable();
|
||||||
|
table.datetime('updated_at').defaultTo(db.fn.now());
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultData = {
|
||||||
|
personal: { name: 'Test User', title: 'Developer', email: 'test@test.com' },
|
||||||
|
experience: [],
|
||||||
|
skills: {},
|
||||||
|
education: [],
|
||||||
|
projects: []
|
||||||
|
};
|
||||||
|
|
||||||
|
await db('cv_data').insert({ id: 1, data: JSON.stringify(defaultData) });
|
||||||
|
|
||||||
|
registerToken(TEST_TOKEN);
|
||||||
|
|
||||||
|
app = express();
|
||||||
|
app.use(cors());
|
||||||
|
app.use(express.json());
|
||||||
|
app.use('/api/cv', createCVRoutes(db));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
if (db) {
|
||||||
|
await db.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('CV API', () => {
|
||||||
|
it('GET /api/cv returns CV data', async () => {
|
||||||
|
const response = await request(app).get('/api/cv');
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
expect(response.body.personal.name).toBe('Test User');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('PUT /api/cv updates CV data', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.put('/api/cv')
|
||||||
|
.set('Authorization', `Bearer ${TEST_TOKEN}`)
|
||||||
|
.send({
|
||||||
|
personal: { name: 'Updated Name', title: 'Dev', email: 'test@test.com' },
|
||||||
|
experience: [],
|
||||||
|
skills: {},
|
||||||
|
education: [],
|
||||||
|
projects: []
|
||||||
|
});
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
expect(response.body.success).toBe(true);
|
||||||
|
|
||||||
|
const getResponse = await request(app).get('/api/cv');
|
||||||
|
expect(getResponse.body.personal.name).toBe('Updated Name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('PUT /api/cv validates required fields', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.put('/api/cv')
|
||||||
|
.set('Authorization', `Bearer ${TEST_TOKEN}`)
|
||||||
|
.send({ personal: {} });
|
||||||
|
expect(response.status).toBe(400);
|
||||||
|
expect(response.body.error).toContain('name is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('PUT /api/cv requires authentication', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.put('/api/cv')
|
||||||
|
.send({
|
||||||
|
personal: { name: 'Test', title: 'Dev', email: 'test@test.com' },
|
||||||
|
experience: [],
|
||||||
|
skills: {},
|
||||||
|
education: [],
|
||||||
|
projects: []
|
||||||
|
});
|
||||||
|
expect(response.status).toBe(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /api/cv/export returns JSON file', async () => {
|
||||||
|
const response = await request(app).get('/api/cv/export');
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
expect(response.headers['content-type']).toContain('application/json');
|
||||||
|
const data = JSON.parse(response.text);
|
||||||
|
expect(data.personal).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user