tududi/backend/tests/integration/inbox.test.js
Chris 10d96397c3
Sorting fixes (#174)
* Update version

* Order Inbox items by creation timestamp, desc

* Fix input keyboard tab and enter handling

* Fix lint issues

* Move in progress items to the top of today list

* Make tags and projects clickable

* fixup! Make tags and projects clickable

* fixup! fixup! Make tags and projects clickable
2025-07-17 17:43:56 +03:00

330 lines
11 KiB
JavaScript

const request = require('supertest');
const app = require('../../app');
const { InboxItem, User } = require('../../models');
const { createTestUser } = require('../helpers/testUtils');
describe('Inbox Routes', () => {
let user, agent;
beforeEach(async () => {
user = await createTestUser({
email: 'test@example.com',
});
// Create authenticated agent
agent = request.agent(app);
await agent.post('/api/login').send({
email: 'test@example.com',
password: 'password123',
});
});
describe('POST /api/inbox', () => {
it('should create a new inbox item', async () => {
const inboxData = {
content: 'Remember to buy groceries',
source: 'web',
};
const response = await agent.post('/api/inbox').send(inboxData);
expect(response.status).toBe(201);
expect(response.body.content).toBe(inboxData.content);
expect(response.body.source).toBe(inboxData.source);
expect(response.body.status).toBe('added');
expect(response.body.user_id).toBe(user.id);
});
it('should require authentication', async () => {
const inboxData = {
content: 'Test content',
};
const response = await request(app)
.post('/api/inbox')
.send(inboxData);
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
it('should require content', async () => {
const inboxData = {};
const response = await agent.post('/api/inbox').send(inboxData);
expect(response.status).toBe(400);
expect(response.body.error).toBe('Content is required');
});
});
describe('GET /api/inbox', () => {
let inboxItem1, inboxItem2;
beforeEach(async () => {
inboxItem1 = await InboxItem.create({
content: 'First item',
status: 'added',
source: 'test',
user_id: user.id,
});
inboxItem2 = await InboxItem.create({
content: 'Second item',
status: 'processed',
source: 'test',
user_id: user.id,
});
});
it('should get all user inbox items', async () => {
const response = await agent.get('/api/inbox');
expect(response.status).toBe(200);
expect(Array.isArray(response.body)).toBe(true);
expect(response.body.length).toBe(1); // Only items with status 'added' are returned
expect(response.body.map((i) => i.id)).toContain(inboxItem1.id);
});
it('should only return items with added status', async () => {
const response = await agent.get('/api/inbox');
expect(response.status).toBe(200);
expect(response.body.length).toBe(1);
expect(response.body[0].id).toBe(inboxItem1.id);
expect(response.body[0].status).toBe('added');
});
it('should return inbox items ordered by created_at DESC (newest first)', async () => {
// Create additional items with slight delay to ensure different timestamps
const item1 = await InboxItem.create({
content: 'First item (oldest)',
status: 'added',
source: 'test',
user_id: user.id,
});
// Small delay to ensure different timestamps
await new Promise((resolve) => setTimeout(resolve, 10));
const item2 = await InboxItem.create({
content: 'Second item',
status: 'added',
source: 'test',
user_id: user.id,
});
await new Promise((resolve) => setTimeout(resolve, 10));
const item3 = await InboxItem.create({
content: 'Third item (newest)',
status: 'added',
source: 'test',
user_id: user.id,
});
const response = await agent.get('/api/inbox');
expect(response.status).toBe(200);
expect(response.body.length).toBe(4); // Including the item from beforeEach
// Check that items are ordered by newest first
expect(response.body[0].id).toBe(item3.id);
expect(response.body[1].id).toBe(item2.id);
expect(response.body[2].id).toBe(item1.id);
// Verify the content matches expected order
expect(response.body[0].content).toBe('Third item (newest)');
expect(response.body[1].content).toBe('Second item');
expect(response.body[2].content).toBe('First item (oldest)');
});
it('should require authentication', async () => {
const response = await request(app).get('/api/inbox');
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
describe('GET /api/inbox/:id', () => {
let inboxItem;
beforeEach(async () => {
inboxItem = await InboxItem.create({
content: 'Test content',
source: 'test',
user_id: user.id,
});
});
it('should get inbox item by id', async () => {
const response = await agent.get(`/api/inbox/${inboxItem.id}`);
expect(response.status).toBe(200);
expect(response.body.id).toBe(inboxItem.id);
expect(response.body.content).toBe(inboxItem.content);
});
it('should return 404 for non-existent inbox item', async () => {
const response = await agent.get('/api/inbox/999999');
expect(response.status).toBe(404);
expect(response.body.error).toBe('Inbox item not found.');
});
it("should not allow access to other user's inbox items", async () => {
const bcrypt = require('bcrypt');
const otherUser = await User.create({
email: 'other@example.com',
password_digest: await bcrypt.hash('password123', 10),
});
const otherInboxItem = await InboxItem.create({
content: 'Other content',
source: 'test',
user_id: otherUser.id,
});
const response = await agent.get(`/api/inbox/${otherInboxItem.id}`);
expect(response.status).toBe(404);
expect(response.body.error).toBe('Inbox item not found.');
});
it('should require authentication', async () => {
const response = await request(app).get(
`/api/inbox/${inboxItem.id}`
);
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
describe('PATCH /api/inbox/:id', () => {
let inboxItem;
beforeEach(async () => {
inboxItem = await InboxItem.create({
content: 'Test content',
status: 'added',
source: 'test',
user_id: user.id,
});
});
it('should update inbox item', async () => {
const updateData = {
content: 'Updated content',
status: 'processed',
};
const response = await agent
.patch(`/api/inbox/${inboxItem.id}`)
.send(updateData);
expect(response.status).toBe(200);
expect(response.body.content).toBe(updateData.content);
expect(response.body.status).toBe(updateData.status);
});
it('should return 404 for non-existent inbox item', async () => {
const response = await agent
.patch('/api/inbox/999999')
.send({ content: 'Updated' });
expect(response.status).toBe(404);
expect(response.body.error).toBe('Inbox item not found.');
});
it('should require authentication', async () => {
const response = await request(app)
.patch(`/api/inbox/${inboxItem.id}`)
.send({ content: 'Updated' });
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
describe('DELETE /api/inbox/:id', () => {
let inboxItem;
beforeEach(async () => {
inboxItem = await InboxItem.create({
content: 'Test content',
source: 'test',
user_id: user.id,
});
});
it('should delete inbox item', async () => {
const response = await agent.delete(`/api/inbox/${inboxItem.id}`);
expect(response.status).toBe(200);
expect(response.body.message).toBe(
'Inbox item successfully deleted'
);
// Verify inbox item status is updated to deleted
const deletedItem = await InboxItem.findByPk(inboxItem.id);
expect(deletedItem).not.toBeNull();
expect(deletedItem.status).toBe('deleted');
});
it('should return 404 for non-existent inbox item', async () => {
const response = await agent.delete('/api/inbox/999999');
expect(response.status).toBe(404);
expect(response.body.error).toBe('Inbox item not found.');
});
it('should require authentication', async () => {
const response = await request(app).delete(
`/api/inbox/${inboxItem.id}`
);
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
describe('PATCH /api/inbox/:id/process', () => {
let inboxItem;
beforeEach(async () => {
inboxItem = await InboxItem.create({
content: 'Test content',
status: 'added',
source: 'test',
user_id: user.id,
});
});
it('should process inbox item', async () => {
const response = await agent.patch(
`/api/inbox/${inboxItem.id}/process`
);
expect(response.status).toBe(200);
expect(response.body.status).toBe('processed');
});
it('should return 404 for non-existent inbox item', async () => {
const response = await agent.patch('/api/inbox/999999/process');
expect(response.status).toBe(404);
expect(response.body.error).toBe('Inbox item not found.');
});
it('should require authentication', async () => {
const response = await request(app).patch(
`/api/inbox/${inboxItem.id}/process`
);
expect(response.status).toBe(401);
expect(response.body.error).toBe('Authentication required');
});
});
});