1+ // Licensed to the .NET Foundation under one or more agreements.
2+ // The .NET Foundation licenses this file to you under the MIT license.
3+
4+ using Aspire . Cli . Commands ;
5+ using Xunit ;
6+
7+ namespace Aspire . Cli . Tests . Commands ;
8+
9+ public class ProjectNameValidatorTests
10+ {
11+ [ Theory ]
12+ [ InlineData ( "项目1" , true ) ] // Chinese
13+ [ InlineData ( "Проект1" , true ) ] // Cyrillic
14+ [ InlineData ( "プロジェクト1" , true ) ] // Japanese
15+ [ InlineData ( "مشروع1" , true ) ] // Arabic
16+ [ InlineData ( "Project_1" , true ) ] // Latin with underscore
17+ [ InlineData ( "Project-1" , true ) ] // Latin with dash
18+ [ InlineData ( "Project.1" , true ) ] // Latin with dot
19+ [ InlineData ( "MyApp" , true ) ] // Simple ASCII
20+ [ InlineData ( "A" , true ) ] // Single character
21+ [ InlineData ( "1" , true ) ] // Single number
22+ [ InlineData ( "プ" , true ) ] // Single Unicode character
23+ [ InlineData ( "Test123" , true ) ] // Mixed letters and numbers
24+ [ InlineData ( "My_Cool-Project.v2" , true ) ] // Complex valid name
25+ [ InlineData ( "Project:1" , true ) ] // Colon (now allowed)
26+ [ InlineData ( "Project*1" , true ) ] // Asterisk (now allowed)
27+ [ InlineData ( "Project?1" , true ) ] // Question mark (now allowed)
28+ [ InlineData ( "Project\" 1" , true ) ] // Quote (now allowed)
29+ [ InlineData ( "Project<1" , true ) ] // Less than (now allowed)
30+ [ InlineData ( "Project>1" , true ) ] // Greater than (now allowed)
31+ [ InlineData ( "Project|1" , true ) ] // Pipe (now allowed)
32+ [ InlineData ( "Project " , true ) ] // Ends with space (now allowed)
33+ [ InlineData ( " Project" , true ) ] // Starts with space (now allowed)
34+ [ InlineData ( "Pro ject" , true ) ] // Space in middle (now allowed)
35+ [ InlineData ( "-Project" , true ) ] // Starts with dash (now allowed)
36+ [ InlineData ( "Project-" , true ) ] // Ends with dash (now allowed)
37+ [ InlineData ( ".Project" , true ) ] // Starts with dot (now allowed)
38+ [ InlineData ( "Project." , true ) ] // Ends with dot (now allowed)
39+ [ InlineData ( "_Project" , true ) ] // Starts with underscore (now allowed)
40+ [ InlineData ( "Project_" , true ) ] // Ends with underscore (now allowed)
41+ public void IsProjectNameValid_ValidNames_ReturnsTrue ( string projectName , bool expected )
42+ {
43+ // Act
44+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
45+
46+ // Assert
47+ Assert . Equal ( expected , result ) ;
48+ }
49+
50+ [ Theory ]
51+ [ InlineData ( "Project/1" , false ) ] // Forward slash (path separator)
52+ [ InlineData ( "Project\\ 1" , false ) ] // Backslash (path separator)
53+ [ InlineData ( "" , false ) ] // Empty string
54+ [ InlineData ( " " , false ) ] // Space only
55+ [ InlineData ( " " , false ) ] // Multiple spaces only
56+ [ InlineData ( "\t " , false ) ] // Tab only
57+ [ InlineData ( "\n " , false ) ] // Newline only
58+ public void IsProjectNameValid_InvalidNames_ReturnsFalse ( string projectName , bool expected )
59+ {
60+ // Act
61+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
62+
63+ // Assert
64+ Assert . Equal ( expected , result ) ;
65+ }
66+
67+ [ Fact ]
68+ public void IsProjectNameValid_MaxLength254_ReturnsTrue ( )
69+ {
70+ // Arrange
71+ var projectName = new string ( 'A' , 254 ) ;
72+
73+ // Act
74+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
75+
76+ // Assert
77+ Assert . True ( result ) ;
78+ }
79+
80+ [ Fact ]
81+ public void IsProjectNameValid_Length255_ReturnsFalse ( )
82+ {
83+ // Arrange
84+ var projectName = new string ( 'A' , 255 ) ;
85+
86+ // Act
87+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
88+
89+ // Assert
90+ Assert . False ( result ) ;
91+ }
92+
93+ [ Theory ]
94+ [ InlineData ( "项目测试名称很长的中文项目名称" ) ] // Long Chinese name
95+ [ InlineData ( "очень_длинное_русское_имя_проекта" ) ] // Long Russian name
96+ [ InlineData ( "とても長い日本語のプロジェクト名" ) ] // Long Japanese name
97+ [ InlineData ( "اسم_مشروع_طويل_جدا_بالعربية" ) ] // Long Arabic name
98+ public void IsProjectNameValid_LongUnicodeNames_ReturnsTrue ( string projectName )
99+ {
100+ // Act
101+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
102+
103+ // Assert
104+ Assert . True ( result , $ "Unicode project name should be valid: { projectName } ") ;
105+ }
106+
107+ [ Theory ]
108+ [ InlineData ( "Ελληνικά" , true ) ] // Greek
109+ [ InlineData ( "עברית" , true ) ] // Hebrew
110+ [ InlineData ( "हिन्दी" , true ) ] // Hindi
111+ [ InlineData ( "ไทย" , true ) ] // Thai
112+ [ InlineData ( "한국어" , true ) ] // Korean
113+ [ InlineData ( "Türkçe" , true ) ] // Turkish
114+ [ InlineData ( "Português" , true ) ] // Portuguese with accent
115+ [ InlineData ( "Français" , true ) ] // French with accent
116+ [ InlineData ( "Español" , true ) ] // Spanish with accent
117+ [ InlineData ( "Deutsch" , true ) ] // German
118+ public void IsProjectNameValid_VariousLanguages_ReturnsTrue ( string projectName , bool expected )
119+ {
120+ // Act
121+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
122+
123+ // Assert
124+ Assert . Equal ( expected , result ) ;
125+ }
126+
127+ [ Theory ]
128+ [ InlineData ( "Test123-Project_Name.v2" ) ] // Complex valid with all allowed characters
129+ [ InlineData ( "A1-B2_C3.D4" ) ] // Mixed with separators
130+ [ InlineData ( "项目-测试_版本.1" ) ] // Unicode with separators
131+ public void IsProjectNameValid_ComplexValidNames_ReturnsTrue ( string projectName )
132+ {
133+ // Act
134+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
135+
136+ // Assert
137+ Assert . True ( result , $ "Complex valid project name should be valid: { projectName } ") ;
138+ }
139+
140+ [ Theory ]
141+ [ InlineData ( "Test..Name" ) ] // Double dot
142+ [ InlineData ( "Test--Name" ) ] // Double dash
143+ [ InlineData ( "Test__Name" ) ] // Double underscore
144+ public void IsProjectNameValid_ConsecutiveSpecialChars_ReturnsTrue ( string projectName )
145+ {
146+ // These should be valid as the spec doesn't prohibit consecutive allowed characters
147+ // Act
148+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
149+
150+ // Assert
151+ Assert . True ( result , $ "Consecutive allowed characters should be valid: { projectName } ") ;
152+ }
153+
154+ [ Theory ]
155+ [ InlineData ( "My/Project" ) ] // Forward slash in middle
156+ [ InlineData ( "/MyProject" ) ] // Forward slash at start
157+ [ InlineData ( "MyProject/" ) ] // Forward slash at end
158+ [ InlineData ( "My\\ Project" ) ] // Backslash in middle
159+ [ InlineData ( "\\ MyProject" ) ] // Backslash at start
160+ [ InlineData ( "MyProject\\ " ) ] // Backslash at end
161+ [ InlineData ( "My/Project/Name" ) ] // Multiple forward slashes
162+ [ InlineData ( "My\\ Project\\ Name" ) ] // Multiple backslashes
163+ [ InlineData ( "My/Project\\ Name" ) ] // Mixed path separators
164+ public void IsProjectNameValid_PathSeparators_ReturnsFalse ( string projectName )
165+ {
166+ // Act
167+ var result = ProjectNameValidator . IsProjectNameValid ( projectName ) ;
168+
169+ // Assert
170+ Assert . False ( result , $ "Project name with path separators should be invalid: { projectName } ") ;
171+ }
172+ }
0 commit comments