Add a ScanWiaSavePdf verification test

This commit is contained in:
Ben Olden-Cooligan 2022-07-30 14:57:21 -07:00
parent f97d2e486c
commit ef13f727f2
7 changed files with 135 additions and 55 deletions

View File

@ -1,15 +0,0 @@
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
namespace NAPS2.App.Tests.Appium;
public static class AppiumHelper
{
public static WindowsDriver<WindowsElement> StartSession(string exeName, string appData)
{
var opts = new AppiumOptions();
opts.AddAdditionalCapability("app", AppTestHelper.GetExePath(exeName));
opts.AddAdditionalCapability("appArguments", $"/Naps2TestData \"{appData}\"");
return new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), opts);
}
}

View File

@ -0,0 +1,66 @@
using System.Threading;
using NAPS2.Sdk.Tests;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
namespace NAPS2.App.Tests.Appium;
public class AppiumTests : ContextualTests
{
protected readonly WindowsDriver<WindowsElement> _session;
private static WindowsDriver<WindowsElement> StartSession(string exeName, string appData)
{
var opts = new AppiumOptions();
opts.AddAdditionalCapability("app", AppTestHelper.GetExePath(exeName));
opts.AddAdditionalCapability("appArguments", $"/Naps2TestData \"{appData}\"");
return new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), opts);
}
public AppiumTests()
{
_session = StartSession("NAPS2.exe", FolderPath);
}
public override void Dispose()
{
_session.Dispose();
base.Dispose();
}
protected void WaitUntilGone(string name)
{
try
{
while (true)
{
if (_session.FindElementsByName(name).Count == 0)
{
break;
}
Thread.Sleep(100);
}
}
catch (InvalidOperationException)
{
}
}
protected void ResetMainWindow()
{
_session.SwitchTo().Window(_session.WindowHandles[0]);
}
protected void ClickAt(WindowsElement element)
{
#pragma warning disable CS0618
// This is apparently obsolete, but the "correct" code is 10x as complicated so whatever
_session.Mouse.Click(element.Coordinates);
#pragma warning restore CS0618
}
protected void ClickAtName(string name)
{
ClickAt(_session.FindElementByName(name));
}
}

View File

@ -1,74 +1,51 @@
using System.Collections.ObjectModel;
using NAPS2.App.Tests.Verification;
using NAPS2.Sdk.Tests;
using OpenQA.Selenium.Appium.Windows;
using Xunit;
// ReSharper disable StringLiteralTypo
namespace NAPS2.App.Tests.Appium;
public class LanguageSelectionTests : ContextualTests
[Collection("appium")]
public class LanguageSelectionTests : AppiumTests
{
// TODO: Verify why zh-TW isn't here (and that hi still hasn't been translated)
private static readonly HashSet<string> ExpectedMissingLanguages = new() { "zh-TW", "hi" };
private readonly WindowsDriver<WindowsElement> _session;
public LanguageSelectionTests()
{
_session = AppiumHelper.StartSession("NAPS2.exe", FolderPath);
}
public override void Dispose()
{
_session.Dispose();
base.Dispose();
}
[VerifyFact]
public void OpenLanguageDropdown()
{
// Open the Language dropdown
ClickAt(_session.FindElementByName("Language"));
ClickAtName("Language");
var menuItems = GetMenuItems();
// Verify all expected languages have menu items
var menuItemTexts = menuItems.Select(x => x.Text).ToHashSet();
var allLanguages = GetAllLanguages();
var missingLanguages = allLanguages
.Where(x => !menuItemTexts.Contains(x.langName) && !ExpectedMissingLanguages.Contains(x.langCode)).ToList();
Assert.True(missingLanguages.Count == 0, $"Missing languages: {string.Join(",", missingLanguages)}");
// Verify French (fr) translation as a standard language example
ClickAt(_session.FindElementByName("Français"));
ClickAt(_session.FindElementByName("Langue"));
ClickAtName("Français");
ClickAtName("Langue");
// Verify Portuguese (pt-BR) translation as a country-specific language example
ClickAt(_session.FindElementByName("Português (Brasil)"));
ClickAt(_session.FindElementByName("Idioma"));
ClickAtName("Português (Brasil)");
ClickAtName("Idioma");
// Verify Hebrew translation as a RTL language example
ClickAt(_session.FindElementByName("עברית"));
ClickAtName("עברית");
// Toggling RTL causes a new window to be created
ResetMainWindow();
ClickAt(_session.FindElementByName("שפה"));
ClickAtName("שפה");
// And back to English
ClickAt(_session.FindElementByName("English"));
ClickAtName("English");
ResetMainWindow();
ClickAt(_session.FindElementByName("Language"));
}
private void ResetMainWindow()
{
_session.SwitchTo().Window(_session.WindowHandles[0]);
}
private void ClickAt(WindowsElement element)
{
#pragma warning disable CS0618
// This is apparently obsolete, but the "correct" code is 10x as complicated so whatever
_session.Mouse.Click(element.Coordinates);
#pragma warning restore CS0618
ClickAtName("Language");
AppTestHelper.AssertNoErrorLog(FolderPath);
}
private List<(string langCode, string langName)> GetAllLanguages()

View File

@ -0,0 +1,39 @@
using System.Threading;
using NAPS2.Sdk.Tests.Asserts;
using Xunit;
namespace NAPS2.App.Tests.Appium;
[Collection("appium")]
public class ScanAndSaveTests : AppiumTests
{
[Fact]
public void ScanWiaSavePdf()
{
// Clicking Scan without a profile opens the profile settings window
ClickAtName("Scan");
// WIA driver is selected by default, so we open the WIA device dialog
ClickAtName("Choose device");
Thread.Sleep(100);
// Click OK in the wia device dialog (selecting the first available device by default)
ClickAt(_session.FindElementsByName("OK")[1]);
// Click OK in the profile settings window
ClickAtName("OK");
// Wait for scanning to finish
WaitUntilGone("Cancel");
ResetMainWindow();
// Save "test.pdf" in the default location (which will be the test data path as NAPS2 knows we're in a test)^
ClickAtName("Save PDF");
ResetMainWindow();
var fileNameElements = _session.FindElementsByName("File name:");
var fileTextBox = fileNameElements.Last();
ClickAt(fileTextBox);
fileTextBox.SendKeys("test.pdf");
ClickAtName("Save");
// Wait for the save to finish, it should be almost instant
Thread.Sleep(200);
PdfAsserts.AssertPageCount(1, Path.Combine(FolderPath, "test.pdf"));
AppTestHelper.AssertNoErrorLog(FolderPath);
}
}

View File

@ -21,6 +21,7 @@
<PackageReference Include="Appium.WebDriver" Version="4.3.2" />
<PackageReference Include="Moq" Version="4.18.1" />
<PackageReference Include="NAPS2.Wia" Version="1.0.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
</ItemGroup>

View File

@ -25,12 +25,14 @@ public static class Paths
if (!string.IsNullOrEmpty(dataPathFromEnv))
{
AppDataPath = dataPathFromEnv;
IsTestAppDataPath = true;
}
var args = Environment.GetCommandLineArgs();
var flagIndex = Array.IndexOf(args, "/Naps2TestData");
if (flagIndex >= 0 && flagIndex < args.Length - 1)
{
AppDataPath = args[flagIndex + 1];
IsTestAppDataPath = true;
}
TempPath = Path.Combine(AppDataPath, "temp");
@ -38,6 +40,11 @@ public static class Paths
ComponentsPath = Path.Combine(AppDataPath, "components");
}
/// <summary>
/// Whether we're in a test and NAPS2_TEST_DATA or /Naps2TestData is set.
/// </summary>
public static readonly bool IsTestAppDataPath;
public static string AppData => EnsureFolderExists(AppDataPath);
public static string Executable => EnsureFolderExists(ExecutablePath);

View File

@ -111,6 +111,11 @@ public class WinFormsDialogHelper : DialogHelper
private string? GetDir(string? defaultPath)
{
if (Paths.IsTestAppDataPath)
{
// For UI test automation we choose the appdata folder for test isolation and consistency
return Paths.AppData;
}
return Path.IsPathRooted(defaultPath)
? Path.GetDirectoryName(defaultPath)
: "";