From 2f04c6f2e1d35107cde26ac6b388f1565658240f Mon Sep 17 00:00:00 2001 From: Volodymyr Demianenko Date: Tue, 27 Aug 2024 10:31:54 +0300 Subject: [PATCH] Add PasePage, DataLoader and Serialization examples from lesson 32 --- .../BasePageAndDataLoader.csproj | 25 +++++++ BasePageAndDataLoader/Data/DataLoader.cs | 34 +++++++++ BasePageAndDataLoader/Data/TestDataLoader.cs | 63 ++++++++++++++++ BasePageAndDataLoader/PageObjects/BasePage.cs | 30 ++++++++ BasePageAndDataLoader/PageObjects/ShopPage.cs | 26 +++++++ .../PageObjects/SolarPanelsPage.cs | 74 +++++++++++++++++++ .../SolarTechnologyTests.cs | 46 ++++++++++++ BasePageAndDataLoader/UITestFixture.cs | 36 +++++++++ HilelTests.sln | 6 ++ 9 files changed, 340 insertions(+) create mode 100644 BasePageAndDataLoader/BasePageAndDataLoader.csproj create mode 100644 BasePageAndDataLoader/Data/DataLoader.cs create mode 100644 BasePageAndDataLoader/Data/TestDataLoader.cs create mode 100644 BasePageAndDataLoader/PageObjects/BasePage.cs create mode 100644 BasePageAndDataLoader/PageObjects/ShopPage.cs create mode 100644 BasePageAndDataLoader/PageObjects/SolarPanelsPage.cs create mode 100644 BasePageAndDataLoader/SolarTechologyTests/SolarTechnologyTests.cs create mode 100644 BasePageAndDataLoader/UITestFixture.cs diff --git a/BasePageAndDataLoader/BasePageAndDataLoader.csproj b/BasePageAndDataLoader/BasePageAndDataLoader.csproj new file mode 100644 index 0000000..d7aefca --- /dev/null +++ b/BasePageAndDataLoader/BasePageAndDataLoader.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + diff --git a/BasePageAndDataLoader/Data/DataLoader.cs b/BasePageAndDataLoader/Data/DataLoader.cs new file mode 100644 index 0000000..17b424b --- /dev/null +++ b/BasePageAndDataLoader/Data/DataLoader.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SolarTechnology.Data +{ + public class ManufacturerData + { + public string Manufacturer { get; set; } + public int Id { get; set; } + public string aaaaa { get; set; } + } + + public static class DataLoader + { + public static string GetManufacturer() + { + var save = new ManufacturerData(); + save.Manufacturer = "save text"; + save.Id = 20; + + + TestDataLoader.SaveJson(@"C:\tmp\m2.json", save); + + var testData = TestDataLoader.LoadJson(@"C:\tmp\m.json"); + + // Use test data in the test + return testData.Manufacturer; + + } + } +} diff --git a/BasePageAndDataLoader/Data/TestDataLoader.cs b/BasePageAndDataLoader/Data/TestDataLoader.cs new file mode 100644 index 0000000..18f0456 --- /dev/null +++ b/BasePageAndDataLoader/Data/TestDataLoader.cs @@ -0,0 +1,63 @@ +using System.IO; +using Newtonsoft.Json; + +namespace SolarTechnology.Data +{ + + public static class TestDataLoader + { + /// + /// Loads test data from a JSON file. + /// + /// The type of object to deserialize the data into. + /// The relative or absolute path to the JSON file. + /// The deserialized object of type T. + public static ManufacturerData LoadJson(string filePath) + { + if (!File.Exists(filePath)) + { + throw new FileNotFoundException($"The file '{filePath}' was not found."); + } + + string jsonData = File.ReadAllText(filePath); + return JsonConvert.DeserializeObject(jsonData); + } + + public static void SaveJson(string filePath, T objectToSave) + { + File.WriteAllText(filePath, JsonConvert.SerializeObject(objectToSave)); + } + + /// + /// Loads test data from a CSV file. + /// + /// The relative or absolute path to the CSV file. + /// A list of string arrays representing the rows in the CSV file. + public static List LoadCsv(string filePath) + { + if (!File.Exists(filePath)) + { + throw new FileNotFoundException($"The file '{filePath}' was not found."); + } + + var lines = File.ReadAllLines(filePath); + return lines.Select(line => line.Split(',')).ToList(); + } + + /// + /// Loads test data from a plain text file. + /// + /// The relative or absolute path to the text file. + /// A string representing the content of the text file. + public static string LoadText(string filePath) + { + if (!File.Exists(filePath)) + { + throw new FileNotFoundException($"The file '{filePath}' was not found."); + } + + return File.ReadAllText(filePath); + } + } + +} diff --git a/BasePageAndDataLoader/PageObjects/BasePage.cs b/BasePageAndDataLoader/PageObjects/BasePage.cs new file mode 100644 index 0000000..bbb0747 --- /dev/null +++ b/BasePageAndDataLoader/PageObjects/BasePage.cs @@ -0,0 +1,30 @@ +using Microsoft.Playwright; + +namespace SolarTechnology.PageObjects +{ + internal abstract class BasePage + { + internal IPage Page; + + + public BasePage(IPage page) + { + Page = page; + } + + public abstract string GetUrl(); + + public async Task GoTo() + { + await Page.GotoAsync(GetUrl()); + } + + public async Task WaitForLoader() + { + ILocator locator = Page.Locator("#p_prldr"); + await locator.WaitForAsync(new() { State = WaitForSelectorState.Visible }); + await locator.WaitForAsync(new() { State = WaitForSelectorState.Hidden }); + } + + } +} diff --git a/BasePageAndDataLoader/PageObjects/ShopPage.cs b/BasePageAndDataLoader/PageObjects/ShopPage.cs new file mode 100644 index 0000000..2db919a --- /dev/null +++ b/BasePageAndDataLoader/PageObjects/ShopPage.cs @@ -0,0 +1,26 @@ +using Microsoft.Playwright; + +namespace SolarTechnology.PageObjects +{ + internal class ShopPage : BasePage + { + //private IPage _page; + private string shopPageUrl = "https://solartechnology.com.ua/shop"; + + public override string GetUrl() + { + return shopPageUrl; + } + + public ShopPage(IPage page) : base (page) + { + //_page = page; + } + + //public async Task GoToShopPage() + //{ + // await Page.GotoAsync(shopPageUrl); + //} + + } +} diff --git a/BasePageAndDataLoader/PageObjects/SolarPanelsPage.cs b/BasePageAndDataLoader/PageObjects/SolarPanelsPage.cs new file mode 100644 index 0000000..14816cf --- /dev/null +++ b/BasePageAndDataLoader/PageObjects/SolarPanelsPage.cs @@ -0,0 +1,74 @@ +using Microsoft.Playwright; + +namespace SolarTechnology.PageObjects +{ + internal class SolarPanelsPage : BasePage + { + //private IPage Page; + private string shopSolarPanelsUrl = "https://solartechnology.com.ua/shop/solar-panels"; + public override string GetUrl() + { + return shopSolarPanelsUrl; + } + + public SolarPanelsPage(IPage page) : base(page) + { + //Page = page; + } + + //public async Task GoToSolarPanelsPage() + //{ + // await Page.GotoAsync(shopSolarPanelsUrl); + //} + + public async Task ClickFiltersButton() + { + await Page.GetByText("Фільтр товарів").ClickAsync(); + } + + public async Task GetFirstProductFullTitle() + { + return await Page.Locator(".list-product-title").First.InnerTextAsync(); + } + + public async Task ClickFilterManufacturerByName(string name) + { + //var waitForRequestTask = Page.WaitForRequestAsync("**/solar-panels?filter%5Bbrand%5D=*"); + await Page.Locator($"//span[text()='{name}']").ClickAsync(); + + await WaitForLoader(); + + //await waitForRequestTask; + } + + public async Task VerifySolarPanelsPageLoaded() + { + //await Page.WaitForURLAsync(shopSolarPanelsUrl); + await Page.WaitForURLAsync(GetUrl()); + var linkElements = Page.GetByRole(AriaRole.Link); + await Assertions.Expect(linkElements.First).ToBeVisibleAsync(); + } + + public async Task VerifyFilterSectionVisible() + { + await Assertions.Expect(Page.Locator("[name='filter[elements]']").First).ToBeVisibleAsync(); + } + + public async Task CheckProductSectionLoaded() + { + await Assertions.Expect(Page.Locator(".list-product-title").Last).ToBeVisibleAsync(); + } + + public async Task IsFirstProductTitleContainsExpectedText(string expected_text) + { + await Page.WaitForSelectorAsync(".list-product-title"); + string productInnertext = await Page.Locator(".list-product-title").First.InnerTextAsync(); + var spaceIndex = productInnertext.IndexOf(' '); + + string trimmedExpected = expected_text.Remove(spaceIndex).ToLower(); + string trimmedTitle = productInnertext.Remove(spaceIndex).ToLower(); + + return (trimmedExpected == trimmedTitle); + } + } +} diff --git a/BasePageAndDataLoader/SolarTechologyTests/SolarTechnologyTests.cs b/BasePageAndDataLoader/SolarTechologyTests/SolarTechnologyTests.cs new file mode 100644 index 0000000..e0342bc --- /dev/null +++ b/BasePageAndDataLoader/SolarTechologyTests/SolarTechnologyTests.cs @@ -0,0 +1,46 @@ +using PlaywrigthUITests; +using SolarTechnology.Data; +using SolarTechnology.PageObjects; + +namespace SolarTechnology.SolarTechologyTests; + +public class SolarTechnologyTests : UITestFixture +{ + private ShopPage _shopPage; + private SolarPanelsPage _solarPanelsPage; + + [Description("Checking 'Solar panels' page functionality")] + [SetUp] + public void SetupShopPage() + { + _shopPage = new ShopPage(Page); + _solarPanelsPage = new SolarPanelsPage(Page); + } + + [Test] + [Description("Verify that catalog filter by name works correctly")] + public async Task CheckSolarPanelCatalogFilterByName() + { + //Arrange + await _shopPage.GoTo(); + + //await _solarPanelsPage.GoToSolarPanelsPage(); + await _solarPanelsPage.GoTo(); + await _solarPanelsPage.VerifySolarPanelsPageLoaded(); + await _solarPanelsPage.ClickFiltersButton(); + await _solarPanelsPage.VerifyFilterSectionVisible(); + + //Act + + var manufacturer = DataLoader.GetManufacturer(); + + //string manufacturer = await _solarPanelsPage.GetFilterManufacturerNameById(id); + await _solarPanelsPage.CheckProductSectionLoaded(); + await _solarPanelsPage.ClickFilterManufacturerByName(manufacturer); + var result = await _solarPanelsPage.IsFirstProductTitleContainsExpectedText(manufacturer); + + //Assert + Assert.True(result == true, $"Manufaturer {manufacturer} is not equal to expected product title after filtering"); + } + +} \ No newline at end of file diff --git a/BasePageAndDataLoader/UITestFixture.cs b/BasePageAndDataLoader/UITestFixture.cs new file mode 100644 index 0000000..9c94333 --- /dev/null +++ b/BasePageAndDataLoader/UITestFixture.cs @@ -0,0 +1,36 @@ +using Microsoft.Playwright; + +namespace PlaywrigthUITests +{ + [Parallelizable(ParallelScope.Self)] + [TestFixture] + public class UITestFixture + { + public IPage Page { get; private set; } + private IBrowser browser; + + [SetUp] + public async Task Setup() + { + var playwrightDriver = await Playwright.CreateAsync(); + browser = await playwrightDriver.Chromium.LaunchAsync(new BrowserTypeLaunchOptions + { + Headless = false, + Args = new List { "--start-maximized" } + }); + var context = await browser.NewContextAsync(new BrowserNewContextOptions + { + ViewportSize = ViewportSize.NoViewport + }); + + Page = await context.NewPageAsync(); + } + + [TearDown] + public async Task Teardown() + { + await Page.CloseAsync(); + await browser.CloseAsync(); + } + } +} diff --git a/HilelTests.sln b/HilelTests.sln index 3ef15f0..35d2f04 100644 --- a/HilelTests.sln +++ b/HilelTests.sln @@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeleniumWithApi", "Selenium EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DifferentExamples", "DifferentExamples\DifferentExamples.csproj", "{6812F743-9C6A-4AFF-B4CD-4F124403B997}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasePageAndDataLoader", "BasePageAndDataLoader\BasePageAndDataLoader.csproj", "{30ADB641-B9F1-4ACE-AA4A-11AA59325636}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -51,6 +53,10 @@ Global {6812F743-9C6A-4AFF-B4CD-4F124403B997}.Debug|Any CPU.Build.0 = Debug|Any CPU {6812F743-9C6A-4AFF-B4CD-4F124403B997}.Release|Any CPU.ActiveCfg = Release|Any CPU {6812F743-9C6A-4AFF-B4CD-4F124403B997}.Release|Any CPU.Build.0 = Release|Any CPU + {30ADB641-B9F1-4ACE-AA4A-11AA59325636}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30ADB641-B9F1-4ACE-AA4A-11AA59325636}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30ADB641-B9F1-4ACE-AA4A-11AA59325636}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30ADB641-B9F1-4ACE-AA4A-11AA59325636}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE