@@ -241,6 +241,182 @@ public function testAllWithNonExistentTable(): void
241241 $ this ->assertEquals ('------ ' , $ result [0 ]->description );
242242 }
243243
244+ public function testFieldNameValidation (): void
245+ {
246+ // Crear almacenes de prueba con códigos válidos (1-4 caracteres) en mayúsculas y nombres con mayúsculas/minúsculas
247+ $ almacen1 = $ this ->getRandomWarehouse ();
248+ $ almacen1 ->codalmacen = 'TST1 ' ;
249+ $ almacen1 ->nombre = 'Almacen Principal ' ;
250+ $ this ->assertTrue ($ almacen1 ->save ());
251+
252+ $ almacen2 = $ this ->getRandomWarehouse ();
253+ $ almacen2 ->codalmacen = 'TST2 ' ;
254+ $ almacen2 ->nombre = 'Almacen Secundario ' ;
255+ $ this ->assertTrue ($ almacen2 ->save ());
256+
257+ // Test con campos normales - el código debe estar en mayúsculas como se guardó
258+ $ result = CodeModel::all ('almacenes ' , 'codalmacen ' , 'nombre ' , false );
259+ $ this ->assertIsArray ($ result );
260+ $ found = false ;
261+ foreach ($ result as $ item ) {
262+ if ($ item ->code === 'TST1 ' ) {
263+ $ this ->assertEquals ('Almacen Principal ' , $ item ->description );
264+ $ found = true ;
265+ break ;
266+ }
267+ }
268+ $ this ->assertTrue ($ found , 'No se encontró el almacén TST1 ' );
269+
270+ // Test con lower() en fieldCode - el código debe estar en minúsculas
271+ $ result = CodeModel::all ('almacenes ' , 'lower(codalmacen) ' , 'nombre ' , false );
272+ $ this ->assertIsArray ($ result );
273+ $ found = false ;
274+ foreach ($ result as $ item ) {
275+ if ($ item ->code === 'tst1 ' ) {
276+ $ this ->assertEquals ('Almacen Principal ' , $ item ->description );
277+ // Verificar que NO está en mayúsculas
278+ $ this ->assertNotEquals ('TST1 ' , $ item ->code );
279+ $ found = true ;
280+ break ;
281+ }
282+ }
283+ $ this ->assertTrue ($ found , 'No se encontró el código en minúsculas tst1 ' );
284+
285+ // Test con upper() en fieldCode - el código debe estar en mayúsculas
286+ $ result = CodeModel::all ('almacenes ' , 'upper(codalmacen) ' , 'nombre ' , false );
287+ $ this ->assertIsArray ($ result );
288+ $ found = false ;
289+ foreach ($ result as $ item ) {
290+ if ($ item ->code === 'TST1 ' ) {
291+ $ this ->assertEquals ('Almacen Principal ' , $ item ->description );
292+ $ found = true ;
293+ break ;
294+ }
295+ }
296+ $ this ->assertTrue ($ found , 'No se encontró el código en mayúsculas TST1 ' );
297+
298+ // Test con LOWER() en mayúsculas (case-insensitive) - debe funcionar igual
299+ $ result = CodeModel::all ('almacenes ' , 'LOWER(codalmacen) ' , 'nombre ' , false );
300+ $ this ->assertIsArray ($ result );
301+ $ found = false ;
302+ foreach ($ result as $ item ) {
303+ if ($ item ->code === 'tst2 ' ) {
304+ $ this ->assertEquals ('Almacen Secundario ' , $ item ->description );
305+ $ found = true ;
306+ break ;
307+ }
308+ }
309+ $ this ->assertTrue ($ found , 'LOWER() no funcionó correctamente ' );
310+
311+ // Test con lower() en fieldDescription - la descripción debe estar en minúsculas
312+ $ result = CodeModel::all ('almacenes ' , 'codalmacen ' , 'lower(nombre) ' , false );
313+ $ this ->assertIsArray ($ result );
314+ $ found = false ;
315+ foreach ($ result as $ item ) {
316+ if ($ item ->code === 'TST1 ' ) {
317+ $ this ->assertEquals ('almacen principal ' , $ item ->description );
318+ // Verificar que NO tiene mayúsculas
319+ $ this ->assertNotEquals ('Almacen Principal ' , $ item ->description );
320+ $ found = true ;
321+ break ;
322+ }
323+ }
324+ $ this ->assertTrue ($ found , 'No se encontró la descripción en minúsculas ' );
325+
326+ // Test con upper() en fieldDescription - la descripción debe estar en mayúsculas
327+ $ result = CodeModel::all ('almacenes ' , 'codalmacen ' , 'upper(nombre) ' , false );
328+ $ this ->assertIsArray ($ result );
329+ $ found = false ;
330+ foreach ($ result as $ item ) {
331+ if ($ item ->code === 'TST2 ' ) {
332+ $ this ->assertEquals ('ALMACEN SECUNDARIO ' , $ item ->description );
333+ // Verificar que NO tiene minúsculas
334+ $ this ->assertNotEquals ('Almacen Secundario ' , $ item ->description );
335+ $ found = true ;
336+ break ;
337+ }
338+ }
339+ $ this ->assertTrue ($ found , 'No se encontró la descripción en mayúsculas ' );
340+
341+ // Test con lower() en ambos campos
342+ $ result = CodeModel::all ('almacenes ' , 'lower(codalmacen) ' , 'lower(nombre) ' , false );
343+ $ this ->assertIsArray ($ result );
344+ $ found = false ;
345+ foreach ($ result as $ item ) {
346+ if ($ item ->code === 'tst1 ' ) {
347+ $ this ->assertEquals ('almacen principal ' , $ item ->description );
348+ $ found = true ;
349+ break ;
350+ }
351+ }
352+ $ this ->assertTrue ($ found , 'No funcionó lower() en ambos campos ' );
353+
354+ // Test con upper() en ambos campos
355+ $ result = CodeModel::all ('almacenes ' , 'upper(codalmacen) ' , 'upper(nombre) ' , false );
356+ $ this ->assertIsArray ($ result );
357+ $ found = false ;
358+ foreach ($ result as $ item ) {
359+ if ($ item ->code === 'TST2 ' ) {
360+ $ this ->assertEquals ('ALMACEN SECUNDARIO ' , $ item ->description );
361+ $ found = true ;
362+ break ;
363+ }
364+ }
365+ $ this ->assertTrue ($ found , 'No funcionó upper() en ambos campos ' );
366+
367+ // Test con campo de tabla con punto
368+ $ result = CodeModel::all ('almacenes ' , 'almacenes.codalmacen ' , 'almacenes.nombre ' , false );
369+ $ this ->assertIsArray ($ result );
370+ $ found = false ;
371+ foreach ($ result as $ item ) {
372+ if ($ item ->code === 'TST1 ' ) {
373+ $ found = true ;
374+ break ;
375+ }
376+ }
377+ $ this ->assertTrue ($ found , 'No funcionó con tabla.campo ' );
378+
379+ // Test con lower() y tabla.campo
380+ $ result = CodeModel::all ('almacenes ' , 'lower(almacenes.codalmacen) ' , 'nombre ' , false );
381+ $ this ->assertIsArray ($ result );
382+ $ found = false ;
383+ foreach ($ result as $ item ) {
384+ if ($ item ->code === 'tst1 ' ) {
385+ $ found = true ;
386+ break ;
387+ }
388+ }
389+ $ this ->assertTrue ($ found , 'No funcionó lower() con tabla.campo ' );
390+
391+ // Test con función no permitida concat() - debe fallar
392+ $ result = CodeModel::all ('almacenes ' , 'concat(codalmacen, nombre) ' , 'nombre ' , true );
393+ $ this ->assertIsArray ($ result );
394+ $ this ->assertCount (1 , $ result ); // Solo debe retornar el elemento vacío
395+ $ this ->assertNull ($ result [0 ]->code );
396+
397+ // Test con función no permitida substring() - debe fallar
398+ $ result = CodeModel::all ('almacenes ' , 'codalmacen ' , 'substring(nombre, 1, 10) ' , true );
399+ $ this ->assertIsArray ($ result );
400+ $ this ->assertCount (1 , $ result ); // Solo debe retornar el elemento vacío
401+ $ this ->assertNull ($ result [0 ]->code );
402+
403+ // Test con intento de SQL injection - debe fallar
404+ $ result = CodeModel::all ('almacenes ' , 'codalmacen; DROP TABLE almacenes-- ' , 'nombre ' , true );
405+ $ this ->assertIsArray ($ result );
406+ $ this ->assertCount (1 , $ result ); // Solo debe retornar el elemento vacío
407+ $ this ->assertNull ($ result [0 ]->code );
408+
409+ // Test con caracteres especiales no permitidos - debe fallar
410+ $ result = CodeModel::all ('almacenes ' , 'codalmacen OR 1=1 ' , 'nombre ' , true );
411+ $ this ->assertIsArray ($ result );
412+ $ this ->assertCount (1 , $ result ); // Solo debe retornar el elemento vacío
413+ $ this ->assertNull ($ result [0 ]->code );
414+
415+ // Limpiar datos de prueba
416+ $ this ->assertTrue ($ almacen1 ->delete ());
417+ $ this ->assertTrue ($ almacen2 ->delete ());
418+ }
419+
244420 protected function tearDown (): void
245421 {
246422 $ this ->logErrors ();
0 commit comments