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