webtestpractice/PlaywrightTests/GumbyPageTests.cs

138 lines
4.4 KiB
C#
Executable File

using NUnit.Framework;
using System.Text.RegularExpressions;
using Microsoft.Playwright;
using Microsoft.Playwright.NUnit;
using NUnit.Framework.Internal;
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
[TestFixture]
public partial class GumbyPageTests : PageTest
{
private const string ScreenshotRoot = "../../../screenshots/";
private const string HomeUrl = "http://localhost:5296";
private const int AppInitDelay = 5000;
private IPage? _page;
private IBrowser? _browser;
[GeneratedRegex("Home page")]
private static partial Regex HomePageRegex();
[GeneratedRegex(".*Gumby")]
private static partial Regex GumbyUrlRegex();
[SetUp]
public async Task Init()
{
_browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions() { Headless = true, });
_page = await _browser.NewPageAsync();
await WaitForApp(_page);
}
[Test]
public async Task GumbyOptionShouldBePresentInMenu()
{
// Confirm we've found the Gumby link in the header
var gumbyPageLink = _page!.GetByRole(AriaRole.Link, new PageGetByRoleOptions { Name = "Gumby" });
await Expect(gumbyPageLink).ToHaveAttributeAsync("href", "/Gumby");
}
[Test]
public async Task NavigationToGumbyPageShouldSucceed()
{
await GotoGumby(_page!);
await PageSnap(_page!, "gumby.png");
await Expect(_page!).ToHaveURLAsync(GumbyUrlRegex());
}
[Test]
public async Task GumbyImageShouldBePresentOnBrowser()
{
await GotoGumby(_page!);
Expect(_page!.GetByRole(AriaRole.Img, new PageGetByRoleOptions { Name = "Gumby" }));
}
[Test]
public async Task ResponseFromButtonShouldNotTakeTooLong()
{
/*
* This test will sometimes pass, and sometimes fail, if the randomizer on MyWebApp is working correctly.
* That is BY DESIGN. It's meant to show (at least in a rudimentary way) how a Playwright test can be used
* to do synthetic monitoring.
*/
await GotoGumby(_page!);
const int delay = 10; //MyWebApp is set to 12 seconds, so it should fail sometimes
const int delayMillis = delay * 1000; // A thousand milliseconds in a second
await _page!.GetByText("Clear").ClickAsync(); //clear the label first.
await PageSnap(_page!, "gumby-before-button-press.png");
await _page!.GetByText("Press Me!").ClickAsync();
await PageSnap(_page!, "/gumby-after-button-press-during-wait.png");
await Expect(_page!.Locator("label[id=result]"))
.ToContainTextAsync("You Pressed The Button", new LocatorAssertionsToContainTextOptions {Timeout = delayMillis});
await PageSnap(_page!, "gumby-after-test-completion.png");
}
/*** HELPERS ***/
private static async Task PageSnap(IPage page, string filename)
{
await page.ScreenshotAsync(new PageScreenshotOptions { FullPage = true, Path = ScreenshotRoot+"/"+filename});
}
private static async Task ElementSnap(ILocator locator, string filename)
{
await locator.ScreenshotAsync(new LocatorScreenshotOptions { Path = ScreenshotRoot+"/"+filename });
}
private static async Task GotoGumby(IPage page)
{
await page.GetByRole(AriaRole.Link, new PageGetByRoleOptions { Name = "Gumby" }).ClickAsync();
}
private static async Task WaitForApp(IPage page)
{
var pageIsLoaded = false;
while (!pageIsLoaded)
{
try
{
await page.GotoAsync(HomeUrl, new PageGotoOptions() { Timeout = AppInitDelay });
pageIsLoaded = true;
}
catch
{
await Task.Delay(AppInitDelay);
}
}
var appIsLoaded = false;
while (!appIsLoaded)
{
try
{
var titleAsync = await page.TitleAsync();
if (HomePageRegex().Match(titleAsync).Success)
{
appIsLoaded = true;
continue;
};
}
catch
{
// _logger.Information("Error loading app");
}
// _logger.Information("App not loaded, delaying before retrying...");
await Task.Delay(AppInitDelay);
}
// _logger.Information($"{nameof(WaitForApp)} completed");
}
}