@@ -29,6 +29,15 @@ protected VirtualFileSystemTests(TFixture fixture)
2929 private Task < VirtualFileSystemTestContext > CreateContextAsync ( ) => _fixture . CreateContextAsync ( ) ;
3030 private VirtualFileSystemCapabilities Capabilities => _fixture . Capabilities ;
3131
32+ public static IEnumerable < object [ ] > UnicodeFolderTestCases => new [ ]
33+ {
34+ new object [ ] { "Українська-папка" , "лист-привіт" , "Привіт з Києва!" } ,
35+ new object [ ] { "中文目錄" , "測試文件" , "雲端中的內容" } ,
36+ new object [ ] { "日本語ディレクトリ" , "テストファイル" , "東京からこんにちは" } ,
37+ new object [ ] { "한국어_폴더" , "테스트-파일" , "부산에서 안녕하세요" } ,
38+ new object [ ] { "emoji📁" , "😀-файл" , "multi🌐lingual content" }
39+ } ;
40+
3241 [ Fact ]
3342 public async Task WriteAndReadFile_ShouldRoundtrip ( )
3443 {
@@ -178,6 +187,55 @@ await file.SetMetadataAsync(new Dictionary<string, string>
178187 metadataManager . CustomMetadataRequests . ShouldBe ( 0 ) ;
179188 }
180189
190+ [ Theory ]
191+ [ MemberData ( nameof ( UnicodeFolderTestCases ) ) ]
192+ public async Task WriteAndReadFile_WithUnicodeDirectories_ShouldRoundtrip (
193+ string directoryName ,
194+ string fileName ,
195+ string content )
196+ {
197+ if ( ! Capabilities . Enabled )
198+ {
199+ return ;
200+ }
201+
202+ await using var context = await CreateContextAsync ( ) ;
203+ var vfs = context . FileSystem ;
204+
205+ var path = new VfsPath ( $ "/international/{ directoryName } /{ fileName } .txt") ;
206+ var file = await vfs . GetFileAsync ( path ) ;
207+
208+ await file . WriteAllTextAsync ( content ) ;
209+
210+ ( await file . ReadAllTextAsync ( ) ) . ShouldBe ( content ) ;
211+ file . Path . GetFileName ( ) . ShouldBe ( $ "{ fileName } .txt") ;
212+ file . Path . GetFileNameWithoutExtension ( ) . ShouldBe ( fileName ) ;
213+ file . Path . GetExtension ( ) . ShouldBe ( ".txt" ) ;
214+ file . Path . GetParent ( ) . Value . ShouldBe ( $ "/international/{ directoryName } ") ;
215+ file . Path . ToBlobKey ( ) . ShouldBe ( $ "international/{ directoryName } /{ fileName } .txt") ;
216+
217+ ( await vfs . FileExistsAsync ( path ) ) . ShouldBeTrue ( ) ;
218+
219+ if ( Capabilities . SupportsListing )
220+ {
221+ var entries = new List < IVfsNode > ( ) ;
222+ await foreach ( var entry in vfs . ListAsync ( new VfsPath ( $ "/international/{ directoryName } ") , new ListOptions
223+ {
224+ IncludeFiles = true ,
225+ IncludeDirectories = false ,
226+ Recursive = false
227+ } ) )
228+ {
229+ entries . Add ( entry ) ;
230+ }
231+
232+ entries . ShouldContain ( e => e . Path . Value == path . Value ) ;
233+ }
234+
235+ ( await file . DeleteAsync ( ) ) . ShouldBeTrue ( ) ;
236+ ( await vfs . FileExistsAsync ( path ) ) . ShouldBeFalse ( ) ;
237+ }
238+
181239 [ Fact ]
182240 public async Task DeleteDirectoryAsync_NonRecursive_ShouldPreserveNestedContent ( )
183241 {
0 commit comments