195 lines
5.4 KiB
C#
195 lines
5.4 KiB
C#
using PuppeteerSharp;
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|
|
|
namespace BCards.IntegrationTests.Helpers;
|
|
|
|
public class PuppeteerTestHelper : IAsyncDisposable
|
|
{
|
|
private IBrowser? _browser;
|
|
private IPage? _page;
|
|
private readonly string _baseUrl;
|
|
|
|
public PuppeteerTestHelper(WebApplicationFactory<Program> factory)
|
|
{
|
|
_baseUrl = factory.Server.BaseAddress?.ToString() ?? "https://localhost:49178";
|
|
}
|
|
|
|
public async Task InitializeAsync()
|
|
{
|
|
// Download Chrome if not available
|
|
await new BrowserFetcher().DownloadAsync();
|
|
|
|
_browser = await Puppeteer.LaunchAsync(new LaunchOptions
|
|
{
|
|
Headless = true, // Set to false for debugging
|
|
Args = new[]
|
|
{
|
|
"--no-sandbox",
|
|
"--disable-setuid-sandbox",
|
|
"--disable-dev-shm-usage",
|
|
"--disable-web-security",
|
|
"--allow-running-insecure-content",
|
|
"--ignore-certificate-errors"
|
|
}
|
|
});
|
|
|
|
_page = await _browser.NewPageAsync();
|
|
|
|
// Set viewport for consistent testing
|
|
await _page.SetViewportAsync(new ViewPortOptions
|
|
{
|
|
Width = 1920,
|
|
Height = 1080
|
|
});
|
|
}
|
|
|
|
public IPage Page => _page ?? throw new InvalidOperationException("PuppeteerTestHelper not initialized. Call InitializeAsync first.");
|
|
|
|
public async Task NavigateToAsync(string relativeUrl)
|
|
{
|
|
var fullUrl = new Uri(new Uri(_baseUrl), relativeUrl).ToString();
|
|
await Page.GoToAsync(fullUrl, new NavigationOptions
|
|
{
|
|
WaitUntil = new[] { WaitUntilNavigation.Networkidle0 }
|
|
});
|
|
}
|
|
|
|
public async Task<string> GetPageContentAsync()
|
|
{
|
|
return await Page.GetContentAsync();
|
|
}
|
|
|
|
public async Task<string> GetPageTitleAsync()
|
|
{
|
|
return await Page.GetTitleAsync();
|
|
}
|
|
|
|
public async Task<bool> ElementExistsAsync(string selector)
|
|
{
|
|
try
|
|
{
|
|
await Page.WaitForSelectorAsync(selector, new WaitForSelectorOptions
|
|
{
|
|
Timeout = 5000
|
|
});
|
|
return true;
|
|
}
|
|
catch (WaitTaskTimeoutException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task ClickAsync(string selector)
|
|
{
|
|
await Page.WaitForSelectorAsync(selector);
|
|
await Page.ClickAsync(selector);
|
|
}
|
|
|
|
public async Task TypeAsync(string selector, string text)
|
|
{
|
|
await Page.WaitForSelectorAsync(selector);
|
|
await Page.TypeAsync(selector, text);
|
|
}
|
|
|
|
public async Task FillFormAsync(Dictionary<string, string> formData)
|
|
{
|
|
foreach (var kvp in formData)
|
|
{
|
|
await Page.WaitForSelectorAsync(kvp.Key);
|
|
await Page.EvaluateExpressionAsync($"document.querySelector('{kvp.Key}').value = ''");
|
|
await Page.TypeAsync(kvp.Key, kvp.Value);
|
|
}
|
|
}
|
|
|
|
public async Task SubmitFormAsync(string formSelector)
|
|
{
|
|
await Page.ClickAsync($"{formSelector} button[type='submit'], {formSelector} input[type='submit']");
|
|
}
|
|
|
|
public async Task WaitForNavigationAsync()
|
|
{
|
|
await Page.WaitForNavigationAsync(new NavigationOptions
|
|
{
|
|
WaitUntil = new[] { WaitUntilNavigation.Networkidle0 }
|
|
});
|
|
}
|
|
|
|
public async Task WaitForElementAsync(string selector, int timeoutMs = 10000)
|
|
{
|
|
await Page.WaitForSelectorAsync(selector, new WaitForSelectorOptions
|
|
{
|
|
Timeout = timeoutMs
|
|
});
|
|
}
|
|
|
|
public async Task<string> GetElementTextAsync(string selector)
|
|
{
|
|
await Page.WaitForSelectorAsync(selector);
|
|
var element = await Page.QuerySelectorAsync(selector);
|
|
var text = await Page.EvaluateFunctionAsync<string>("el => el.textContent", element);
|
|
return text?.Trim() ?? string.Empty;
|
|
}
|
|
|
|
public async Task<string> GetElementValueAsync(string selector)
|
|
{
|
|
await Page.WaitForSelectorAsync(selector);
|
|
var element = await Page.QuerySelectorAsync(selector);
|
|
var value = await Page.EvaluateFunctionAsync<string>("el => el.value", element);
|
|
return value ?? string.Empty;
|
|
}
|
|
|
|
public async Task<bool> IsElementVisibleAsync(string selector)
|
|
{
|
|
try
|
|
{
|
|
await Page.WaitForSelectorAsync(selector, new WaitForSelectorOptions
|
|
{
|
|
Visible = true,
|
|
Timeout = 2000
|
|
});
|
|
return true;
|
|
}
|
|
catch (WaitTaskTimeoutException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task TakeScreenshotAsync(string fileName)
|
|
{
|
|
await Page.ScreenshotAsync(fileName);
|
|
}
|
|
|
|
public async Task<string> GetCurrentUrlAsync()
|
|
{
|
|
return Page.Url;
|
|
}
|
|
|
|
public async Task<List<string>> GetAllElementTextsAsync(string selector)
|
|
{
|
|
var elements = await Page.QuerySelectorAllAsync(selector);
|
|
var texts = new List<string>();
|
|
|
|
foreach (var element in elements)
|
|
{
|
|
var text = await Page.EvaluateFunctionAsync<string>("el => el.textContent", element);
|
|
texts.Add(text?.Trim() ?? string.Empty);
|
|
}
|
|
|
|
return texts;
|
|
}
|
|
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
if (_page != null)
|
|
{
|
|
await _page.CloseAsync();
|
|
}
|
|
|
|
if (_browser != null)
|
|
{
|
|
await _browser.CloseAsync();
|
|
}
|
|
}
|
|
} |