/ 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  }