|
|
|
|
using System;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.IO.Compression;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Net.Sockets;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using FluentAssertions;
|
|
|
|
|
using Mono.Unix.Native;
|
|
|
|
|
using NLog;
|
|
|
|
|
using NUnit.Framework;
|
|
|
|
|
using NzbDrone.Automation.Test.PageModel;
|
|
|
|
|
using NzbDrone.Common.EnvironmentInfo;
|
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
|
|
using NzbDrone.Common.Processes;
|
|
|
|
|
using NzbDrone.Test.Common;
|
|
|
|
|
using OpenQA.Selenium.Remote;
|
|
|
|
|
|
|
|
|
|
namespace NzbDrone.Automation.Test
|
|
|
|
|
{
|
|
|
|
|
[TestFixture("", "Windows", "10", "Chrome", "63", 9901)]
|
|
|
|
|
[TestFixture("", "Windows", "10", "Firefox", "67", 9902)]
|
|
|
|
|
[TestFixture("", "Windows", "10", "Edge", "18", 9903)]
|
|
|
|
|
[TestFixture("", "OS X", "Mojave", "Safari", "12.1", 9904)]
|
|
|
|
|
// [TestFixture("iPhone X", "", "11", "iPhone", "", 9905)]
|
|
|
|
|
// [TestFixture("Samsung Galaxy S9 Plus", "", "9.0", "android", "", 9906)]
|
|
|
|
|
[Parallelizable(ParallelScope.Fixtures)]
|
|
|
|
|
public class BrowserStackAutomationTest : MainPagesTest
|
|
|
|
|
{
|
|
|
|
|
protected string browser;
|
|
|
|
|
protected string browserVersion;
|
|
|
|
|
protected string os;
|
|
|
|
|
protected string osVersion;
|
|
|
|
|
protected string device;
|
|
|
|
|
|
|
|
|
|
private readonly Logger _logger;
|
|
|
|
|
|
|
|
|
|
private ProcessProvider _processProvider;
|
|
|
|
|
private Process _browserStackLocalProcess;
|
|
|
|
|
|
|
|
|
|
public BrowserStackAutomationTest(string device, string os, string osVersion, string browser, string browserVersion, int port)
|
|
|
|
|
{
|
|
|
|
|
this.device = device;
|
|
|
|
|
this.browser = browser;
|
|
|
|
|
this.browserVersion = browserVersion;
|
|
|
|
|
this.os = os;
|
|
|
|
|
this.osVersion = osVersion;
|
|
|
|
|
|
|
|
|
|
_logger = LogManager.GetCurrentClassLogger();
|
|
|
|
|
_processProvider = new ProcessProvider(_logger);
|
|
|
|
|
_runner = new NzbDroneRunner(_logger, port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[OneTimeSetUp]
|
|
|
|
|
public override void SmokeTestSetup()
|
|
|
|
|
{
|
|
|
|
|
string username = Environment.GetEnvironmentVariable("BROWSERSTACK_USERNAME");
|
|
|
|
|
string accessKey = Environment.GetEnvironmentVariable("BROWSERSTACK_ACCESS_KEY");
|
|
|
|
|
|
|
|
|
|
if (username.IsNullOrWhiteSpace() || accessKey.IsNullOrWhiteSpace())
|
|
|
|
|
{
|
|
|
|
|
Assert.Ignore("BrowserStack Tests Disabled, No Credentials");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_runner.Start();
|
|
|
|
|
|
|
|
|
|
string browserstackLocal = "true";
|
|
|
|
|
string browserstackLocalIdentifier = string.Format("Lidarr_{0}_{1}", DateTime.UtcNow.Ticks, new Random().Next());
|
|
|
|
|
string buildName = BuildInfo.Version.ToString();
|
|
|
|
|
string serverOs = OsInfo.Os.ToString();
|
|
|
|
|
|
|
|
|
|
DesiredCapabilities capabilities = new DesiredCapabilities();
|
|
|
|
|
|
|
|
|
|
capabilities.SetCapability("device", device);
|
|
|
|
|
capabilities.SetCapability("os", os);
|
|
|
|
|
capabilities.SetCapability("os_version", osVersion);
|
|
|
|
|
capabilities.SetCapability("browser", browser);
|
|
|
|
|
capabilities.SetCapability("browser_version", browserVersion);
|
|
|
|
|
capabilities.SetCapability("browserstack.local", browserstackLocal);
|
|
|
|
|
capabilities.SetCapability("browserstack.localIdentifier", browserstackLocalIdentifier);
|
|
|
|
|
capabilities.SetCapability("browserstack.debug", "true");
|
|
|
|
|
capabilities.SetCapability("browserstack.console", "verbose");
|
|
|
|
|
capabilities.SetCapability("name", string.Format("Functional Tests: {0} - {1}", serverOs, browser));
|
|
|
|
|
capabilities.SetCapability("project", "Lidarr");
|
|
|
|
|
capabilities.SetCapability("build", buildName);
|
|
|
|
|
|
|
|
|
|
var bsLocalArgs = $"--key {accessKey} --local-identifier {browserstackLocalIdentifier} --verbose";
|
|
|
|
|
_browserStackLocalProcess = StartBrowserStackLocal(_runner.AppData, bsLocalArgs);
|
|
|
|
|
|
|
|
|
|
driver = new RemoteWebDriver(new Uri("https://" + username + ":" + accessKey + "@hub.browserstack.com/wd/hub"), capabilities);
|
|
|
|
|
|
|
|
|
|
driver.Url = $"http://{LocalIPAddress()}:{_runner.Port}";
|
|
|
|
|
|
|
|
|
|
var page = GetPageBase(driver, device);
|
|
|
|
|
page.WaitForNoSpinner();
|
|
|
|
|
|
|
|
|
|
driver.ExecuteScript("window.Lidarr.NameViews = true;");
|
|
|
|
|
|
|
|
|
|
GetPageErrors().Should().BeEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IPAddress LocalIPAddress()
|
|
|
|
|
{
|
|
|
|
|
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
|
|
|
|
|
|
|
|
|
|
return host.AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private PageBase GetPageBase(RemoteWebDriver driver, string device)
|
|
|
|
|
{
|
|
|
|
|
if (device.IsNullOrWhiteSpace())
|
|
|
|
|
{
|
|
|
|
|
return new PageBase(driver);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new PageBaseMobile(driver);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[SetUp]
|
|
|
|
|
public override void Setup()
|
|
|
|
|
{
|
|
|
|
|
page = GetPageBase(driver, device);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[OneTimeTearDown]
|
|
|
|
|
public override void SmokeTestTearDown()
|
|
|
|
|
{
|
|
|
|
|
driver?.Quit();
|
|
|
|
|
|
|
|
|
|
if (_browserStackLocalProcess != null && !_browserStackLocalProcess.HasExited)
|
|
|
|
|
{
|
|
|
|
|
_browserStackLocalProcess.Kill();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_runner?.Kill();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Process StartBrowserStackLocal(string tempDir, string args = null)
|
|
|
|
|
{
|
|
|
|
|
string url;
|
|
|
|
|
string name;
|
|
|
|
|
|
|
|
|
|
if (OsInfo.IsWindows)
|
|
|
|
|
{
|
|
|
|
|
url = "https://www.browserstack.com/browserstack-local/BrowserStackLocal-win32.zip";
|
|
|
|
|
name = "BrowserStackLocal.exe";
|
|
|
|
|
}
|
|
|
|
|
else if (OsInfo.IsOsx)
|
|
|
|
|
{
|
|
|
|
|
url = "https://www.browserstack.com/browserstack-local/BrowserStackLocal-darwin-x64.zip";
|
|
|
|
|
name = "BrowserStackLocal";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
url = "https://www.browserstack.com/browserstack-local/BrowserStackLocal-linux-x64.zip";
|
|
|
|
|
name = "BrowserStackLocal";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dest = Path.Combine(tempDir, "browserstack.zip");
|
|
|
|
|
TestContext.Progress.WriteLine("Fetching browserstack local");
|
|
|
|
|
|
|
|
|
|
using (var client = new WebClient())
|
|
|
|
|
{
|
|
|
|
|
client.DownloadFile(url, dest);
|
|
|
|
|
}
|
|
|
|
|
ZipFile.ExtractToDirectory(dest, tempDir);
|
|
|
|
|
|
|
|
|
|
var browserStack = Path.Combine(tempDir, name);
|
|
|
|
|
|
|
|
|
|
if (OsInfo.IsNotWindows)
|
|
|
|
|
{
|
|
|
|
|
Syscall.chmod(browserStack, FilePermissions.DEFFILEMODE | FilePermissions.S_IRWXU | FilePermissions.S_IXGRP | FilePermissions.S_IXOTH);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TestContext.Progress.WriteLine("Starting browserstack local");
|
|
|
|
|
|
|
|
|
|
var processStarted = new ManualResetEventSlim();
|
|
|
|
|
|
|
|
|
|
var process = _processProvider.Start(browserStack, args, onOutputDataReceived: (string data) => {
|
|
|
|
|
TestContext.Progress.WriteLine(data);
|
|
|
|
|
if (data.Contains("You can now access your local server"))
|
|
|
|
|
{
|
|
|
|
|
processStarted.Set();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!processStarted.Wait(10000))
|
|
|
|
|
{
|
|
|
|
|
Assert.Fail("Failed to start browserstack within 10 sec");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TestContext.Progress.WriteLine($"Successfully started browserstacklocal pid {process.Id}");
|
|
|
|
|
|
|
|
|
|
return process;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|