@@ -1355,4 +1355,157 @@ describe('TranslateCommand', () => {
13551355 expect ( mockFs . readFileSync ) . toHaveBeenCalledWith ( '/path/to/unicode.txt' , 'utf-8' ) ;
13561356 } ) ;
13571357 } ) ;
1358+
1359+ describe ( 'isFilePath() - cross-platform path detection (Issue #4)' , ( ) => {
1360+ it ( 'should detect Windows paths with backslashes (C:\\Users\\file.txt)' , async ( ) => {
1361+ const fs = jest . requireActual ( 'fs' ) ;
1362+ jest . spyOn ( fs , 'existsSync' ) . mockReturnValue ( false ) ;
1363+
1364+ // Access the private isFilePath method via translate()
1365+ // Windows path should be detected as file path
1366+ const spy = jest . spyOn ( translateCommand as any , 'translateFile' )
1367+ . mockResolvedValue ( 'File translation result' ) ;
1368+
1369+ // Mock fileTranslationService.isSupportedFile to return true for .txt
1370+ const mockFileService = ( translateCommand as any ) . fileTranslationService ;
1371+ jest . spyOn ( mockFileService , 'isSupportedFile' ) . mockReturnValue ( true ) ;
1372+
1373+ await translateCommand . translate ( 'C:\\Users\\Documents\\file.txt' , {
1374+ to : 'es' ,
1375+ output : '/out.txt' ,
1376+ } ) ;
1377+
1378+ expect ( spy ) . toHaveBeenCalledWith ( 'C:\\Users\\Documents\\file.txt' , { to : 'es' , output : '/out.txt' } ) ;
1379+ spy . mockRestore ( ) ;
1380+ } ) ;
1381+
1382+ it ( 'should detect Unix paths with forward slashes (/home/user/file.txt)' , async ( ) => {
1383+ const fs = jest . requireActual ( 'fs' ) ;
1384+ jest . spyOn ( fs , 'existsSync' ) . mockReturnValue ( false ) ;
1385+
1386+ const spy = jest . spyOn ( translateCommand as any , 'translateFile' )
1387+ . mockResolvedValue ( 'File translation result' ) ;
1388+
1389+ const mockFileService = ( translateCommand as any ) . fileTranslationService ;
1390+ jest . spyOn ( mockFileService , 'isSupportedFile' ) . mockReturnValue ( true ) ;
1391+
1392+ await translateCommand . translate ( '/home/user/documents/file.txt' , {
1393+ to : 'es' ,
1394+ output : '/out.txt' ,
1395+ } ) ;
1396+
1397+ expect ( spy ) . toHaveBeenCalledWith ( '/home/user/documents/file.txt' , { to : 'es' , output : '/out.txt' } ) ;
1398+ spy . mockRestore ( ) ;
1399+ } ) ;
1400+
1401+ it ( 'should NOT treat URLs as file paths (http://example.com/file.txt)' , async ( ) => {
1402+ const fs = jest . requireActual ( 'fs' ) ;
1403+ jest . spyOn ( fs , 'existsSync' ) . mockReturnValue ( false ) ;
1404+
1405+ const mockFileService = ( translateCommand as any ) . fileTranslationService ;
1406+ jest . spyOn ( mockFileService , 'isSupportedFile' ) . mockReturnValue ( true ) ;
1407+
1408+ ( mockTranslationService . translate as jest . Mock ) . mockResolvedValueOnce ( {
1409+ text : 'Texto traducido' ,
1410+ } ) ;
1411+
1412+ // URL should be treated as text, not file path
1413+ await translateCommand . translate ( 'http://example.com/file.txt' , {
1414+ to : 'es' ,
1415+ } ) ;
1416+
1417+ // Should call translateText, NOT translateFile
1418+ expect ( mockTranslationService . translate ) . toHaveBeenCalledWith (
1419+ 'http://example.com/file.txt' ,
1420+ expect . any ( Object ) ,
1421+ expect . any ( Object )
1422+ ) ;
1423+ } ) ;
1424+
1425+ it ( 'should NOT treat text containing "/" as file path' , async ( ) => {
1426+ const fs = jest . requireActual ( 'fs' ) ;
1427+ jest . spyOn ( fs , 'existsSync' ) . mockReturnValue ( false ) ;
1428+
1429+ const mockFileService = ( translateCommand as any ) . fileTranslationService ;
1430+ jest . spyOn ( mockFileService , 'isSupportedFile' ) . mockReturnValue ( false ) ;
1431+
1432+ ( mockTranslationService . translate as jest . Mock ) . mockResolvedValueOnce ( {
1433+ text : 'Texto traducido' ,
1434+ } ) ;
1435+
1436+ // Text with / should be treated as text, not file path
1437+ await translateCommand . translate ( 'Check https://example.com for details' , {
1438+ to : 'es' ,
1439+ } ) ;
1440+
1441+ // Should call translateText, NOT translateFile
1442+ expect ( mockTranslationService . translate ) . toHaveBeenCalledWith (
1443+ 'Check https://example.com for details' ,
1444+ expect . any ( Object ) ,
1445+ expect . any ( Object )
1446+ ) ;
1447+ } ) ;
1448+
1449+ it ( 'should detect relative Windows paths (folder\\file.txt)' , async ( ) => {
1450+ const fs = jest . requireActual ( 'fs' ) ;
1451+ jest . spyOn ( fs , 'existsSync' ) . mockReturnValue ( false ) ;
1452+
1453+ const spy = jest . spyOn ( translateCommand as any , 'translateFile' )
1454+ . mockResolvedValue ( 'File translation result' ) ;
1455+
1456+ const mockFileService = ( translateCommand as any ) . fileTranslationService ;
1457+ jest . spyOn ( mockFileService , 'isSupportedFile' ) . mockReturnValue ( true ) ;
1458+
1459+ await translateCommand . translate ( 'folder\\subfolder\\file.txt' , {
1460+ to : 'es' ,
1461+ output : '/out.txt' ,
1462+ } ) ;
1463+
1464+ expect ( spy ) . toHaveBeenCalledWith ( 'folder\\subfolder\\file.txt' , { to : 'es' , output : '/out.txt' } ) ;
1465+ spy . mockRestore ( ) ;
1466+ } ) ;
1467+
1468+ it ( 'should detect relative Unix paths (folder/file.txt)' , async ( ) => {
1469+ const fs = jest . requireActual ( 'fs' ) ;
1470+ jest . spyOn ( fs , 'existsSync' ) . mockReturnValue ( false ) ;
1471+
1472+ const spy = jest . spyOn ( translateCommand as any , 'translateFile' )
1473+ . mockResolvedValue ( 'File translation result' ) ;
1474+
1475+ const mockFileService = ( translateCommand as any ) . fileTranslationService ;
1476+ jest . spyOn ( mockFileService , 'isSupportedFile' ) . mockReturnValue ( true ) ;
1477+
1478+ await translateCommand . translate ( 'folder/subfolder/file.txt' , {
1479+ to : 'es' ,
1480+ output : '/out.txt' ,
1481+ } ) ;
1482+
1483+ expect ( spy ) . toHaveBeenCalledWith ( 'folder/subfolder/file.txt' , { to : 'es' , output : '/out.txt' } ) ;
1484+ spy . mockRestore ( ) ;
1485+ } ) ;
1486+
1487+ it ( 'should handle files with no path separator (file.txt) as text when file doesn\'t exist' , async ( ) => {
1488+ const fs = jest . requireActual ( 'fs' ) ;
1489+ jest . spyOn ( fs , 'existsSync' ) . mockReturnValue ( false ) ;
1490+
1491+ const mockFileService = ( translateCommand as any ) . fileTranslationService ;
1492+ jest . spyOn ( mockFileService , 'isSupportedFile' ) . mockReturnValue ( true ) ;
1493+
1494+ ( mockTranslationService . translate as jest . Mock ) . mockResolvedValueOnce ( {
1495+ text : 'archivo.txt' ,
1496+ } ) ;
1497+
1498+ // No path separator and file doesn't exist -> treat as text
1499+ await translateCommand . translate ( 'file.txt' , {
1500+ to : 'es' ,
1501+ } ) ;
1502+
1503+ // Should call translateText, NOT translateFile
1504+ expect ( mockTranslationService . translate ) . toHaveBeenCalledWith (
1505+ 'file.txt' ,
1506+ expect . any ( Object ) ,
1507+ expect . any ( Object )
1508+ ) ;
1509+ } ) ;
1510+ } ) ;
13581511} ) ;
0 commit comments