App test fixes

This commit is contained in:
Ben Olden-Cooligan 2022-11-13 11:09:22 -08:00
parent cd81202db9
commit c84de96ad9
8 changed files with 431 additions and 27 deletions

View File

@ -1,5 +1,6 @@
using System.Threading;
using NAPS2.Sdk.Tests;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
@ -28,8 +29,9 @@ public class AppiumTests : ContextualTests
base.Dispose();
}
protected void WaitUntilGone(string name)
protected void WaitUntilGone(string name, int timeoutInMs)
{
var stopwatch = Stopwatch.StartNew();
try
{
while (true)
@ -38,6 +40,10 @@ public class AppiumTests : ContextualTests
{
break;
}
if (stopwatch.ElapsedMilliseconds > timeoutInMs)
{
throw new WebDriverException("Timeout waiting for element to be gone");
}
Thread.Sleep(100);
}
}
@ -61,7 +67,7 @@ public class AppiumTests : ContextualTests
protected void ClickAtName(string name)
{
ClickAt(_session.FindElementByName(name));
ClickAt(WaitAndFindElementByName(name));
}
protected void DoubleClickAt(WindowsElement element)
@ -75,6 +81,23 @@ public class AppiumTests : ContextualTests
protected void DoubleClickAtName(string name)
{
DoubleClickAt(_session.FindElementByName(name));
DoubleClickAt(WaitAndFindElementByName(name));
}
protected WindowsElement WaitAndFindElementByName(string name)
{
int i = 0;
while(true)
{
try
{
return _session.FindElementByName(name);
}
catch (WebDriverException)
{
if (++i > 10) throw;
Thread.Sleep(100);
}
}
}
}

View File

@ -12,42 +12,49 @@ 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" };
[VerifyFact]
[VerifyFact(AllowDebug = true)]
public void OpenLanguageDropdown()
{
// Open the Language dropdown
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)}");
if (!Debugger.IsAttached)
{
// 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
ClickAtName("Français");
ClickAtName("Langue");
ClickAndResetWindow("Français");
ClickAndResetWindow("Langue");
// Verify Portuguese (pt-BR) translation as a country-specific language example
ClickAtName("Português (Brasil)");
ClickAtName("Idioma");
ClickAndResetWindow("Português (Brasil)");
ClickAndResetWindow("Idioma");
// Verify Hebrew translation as a RTL language example
ClickAtName("עברית");
// Toggling RTL causes a new window to be created
ResetMainWindow();
ClickAtName("שפה");
ClickAndResetWindow("עברית");
ClickAndResetWindow("שפה");
// And back to English
ClickAtName("English");
ResetMainWindow();
ClickAndResetWindow("English");
ClickAtName("Language");
AppTestHelper.AssertNoErrorLog(FolderPath);
}
private void ClickAndResetWindow(string name)
{
ClickAtName(name);
ResetMainWindow();
}
private List<(string langCode, string langName)> GetAllLanguages()
{
return new CultureHelper(Naps2Config.Stub()).GetAllCultures().ToList();

View File

@ -8,6 +8,9 @@ namespace NAPS2.App.Tests.Appium;
[Collection("appium")]
public class ScanAndSaveTests : AppiumTests
{
private const string WIA_DEVICE_NAME = "";
private const string TWAIN_DEVICE_NAME = "Canon MP495 ser";
[VerifyFact(AllowDebug = true)]
public void ScanWiaSavePdf()
{
@ -16,12 +19,15 @@ public class ScanAndSaveTests : AppiumTests
// WIA driver is selected by default, so we open the WIA device dialog
ClickAtName("Choose device");
Thread.Sleep(100);
if (WIA_DEVICE_NAME != "") ClickAtName(WIA_DEVICE_NAME);
// Click OK in the wia device dialog (selecting the first available device by default)
ClickAt(_session.FindElementsByName("OK")[1]);
// TODO: More consistent way to pick the right OK button
ClickAt(_session.FindElementsByName("OK")[0]);
WaitUntilGone("Properties", 1_000);
// Click OK in the profile settings window
ClickAtName("OK");
// Wait for scanning to finish
WaitUntilGone("Cancel");
WaitUntilGone("Cancel", 30_000);
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");
@ -47,12 +53,14 @@ public class ScanAndSaveTests : AppiumTests
// Open the TWAIN device dialog
ClickAtName("Choose device");
Thread.Sleep(100);
if (TWAIN_DEVICE_NAME != "") ClickAtName(TWAIN_DEVICE_NAME);
// Click Select in the twain device dialog (selecting the first available device by default)
ClickAtName("Select");
WaitUntilGone("Select", 1_000);
// Click OK in the profile settings window
ClickAtName("OK");
// Wait for scanning to finish
WaitUntilGone("Cancel");
WaitUntilGone("Cancel", 30_000);
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 Images");

View File

@ -14,7 +14,7 @@ public class WorkerAppTests : ContextualTests
try
{
Assert.Equal("ready", process.StandardOutput.ReadLine());
string pipeName = $"NAPS2.Worker/{process.Id}";
string pipeName = $"NAPS2.Worker.{process.Id}";
var client = new WorkerServiceAdapter(new NamedPipeChannel(".", pipeName));
client.Init(FolderPath);
AppTestHelper.AssertNoErrorLog(FolderPath);

View File

@ -72,6 +72,9 @@
<data name="FileTypeTiff" xml:space="preserve">
<value>Arquivo TIFF (*.tiff, *.tif)</value>
</data>
<data name="FileTypeJp2" xml:space="preserve">
<value>JPEG2000 File (*.jp2, *.jpx)</value>
</data>
<data name="NameMissing" xml:space="preserve">
<value>Nome está faltando.</value>
</data>
@ -360,6 +363,9 @@
<data name="CheckingForUpdates" xml:space="preserve">
<value>Verificando...</value>
</data>
<data name="UpdateCheckDisabled" xml:space="preserve">
<value>Update checking is disabled.</value>
</data>
<data name="UpdateError" xml:space="preserve">
<value>Ocorreu um erro ao tentar instalar a atualização.</value>
</data>

View File

@ -13,7 +13,7 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BitDepth_1BlackAndWhite" xml:space="preserve">
<value>Preto e Branco</value>
<value>Black/White</value>
</data>
<data name="BitDepth_24Color" xml:space="preserve">
<value>Colorido 24 bits</value>
@ -153,4 +153,13 @@
<data name="WiaVersion_Default" xml:space="preserve">
<value>Padrão</value>
</data>
<data name="OcrMode_Fast" xml:space="preserve">
<value>Fast</value>
</data>
<data name="OcrMode_Best" xml:space="preserve">
<value>Best</value>
</data>
<data name="OcrMode_Legacy" xml:space="preserve">
<value>Legacy</value>
</data>
</root>

View File

@ -0,0 +1,348 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AboutFormTitle" xml:space="preserve">
<value>Sobre</value>
</data>
<data name="Copyright" xml:space="preserve">
<value>Copyright 2009, 2012-2020 NAPS2 Contributors</value>
</data>
<data name="IconsFrom" xml:space="preserve">
<value>Ícones de:</value>
</data>
<data name="CheckForUpdates" xml:space="preserve">
<value>Verificar atualizações</value>
</data>
<data name="OK" xml:space="preserve">
<value>OK</value>
</data>
<data name="Donate" xml:space="preserve">
<value>Doar</value>
</data>
<data name="ProfilesFormTitle" xml:space="preserve">
<value>Perfis</value>
</data>
<data name="Add" xml:space="preserve">
<value>Add</value>
</data>
<data name="Edit" xml:space="preserve">
<value>Editar</value>
</data>
<data name="Delete" xml:space="preserve">
<value>Apagar</value>
</data>
<data name="Scan" xml:space="preserve">
<value>Digitalizar</value>
</data>
<data name="SetDefault" xml:space="preserve">
<value>Definir Padrão</value>
</data>
<data name="Copy" xml:space="preserve">
<value>Copiar</value>
</data>
<data name="Paste" xml:space="preserve">
<value>Colar</value>
</data>
<data name="Done" xml:space="preserve">
<value>Concluído</value>
</data>
<data name="Default" xml:space="preserve">
<value>Padrão</value>
</data>
<data name="NewProfile" xml:space="preserve">
<value>Novo perfil</value>
</data>
<data name="BatchScan" xml:space="preserve">
<value>Digitalização em lote</value>
</data>
<data name="Ocr" xml:space="preserve">
<value>OCR</value>
</data>
<data name="Profiles" xml:space="preserve">
<value>Perfis</value>
</data>
<data name="Import" xml:space="preserve">
<value>Importar</value>
</data>
<data name="SavePdf" xml:space="preserve">
<value>Salvar PDF</value>
</data>
<data name="PdfSettings" xml:space="preserve">
<value>Configurações de PDF</value>
</data>
<data name="SaveImages" xml:space="preserve">
<value>Salvar imagens</value>
</data>
<data name="ImageSettings" xml:space="preserve">
<value>Configurações de imagem</value>
</data>
<data name="EmailPdf" xml:space="preserve">
<value>Email PDF</value>
</data>
<data name="EmailSettings" xml:space="preserve">
<value>Configurações de e-mail</value>
</data>
<data name="Print" xml:space="preserve">
<value>Imprimir</value>
</data>
<data name="Image" xml:space="preserve">
<value>Imagem</value>
</data>
<data name="View" xml:space="preserve">
<value>Visualizar</value>
</data>
<data name="Crop" xml:space="preserve">
<value>Cortar</value>
</data>
<data name="BrightnessContrast" xml:space="preserve">
<value>Brilho / Contraste</value>
</data>
<data name="HueSaturation" xml:space="preserve">
<value>Tom / Saturação</value>
</data>
<data name="BlackAndWhite" xml:space="preserve">
<value>Preto e Branco</value>
</data>
<data name="Sharpen" xml:space="preserve">
<value>Nitidez</value>
</data>
<data name="DocumentCorrection" xml:space="preserve">
<value>Document Correction</value>
</data>
<data name="Reset" xml:space="preserve">
<value>Restaurar</value>
</data>
<data name="Rotate" xml:space="preserve">
<value>Rotacionar</value>
</data>
<data name="RotateLeft" xml:space="preserve">
<value>Girar para esquerda</value>
</data>
<data name="RotateRight" xml:space="preserve">
<value>Girar para direita</value>
</data>
<data name="Flip" xml:space="preserve">
<value>Inverter</value>
</data>
<data name="Deskew" xml:space="preserve">
<value>Endireitar</value>
</data>
<data name="CustomRotation" xml:space="preserve">
<value>Rotação personalizada</value>
</data>
<data name="MoveUp" xml:space="preserve">
<value>Mover acima</value>
</data>
<data name="MoveDown" xml:space="preserve">
<value>Mover abaixo</value>
</data>
<data name="Reorder" xml:space="preserve">
<value>Reordenar</value>
</data>
<data name="Interleave" xml:space="preserve">
<value>Intercalar</value>
</data>
<data name="Deinterleave" xml:space="preserve">
<value>Desintercalar</value>
</data>
<data name="AltInterleave" xml:space="preserve">
<value>Intercalar Alternado</value>
</data>
<data name="AltDeinterleave" xml:space="preserve">
<value>Desintercalar Alternado</value>
</data>
<data name="Reverse" xml:space="preserve">
<value>Inverter</value>
</data>
<data name="Clear" xml:space="preserve">
<value>Limpar</value>
</data>
<data name="ClearAll" xml:space="preserve">
<value>Clear All</value>
</data>
<data name="Language" xml:space="preserve">
<value>Idioma</value>
</data>
<data name="About" xml:space="preserve">
<value>Sobre</value>
</data>
<data name="Zoom" xml:space="preserve">
<value>Zoom</value>
</data>
<data name="ZoomIn" xml:space="preserve">
<value>Ampliar</value>
</data>
<data name="ZoomOut" xml:space="preserve">
<value>Diminuir</value>
</data>
<data name="Save" xml:space="preserve">
<value>Save</value>
</data>
<data name="SaveAllAsPdf" xml:space="preserve">
<value>Save All as PDF</value>
</data>
<data name="SaveSelectedAsPdf" xml:space="preserve">
<value>Save Selected as PDF</value>
</data>
<data name="SaveAllAsImages" xml:space="preserve">
<value>Save All as Images</value>
</data>
<data name="SaveSelectedAsImages" xml:space="preserve">
<value>Save Selected as Images</value>
</data>
<data name="EmailAllAsPdf" xml:space="preserve">
<value>Email All as PDF</value>
</data>
<data name="EmailSelectedAsPdf" xml:space="preserve">
<value>Email Selected as PDF</value>
</data>
<data name="EditProfileFormTitle" xml:space="preserve">
<value>Configurar Perfil</value>
</data>
<data name="DisplayNameLabel" xml:space="preserve">
<value>Nome para exibição:</value>
</data>
<data name="WiaDriver" xml:space="preserve">
<value>Driver WIA</value>
</data>
<data name="TwainDriver" xml:space="preserve">
<value>Driver TWAIN</value>
</data>
<data name="AppleDriver" xml:space="preserve">
<value>Apple Driver</value>
</data>
<data name="SaneDriver" xml:space="preserve">
<value>Driver SANE</value>
</data>
<data name="DeviceLabel" xml:space="preserve">
<value>Dispositivo:</value>
</data>
<data name="ChooseDevice" xml:space="preserve">
<value>Escolha o dispositivo</value>
</data>
<data name="UsePredefinedSettings" xml:space="preserve">
<value>Usar configurações padrões</value>
</data>
<data name="UseNativeUi" xml:space="preserve">
<value>Usar WIA UI nativo</value>
</data>
<data name="PaperSourceLabel" xml:space="preserve">
<value>Origem do papel:</value>
</data>
<data name="PageSizeLabel" xml:space="preserve">
<value>Tamanho da folha:</value>
</data>
<data name="ResolutionLabel" xml:space="preserve">
<value>Resolução:</value>
</data>
<data name="BrightnessLabel" xml:space="preserve">
<value>Brilho:</value>
</data>
<data name="BitDepthLabel" xml:space="preserve">
<value>Qualidade:</value>
</data>
<data name="HorizontalAlignLabel" xml:space="preserve">
<value>Alinhamento horizontal:</value>
</data>
<data name="ScaleLabel" xml:space="preserve">
<value>Escala:</value>
</data>
<data name="ContrastLabel" xml:space="preserve">
<value>Contraste:</value>
</data>
<data name="EnableAutoSave" xml:space="preserve">
<value>Ativar Auto Salvamento</value>
</data>
<data name="AutoSaveSettings" xml:space="preserve">
<value>Configurações de salvamento automático</value>
</data>
<data name="Advanced" xml:space="preserve">
<value>Avançado</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancelar</value>
</data>
<data name="Select" xml:space="preserve">
<value>Selecionar</value>
</data>
<data name="SelectSource" xml:space="preserve">
<value>Selecionar origem</value>
</data>
<data name="RunInBackground" xml:space="preserve">
<value>Executar em segundo plano</value>
</data>
<data name="Naps2" xml:space="preserve">
<value>NAPS2</value>
</data>
<data name="Naps2TitleFormat" xml:space="preserve">
<value>NAPS2 - {0}</value>
</data>
<data name="Naps2FullName" xml:space="preserve">
<value>Not Another PDF Scanner</value>
</data>
<data name="OcrSetupFormTitle" xml:space="preserve">
<value>Configuração do OCR</value>
</data>
<data name="MakePdfsSearchable" xml:space="preserve">
<value>Criar PDF pesquisável usando OCR</value>
</data>
<data name="OcrLanguageLabel" xml:space="preserve">
<value>Idioma do OCR:</value>
</data>
<data name="OcrModeLabel" xml:space="preserve">
<value>Modo do OCR:</value>
</data>
<data name="RunOcrAfterScanning" xml:space="preserve">
<value>Executar automaticamente o OCR após a digitalização</value>
</data>
<data name="GetMoreLanguages" xml:space="preserve">
<value>Instalar mais idiomas</value>
</data>
<data name="OcrDownloadFormTitle" xml:space="preserve">
<value>Baixar OCR</value>
</data>
<data name="OcrDownloadSummaryText" xml:space="preserve">
<value>O uso do OCR requer que você baixe cada linguagem que deseja escanear.</value>
</data>
<data name="OcrSelectLanguageLabel" xml:space="preserve">
<value>Selecione uma ou mais linguagens:</value>
</data>
<data name="EstimatedDownloadSize" xml:space="preserve">
<value>Tamanho estimado do download: {0} MB</value>
</data>
<data name="Download" xml:space="preserve">
<value>Baixar</value>
</data>
<data name="DownloadProgressFormTitle" xml:space="preserve">
<value>Progresso do download</value>
</data>
<data name="PreviewFormTitle" xml:space="preserve">
<value>Visualizar</value>
</data>
<data name="Next" xml:space="preserve">
<value>Próximo</value>
</data>
<data name="Previous" xml:space="preserve">
<value>Anterior</value>
</data>
<data name="XOfY" xml:space="preserve">
<value>{0} de {1}</value>
</data>
<data name="Revert" xml:space="preserve">
<value>Reverter</value>
</data>
<data name="ApplyToSelected" xml:space="preserve">
<value>Aplicar para todas as {0} imagens selecionadas</value>
</data>
</root>

View File

@ -50,6 +50,7 @@
<EmbeddedResource Remove="Lang\Resources\SettingsResources.*.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\SettingsResources.fr.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\SettingsResources.he.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\SettingsResources.pt-BR.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Update="Lang\Resources\SettingsResources.*.resx">
<DependentUpon>SettingsResources.resx</DependentUpon>
</EmbeddedResource>
@ -57,6 +58,7 @@
<EmbeddedResource Remove="Lang\Resources\MiscResources.*.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\MiscResources.fr.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\MiscResources.he.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\MiscResources.pt-BR.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Update="Lang\Resources\MiscResources.*.resx">
<DependentUpon>MiscResources.resx</DependentUpon>
</EmbeddedResource>
@ -64,6 +66,7 @@
<EmbeddedResource Remove="Lang\Resources\UiStrings.*.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\UiStrings.fr.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\UiStrings.he.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Include="Lang\Resources\UiStrings.pt-BR.resx" Condition="'$(Configuration)' == 'Debug'" />
<EmbeddedResource Update="Lang\Resources\UiStrings.*.resx">
<DependentUpon>UiStrings.resx</DependentUpon>
</EmbeddedResource>