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+ } ) ;
0 commit comments