diff --git a/test/integration/Properties/Resources.Designer.cs b/test/integration/Properties/Resources.Designer.cs index 400c7e3e..02421c41 100644 --- a/test/integration/Properties/Resources.Designer.cs +++ b/test/integration/Properties/Resources.Designer.cs @@ -8,10 +8,10 @@ // //------------------------------------------------------------------------------ -namespace Appium.Net.Integration.Tests.Properties -{ - - +namespace Appium.Net.Integration.Tests.Properties { + using System; + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -19,7 +19,7 @@ namespace Appium.Net.Integration.Tests.Properties // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { @@ -70,36 +70,6 @@ public static byte[] ApiDemos_debug { } } - /// - /// Looks up a localized resource of type System.Byte[]. - /// - public static byte[] PathToLinuxNode { - get { - object obj = ResourceManager.GetObject("PathToLinuxNode", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - public static byte[] PathToMacOSNode { - get { - object obj = ResourceManager.GetObject("PathToMacOSNode", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - public static byte[] PathToWindowsNode { - get { - object obj = ResourceManager.GetObject("PathToWindowsNode", resourceCulture); - return ((byte[])(obj)); - } - } - /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/test/integration/Properties/Resources.resx b/test/integration/Properties/Resources.resx index f6ac0653..a1013a48 100644 --- a/test/integration/Properties/Resources.resx +++ b/test/integration/Properties/Resources.resx @@ -118,15 +118,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\helpers\PathToLinuxNode;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\helpers\PathToMacOSNode;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\helpers\PathToWindowsNode;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ..\apps\ApiDemos-debug.apk;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs b/test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs index 14bb79a3..91d0aa38 100644 --- a/test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs +++ b/test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs @@ -4,9 +4,8 @@ using System.Net; using System.Text; using System.Threading; -using Appium.Net.Integration.Tests.Properties; +using Appium.Net.Integration.Tests.Helpers; using NUnit.Framework; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Enums; using OpenQA.Selenium.Appium.Service; @@ -18,15 +17,12 @@ namespace Appium.Net.Integration.Tests.ServerTests [TestFixture] public class AppiumLocalServerLaunchingTest { - private string _pathToCustomizedAppiumJs; + private string _pathToAppiumPackageIndex; private string _testIp; [OneTimeSetUp] public void BeforeAll() { - var isWindows = Platform.CurrentPlatform.IsPlatformType(PlatformType.Windows); - var isMacOs = Platform.CurrentPlatform.IsPlatformType(PlatformType.Mac); - var isLinux = Platform.CurrentPlatform.IsPlatformType(PlatformType.Linux); IPHostEntry host; var hostName = Dns.GetHostName(); @@ -41,25 +37,7 @@ public void BeforeAll() } Console.WriteLine(_testIp); - byte[] bytes; - if (isWindows) - { - bytes = Resources.PathToWindowsNode; - _pathToCustomizedAppiumJs = Encoding.UTF8.GetString(bytes); - return; - } - if (isMacOs) - { - bytes = Resources.PathToMacOSNode; - _pathToCustomizedAppiumJs = Encoding.UTF8.GetString(bytes); - return; - } - if (isLinux) - { - bytes = Resources.PathToLinuxNode; - _pathToCustomizedAppiumJs = Encoding.UTF8.GetString(bytes); - return; - } + _pathToAppiumPackageIndex = new Paths().PathToAppiumPackageIndex; } [Test] @@ -105,7 +83,7 @@ public void CheckAbilityToBuildServiceUsingNodeDefinedInProperties() AppiumLocalService service = null; try { - var definedNode = _pathToCustomizedAppiumJs; + var definedNode = _pathToAppiumPackageIndex; Environment.SetEnvironmentVariable(AppiumServiceConstants.AppiumBinaryPath, definedNode); service = AppiumLocalService.BuildDefaultService(); service.Start(); @@ -124,7 +102,7 @@ public void CheckAbilityToBuildServiceUsingNodeDefinedExplicitly() AppiumLocalService service = null; try { - service = new AppiumServiceBuilder().WithAppiumJS(new FileInfo(_pathToCustomizedAppiumJs)).Build(); + service = new AppiumServiceBuilder().WithAppiumJS(new FileInfo(_pathToAppiumPackageIndex)).Build(); service.Start(); Assert.AreEqual(true, service.IsRunning); } diff --git a/test/integration/helpers/Npm.cs b/test/integration/helpers/Npm.cs new file mode 100644 index 00000000..d3605116 --- /dev/null +++ b/test/integration/helpers/Npm.cs @@ -0,0 +1,93 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; + +namespace Appium.Net.Integration.Tests.helpers +{ + internal class Npm + { + + public static string GetNpmPrefixPath() + { + string npmPath = GetNpmExecutablePath(); + string npmPrefixPath = RunCommand(npmPath, "-g root"); + + return npmPrefixPath.Trim(); + } + + private static string RunCommand(string command, string arguments, int timeoutMilliseconds = 30000) + { + int exitCode; + string output; + try + { + using (Process process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = command, + Arguments = arguments, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + } + }) + { + process.Start(); + + output = process.StandardOutput.ReadToEnd(); + string errorOutput = process.StandardError.ReadToEnd(); + _ = process.WaitForExit(timeoutMilliseconds); + + exitCode = process.ExitCode; + } + if ((exitCode == 1) && command.Contains("npm")) + { + Console.WriteLine($"npm Error upon command: `{arguments}`. {output}"); + throw new NpmUnknownCommandException($"Command: `{arguments}` exited with code {exitCode}. Error: {output}"); + } + + return output; + } + + catch (Win32Exception ex) when (command.Contains("npm")) + { + Console.WriteLine(ex.Message); + throw new NpmNotFoundException($"npm not found under {command}", ex); + } + } + + private static string GetNpmExecutablePath() + { + string commandName = IsWindows() ? "where" : "which"; + string result = RunCommand(commandName, "npm"); + + string npmPath; + + string[] lines = result?.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + + if (IsWindows()) + { + npmPath = lines?.FirstOrDefault(line => !string.IsNullOrWhiteSpace(line) && line.EndsWith("npm.cmd")); + } + else + { + npmPath = lines?.FirstOrDefault(line => !string.IsNullOrWhiteSpace(line)); + } + + if (string.IsNullOrWhiteSpace(npmPath)) + { + throw new NpmNotFoundException("NPM executable not found. Please make sure the NPM executable is installed and check the configured PATH environment variable."); + } + + return npmPath; + } + + private static bool IsWindows() + { + return Environment.OSVersion.Platform == PlatformID.Win32NT; + } + } +} diff --git a/test/integration/helpers/NpmNotFoundException.cs b/test/integration/helpers/NpmNotFoundException.cs new file mode 100644 index 00000000..71521797 --- /dev/null +++ b/test/integration/helpers/NpmNotFoundException.cs @@ -0,0 +1,22 @@ +using System; + +namespace Appium.Net.Integration.Tests.helpers +{ + public class NpmNotFoundException : Exception + { + public NpmNotFoundException() + : base("Node Package Manager (npm) cannot be found. Make sure Node.js is installed and present in PATH.") + { + } + + public NpmNotFoundException(string message) + : base(message) + { + } + + public NpmNotFoundException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/test/integration/helpers/NpmUnknownCommandException.cs b/test/integration/helpers/NpmUnknownCommandException.cs new file mode 100644 index 00000000..492dbf98 --- /dev/null +++ b/test/integration/helpers/NpmUnknownCommandException.cs @@ -0,0 +1,17 @@ +using System; + +namespace Appium.Net.Integration.Tests.helpers +{ + public class NpmUnknownCommandException : Exception + { + public NpmUnknownCommandException() + : base("Unknown npm command encountered. ") + { + } + + public NpmUnknownCommandException(string message) + : base(message) + { + } + } +} diff --git a/test/integration/helpers/PathToLinuxNode b/test/integration/helpers/PathToLinuxNode deleted file mode 100644 index 1932de20..00000000 --- a/test/integration/helpers/PathToLinuxNode +++ /dev/null @@ -1 +0,0 @@ -/Applications/Appium.app/Contents/Resources/node_modules/appium/bin/appium.js \ No newline at end of file diff --git a/test/integration/helpers/PathToMacOSNode b/test/integration/helpers/PathToMacOSNode deleted file mode 100644 index 1932de20..00000000 --- a/test/integration/helpers/PathToMacOSNode +++ /dev/null @@ -1 +0,0 @@ -/Applications/Appium.app/Contents/Resources/node_modules/appium/bin/appium.js \ No newline at end of file diff --git a/test/integration/helpers/PathToWindowsNode b/test/integration/helpers/PathToWindowsNode deleted file mode 100644 index ed0acb16..00000000 --- a/test/integration/helpers/PathToWindowsNode +++ /dev/null @@ -1 +0,0 @@ -C:/Program Files (x86)/Appium/node_modules/appium/bin/appium.js \ No newline at end of file diff --git a/test/integration/helpers/Paths.cs b/test/integration/helpers/Paths.cs new file mode 100644 index 00000000..a61d2225 --- /dev/null +++ b/test/integration/helpers/Paths.cs @@ -0,0 +1,36 @@ +using Appium.Net.Integration.Tests.helpers; +using System.IO; + +namespace Appium.Net.Integration.Tests.Helpers +{ + internal class Paths + { + private string _pathToAppiumPackageIndex; + + public string PathToAppiumPackageIndex + { + get + { + if (_pathToAppiumPackageIndex == null) + { + InitAppiumPackageIndexPath(); + } + return _pathToAppiumPackageIndex; + } + } + + /// + /// Initializes the Appium package index path by combining the components "appium" and "index.js" with the npm prefix path. + /// + /// + /// This method sets the _pathToAppiumPackageIndex variable by combining the specified components with the npm prefix path. + /// + private void InitAppiumPackageIndexPath() + { + string[] appiumJsPathComponents = { "appium", "index.js" }; + string npmPath = Npm.GetNpmPrefixPath(); + + _pathToAppiumPackageIndex = Path.Combine(npmPath, Path.Combine(appiumJsPathComponents)); + } + } +}