@@ -3061,6 +3061,31 @@ public function testFindNotContains(): void
30613061
30623062 $ this ->assertEquals (6 , count ($ documents ));
30633063
3064+ // Test notContains with string attribute (substring search)
3065+ $ documents = $ database ->find ('movies ' , [
3066+ Query::notContains ('name ' , ['Captain ' ])
3067+ ]);
3068+ $ this ->assertEquals (4 , count ($ documents )); // All movies except those containing 'Captain'
3069+
3070+ // Test notContains with empty array - should return all documents
3071+ $ documents = $ database ->find ('movies ' , [
3072+ Query::notContains ('genres ' , [])
3073+ ]);
3074+ $ this ->assertEquals (6 , count ($ documents )); // All movies since no values to exclude
3075+
3076+ // Test notContains combined with other queries (AND logic)
3077+ $ documents = $ database ->find ('movies ' , [
3078+ Query::notContains ('genres ' , ['comics ' ]),
3079+ Query::greaterThan ('year ' , 2000 )
3080+ ]);
3081+ $ this ->assertLessThanOrEqual (4 , count ($ documents )); // Subset of movies without 'comics' and after 2000
3082+
3083+ // Test notContains with case sensitivity
3084+ $ documents = $ database ->find ('movies ' , [
3085+ Query::notContains ('genres ' , ['COMICS ' ]) // Different case
3086+ ]);
3087+ $ this ->assertEquals (6 , count ($ documents )); // All movies since case doesn't match
3088+
30643089 // Test error handling for invalid attribute type
30653090 try {
30663091 $ database ->find ('movies ' , [
@@ -3112,6 +3137,25 @@ public function testFindNotSearch(): void
31123137
31133138 $ this ->assertEquals (4 , count ($ documents )); // All movies except those matching 'cap'
31143139 }
3140+
3141+ // Test notSearch with empty string - should return all documents
3142+ $ documents = $ database ->find ('movies ' , [
3143+ Query::notSearch ('name ' , '' ),
3144+ ]);
3145+ $ this ->assertEquals (6 , count ($ documents )); // All movies since empty search matches nothing
3146+
3147+ // Test notSearch combined with other filters
3148+ $ documents = $ database ->find ('movies ' , [
3149+ Query::notSearch ('name ' , 'captain ' ),
3150+ Query::lessThan ('year ' , 2010 )
3151+ ]);
3152+ $ this ->assertLessThanOrEqual (4 , count ($ documents )); // Subset of non-captain movies before 2010
3153+
3154+ // Test notSearch with special characters
3155+ $ documents = $ database ->find ('movies ' , [
3156+ Query::notSearch ('name ' , '@#$% ' ),
3157+ ]);
3158+ $ this ->assertEquals (6 , count ($ documents )); // All movies since special chars don't match
31153159 }
31163160
31173161 $ this ->assertEquals (true , true ); // Test must do an assertion
@@ -3148,6 +3192,31 @@ public function testFindNotStartsWith(): void
31483192 }
31493193
31503194 $ this ->assertEquals (6 , count ($ documents )); // Should return all since no movie starts with these patterns
3195+
3196+ // Test notStartsWith with empty string - should return no documents (all strings start with empty)
3197+ $ documents = $ database ->find ('movies ' , [
3198+ Query::notStartsWith ('name ' , '' ),
3199+ ]);
3200+ $ this ->assertEquals (0 , count ($ documents )); // No documents since all strings start with empty string
3201+
3202+ // Test notStartsWith with single character
3203+ $ documents = $ database ->find ('movies ' , [
3204+ Query::notStartsWith ('name ' , 'C ' ),
3205+ ]);
3206+ $ this ->assertGreaterThanOrEqual (4 , count ($ documents )); // Movies not starting with 'C'
3207+
3208+ // Test notStartsWith with case sensitivity
3209+ $ documents = $ database ->find ('movies ' , [
3210+ Query::notStartsWith ('name ' , 'work ' ), // lowercase vs 'Work'
3211+ ]);
3212+ $ this ->assertEquals (6 , count ($ documents )); // All movies since case doesn't match
3213+
3214+ // Test notStartsWith combined with other queries
3215+ $ documents = $ database ->find ('movies ' , [
3216+ Query::notStartsWith ('name ' , 'Work ' ),
3217+ Query::equal ('year ' , 2006 )
3218+ ]);
3219+ $ this ->assertLessThanOrEqual (4 , count ($ documents )); // Subset of non-Work movies from 2006
31513220 }
31523221
31533222 public function testFindNotEndsWith (): void
@@ -3175,6 +3244,32 @@ public function testFindNotEndsWith(): void
31753244 ]);
31763245
31773246 $ this ->assertEquals (5 , count ($ documents )); // All movies except the 1 ending with 'vel' (from 'Marvel')
3247+
3248+ // Test notEndsWith with empty string - should return no documents (all strings end with empty)
3249+ $ documents = $ database ->find ('movies ' , [
3250+ Query::notEndsWith ('name ' , '' ),
3251+ ]);
3252+ $ this ->assertEquals (0 , count ($ documents )); // No documents since all strings end with empty string
3253+
3254+ // Test notEndsWith with single character
3255+ $ documents = $ database ->find ('movies ' , [
3256+ Query::notEndsWith ('name ' , 'l ' ),
3257+ ]);
3258+ $ this ->assertGreaterThanOrEqual (5 , count ($ documents )); // Movies not ending with 'l'
3259+
3260+ // Test notEndsWith with case sensitivity
3261+ $ documents = $ database ->find ('movies ' , [
3262+ Query::notEndsWith ('name ' , 'marvel ' ), // lowercase vs 'Marvel'
3263+ ]);
3264+ $ this ->assertEquals (6 , count ($ documents )); // All movies since case doesn't match
3265+
3266+ // Test notEndsWith combined with limit
3267+ $ documents = $ database ->find ('movies ' , [
3268+ Query::notEndsWith ('name ' , 'Marvel ' ),
3269+ Query::limit (3 )
3270+ ]);
3271+ $ this ->assertEquals (3 , count ($ documents )); // Limited to 3 results
3272+ $ this ->assertLessThanOrEqual (5 , count ($ documents )); // But still excluding Marvel movies
31783273 }
31793274
31803275 public function testFindNotBetween (): void
@@ -3211,6 +3306,44 @@ public function testFindNotBetween(): void
32113306 Query::notBetween ('$updatedAt ' , '2000-01-01T00:00:00.000+00:00 ' , '2001-01-01T00:00:00.000+00:00 ' ),
32123307 ]);
32133308 $ this ->assertEquals (6 , count ($ documents )); // All movies should be outside this narrow range
3309+
3310+ // Test notBetween with year range (integer values)
3311+ $ documents = $ database ->find ('movies ' , [
3312+ Query::notBetween ('year ' , 2005 , 2007 ),
3313+ ]);
3314+ $ this ->assertLessThanOrEqual (6 , count ($ documents )); // Movies outside 2005-2007 range
3315+
3316+ // Test notBetween with reversed range (start > end) - should still work
3317+ $ documents = $ database ->find ('movies ' , [
3318+ Query::notBetween ('price ' , 25.99 , 25.94 ), // Note: reversed order
3319+ ]);
3320+ $ this ->assertGreaterThanOrEqual (4 , count ($ documents )); // Should handle reversed range gracefully
3321+
3322+ // Test notBetween with same start and end values
3323+ $ documents = $ database ->find ('movies ' , [
3324+ Query::notBetween ('year ' , 2006 , 2006 ),
3325+ ]);
3326+ $ this ->assertGreaterThanOrEqual (5 , count ($ documents )); // All movies except those from exactly 2006
3327+
3328+ // Test notBetween combined with other filters
3329+ $ documents = $ database ->find ('movies ' , [
3330+ Query::notBetween ('price ' , 25.94 , 25.99 ),
3331+ Query::orderDesc ('year ' ),
3332+ Query::limit (2 )
3333+ ]);
3334+ $ this ->assertEquals (2 , count ($ documents )); // Limited results, ordered, excluding price range
3335+
3336+ // Test notBetween with extreme ranges
3337+ $ documents = $ database ->find ('movies ' , [
3338+ Query::notBetween ('year ' , -1000 , 1000 ), // Very wide range
3339+ ]);
3340+ $ this ->assertLessThanOrEqual (6 , count ($ documents )); // Movies outside this range
3341+
3342+ // Test notBetween with float precision
3343+ $ documents = $ database ->find ('movies ' , [
3344+ Query::notBetween ('price ' , 25.945 , 25.955 ), // Very narrow range
3345+ ]);
3346+ $ this ->assertGreaterThanOrEqual (4 , count ($ documents )); // Most movies should be outside this narrow range
32143347 }
32153348
32163349 public function testFindSelect (): void
0 commit comments