@@ -8,7 +8,6 @@ describe('InMemoryDriver', () => {
88 beforeEach ( async ( ) => {
99 driver = new InMemoryDriver ( ) ;
1010 await driver . connect ( ) ;
11- // No explicit clear DB method exposed, but new instance is clean.
1211 } ) ;
1312
1413 describe ( 'Lifecycle' , ( ) => {
@@ -86,6 +85,23 @@ describe('InMemoryDriver', () => {
8685 expect ( results ) . toHaveLength ( 1 ) ;
8786 expect ( results [ 0 ] . name ) . toBe ( 'David' ) ;
8887 } ) ;
88+
89+ it ( 'should return a copy of created record (immutability)' , async ( ) => {
90+ const created = await driver . create ( testTable , { id : '1' , name : 'Alice' } ) ;
91+ created . name = 'Modified' ;
92+
93+ const found = await driver . find ( testTable , { object : testTable } ) ;
94+ expect ( found [ 0 ] . name ) . toBe ( 'Alice' ) ;
95+ } ) ;
96+
97+ it ( 'should preserve created_at on update' , async ( ) => {
98+ const created = await driver . create ( testTable , { id : '1' , name : 'Alice' } ) ;
99+ const originalCreatedAt = created . created_at ;
100+
101+ const updated = await driver . update ( testTable , '1' , { name : 'Alice Updated' } ) ;
102+ expect ( updated . created_at ) . toBe ( originalCreatedAt ) ;
103+ expect ( updated . name ) . toBe ( 'Alice Updated' ) ;
104+ } ) ;
89105 } ) ;
90106
91107 describe ( 'Query Capability' , ( ) => {
@@ -116,5 +132,250 @@ describe('InMemoryDriver', () => {
116132
117133 expect ( results ) . toHaveLength ( 2 ) ;
118134 } ) ;
135+
136+ it ( 'should project specific fields' , async ( ) => {
137+ await driver . create ( testTable , { id : '1' , name : 'Alice' , age : 30 , role : 'admin' } ) ;
138+
139+ const results = await driver . find ( testTable , {
140+ fields : [ 'name' , 'age' ] ,
141+ object : testTable ,
142+ } ) ;
143+
144+ expect ( results ) . toHaveLength ( 1 ) ;
145+ expect ( results [ 0 ] . name ) . toBe ( 'Alice' ) ;
146+ expect ( results [ 0 ] . age ) . toBe ( 30 ) ;
147+ expect ( results [ 0 ] . id ) . toBe ( '1' ) ; // id always included
148+ expect ( results [ 0 ] . role ) . toBeUndefined ( ) ;
149+ } ) ;
150+ } ) ;
151+
152+ describe ( 'Initial Data' , ( ) => {
153+ it ( 'should load initial data on connect' , async ( ) => {
154+ const driverWithData = new InMemoryDriver ( {
155+ initialData : {
156+ users : [
157+ { id : '1' , name : 'Alice' } ,
158+ { id : '2' , name : 'Bob' } ,
159+ ] ,
160+ posts : [
161+ { id : '1' , title : 'Hello World' } ,
162+ ] ,
163+ } ,
164+ } ) ;
165+ await driverWithData . connect ( ) ;
166+
167+ const users = await driverWithData . find ( 'users' , { object : 'users' } ) ;
168+ expect ( users ) . toHaveLength ( 2 ) ;
169+ expect ( users [ 0 ] . name ) . toBe ( 'Alice' ) ;
170+
171+ const posts = await driverWithData . find ( 'posts' , { object : 'posts' } ) ;
172+ expect ( posts ) . toHaveLength ( 1 ) ;
173+ } ) ;
174+
175+ it ( 'should generate IDs for initial data without IDs' , async ( ) => {
176+ const driverWithData = new InMemoryDriver ( {
177+ initialData : {
178+ items : [ { name : 'Widget' } ] ,
179+ } ,
180+ } ) ;
181+ await driverWithData . connect ( ) ;
182+
183+ const items = await driverWithData . find ( 'items' , { object : 'items' } ) ;
184+ expect ( items ) . toHaveLength ( 1 ) ;
185+ expect ( items [ 0 ] . id ) . toBeDefined ( ) ;
186+ expect ( typeof items [ 0 ] . id ) . toBe ( 'string' ) ;
187+ } ) ;
188+ } ) ;
189+
190+ describe ( 'Strict Mode' , ( ) => {
191+ it ( 'should throw on update of missing record in strict mode' , async ( ) => {
192+ const strictDriver = new InMemoryDriver ( { strictMode : true } ) ;
193+ await strictDriver . connect ( ) ;
194+
195+ await expect (
196+ strictDriver . update ( testTable , 'non-existent' , { name : 'Test' } )
197+ ) . rejects . toThrow ( 'Record with ID non-existent not found' ) ;
198+ } ) ;
199+
200+ it ( 'should throw on delete of missing record in strict mode' , async ( ) => {
201+ const strictDriver = new InMemoryDriver ( { strictMode : true } ) ;
202+ await strictDriver . connect ( ) ;
203+
204+ await expect (
205+ strictDriver . delete ( testTable , 'non-existent' )
206+ ) . rejects . toThrow ( 'Record with ID non-existent not found' ) ;
207+ } ) ;
208+
209+ it ( 'should return null on update of missing record in default mode' , async ( ) => {
210+ const result = await driver . update ( testTable , 'non-existent' , { name : 'Test' } ) ;
211+ expect ( result ) . toBeNull ( ) ;
212+ } ) ;
213+
214+ it ( 'should return false on delete of missing record in default mode' , async ( ) => {
215+ const result = await driver . delete ( testTable , 'non-existent' ) ;
216+ expect ( result ) . toBe ( false ) ;
217+ } ) ;
218+ } ) ;
219+
220+ describe ( 'Transaction Support' , ( ) => {
221+ it ( 'should begin and commit a transaction' , async ( ) => {
222+ await driver . create ( testTable , { id : '1' , name : 'Alice' } ) ;
223+
224+ const tx = await driver . beginTransaction ( ) ;
225+ await driver . create ( testTable , { id : '2' , name : 'Bob' } ) ;
226+ await driver . commit ( tx ) ;
227+
228+ const results = await driver . find ( testTable , { object : testTable } ) ;
229+ expect ( results ) . toHaveLength ( 2 ) ;
230+ } ) ;
231+
232+ it ( 'should rollback a transaction' , async ( ) => {
233+ await driver . create ( testTable , { id : '1' , name : 'Alice' } ) ;
234+
235+ const tx = await driver . beginTransaction ( ) ;
236+ await driver . create ( testTable , { id : '2' , name : 'Bob' } ) ;
237+
238+ // Verify Bob exists before rollback
239+ let results = await driver . find ( testTable , { object : testTable } ) ;
240+ expect ( results ) . toHaveLength ( 2 ) ;
241+
242+ await driver . rollback ( tx ) ;
243+
244+ // After rollback, Bob should be gone
245+ results = await driver . find ( testTable , { object : testTable } ) ;
246+ expect ( results ) . toHaveLength ( 1 ) ;
247+ expect ( results [ 0 ] . name ) . toBe ( 'Alice' ) ;
248+ } ) ;
249+
250+ it ( 'should handle rollback of updates' , async ( ) => {
251+ await driver . create ( testTable , { id : '1' , name : 'Alice' } ) ;
252+
253+ const tx = await driver . beginTransaction ( ) ;
254+ await driver . update ( testTable , '1' , { name : 'Alice Modified' } ) ;
255+ await driver . rollback ( tx ) ;
256+
257+ const results = await driver . find ( testTable , { object : testTable } ) ;
258+ expect ( results [ 0 ] . name ) . toBe ( 'Alice' ) ;
259+ } ) ;
260+
261+ it ( 'should support capabilities.transactions = true' , ( ) => {
262+ expect ( driver . supports . transactions ) . toBe ( true ) ;
263+ } ) ;
264+ } ) ;
265+
266+ describe ( 'Utility Methods' , ( ) => {
267+ it ( 'should clear all data' , async ( ) => {
268+ await driver . create ( testTable , { id : '1' , name : 'Alice' } ) ;
269+ await driver . create ( 'other_table' , { id : '1' , name : 'Bob' } ) ;
270+
271+ expect ( driver . getSize ( ) ) . toBe ( 2 ) ;
272+
273+ await driver . clear ( ) ;
274+
275+ expect ( driver . getSize ( ) ) . toBe ( 0 ) ;
276+ } ) ;
277+
278+ it ( 'should return correct size' , async ( ) => {
279+ expect ( driver . getSize ( ) ) . toBe ( 0 ) ;
280+
281+ await driver . create ( testTable , { id : '1' } ) ;
282+ expect ( driver . getSize ( ) ) . toBe ( 1 ) ;
283+
284+ await driver . create ( testTable , { id : '2' } ) ;
285+ expect ( driver . getSize ( ) ) . toBe ( 2 ) ;
286+
287+ await driver . create ( 'other' , { id : '1' } ) ;
288+ expect ( driver . getSize ( ) ) . toBe ( 3 ) ;
289+ } ) ;
290+
291+ it ( 'should return distinct values for a field' , async ( ) => {
292+ await driver . create ( testTable , { id : '1' , role : 'admin' } ) ;
293+ await driver . create ( testTable , { id : '2' , role : 'user' } ) ;
294+ await driver . create ( testTable , { id : '3' , role : 'user' } ) ;
295+ await driver . create ( testTable , { id : '4' , role : 'moderator' } ) ;
296+
297+ const roles = await driver . distinct ( testTable , 'role' ) ;
298+ expect ( roles ) . toHaveLength ( 3 ) ;
299+ expect ( roles ) . toContain ( 'admin' ) ;
300+ expect ( roles ) . toContain ( 'user' ) ;
301+ expect ( roles ) . toContain ( 'moderator' ) ;
302+ } ) ;
303+
304+ it ( 'should return distinct values with filter' , async ( ) => {
305+ await driver . create ( testTable , { id : '1' , role : 'admin' , active : true } ) ;
306+ await driver . create ( testTable , { id : '2' , role : 'user' , active : false } ) ;
307+ await driver . create ( testTable , { id : '3' , role : 'user' , active : true } ) ;
308+
309+ const roles = await driver . distinct ( testTable , 'role' , {
310+ object : testTable ,
311+ where : { active : true } ,
312+ } ) ;
313+ expect ( roles ) . toHaveLength ( 2 ) ;
314+ expect ( roles ) . toContain ( 'admin' ) ;
315+ expect ( roles ) . toContain ( 'user' ) ;
316+ } ) ;
317+ } ) ;
318+
319+ describe ( 'Schema Management' , ( ) => {
320+ it ( 'should create table on syncSchema' , async ( ) => {
321+ await driver . syncSchema ( 'new_table' , { } ) ;
322+ const results = await driver . find ( 'new_table' , { object : 'new_table' } ) ;
323+ expect ( results ) . toHaveLength ( 0 ) ;
324+ } ) ;
325+
326+ it ( 'should drop table' , async ( ) => {
327+ await driver . create ( testTable , { id : '1' , name : 'test' } ) ;
328+ await driver . dropTable ( testTable ) ;
329+ const results = await driver . find ( testTable , { object : testTable } ) ;
330+ expect ( results ) . toHaveLength ( 0 ) ;
331+ } ) ;
332+ } ) ;
333+
334+ describe ( 'Bulk Operations' , ( ) => {
335+ it ( 'should bulk create records' , async ( ) => {
336+ const records = [
337+ { name : 'Alice' } ,
338+ { name : 'Bob' } ,
339+ { name : 'Charlie' } ,
340+ ] ;
341+ const results = await driver . bulkCreate ( testTable , records ) ;
342+ expect ( results ) . toHaveLength ( 3 ) ;
343+ expect ( results [ 0 ] . name ) . toBe ( 'Alice' ) ;
344+ expect ( results [ 1 ] . name ) . toBe ( 'Bob' ) ;
345+ } ) ;
346+
347+ it ( 'should count records' , async ( ) => {
348+ await driver . create ( testTable , { id : '1' , role : 'admin' } ) ;
349+ await driver . create ( testTable , { id : '2' , role : 'user' } ) ;
350+ await driver . create ( testTable , { id : '3' , role : 'user' } ) ;
351+
352+ const total = await driver . count ( testTable ) ;
353+ expect ( total ) . toBe ( 3 ) ;
354+
355+ const userCount = await driver . count ( testTable , {
356+ object : testTable ,
357+ where : { role : 'user' } ,
358+ } ) ;
359+ expect ( userCount ) . toBe ( 2 ) ;
360+ } ) ;
361+ } ) ;
362+
363+ describe ( 'ID Generation' , ( ) => {
364+ it ( 'should generate unique counter-based IDs' , async ( ) => {
365+ const r1 = await driver . create ( testTable , { name : 'A' } ) ;
366+ const r2 = await driver . create ( testTable , { name : 'B' } ) ;
367+
368+ expect ( r1 . id ) . toBeDefined ( ) ;
369+ expect ( r2 . id ) . toBeDefined ( ) ;
370+ expect ( r1 . id ) . not . toBe ( r2 . id ) ;
371+ // Counter-based IDs include the table name
372+ expect ( r1 . id ) . toContain ( testTable ) ;
373+ } ) ;
374+ } ) ;
375+
376+ describe ( 'Version' , ( ) => {
377+ it ( 'should report version 1.0.0' , ( ) => {
378+ expect ( driver . version ) . toBe ( '1.0.0' ) ;
379+ } ) ;
119380 } ) ;
120381} ) ;
0 commit comments