99# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
1010# specific language governing permissions and limitations under the License.
1111
12+ import os
1213import pathlib
1314import tempfile
1415
16+ import pytest
17+
1518from taipy .gui import Gui
16- from taipy .gui .utils import _get_non_existent_file_path
19+ from taipy .gui .utils import _get_non_existent_file_path , _secure_filename_unicode
1720
1821
1922def test_empty_file_name (gui : Gui , helpers ):
@@ -39,3 +42,120 @@ def test_existent_file(gui: Gui, helpers):
3942 assert file_path .exists ()
4043 file_path = _get_non_existent_file_path (pathlib .Path (tempfile .gettempdir ()), "" )
4144 assert file_path .name == f"{ file_stem } .{ index + 2 } { file_suffix } "
45+
46+
47+ @pytest .mark .parametrize (
48+ "input_filename,expected_output" ,
49+ [
50+ ("normal_file.txt" , "normal_file.txt" ),
51+ ("file with spaces.txt" , "file_with_spaces.txt" ),
52+ ("file.with.dots.txt" , "file.with.dots.txt" ),
53+ ],
54+ )
55+ def test_secure_filename_unicode_valid_cases (gui : Gui , helpers , input_filename , expected_output ):
56+ """Test that valid filenames pass through unchanged"""
57+ assert _secure_filename_unicode (input_filename ) == expected_output
58+
59+
60+ @pytest .mark .parametrize (
61+ "input_filename,expected_output" ,
62+ [
63+ ('file<>:"/\\ |?*.txt' , "file_.txt" ),
64+ ("file<s>.txt" , "files.txt" ),
65+ ("file:name.txt" , "filename.txt" ),
66+ ('file"name".txt' , "filename.txt" ),
67+ ("file|name.txt" , "filename.txt" ),
68+ ("file\x00 \x1f \x7f .txt" , "file.txt" ),
69+ ],
70+ )
71+ def test_secure_filename_unicode_special_chars (gui : Gui , helpers , input_filename , expected_output ):
72+ """Test removal of forbidden and control characters"""
73+ assert _secure_filename_unicode (input_filename ) == expected_output
74+
75+
76+ @pytest .mark .parametrize (
77+ "input_filename,expected_output" ,
78+ [
79+ ("café.txt" , "café.txt" ),
80+ ("naïve.txt" , "naïve.txt" ),
81+ ("résumé.txt" , "résumé.txt" ),
82+ ("测试文件.txt" , "测试文件.txt" ),
83+ ("файл.txt" , "файл.txt" ),
84+ ("café" , "café" ),
85+ ("poup\u00e9 e" , "poupée" ),
86+ ("cafe\u0301 " , "café" ),
87+ ],
88+ )
89+ def test_secure_filename_unicode_preservation (gui : Gui , helpers , input_filename , expected_output ):
90+ """Test Unicode character preservation and normalization"""
91+ assert _secure_filename_unicode (input_filename ) == expected_output
92+
93+
94+ @pytest .mark .parametrize (
95+ "input_filename,expected_output" ,
96+ [
97+ (" file .txt " , "file_.txt" ),
98+ ("file with spaces.txt" , "file_with_spaces.txt" ),
99+ ("file\n with\t tabs.txt" , "filewithtabs.txt" ),
100+ ("..file.txt" , "file.txt" ),
101+ ("file..txt" , "file..txt" ),
102+ ("__file__.txt" , "file_.txt" ),
103+ (".file_.txt" , "file_.txt" ),
104+ ],
105+ )
106+ def test_secure_filename_unicode_whitespace_cleanup (gui : Gui , helpers , input_filename , expected_output ):
107+ """Test whitespace handling and leading/trailing character cleanup"""
108+ assert _secure_filename_unicode (input_filename ) == expected_output
109+
110+
111+ @pytest .mark .parametrize (
112+ "input_filename,expected_output" ,
113+ [
114+ ("" , "" ),
115+ (" " , "" ),
116+ ("..." , "" ),
117+ ("___" , "" ),
118+ ('<>:"/\\ |?*' , "" ),
119+ ],
120+ )
121+ def test_secure_filename_unicode_empty_cases (gui : Gui , helpers , input_filename , expected_output ):
122+ """Test edge cases that result in empty filenames"""
123+ assert _secure_filename_unicode (input_filename ) == expected_output
124+
125+
126+ @pytest .mark .parametrize (
127+ "input_filename,expected_output" ,
128+ [
129+ ("My Document (Final Version).pdf" , "My_Document_(Final_Version).pdf" ),
130+ ("Report 2024: Q1 Results.xlsx" , "Report_2024_Q1_Results.xlsx" ),
131+ ('User\' s File: "Important".docx' , "User's_File_Important.docx" ),
132+ ("café & naïve résumé.pdf" , "café_&_naïve_résumé.pdf" ),
133+ ],
134+ )
135+ def test_secure_filename_unicode_real_world_cases (gui : Gui , helpers , input_filename , expected_output ):
136+ """Test realistic filename scenarios with mixed issues"""
137+ assert _secure_filename_unicode (input_filename ) == expected_output
138+
139+
140+ @pytest .mark .parametrize (
141+ "input_filename,expected_output_windows,expected_output_non_windows" ,
142+ [
143+ ("CON.txt" , "_CON.txt" , "CON.txt" ),
144+ ("PRN.txt" , "_PRN.txt" , "PRN.txt" ),
145+ ("AUX.txt" , "_AUX.txt" , "AUX.txt" ),
146+ ("NUL.txt" , "_NUL.txt" , "NUL.txt" ),
147+ ("COM1.txt" , "_COM1.txt" , "COM1.txt" ),
148+ ("LPT1.txt" , "_LPT1.txt" , "LPT1.txt" ),
149+ ("con.txt" , "_con.txt" , "con.txt" ),
150+ ("Con.Txt" , "_Con.Txt" , "Con.Txt" ),
151+ ],
152+ )
153+ def test_secure_filename_unicode_windows_device_files (
154+ gui : Gui , helpers , input_filename , expected_output_windows , expected_output_non_windows
155+ ):
156+ """Test Windows device file handling (platform-specific)"""
157+
158+ if os .name == "nt" :
159+ assert _secure_filename_unicode (input_filename ) == expected_output_windows
160+ else :
161+ assert _secure_filename_unicode (input_filename ) == expected_output_non_windows
0 commit comments