/ src / modules / cmdpal / Tests / Microsoft.CmdPal.Ext.Bookmarks.UnitTests / BookmarkResolverTests.Common.cs
BookmarkResolverTests.Common.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections.Generic; 7 using System.IO; 8 using System.Threading.Tasks; 9 using Microsoft.CmdPal.Ext.Bookmarks.Helpers; 10 using Microsoft.VisualStudio.TestTools.UnitTesting; 11 12 namespace Microsoft.CmdPal.Ext.Bookmarks.UnitTests; 13 14 [TestClass] 15 public partial class BookmarkResolverTests 16 { 17 [DataTestMethod] 18 [DynamicData(nameof(CommonClassificationData.CommonCases), typeof(CommonClassificationData), DynamicDataDisplayName = nameof(FromCase))] 19 public async Task Common_ValidateCommonClassification(PlaceholderClassificationCase c) => await RunShared(c); 20 21 [DataTestMethod] 22 [DynamicData(nameof(CommonClassificationData.UwpAumidCases), typeof(CommonClassificationData), DynamicDataDisplayName = nameof(FromCase))] 23 public async Task Common_ValidateUwpAumidClassification(PlaceholderClassificationCase c) => await RunShared(c); 24 25 [DataTestMethod] 26 [DynamicData(dynamicDataSourceName: nameof(CommonClassificationData.UnquotedRelativePaths), dynamicDataDeclaringType: typeof(CommonClassificationData), DynamicDataDisplayName = nameof(FromCase))] 27 public async Task Common_ValidateUnquotedRelativePathScenarios(PlaceholderClassificationCase c) => await RunShared(c: c); 28 29 [DataTestMethod] 30 [DynamicData(dynamicDataSourceName: nameof(CommonClassificationData.UnquotedShellProtocol), dynamicDataDeclaringType: typeof(CommonClassificationData), DynamicDataDisplayName = nameof(FromCase))] 31 public async Task Common_ValidateUnquotedShellProtocolScenarios(PlaceholderClassificationCase c) => await RunShared(c: c); 32 33 private static class CommonClassificationData 34 { 35 public static IEnumerable<object[]> CommonCases() 36 { 37 return 38 [ 39 [ 40 new PlaceholderClassificationCase( 41 Name: "HTTPS URL", 42 Input: "https://microsoft.com", 43 ExpectSuccess: true, 44 ExpectedKind: CommandKind.WebUrl, 45 ExpectedTarget: "https://microsoft.com", 46 ExpectedLaunch: LaunchMethod.ShellExecute, 47 ExpectedIsPlaceholder: false) 48 ], 49 [ 50 new PlaceholderClassificationCase( 51 Name: "WWW URL without scheme", 52 Input: "www.example.com", 53 ExpectSuccess: true, 54 ExpectedKind: CommandKind.WebUrl, 55 ExpectedTarget: "https://www.example.com", 56 ExpectedLaunch: LaunchMethod.ShellExecute, 57 ExpectedIsPlaceholder: false), 58 ], 59 [ 60 new PlaceholderClassificationCase( 61 Name: "HTTP URL with query", 62 Input: "http://yahoo.com?p=search", 63 ExpectSuccess: true, 64 ExpectedKind: CommandKind.WebUrl, 65 ExpectedTarget: "http://yahoo.com?p=search", 66 ExpectedLaunch: LaunchMethod.ShellExecute, 67 ExpectedIsPlaceholder: false), 68 ], 69 [ 70 new PlaceholderClassificationCase( 71 Name: "Mailto protocol", 72 Input: "mailto:user@example.com", 73 ExpectSuccess: true, 74 ExpectedKind: CommandKind.Protocol, 75 ExpectedTarget: "mailto:user@example.com", 76 ExpectedLaunch: LaunchMethod.ShellExecute, 77 ExpectedIsPlaceholder: false), 78 ], 79 [ 80 new PlaceholderClassificationCase( 81 Name: "MS-Settings protocol", 82 Input: "ms-settings:display", 83 ExpectSuccess: true, 84 ExpectedKind: CommandKind.Protocol, 85 ExpectedTarget: "ms-settings:display", 86 ExpectedLaunch: LaunchMethod.ShellExecute, 87 ExpectedIsPlaceholder: false), 88 ], 89 [ 90 new PlaceholderClassificationCase( 91 Name: "Custom protocol", 92 Input: "myapp:doit", 93 ExpectSuccess: true, 94 ExpectedKind: CommandKind.Protocol, 95 ExpectedTarget: "myapp:doit", 96 ExpectedLaunch: LaunchMethod.ShellExecute, 97 ExpectedIsPlaceholder: false), 98 ], 99 [ 100 new PlaceholderClassificationCase( 101 Name: "Not really a valid protocol", 102 Input: "this is not really a protocol myapp: doit", 103 ExpectSuccess: true, 104 ExpectedKind: CommandKind.Unknown, 105 ExpectedTarget: "this", 106 ExpectedArguments: "is not really a protocol myapp: doit", 107 ExpectedLaunch: LaunchMethod.ShellExecute, 108 ExpectedIsPlaceholder: false), 109 ], 110 [ 111 new PlaceholderClassificationCase( 112 Name: "Drive", 113 Input: "C:\\.", 114 ExpectSuccess: true, 115 ExpectedKind: CommandKind.Directory, 116 ExpectedTarget: "C:\\", 117 ExpectedLaunch: LaunchMethod.ExplorerOpen, 118 ExpectedIsPlaceholder: false), 119 ], 120 [ 121 new PlaceholderClassificationCase( 122 Name: "Non-existing path with extension", 123 Input: "C:\\this-folder-should-not-exist-12345\\file.txt", 124 ExpectSuccess: true, 125 ExpectedKind: CommandKind.FileDocument, 126 ExpectedTarget: "C:\\this-folder-should-not-exist-12345\\file.txt", 127 ExpectedLaunch: LaunchMethod.ShellExecute, 128 ExpectedIsPlaceholder: false), 129 ], 130 [ 131 new PlaceholderClassificationCase( 132 Name: "Unknown fallback", 133 Input: "some_unlikely_command_name_12345", 134 ExpectSuccess: true, 135 ExpectedKind: CommandKind.Unknown, 136 ExpectedTarget: "some_unlikely_command_name_12345", 137 ExpectedLaunch: LaunchMethod.ShellExecute, 138 ExpectedIsPlaceholder: false), 139 ], 140 141 [new PlaceholderClassificationCase( 142 Name: "Simple unquoted executable path", 143 Input: "C:\\Windows\\System32\\notepad.exe", 144 ExpectSuccess: true, 145 ExpectedKind: CommandKind.FileExecutable, 146 ExpectedTarget: "C:\\Windows\\System32\\notepad.exe", 147 ExpectedArguments: string.Empty, 148 ExpectedLaunch: LaunchMethod.ShellExecute, 149 ExpectedIsPlaceholder: false), 150 ], 151 [ 152 new PlaceholderClassificationCase( 153 Name: "Unquoted document path (non existed file)", 154 Input: "C:\\Users\\John\\Documents\\file.txt", 155 ExpectSuccess: true, 156 ExpectedKind: CommandKind.FileDocument, 157 ExpectedTarget: "C:\\Users\\John\\Documents\\file.txt", 158 ExpectedArguments: string.Empty, 159 ExpectedLaunch: LaunchMethod.ShellExecute, 160 ExpectedIsPlaceholder: false), 161 ] 162 ]; 163 } 164 165 public static IEnumerable<object[]> UwpAumidCases() => 166 [ 167 [ 168 new PlaceholderClassificationCase( 169 Name: "UWP AUMID with AppsFolder prefix", 170 Input: "shell:AppsFolder\\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App", 171 ExpectSuccess: true, 172 ExpectedKind: CommandKind.Aumid, 173 ExpectedTarget: "shell:AppsFolder\\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App", 174 ExpectedLaunch: LaunchMethod.ActivateAppId, 175 ExpectedIsPlaceholder: false), 176 ], 177 [ 178 new PlaceholderClassificationCase( 179 Name: "UWP AUMID with AppsFolder prefix and argument (Trap)", 180 Input: "shell:AppsFolder\\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App --maximized", 181 ExpectSuccess: true, 182 ExpectedKind: CommandKind.Aumid, 183 ExpectedTarget: "shell:AppsFolder\\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App --maximized", 184 ExpectedArguments: string.Empty, 185 ExpectedLaunch: LaunchMethod.ActivateAppId, 186 ExpectedIsPlaceholder: false), 187 ], 188 [ 189 new PlaceholderClassificationCase( 190 Name: "UWP AUMID via AppsFolder", 191 Input: "shell:AppsFolder\\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App", 192 ExpectSuccess: true, 193 ExpectedKind: CommandKind.Aumid, 194 ExpectedTarget: "shell:AppsFolder\\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App", 195 ExpectedLaunch: LaunchMethod.ActivateAppId, 196 ExpectedIsPlaceholder: false), 197 ], 198 ]; 199 200 public static IEnumerable<object[]> UnquotedShellProtocol() => 201 [ 202 [ 203 new PlaceholderClassificationCase( 204 Name: "Shell for This PC (shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D})", 205 Input: "shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 206 ExpectSuccess: true, 207 ExpectedKind: CommandKind.VirtualShellItem, 208 ExpectedTarget: "shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 209 ExpectedLaunch: LaunchMethod.ShellExecute, 210 ExpectedIsPlaceholder: false), 211 ], 212 [ 213 new PlaceholderClassificationCase( 214 Name: "Shell for This PC (::{20D04FE0-3AEA-1069-A2D8-08002B30309D})", 215 Input: "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 216 ExpectSuccess: true, 217 ExpectedKind: CommandKind.VirtualShellItem, 218 ExpectedTarget: "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 219 ExpectedLaunch: LaunchMethod.ShellExecute, 220 ExpectedIsPlaceholder: false), 221 ], 222 [ 223 new PlaceholderClassificationCase( 224 Name: "Shell protocol for My Documents (shell:::{450D8FBA-AD25-11D0-98A8-0800361B1103}", 225 Input: "shell:::{450D8FBA-AD25-11D0-98A8-0800361B1103}", 226 ExpectSuccess: true, 227 ExpectedKind: CommandKind.Directory, 228 ExpectedTarget: Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), 229 ExpectedLaunch: LaunchMethod.ExplorerOpen, 230 ExpectedIsPlaceholder: false), 231 ], 232 [ 233 new PlaceholderClassificationCase( 234 Name: "Shell protocol for My Documents (::{450D8FBA-AD25-11D0-98A8-0800361B1103}", 235 Input: "::{450D8FBA-AD25-11D0-98A8-0800361B1103}", 236 ExpectSuccess: true, 237 ExpectedKind: CommandKind.Directory, 238 ExpectedTarget: Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), 239 ExpectedLaunch: LaunchMethod.ExplorerOpen, 240 ExpectedIsPlaceholder: false), 241 ], 242 [ 243 new PlaceholderClassificationCase( 244 Name: "Shell protocol for AppData (shell:appdata)", 245 Input: "shell:appdata", 246 ExpectSuccess: true, 247 ExpectedKind: CommandKind.Directory, 248 ExpectedTarget: Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), 249 ExpectedLaunch: LaunchMethod.ExplorerOpen, 250 ExpectedIsPlaceholder: false), 251 ], 252 [ 253 254 // let's pray this works on all systems 255 new PlaceholderClassificationCase( 256 Name: "Shell protocol for AppData + subpath (shell:appdata\\microsoft)", 257 Input: "shell:appdata\\microsoft", 258 ExpectSuccess: true, 259 ExpectedKind: CommandKind.Directory, 260 ExpectedTarget: Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft"), 261 ExpectedLaunch: LaunchMethod.ExplorerOpen, 262 ExpectedIsPlaceholder: false), 263 ], 264 ]; 265 266 public static IEnumerable<object[]> UnquotedRelativePaths() => 267 [ 268 [ 269 new PlaceholderClassificationCase( 270 Name: "Unquoted relative current path", 271 Input: ".\\file.txt", 272 ExpectSuccess: true, 273 ExpectedKind: CommandKind.FileDocument, 274 ExpectedTarget: Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "file.txt")), 275 ExpectedLaunch: LaunchMethod.ShellExecute, 276 ExpectedIsPlaceholder: false) 277 ], 278 #if CMDPAL_ENABLE_UNSAFE_TESTS 279 It's not really a good idea blindly write to directory out of user profile 280 [ 281 new PlaceholderClassificationCase( 282 Name: "Unquoted relative parent path", 283 Input: "..\\parent folder\\file.txt", 284 ExpectSuccess: true, 285 ExpectedKind: CommandKind.FileDocument, 286 ExpectedTarget: Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "..", "parent folder", "file.txt")), 287 ExpectedLaunch: LaunchMethod.ShellExecute, 288 ExpectedIsPlaceholder: false) 289 ], 290 #endif // CMDPAL_ENABLE_UNSAFE_TESTS 291 [ 292 new PlaceholderClassificationCase( 293 Name: "Unquoted relative home folder", 294 Input: $"~\\{_testDirName}\\app.exe", 295 ExpectSuccess: true, 296 ExpectedKind: CommandKind.FileExecutable, 297 ExpectedTarget: Path.Combine(_testDirPath, "app.exe"), 298 ExpectedLaunch: LaunchMethod.ShellExecute, 299 ExpectedIsPlaceholder: false) 300 ] 301 ]; 302 } 303 }