diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..386c5c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bin +obj +.DS_Store +.vs +local.log +BrowserStackLocal.exe diff --git a/PlaywrightDotnetTests.csproj b/PlaywrightDotnetTests.csproj new file mode 100644 index 0000000..2aa95a6 --- /dev/null +++ b/PlaywrightDotnetTests.csproj @@ -0,0 +1,19 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + + + + diff --git a/PlaywrightDotnetTests.sln b/PlaywrightDotnetTests.sln new file mode 100644 index 0000000..f5b1c1a --- /dev/null +++ b/PlaywrightDotnetTests.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.810.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlaywrightDotnetTests", "PlaywrightDotnetTests.csproj", "{DAF08465-4D94-4B65-AB98-C0965E732F81}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DAF08465-4D94-4B65-AB98-C0965E732F81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DAF08465-4D94-4B65-AB98-C0965E732F81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DAF08465-4D94-4B65-AB98-C0965E732F81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DAF08465-4D94-4B65-AB98-C0965E732F81}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7FAE2CF5-37B9-4938-B8F6-00B4DD9EFE94} + EndGlobalSection +EndGlobal diff --git a/PlaywrightLocalTest.cs b/PlaywrightLocalTest.cs new file mode 100644 index 0000000..5030481 --- /dev/null +++ b/PlaywrightLocalTest.cs @@ -0,0 +1,152 @@ +using Microsoft.Playwright; +using System.Threading.Tasks; +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using BrowserStack; +using System.Collections; + +class PlaywrightLocalTest +{ + + public static async Task main(string[] args) + { + // The following capability variables contains the set of os/browser environments where you want to run your tests. You can choose to alter this list according to your needs. Read more on https://browserstack.com/docs/automate/playwright/browsers-and-os + try + { + ArrayList capabilitiesList = getCapabilitiesList(); + Task[] taskList = new Task[capabilitiesList.Count]; + + Local local = new Local(); + + List> bsLocalArgs = new List>(); + bsLocalArgs.Add(new KeyValuePair("key", "BROWSERSTACK_ACCESS_KEY")); + bsLocalArgs.Add(new KeyValuePair("localIdentifier", "Test123")); + + local.start(bsLocalArgs); + + for (int i = 0; i < capabilitiesList.Count; i++) + { + string capsJson; + capsJson = JsonConvert.SerializeObject(capabilitiesList[i]); + var task = Executetestwithcaps(capsJson); + taskList[i] = task; + } + + await Task.WhenAll(taskList); + local.stop(); + + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + static ArrayList getCapabilitiesList() + { + ArrayList capabilitiesList = new ArrayList(); + + string? BROWSERSTACK_USERNAME = Environment.GetEnvironmentVariable("BROWSERSTACK_USERNAME"); + string? BROWSERSTACK_ACCESS_KEY = Environment.GetEnvironmentVariable("BROWSERSTACK_ACCESS_KEY"); + + Dictionary windowsChromeCap = new Dictionary(); + windowsChromeCap.Add("browser", "chrome"); // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit` + windowsChromeCap.Add("browser_version", "latest"); + windowsChromeCap.Add("os", "Windows"); + windowsChromeCap.Add("os_version", "11"); + windowsChromeCap.Add("build", "browserstack-build-1"); + windowsChromeCap.Add("buildTag", "Regression"); + windowsChromeCap.Add("browserstack.debug", "true"); + windowsChromeCap.Add("browserstack.networkLogs", "true"); + windowsChromeCap.Add("browserstack.console", "info"); + windowsChromeCap.Add("browserstack.local", "true"); + windowsChromeCap.Add("browserstack.localIdentifier", "Test123"); + windowsChromeCap.Add("browserstack.username", BROWSERSTACK_USERNAME); + windowsChromeCap.Add("browserstack.accessKey", BROWSERSTACK_ACCESS_KEY); + capabilitiesList.Add(windowsChromeCap); + + + Dictionary venturaWebkitCap = new Dictionary(); + venturaWebkitCap.Add("browser", "playwright-webkit"); // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit` + venturaWebkitCap.Add("browser_version", "latest"); + venturaWebkitCap.Add("os", "osx"); + venturaWebkitCap.Add("os_version", "Ventura"); + venturaWebkitCap.Add("build", "browserstack-build-1"); + venturaWebkitCap.Add("buildTag", "Regression"); + venturaWebkitCap.Add("browserstack.debug", "true"); + venturaWebkitCap.Add("browserstack.networkLogs", "true"); + venturaWebkitCap.Add("browserstack.console", "info"); + venturaWebkitCap.Add("browserstack.local", "true"); + venturaWebkitCap.Add("browserstack.localIdentifier", "Test123"); + venturaWebkitCap.Add("browserstack.username", BROWSERSTACK_USERNAME); + venturaWebkitCap.Add("browserstack.accessKey", BROWSERSTACK_ACCESS_KEY); + capabilitiesList.Add(venturaWebkitCap); + + Dictionary windowsFirefoxCap = new Dictionary(); + windowsFirefoxCap.Add("browser", "playwright-firefox"); // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit`\ + windowsFirefoxCap.Add("browser_version", "latest"); + windowsFirefoxCap.Add("os", "Windows"); + windowsFirefoxCap.Add("os_version", "11"); + windowsFirefoxCap.Add("build", "browserstack-build-1"); + windowsFirefoxCap.Add("buildTag", "Regression"); + windowsFirefoxCap.Add("browserstack.debug", "true"); + windowsFirefoxCap.Add("browserstack.networkLogs", "true"); + windowsFirefoxCap.Add("browserstack.console", "info"); + windowsFirefoxCap.Add("browserstack.local", "true"); + windowsFirefoxCap.Add("browserstack.localIdentifier", "Test123"); + windowsFirefoxCap.Add("browserstack.username", BROWSERSTACK_USERNAME); + windowsFirefoxCap.Add("browserstack.accessKey", BROWSERSTACK_ACCESS_KEY); + capabilitiesList.Add(windowsFirefoxCap); + + return capabilitiesList; + } + + public static async Task Executetestwithcaps(string capabilities) + { + using var playwright = await Playwright.CreateAsync(); + string cdpUrl = "wss://cdp.browserstack.com/playwright?caps=" + Uri.EscapeDataString(capabilities); + + await using var browser = await playwright.Chromium.ConnectAsync(cdpUrl); + var page = await browser.NewPageAsync(); + try + { + await MarkTestName(page); + page.SetDefaultTimeout(60000); + await page.GotoAsync("http://localhost:3000/"); + await page.Locator("#\\31 > .shelf-item__buy-btn").ClickAsync(); + + var text = await page.Locator("#__next > div > div > div.float-cart.float-cart--open > div.float-cart__content > div.float-cart__shelf-container > div > div.shelf-item__details > p.title").TextContentAsync(); + + if (text == "iPhone 12") + { + await MarkTestStatus("passed", "Item Added", page); + } + else + { + await MarkTestStatus("failed", "Test Failed", page); + } + } + catch (Exception err) + { + Console.WriteLine(err.Message); + await MarkTestStatus("failed", "Something Failed", page); + } + await browser.CloseAsync(); + + } + public static async Task MarkTestStatus(string status, string reason, IPage page) + { + await page.EvaluateAsync("_ => {}", "browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\":\"" + status + "\", \"reason\": \"" + reason + "\"}}"); + } + + public static async Task MarkTestName(IPage page) + { + string? thisFile = new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName(); + string[] result = thisFile.Split(new char[] { '/' }); + string[] filenameResult = result.Last().Split(new char[] { '.' }); + string? testName = filenameResult.First(); + + await page.EvaluateAsync("_ => {}", "browserstack_executor: {\"action\": \"setSessionName\", \"arguments\": {\"name\":\"" + testName + "\"}}"); + } +} diff --git a/PlaywrightParallelTest.cs b/PlaywrightParallelTest.cs new file mode 100644 index 0000000..1d715fe --- /dev/null +++ b/PlaywrightParallelTest.cs @@ -0,0 +1,133 @@ +using Microsoft.Playwright; +using System; +using System.Threading; +using Newtonsoft.Json; +using System.Collections; + +class PlaywrightParallelTest +{ + public static async Task main(string[] args) + { + // The following capability variables contains the set of os/browser environments where you want to run your tests. You can choose to alter this list according to your needs. Read more on https://browserstack.com/docs/automate/playwright/browsers-and-os + try + { + ArrayList capabilitiesList = getCapabilitiesList(); + Task[] taskList = new Task[capabilitiesList.Count]; + + for (int i = 0; i < capabilitiesList.Count; i++) + { + string capsJson; + capsJson = JsonConvert.SerializeObject(capabilitiesList[i]); + var task = Executetestwithcaps(capsJson); + taskList[i] = task; + } + + await Task.WhenAll(taskList); + + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + static ArrayList getCapabilitiesList() + { + ArrayList capabilitiesList = new ArrayList(); + + string? BROWSERSTACK_USERNAME = Environment.GetEnvironmentVariable("BROWSERSTACK_USERNAME"); + string? BROWSERSTACK_ACCESS_KEY = Environment.GetEnvironmentVariable("BROWSERSTACK_ACCESS_KEY"); + + + Dictionary windowsChromeCap = new Dictionary(); + windowsChromeCap.Add("browser", "chrome"); // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit` + windowsChromeCap.Add("browser_version", "latest"); + windowsChromeCap.Add("os", "Windows"); + windowsChromeCap.Add("os_version", "11"); + windowsChromeCap.Add("build", "browserstack-build-1"); + windowsChromeCap.Add("buildTag", "Regression"); + windowsChromeCap.Add("browserstack.debug", "true"); + windowsChromeCap.Add("browserstack.networkLogs", "true"); + windowsChromeCap.Add("browserstack.console", "info"); + windowsChromeCap.Add("browserstack.username", BROWSERSTACK_USERNAME); + windowsChromeCap.Add("browserstack.accessKey", BROWSERSTACK_ACCESS_KEY); + capabilitiesList.Add(windowsChromeCap); + + + Dictionary venturaWebkitCap = new Dictionary(); + venturaWebkitCap.Add("browser", "playwright-webkit"); // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit` + venturaWebkitCap.Add("browser_version", "latest"); + venturaWebkitCap.Add("os", "osx"); + venturaWebkitCap.Add("os_version", "Ventura"); + venturaWebkitCap.Add("build", "browserstack-build-1"); + venturaWebkitCap.Add("buildTag", "Regression"); + venturaWebkitCap.Add("browserstack.debug", "true"); + venturaWebkitCap.Add("browserstack.networkLogs", "true"); + venturaWebkitCap.Add("browserstack.console", "info"); + venturaWebkitCap.Add("browserstack.username", BROWSERSTACK_USERNAME); + venturaWebkitCap.Add("browserstack.accessKey", BROWSERSTACK_ACCESS_KEY); + capabilitiesList.Add(venturaWebkitCap); + + Dictionary windowsFirefoxCap = new Dictionary(); + windowsFirefoxCap.Add("browser", "playwright-firefox"); // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit`\ + windowsFirefoxCap.Add("browser_version", "latest"); + windowsFirefoxCap.Add("os", "Windows"); + windowsFirefoxCap.Add("os_version", "11"); + windowsFirefoxCap.Add("build", "browserstack-build-1"); + windowsFirefoxCap.Add("buildTag", "Regression"); + windowsFirefoxCap.Add("browserstack.debug", "true"); + windowsFirefoxCap.Add("browserstack.networkLogs", "true"); + windowsFirefoxCap.Add("browserstack.console", "info"); + windowsFirefoxCap.Add("browserstack.username", BROWSERSTACK_USERNAME); + windowsFirefoxCap.Add("browserstack.accessKey", BROWSERSTACK_ACCESS_KEY); + capabilitiesList.Add(windowsFirefoxCap); + + return capabilitiesList; + } + + //Executetestwithcaps function takes capabilities from 'SampleTestCase' function and executes the test + public static async Task Executetestwithcaps(string capabilities) + { + using var playwright = await Playwright.CreateAsync(); + string cdpUrl = "wss://cdp.browserstack.com/playwright?caps=" + Uri.EscapeDataString(capabilities); + + await using var browser = await playwright.Chromium.ConnectAsync(cdpUrl); + var page = await browser.NewPageAsync(); + try + { + await MarkTestName(page); + page.SetDefaultTimeout(60000); + await page.GotoAsync("https://bstackdemo.com/"); + await page.Locator("#\\31 > .shelf-item__buy-btn").ClickAsync(); + + var text = await page.Locator("#__next > div > div > div.float-cart.float-cart--open > div.float-cart__content > div.float-cart__shelf-container > div > div.shelf-item__details > p.title").TextContentAsync(); + + if (text == "iPhone 12") + { + await MarkTestStatus("passed", "Item Added", page); + } + else + { + await MarkTestStatus("failed", "Test Failed", page); + } + } + catch (Exception err) + { + Console.WriteLine(err.Message); + await MarkTestStatus("failed", "Something Failed", page); + } + await browser.CloseAsync(); + } + public static async Task MarkTestStatus(string status, string reason, IPage page) + { + await page.EvaluateAsync("_ => {}", "browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\":\"" + status + "\", \"reason\": \"" + reason + "\"}}"); + } + public static async Task MarkTestName(IPage page) + { + string? thisFile = new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName(); + string[] result = thisFile.Split(new char[] { '/' }); + string[] filenameResult = result.Last().Split(new char[] { '.' }); + string? testName = filenameResult.First(); + + await page.EvaluateAsync("_ => {}", "browserstack_executor: {\"action\": \"setSessionName\", \"arguments\": {\"name\":\"" + testName + "\"}}"); + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..bcd3417 --- /dev/null +++ b/Program.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace PlaywrightTesting +{ + class Program + { + public static async Task Main(string[] args) + { + switch (args[0]) + { + case "parallel": + Console.WriteLine("Running Parallel Test"); + await PlaywrightParallelTest.main(args); + break; + case "local": + Console.WriteLine("Running Local Test"); + await PlaywrightLocalTest.main(args); + break; + default: + Console.WriteLine("Running Single Test by default"); + await PlaywrightParallelTest.main(args); + break; + } + } + } +} diff --git a/README.md b/README.md index d381fe3..8f317cd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,39 @@ -# csharp-playwright-browserstack -Creating a sample repo for different Playwright languages and runners +# Testing with playwright-browserstack in C# + +[Playwright](https://playwright.dev/dotnet/) Integration with BrowserStack. + +![BrowserStack Logo](https://d98b8t1nnulk5.cloudfront.net/production/images/layout/logo-header.png?1469004780) + +## Setup + +* Clone the repo and run `cd csharp-playwright-browserstack` +* Set `BROWSERSTACK_USERNAME` and `BROWSERSTACK_ACCESS_KEY` as environment variables with your [BrowserStack Username and Access Key](https://www.browserstack.com/accounts/settings) +* Run `dotnet build` + +## Running your tests + +- To run a parallel test, run command `dotnet run parallel` + + ### [Web application hosted on internal environment] Running your tests on BrowserStack using BrowserStackLocal + + #### Prerequisites + + - Clone the [BrowserStack demo application](https://github.com/browserstack/browserstack-demo-app) repository. + ```sh + git clone https://github.com/browserstack/browserstack-demo-app + ``` + - Please follow the README.md on the BrowserStack demo application repository to install and start the dev server on localhost. + - Note: You may need to provide additional BrowserStackLocal arguments to successfully connect your localhost environment with BrowserStack infrastructure. (e.g if you are behind firewalls, proxy or VPN). + - Further details for successfully creating a BrowserStackLocal connection can be found here: + + - [Local Testing with Automate](https://www.browserstack.com/local-testing/automate) + + #### Running the test using Local Testing: + - You can then run the sample Local test using `dotnet run local` + + +## Notes +* You can view your test results on the [BrowserStack Automate dashboard](https://www.browserstack.com/automate) + +## Additional Resources +* [Documentation for writing Automate test scripts with BrowserStack](https://www.browserstack.com/docs/automate/playwright)