Browse Source

test(BrokenLinks) Now checking for broken links on a few pages

main
Jonathan McCaffrey 4 years ago
parent
commit
c16c0172bc
  1. 8
      IGP/Index.razor
  2. 2
      IGP/PageLayout.razor
  3. 16
      TestAutomation/BaseTest.cs
  4. 29
      TestAutomation/Pages/BasePage.cs
  5. 11
      TestAutomation/Pages/DatabasePage.cs
  6. 13
      TestAutomation/Pages/DatabaseSinglePage.cs
  7. 18
      TestAutomation/Pages/HarassCalculatorPage.cs
  8. 2
      TestAutomation/Shared/BaseElement.cs
  9. 47
      TestAutomation/TestHarassCalculator.cs
  10. 31
      TestAutomation/TestLinks.cs
  11. 43
      TestAutomation/TestSearchFeatures.cs
  12. 53
      TestAutomation/Utils/TestReport.cs
  13. 38
      TestAutomation/Utils/Website.cs
  14. 4
      TestAutomation/_Tests.cs

8
IGP/Index.razor

@ -1,13 +1,5 @@
@page "/" @page "/"
@inject ITrackingNavigationState TrackingNavigationState
@inject IAnalytics GlobalTracking
@layout PageLayout @layout PageLayout
<DevOnlyComponent>
<LinkButtonComponent Href="https://github.com/JonathanMcCaffrey/IGP-Fan-Reference/blob/main/IGP/Pages/HarassCalculatorPage.razor">
View on GitHub <i class="fa-brands fa-github" style="font-size: 24px; margin-left: 5px;"></i>
</LinkButtonComponent>
</DevOnlyComponent>
<HomePage/> <HomePage/>

2
IGP/PageLayout.razor

@ -14,7 +14,7 @@
} }
else else
{ {
<div class="content"> <div id="content" class="content">
@Body @Body
</div> </div>

16
TestAutomation/BaseTest.cs

@ -10,20 +10,11 @@ public enum DeploymentType
public class BaseTest public class BaseTest
{ {
protected static readonly DeploymentType DeploymentType =
Environment.GetEnvironmentVariable("TEST_HOOK") != null
? DeploymentType.Dev
: DeploymentType.Local;
protected static readonly string WebsiteUrl =
DeploymentType.Equals(DeploymentType.Dev)
? "https://calm-mud-04916b210.1.azurestaticapps.net/"
: "https://localhost:7234";
protected static readonly TestReport TestReport = new(); protected static readonly TestReport TestReport = new();
protected static Website WebsiteInstance = default!; protected static Website WebsiteInstance = default!;
protected readonly HttpClient HttpClient = new();
protected static Website Website protected static Website Website
{ {
@ -35,7 +26,7 @@ public class BaseTest
options.AcceptInsecureCertificates = true; options.AcceptInsecureCertificates = true;
if (DeploymentType.Equals(DeploymentType.Dev)) options.AddArgument("--headless"); if (Website.DeploymentType.Equals(DeploymentType.Dev)) options.AddArgument("--headless");
options.AddArgument("--ignore-certificate-errors"); options.AddArgument("--ignore-certificate-errors");
options.AddArgument("--start-maximized"); options.AddArgument("--start-maximized");
options.AddArgument("--test-type"); options.AddArgument("--test-type");
@ -43,10 +34,11 @@ public class BaseTest
IWebDriver webDriver = new FirefoxDriver(Environment.CurrentDirectory, options); IWebDriver webDriver = new FirefoxDriver(Environment.CurrentDirectory, options);
WebsiteInstance = new Website(webDriver); WebsiteInstance = new Website(webDriver, TestReport);
} }
return WebsiteInstance; return WebsiteInstance;
} }
} }
} }

29
TestAutomation/Pages/BasePage.cs

@ -0,0 +1,29 @@
using TestAutomation.Shared;
using TestAutomation.Utils;
namespace TestAutomation.Pages;
public abstract class BasePage : BaseElement
{
protected BasePage(Website website) : base(website)
{
}
private IEnumerable<string> Links =>
Website.FindAllWithTag(Website.Find("content"), "a")
.Select(x => x.GetAttribute("href"));
public abstract string Url { get; set; }
public IEnumerable<string> GetLinks()
{
try
{
return Links;
}
catch (Exception e)
{
throw new Exception($"Couldn't get links on page {Url}");
}
}
}

11
TestAutomation/Pages/DatabasePage.cs

@ -1,10 +1,9 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using TestAutomation.Shared;
using TestAutomation.Utils; using TestAutomation.Utils;
namespace TestAutomation.Pages; namespace TestAutomation.Pages;
public class DatabasePage : BaseElement public class DatabasePage : BasePage
{ {
public DatabasePage(Website website) : base(website) public DatabasePage(Website website) : base(website)
{ {
@ -12,6 +11,8 @@ public class DatabasePage : BaseElement
private IWebElement FilterNameInput => Website.Find("filterName"); private IWebElement FilterNameInput => Website.Find("filterName");
public override string Url { get; set; } = "database";
private ReadOnlyCollection<IWebElement> EntityNames() private ReadOnlyCollection<IWebElement> EntityNames()
{ {
@ -43,4 +44,10 @@ public class DatabasePage : BaseElement
result = EntityNames()[index].Text; result = EntityNames()[index].Text;
return this; return this;
} }
public DatabasePage Goto()
{
Website.Goto(Url);
return this;
}
} }

13
TestAutomation/Pages/DatabaseSinglePage.cs

@ -1,9 +1,8 @@
using TestAutomation.Shared; using TestAutomation.Utils;
using TestAutomation.Utils;
namespace TestAutomation.Pages; namespace TestAutomation.Pages;
public class DatabaseSinglePage : BaseElement public class DatabaseSinglePage : BasePage
{ {
public DatabaseSinglePage(Website website) : base(website) public DatabaseSinglePage(Website website) : base(website)
{ {
@ -15,6 +14,8 @@ public class DatabaseSinglePage : BaseElement
private IWebElement InvalidSearch => Website.Find("invalidSearch"); private IWebElement InvalidSearch => Website.Find("invalidSearch");
private IWebElement ValidSearch => Website.Find("validSearch"); private IWebElement ValidSearch => Website.Find("validSearch");
public override string Url { get; set; } = "database";
public DatabaseSinglePage GetEntityName(out string result) public DatabaseSinglePage GetEntityName(out string result)
{ {
@ -39,4 +40,10 @@ public class DatabaseSinglePage : BaseElement
result = ValidSearch.Text; result = ValidSearch.Text;
return this; return this;
} }
public DatabaseSinglePage Goto(string searchText)
{
Website.Goto($"{Url}/{searchText}");
return this;
}
} }

18
TestAutomation/Pages/HarassCalculatorPage.cs

@ -1,9 +1,8 @@
using TestAutomation.Shared; using TestAutomation.Utils;
using TestAutomation.Utils;
namespace TestAutomation.Pages; namespace TestAutomation.Pages;
public class HarassCalculatorPage : BaseElement public class HarassCalculatorPage : BasePage
{ {
public HarassCalculatorPage(Website website) : base(website) public HarassCalculatorPage(Website website) : base(website)
{ {
@ -24,6 +23,8 @@ public class HarassCalculatorPage : BaseElement
private int ExampleTotalAlloyLossAccurate => Website.FindInt("exampleTotalAlloyLossAccurate"); private int ExampleTotalAlloyLossAccurate => Website.FindInt("exampleTotalAlloyLossAccurate");
private int ExampleTotalAlloyLossAccurateDifference => Website.FindInt("exampleTotalAlloyLossAccurateDifference"); private int ExampleTotalAlloyLossAccurateDifference => Website.FindInt("exampleTotalAlloyLossAccurateDifference");
public override string Url { get; set; } = "harass-calculator";
public HarassCalculatorPage SetWorkersLostToHarass(int number) public HarassCalculatorPage SetWorkersLostToHarass(int number)
{ {
Website.EnterInput(NumberOfWorkersLostToHarass, number); Website.EnterInput(NumberOfWorkersLostToHarass, number);
@ -84,4 +85,15 @@ public class HarassCalculatorPage : BaseElement
result = ExampleTotalAlloyLossAccurateDifference; result = ExampleTotalAlloyLossAccurateDifference;
return this; return this;
} }
protected HarassCalculatorPage NavigateTo()
{
return this;
}
public HarassCalculatorPage Goto()
{
Website.Goto(Url);
return this;
}
} }

2
TestAutomation/Shared/BaseElement.cs

@ -2,7 +2,7 @@
namespace TestAutomation.Shared; namespace TestAutomation.Shared;
public class BaseElement public abstract class BaseElement
{ {
protected readonly Website Website; protected readonly Website Website;

47
TestAutomation/TestHarassCalculator.cs

@ -5,41 +5,43 @@ namespace TestAutomation;
[TestFixture] [TestFixture]
public class TestHarassCalculator : BaseTest public class TestHarassCalculator : BaseTest
{ {
[SetUp]
public void SetUp()
{
TestReport.CreateTest();
}
[TearDown]
public void TearDown()
{
TestReport.ThrowErrors();
}
[Test] [Test]
public void CalculatorInput() public void CalculatorInput()
{ {
TestReport.CreateTest();
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl + "/harass-calculator");
var expectedTotalAlloyHarassment = 240; var expectedTotalAlloyHarassment = 240;
try Website.HarassCalculatorPage
{ .Goto()
Website.HarassCalculatorPage .SetWorkersLostToHarass(3)
.SetWorkersLostToHarass(3) .SetNumberOfTownHallsExisting(2)
.SetNumberOfTownHallsExisting(2) .SetTownHallTravelTime(0, 30)
.SetTownHallTravelTime(0, 30) .GetTotalAlloyHarassment(out var foundTotalAlloyHarassment);
.GetTotalAlloyHarassment(out var foundTotalAlloyHarassment);
TestReport.CheckPassed(expectedTotalAlloyHarassment.Equals(foundTotalAlloyHarassment),
TestReport.CheckPassed(expectedTotalAlloyHarassment.Equals(foundTotalAlloyHarassment), TestMessage.CreateFailedMessage($"expectTotalAlloyHarassment of {expectedTotalAlloyHarassment} " +
TestMessage.CreateFailedMessage($"expectTotalAlloyHarassment of {expectedTotalAlloyHarassment} " + "does not equal " +
"does not equal " + $"foundTotalAlloyHarassment of {foundTotalAlloyHarassment} "));
$"foundTotalAlloyHarassment of {foundTotalAlloyHarassment} "));
}
catch (Exception e)
{
TestReport.CheckPassed(false,
TestMessage.CreateFailedMessage(e.StackTrace!));
}
} }
[Test] [Test]
public void CalculatedExampleInformation() public void CalculatedExampleInformation()
{ {
TestReport.CreateTest();
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl + "/harass-calculator");
var expectedExampleTotalAlloyLoss = 720; var expectedExampleTotalAlloyLoss = 720;
var expectedExampleWorkerCost = 300; var expectedExampleWorkerCost = 300;
@ -49,6 +51,7 @@ public class TestHarassCalculator : BaseTest
var expectedExampleTotalAlloyLossAccurateDifference = 270; var expectedExampleTotalAlloyLossAccurateDifference = 270;
Website.HarassCalculatorPage Website.HarassCalculatorPage
.Goto()
.GetExampleTotalAlloyLoss(out var foundTotalAlloyLoss) .GetExampleTotalAlloyLoss(out var foundTotalAlloyLoss)
.GetExampleWorkerCost(out var foundExampleWorkerCost) .GetExampleWorkerCost(out var foundExampleWorkerCost)
.GetExampleMiningTimeCost(out var foundExampleMiningTimeCost) .GetExampleMiningTimeCost(out var foundExampleMiningTimeCost)

31
TestAutomation/TestLinks.cs

@ -0,0 +1,31 @@
namespace TestAutomation;
[TestFixture]
public class TestLinks : BaseTest
{
[SetUp]
public void SetUp()
{
TestReport.CreateTest();
}
[TearDown]
public void TearDown()
{
TestReport.ThrowErrors();
}
[Test]
public void VerifyPageLinks()
{
Website.HarassCalculatorPage.Goto();
TestReport.VerifyLinks(Website.HarassCalculatorPage).Wait();
Website.DatabasePage.Goto();
TestReport.VerifyLinks(Website.DatabasePage).Wait();
Website.DatabaseSinglePage.Goto("throne");
TestReport.VerifyLinks(Website.DatabaseSinglePage).Wait();
}
}

43
TestAutomation/TestSearchFeatures.cs

@ -5,14 +5,27 @@ namespace TestAutomation;
[TestFixture] [TestFixture]
public class TestSearchFeatures : BaseTest public class TestSearchFeatures : BaseTest
{ {
[SetUp]
public void SetUp()
{
TestReport.CreateTest();
}
[TearDown]
public void TearDown()
{
TestReport.ThrowErrors();
}
[Test] [Test]
public void DesktopOpenCloseSearchDialog() public void DesktopOpenCloseSearchDialog()
{ {
TestReport.CreateTest();
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl + "/");
Website.NavigationBar Website
.Goto()
.NavigationBar
.ClickSearchButton() .ClickSearchButton()
.CloseDialog() .CloseDialog()
.ClickHomeLink(); .ClickHomeLink();
@ -21,12 +34,10 @@ public class TestSearchFeatures : BaseTest
[Test] [Test]
public void DesktopSearchForThrone() public void DesktopSearchForThrone()
{ {
TestReport.CreateTest();
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl + "/");
Website.NavigationBar Website
.ClickSearchButton() .Goto()
.NavigationBar.ClickSearchButton()
.Search("Throne") .Search("Throne")
.SelectSearchEntity("Throne") .SelectSearchEntity("Throne")
.GetEntityName(out var name) .GetEntityName(out var name)
@ -36,45 +47,47 @@ public class TestSearchFeatures : BaseTest
new TestMessage { Description = "Couldn't find Throne via search." }); new TestMessage { Description = "Couldn't find Throne via search." });
TestReport.CheckPassed(!health.Trim().Equals(""), TestReport.CheckPassed(!health.Trim().Equals(""),
new TestMessage { Description = "Throne has no visible health!" }); new TestMessage { Description = "Throne has no visible health!" });
} }
[Test] [Test]
public void DesktopFilterForThrone() public void DesktopFilterForThrone()
{ {
TestReport.CreateTest();
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl + "/database");
Website.DatabasePage Website.DatabasePage
.Goto()
.FilterName("Throne") .FilterName("Throne")
.GetEntityName(0, out var name); .GetEntityName(0, out var name);
TestReport.CheckPassed(name.Equals("Throne"), TestReport.CheckPassed(name.Equals("Throne"),
new TestMessage { Description = "Couldn't find Throne via filter." }); new TestMessage { Description = "Couldn't find Throne via filter." });
} }
[Test] [Test]
public void SeeThroneByDefault() public void SeeThroneByDefault()
{ {
TestReport.CreateTest();
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl + "/database");
Website.DatabasePage Website.DatabasePage
.Goto()
.GetEntityName("army", "throne", out var name); .GetEntityName("army", "throne", out var name);
TestReport.CheckPassed(name.Equals("Throne"), TestReport.CheckPassed(name.Equals("Throne"),
new TestMessage { Description = "Couldn't find Throne on the page by default." }); new TestMessage { Description = "Couldn't find Throne on the page by default." });
} }
[Test] [Test]
public void DirectLinkNotThroneFailure() public void DirectLinkNotThroneFailure()
{ {
TestReport.CreateTest();
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl + "/database/not throne");
Website.DatabaseSinglePage Website.DatabaseSinglePage
.Goto("not throne")
.GetInvalidSearch(out var invalidSearch) .GetInvalidSearch(out var invalidSearch)
.GetValidSearch(out var validSearch); .GetValidSearch(out var validSearch);
@ -83,6 +96,6 @@ public class TestSearchFeatures : BaseTest
TestReport.CheckPassed(validSearch.Equals("Throne"), TestReport.CheckPassed(validSearch.Equals("Throne"),
new TestMessage { Description = "Couldn't find valid search text on the page." }); new TestMessage { Description = "Couldn't find valid search text on the page." });
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl + "/database/not throne");
} }
} }

53
TestAutomation/Utils/TestReport.cs

@ -11,18 +11,63 @@ public class TestReport
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
public Test CreateTest() public Test CreateTest()
{ {
var testName = new StackTrace().GetFrame(1)!.GetMethod()!.Name!; Tests.Add(new Test
Tests.Add(new Test { Name = testName }); {
Name = TestContext.CurrentContext.Test.Name
});
return Tests.Last(); return Tests.Last();
} }
public void ThrowErrors()
{
if (!Tests.Last().Result)
{
string messages = string.Join("\n", Tests.Last().Messages.Select(x => x.Description).ToList());
throw new Exception(
$"{Tests.Last().Name} test failed with {Tests.Last().Messages.Count} messages.\n\n{messages}");
}
}
public async Task VerifyLinks(BasePage page)
{
foreach (var link in page.GetLinks())
try
{
if(link.StartsWith("mailto")) continue;
using var client = new HttpClient();
var response = await client.GetAsync(link);
if (!response.IsSuccessStatusCode)
{
CheckPassed(false,
new TestMessage
{
Color = "red", Title = "Bad Link",
Description = $"{link} failed on page {page.Url} with status code {response.StatusCode}"
});
Console.WriteLine(response.StatusCode.ToString());
}
}
catch (Exception e)
{
CheckPassed(false,
new TestMessage
{
Color = "red", Title = "Bad Link",
Description = $"{link} failed on page {page.Url} with stacktrace {e.StackTrace}"
});
}
}
public void CheckPassed(bool passed, TestMessage message) public void CheckPassed(bool passed, TestMessage message)
{ {
if (passed) return; if (passed) return;
Tests.Last().Result = false; Tests.Last().Result = false;
Tests.Last().Messages.Add(message); Tests.Last().Messages.Add(message);
throw new Exception(message.Description);
} }
public bool DidTestsPass() public bool DidTestsPass()

38
TestAutomation/Utils/Website.cs

@ -7,11 +7,24 @@ namespace TestAutomation.Utils;
public class Website public class Website
{ {
public static readonly DeploymentType DeploymentType =
Environment.GetEnvironmentVariable("TEST_HOOK")!.Contains("localhost")
? DeploymentType.Local
: DeploymentType.Dev;
public static readonly string Url =
DeploymentType.Equals(DeploymentType.Dev)
? "https://calm-mud-04916b210.1.azurestaticapps.net"
: "https://localhost:7234";
public readonly ScreenType ScreenType = ScreenType.Desktop; public readonly ScreenType ScreenType = ScreenType.Desktop;
public Website(IWebDriver webDriver) public TestReport TestReport { get; set; }
public Website(IWebDriver webDriver, TestReport testReport)
{ {
WebDriver = webDriver; WebDriver = webDriver;
TestReport = testReport;
// Pages // Pages
HarassCalculatorPage = new HarassCalculatorPage(this); HarassCalculatorPage = new HarassCalculatorPage(this);
@ -100,6 +113,16 @@ public class Website
} }
} }
public ReadOnlyCollection<IWebElement> FindAllWithTag(string tag)
{
return WebDriver.FindElements(By.TagName(tag));
}
public ReadOnlyCollection<IWebElement> FindAllWithTag(IWebElement parent, string tag)
{
return parent.FindElements(By.TagName(tag));
}
public IWebElement FindButtonWithLabel(string label) public IWebElement FindButtonWithLabel(string label)
{ {
@ -177,4 +200,17 @@ public class Website
{ {
return Find(byId).Text; return Find(byId).Text;
} }
public Website Goto()
{
WebDriver.Navigate().GoToUrl($"{Url}");
return this;
}
public void Goto(string path)
{
var url = $"{Url}/{path}";
WebDriver.Navigate().GoToUrl($"{url}");
}
} }

4
TestAutomation/_Tests.cs

@ -9,15 +9,13 @@ public class Tests : BaseTest
[OneTimeSetUp] [OneTimeSetUp]
public void Setup() public void Setup()
{ {
Website.WebDriver.Navigate().GoToUrl(WebsiteUrl); Website.Goto();
Website.WebDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(15); Website.WebDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(15);
} }
[OneTimeTearDown] [OneTimeTearDown]
public void TearDown() public void TearDown()
{ {
HttpClient HttpClient = new();
Website.WebDriver.Quit(); Website.WebDriver.Quit();
var message = new var message = new

Loading…
Cancel
Save