Skip to content

Commit

Permalink
fix: Update Node path to compile with appium 2 and make him cross-pla…
Browse files Browse the repository at this point in the history
…tform (#659)

* fix: Update WindowsNode path to compile with appium 2
refactor: Move Appium.js path retrieval to helpers.paths class

* refactor!: Retrieve npm prefix path and use cross-platform commands to get appium script

* fix: npm install prefix and npm install path mixup

* fix: make PathToNode compatible with both Windows and Unix-based systems

* chore: Remove redundant NodePaths from the resources

* chore: Remove comment section

* chore: Add exception if npm path cannot be detected

* chore: Rename _pathToCustomizedAppiumJs

* chore: Add timeout for RunCommand
chore: Remove private var envPlatform

* chore: Optimize code performance

* chore: Optimize path readability on Windows platforms

* chore: Switch from `npm list -g --depth=0` to `npm -g root` for better performance

* chore: Remove comment section

* chore: Throw specific exception for npm commands

* chore: Move declaration near reference

* chore: Rename GetAppiumJsPath

* chore: Improve NPM path not found exception

* chore: Rename resource file name

* chore: Remove path replacement and add XML DOC

* chore: Verify exit code on RunCommand() from Npm

* chore: Use GetNpmExecutablePath() on all platforms

* chore: log command upon errorin RunCommand()

* chore: Improve NpmNotFoundException log

* chore: Rename GetAppiumPackageIndexPath()

* chore: Simplify InitAppiumPackageIndexPath()

* chore: Simplify paths creation

* chore: More exceptions mapping for RunCommand

* fix: More exceptions improvements in RunCommand()

* fix: Exceptions makeover pt. 3

* fix: npm typo

* chore: Minimise try-catch

* chore: Remove unnecessary using
  • Loading branch information
Dor-bl authored Nov 13, 2023
1 parent 006ca35 commit 80568b8
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 74 deletions.
40 changes: 5 additions & 35 deletions test/integration/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 0 additions & 9 deletions test/integration/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,6 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="PathToLinuxNode" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\helpers\PathToLinuxNode;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="PathToMacOSNode" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\helpers\PathToMacOSNode;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="PathToWindowsNode" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\helpers\PathToWindowsNode;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="ApiDemos_debug" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\apps\ApiDemos-debug.apk;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
Expand Down
32 changes: 5 additions & 27 deletions test/integration/ServerTests/AppiumLocalServerLaunchingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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]
Expand Down Expand Up @@ -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();
Expand All @@ -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);
}
Expand Down
93 changes: 93 additions & 0 deletions test/integration/helpers/Npm.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
22 changes: 22 additions & 0 deletions test/integration/helpers/NpmNotFoundException.cs
Original file line number Diff line number Diff line change
@@ -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)
{
}
}
}
17 changes: 17 additions & 0 deletions test/integration/helpers/NpmUnknownCommandException.cs
Original file line number Diff line number Diff line change
@@ -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)
{
}
}
}
1 change: 0 additions & 1 deletion test/integration/helpers/PathToLinuxNode

This file was deleted.

1 change: 0 additions & 1 deletion test/integration/helpers/PathToMacOSNode

This file was deleted.

1 change: 0 additions & 1 deletion test/integration/helpers/PathToWindowsNode

This file was deleted.

36 changes: 36 additions & 0 deletions test/integration/helpers/Paths.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}

/// <summary>
/// Initializes the Appium package index path by combining the components "appium" and "index.js" with the npm prefix path.
/// </summary>
/// <remarks>
/// This method sets the _pathToAppiumPackageIndex variable by combining the specified components with the npm prefix path.
/// </remarks>
private void InitAppiumPackageIndexPath()
{
string[] appiumJsPathComponents = { "appium", "index.js" };
string npmPath = Npm.GetNpmPrefixPath();

_pathToAppiumPackageIndex = Path.Combine(npmPath, Path.Combine(appiumJsPathComponents));
}
}
}

0 comments on commit 80568b8

Please sign in to comment.