114 lines
3.5 KiB
JavaScript
114 lines
3.5 KiB
JavaScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
const { mockQuery } = vi.hoisted(() => ({
|
|
mockQuery: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('../db/index.js', () => ({
|
|
query: mockQuery,
|
|
}));
|
|
|
|
import { getAllNotes, getNoteById, createNote, createNotes } from '../db/notes.dao.js';
|
|
|
|
const MOCK_ROWS = [
|
|
{ id: 'note_001', text: 'Login flow feels confusing', x: 193, y: 191, author: 'user_5', color: 'yellow' },
|
|
{ id: 'note_002', text: 'Login flow is broken on mobile', x: 214, y: 281, author: 'user_9', color: 'yellow' },
|
|
];
|
|
|
|
describe('notes.dao', () => {
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('getAllNotes', () => {
|
|
it('should return all notes ordered by id', async () => {
|
|
mockQuery.mockResolvedValue({ rows: MOCK_ROWS });
|
|
|
|
const result = await getAllNotes();
|
|
|
|
expect(result).toEqual(MOCK_ROWS);
|
|
expect(mockQuery).toHaveBeenCalledWith(
|
|
'SELECT id, text, x, y, author, color FROM notes ORDER BY id'
|
|
);
|
|
});
|
|
|
|
it('should return an empty array when no notes exist', async () => {
|
|
mockQuery.mockResolvedValue({ rows: [] });
|
|
|
|
const result = await getAllNotes();
|
|
|
|
expect(result).toEqual([]);
|
|
});
|
|
|
|
it('should propagate database errors', async () => {
|
|
mockQuery.mockRejectedValue(new Error('connection refused'));
|
|
|
|
await expect(getAllNotes()).rejects.toThrow('connection refused');
|
|
});
|
|
});
|
|
|
|
describe('getNoteById', () => {
|
|
it('should return a single note when found', async () => {
|
|
mockQuery.mockResolvedValue({ rows: [MOCK_ROWS[0]] });
|
|
|
|
const result = await getNoteById('note_001');
|
|
|
|
expect(result).toEqual(MOCK_ROWS[0]);
|
|
expect(mockQuery).toHaveBeenCalledWith(
|
|
'SELECT id, text, x, y, author, color FROM notes WHERE id = $1',
|
|
['note_001']
|
|
);
|
|
});
|
|
|
|
it('should return null when note is not found', async () => {
|
|
mockQuery.mockResolvedValue({ rows: [] });
|
|
|
|
const result = await getNoteById('note_999');
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('createNote', () => {
|
|
it('should insert a note and return it', async () => {
|
|
const input = { id: 'note_003', text: 'Export fails', x: 100, y: 200, author: 'user_1', color: 'blue' };
|
|
mockQuery.mockResolvedValue({ rows: [input] });
|
|
|
|
const result = await createNote(input);
|
|
|
|
expect(result).toEqual(input);
|
|
expect(mockQuery).toHaveBeenCalledOnce();
|
|
const [sql, params] = mockQuery.mock.calls[0];
|
|
expect(sql).toContain('INSERT INTO notes');
|
|
expect(params).toEqual(['note_003', 'Export fails', 100, 200, 'user_1', 'blue']);
|
|
});
|
|
|
|
it('should use defaults for missing x, y, and color', async () => {
|
|
const input = { id: 'note_004', text: 'Needs fixing', author: 'user_2' };
|
|
mockQuery.mockResolvedValue({ rows: [{ ...input, x: 0, y: 0, color: 'yellow' }] });
|
|
|
|
await createNote(input);
|
|
|
|
const params = mockQuery.mock.calls[0][1];
|
|
expect(params[2]).toBe(0);
|
|
expect(params[3]).toBe(0);
|
|
expect(params[5]).toBe('yellow');
|
|
});
|
|
});
|
|
|
|
describe('createNotes', () => {
|
|
it('should batch-insert multiple notes and return them', async () => {
|
|
mockQuery.mockResolvedValue({ rows: MOCK_ROWS });
|
|
|
|
const result = await createNotes(MOCK_ROWS);
|
|
|
|
expect(result).toEqual(MOCK_ROWS);
|
|
expect(mockQuery).toHaveBeenCalledOnce();
|
|
const [sql, params] = mockQuery.mock.calls[0];
|
|
expect(sql).toContain('INSERT INTO notes');
|
|
expect(params).toHaveLength(12);
|
|
});
|
|
});
|
|
});
|