Skip to content

Commit ed5982d

Browse files
committed
Add integration tests for MongoDbNoteRepository and update Jest configuration
- Added integration tests with MongoDB container for CRUD operations. - Adjusted coverage thresholds in Jest configuration to reflect increased test coverage. - Refactored MongoDbNoteRepository initialization logic for better clarity.
1 parent 5d40396 commit ed5982d

3 files changed

Lines changed: 180 additions & 7 deletions

File tree

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import {GenericContainer} from 'testcontainers';
2+
import {MongoDbNoteRepository} from '../../src/db/mongodb-note-repository.js';
3+
import {Note} from '../../src/models/note.js';
4+
5+
describe('MongoDbNoteRepository Integration Tests', () => {
6+
let container;
7+
let repository;
8+
const DB_NAME = 'notes_test';
9+
10+
beforeAll(async () => {
11+
console.log('Starting MongoDB container...');
12+
// Start MongoDB container
13+
container = await new GenericContainer('mongo:7.0.20-jammy')
14+
.withExposedPorts(27017)
15+
.withEnvironment({
16+
MONGO_INITDB_ROOT_USERNAME: 'admin',
17+
MONGO_INITDB_ROOT_PASSWORD: 'password'
18+
})
19+
.start();
20+
21+
// Create repository instance
22+
const port = container.getMappedPort(27017);
23+
console.log(`MongoDB container started on port ${port}`);
24+
// 2. Construct a URL with authSource but WITHOUT the database name in the path
25+
// 3. Instantiate and initialize your repository
26+
repository = new MongoDbNoteRepository(
27+
`mongodb://admin:password@localhost:${port}/?authSource=admin`,
28+
DB_NAME
29+
);
30+
31+
// Initialize the database
32+
console.log('Initializing database...');
33+
await repository.init();
34+
console.log('Database initialized successfully');
35+
}, 60000); // Increase timeout for container startup
36+
37+
afterAll(async () => {
38+
console.log('Stopping MongoDB container...');
39+
if (container) {
40+
await container.stop();
41+
console.log('MongoDB container stopped');
42+
}
43+
});
44+
45+
beforeEach(async () => {
46+
try {
47+
const notes = await repository.findAll();
48+
console.log('Cleaning up notes:', notes);
49+
for (const note of notes) {
50+
console.log(`Deleting note ${note.id}...`);
51+
await repository.delete(note.id);
52+
}
53+
console.log('Cleanup completed');
54+
} catch (error) {
55+
console.error('Error during cleanup:', error);
56+
}
57+
});
58+
59+
describe('CRUD Operations', () => {
60+
it('should create and retrieve a note', async () => {
61+
console.log('\nTest: should create and retrieve a note');
62+
const noteData = {
63+
title: 'Test Note',
64+
content: 'Test Content'
65+
};
66+
67+
console.log('Creating note:', noteData);
68+
const createdNote = await repository.create(noteData);
69+
console.log('Created note:', createdNote);
70+
expect(createdNote).toBeInstanceOf(Note);
71+
expect(createdNote.title).toBe(noteData.title);
72+
expect(createdNote.content).toBe(noteData.content);
73+
expect(createdNote.id).toBeDefined();
74+
75+
console.log('Retrieving created note...');
76+
const retrievedNote = await repository.findById(createdNote.id);
77+
console.log('Retrieved note:', retrievedNote);
78+
expect(retrievedNote).toBeInstanceOf(Note);
79+
expect(retrievedNote.id).toBe(createdNote.id);
80+
expect(retrievedNote.title).toBe(noteData.title);
81+
expect(retrievedNote.content).toBe(noteData.content);
82+
});
83+
84+
it('should update a note', async () => {
85+
console.log('\nTest: should update a note');
86+
// Create initial note
87+
const note = await repository.create({
88+
title: 'Original Title',
89+
content: 'Original Content'
90+
});
91+
console.log('Created initial note:', note);
92+
93+
console.log('Verifying initial note...');
94+
const initialNote = await repository.findById(note.id);
95+
console.log('Initial note verified:', initialNote);
96+
expect(initialNote).not.toBeNull();
97+
98+
const updatedData = {
99+
title: 'Updated Title',
100+
content: 'Updated Content'
101+
};
102+
103+
console.log('Updating note with:', updatedData);
104+
const updatedNote = await repository.update(note.id, updatedData);
105+
console.log('Updated note:', updatedNote);
106+
expect(updatedNote).toBeInstanceOf(Note);
107+
expect(updatedNote.id).toBe(note.id);
108+
expect(updatedNote.title).toBe(updatedData.title);
109+
expect(updatedNote.content).toBe(updatedData.content);
110+
111+
console.log('Verifying updated note...');
112+
const retrievedNote = await repository.findById(note.id);
113+
console.log('Retrieved updated note:', retrievedNote);
114+
expect(retrievedNote).not.toBeNull();
115+
expect(retrievedNote.title).toBe(updatedData.title);
116+
expect(retrievedNote.content).toBe(updatedData.content);
117+
});
118+
119+
it('should delete a note', async () => {
120+
console.log('\nTest: should delete a note');
121+
const note = await repository.create({
122+
title: 'To Delete',
123+
content: 'Will be deleted'
124+
});
125+
console.log('Created note to delete:', note);
126+
127+
console.log('Verifying note exists...');
128+
const initialNote = await repository.findById(note.id);
129+
console.log('Initial note verified:', initialNote);
130+
expect(initialNote).not.toBeNull();
131+
132+
console.log('Deleting note...');
133+
const deleteResult = await repository.delete(note.id);
134+
console.log('Delete result:', deleteResult);
135+
expect(deleteResult).toBe(true);
136+
137+
// Verify note is deleted
138+
const deletedNote = await repository.findById(note.id);
139+
expect(deletedNote).toBeNull();
140+
});
141+
142+
it('should list all notes', async () => {
143+
console.log('\nTest: should list all notes');
144+
const notes = [
145+
{title: 'Note 1', content: 'Content 1'},
146+
{title: 'Note 2', content: 'Content 2'},
147+
{title: 'Note 3', content: 'Content 3'}
148+
];
149+
150+
// Create notes sequentially
151+
for (const noteData of notes) {
152+
console.log('Creating note:', noteData);
153+
const created = await repository.create(noteData);
154+
console.log('Created note:', created);
155+
await repository.findById(created.id);
156+
}
157+
158+
// Wait for all notes to be available
159+
console.log('Retrieving all notes...');
160+
const allNotes = await repository.findAll();
161+
console.log('All notes found:', allNotes);
162+
163+
expect(allNotes).toHaveLength(3);
164+
expect(allNotes.every(note => note instanceof Note)).toBe(true);
165+
expect(allNotes.map(note => note.title)).toEqual(
166+
expect.arrayContaining(notes.map(note => note.title))
167+
);
168+
});
169+
});
170+
});

jest.config.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ export default {
1414
coverageDirectory: "coverage",
1515
coverageThreshold: {
1616
global: {
17-
branches: 36,
18-
functions: 45,
19-
lines: 39,
20-
statements: 39
17+
branches: 42,
18+
functions: 64,
19+
lines: 52,
20+
statements: 52
2121
}
2222
},
2323
verbose: true

src/db/mongodb-note-repository.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@ export class MongoDbNoteRepository extends NoteRepository {
2424
*/
2525
async init() {
2626
try {
27-
// Connect to MongoDB
28-
await mongoose.connect(`${this.url}/${this.dbName}`);
29-
console.log('Connected to MongoDB');
27+
// Connect to MongoDB using the provided URL and database name
28+
await mongoose.connect(this.url, { dbName: this.dbName });
29+
// const connectionUrl = this.url.endsWith('/') ? this.url + this.dbName : this.url + '/' + this.dbName;
30+
// await mongoose.connect(connectionUrl);
31+
// await mongoose.connect(`${this.url}/${this.dbName}`);
32+
console.log(`Connected to MongoDB database: ${this.dbName}`);
3033

3134
// Define the schema if it doesn't exist
3235
if (!this.NoteModel) {

0 commit comments

Comments
 (0)