diff --git a/src/Coypu.AcceptanceTests/BasicAuth.cs b/src/Coypu.AcceptanceTests/BasicAuth.cs index b1e9e371..6418d411 100644 --- a/src/Coypu.AcceptanceTests/BasicAuth.cs +++ b/src/Coypu.AcceptanceTests/BasicAuth.cs @@ -35,22 +35,17 @@ public void It_passes_through_basic_auth_from_url_as_auth_header() { Timeout = TimeSpan.FromMilliseconds(1000), Port = site.BaseUri.Port, - AppHost = "http://username:passw0rd@localhost", + AppHost = "http://someUser:passw0rd@localhost", Driver = typeof(PlaywrightDriver), // Selenium can't do this Headless = false, Browser = Drivers.Browser.Chromium }; browser = new BrowserSession(configuration); - browser.Visit("/headers"); - Assert.That(browser, Shows.Content("Authorization: " + GetBasicAuthHeader("username", "passw0rd"))); - - browser.Visit("http://un2:pw2@localhost:" + site.BaseUri.Port + "/headers"); - Assert.That(browser, Shows.Content("Authorization: " + GetBasicAuthHeader("un2", "pw2"))); + browser.Visit("/"); - browser.Visit("http://localhost:" + site.BaseUri.Port + "/headers"); - Assert.That(browser, Shows.Content("Authorization:")); - Assert.That(browser, Shows.No.Content("Authorization: Basic")); + browser.Visit("/headers"); + Assert.That(browser, Shows.Content("Authorization: " + GetBasicAuthHeader("someUser", "passw0rd"))); } private string GetBasicAuthHeader(string username, string password) diff --git a/src/Coypu.AcceptanceTests/sites/SelfHostedSite.cs b/src/Coypu.AcceptanceTests/sites/SelfHostedSite.cs index 37fdbeb1..ea70489e 100644 --- a/src/Coypu.AcceptanceTests/sites/SelfHostedSite.cs +++ b/src/Coypu.AcceptanceTests/sites/SelfHostedSite.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Mime; @@ -39,9 +40,19 @@ public SelfHostedSite() return Results.NoContent(); }); _app.MapGet("/headers", - (HttpRequest req) => + (HttpRequest req, HttpResponse res) => { - return Results.Text(req.Headers.Select(h => $"{h.Key}: {h.Value}").Aggregate((a, b) => $"{a}\n{b}")); + if (string.IsNullOrEmpty(req.Headers["Authorization"])) { + res.Headers.Add("WWW-Authenticate", "Basic realm= \"Coypu Test\""); + return Results.Unauthorized(); + }; + return Results.Content( + "" + + req.Headers.Select(h => $"{h.Key}: {h.Value}").Aggregate((a, b) => $"{a}: {b}
") + + "" + + "" + + "", + MediaTypeNames.Text.Html, Encoding.UTF8); }); _app.StartAsync().Wait(); diff --git a/src/Coypu.Tests/When_interacting_with_the_browser/BrowserInteractionTests.cs b/src/Coypu.Tests/When_interacting_with_the_browser/BrowserInteractionTests.cs index cf107e1f..fcee527a 100644 --- a/src/Coypu.Tests/When_interacting_with_the_browser/BrowserInteractionTests.cs +++ b/src/Coypu.Tests/When_interacting_with_the_browser/BrowserInteractionTests.cs @@ -108,7 +108,7 @@ public StubDriverFactory(IDriver driver) this.driver = driver; } - public IDriver NewWebDriver(Type driverType, Drivers.Browser browser, bool Headless) + public IDriver NewWebDriver(Type driverType, Drivers.Browser browser, bool Headless, string appHost) { return driver; } diff --git a/src/Coypu/ActivatorDriverFactory.cs b/src/Coypu/ActivatorDriverFactory.cs index d97561ad..6f43ea0c 100644 --- a/src/Coypu/ActivatorDriverFactory.cs +++ b/src/Coypu/ActivatorDriverFactory.cs @@ -7,11 +7,11 @@ public class ActivatorDriverFactory : DriverFactory { public static int OpenDrivers { get; set; } - public IDriver NewWebDriver(Type driverType, Drivers.Browser browser, bool headless) + public IDriver NewWebDriver(Type driverType, Drivers.Browser browser, bool headless, string appHost) { try { - var driver = (IDriver)Activator.CreateInstance(driverType, browser, headless); + var driver = (IDriver)Activator.CreateInstance(driverType, browser, headless, appHost); OpenDrivers++; return driver; } diff --git a/src/Coypu/BrowserSession.cs b/src/Coypu/BrowserSession.cs index 4d0226fd..2c863886 100644 --- a/src/Coypu/BrowserSession.cs +++ b/src/Coypu/BrowserSession.cs @@ -72,7 +72,7 @@ internal BrowserSession(SessionConfiguration sessionConfiguration, RestrictedResourceDownloader restrictedResourceDownloader) : base(sessionConfiguration, null, - driverFactory.NewWebDriver(sessionConfiguration.Driver, sessionConfiguration.Browser, sessionConfiguration.Headless), + driverFactory.NewWebDriver(sessionConfiguration.Driver, sessionConfiguration.Browser, sessionConfiguration.Headless, sessionConfiguration.AppHost), timingStrategy, waiter, urlBuilder, diff --git a/src/Coypu/DriverFactory.cs b/src/Coypu/DriverFactory.cs index efd1c896..00914d27 100644 --- a/src/Coypu/DriverFactory.cs +++ b/src/Coypu/DriverFactory.cs @@ -4,6 +4,6 @@ namespace Coypu { public interface DriverFactory { - IDriver NewWebDriver(Type driverType, Drivers.Browser browser, bool headless); + IDriver NewWebDriver(Type driverType, Drivers.Browser browser, bool headless, string appHost); } } diff --git a/src/Coypu/Drivers/Playwright/PlaywrightDriver.cs b/src/Coypu/Drivers/Playwright/PlaywrightDriver.cs index 41e0db7f..195153fa 100644 --- a/src/Coypu/Drivers/Playwright/PlaywrightDriver.cs +++ b/src/Coypu/Drivers/Playwright/PlaywrightDriver.cs @@ -5,7 +5,8 @@ using System.Text.RegularExpressions; using Cookie = System.Net.Cookie; using Microsoft.Playwright; -using System.Text; +using System.Collections.Immutable; +using System.Threading.Tasks; #pragma warning disable 1591 @@ -15,12 +16,12 @@ public class PlaywrightDriver : IDriver { private readonly Browser _browser; private readonly bool _headless; - private readonly Dialogs _dialogs; - private readonly IPlaywright _playwright; + private readonly Dialogs _dialogs; + private readonly IPlaywright _playwright; private readonly IBrowser _playwrightBrowser; - private readonly IBrowserContext _context; + private IBrowserContext _context; - public PlaywrightDriver(Browser browser, bool headless) + public PlaywrightDriver(Browser browser, bool headless, string appHost) { _dialogs = new Dialogs(); _playwright = Microsoft.Playwright.Playwright.CreateAsync().Sync(); @@ -31,18 +32,37 @@ public PlaywrightDriver(Browser browser, bool headless) _playwrightBrowser = browserType.LaunchAsync( new BrowserTypeLaunchOptions { - Headless = headless, - Channel = PlaywrightBrowserChannel(browser) + Headless = headless, + Channel = PlaywrightBrowserChannel(browser), } ).Sync(); - var page = _playwrightBrowser.NewPageAsync().Sync(); + NewContext(appHost); + } + + private void NewContext(string appHost) + { + var options = new BrowserNewPageOptions(); + if (Uri.IsWellFormedUriString(appHost, UriKind.Absolute)) + { + var userInfo = new Uri(appHost).UserInfo; + if (!string.IsNullOrEmpty(userInfo)) { + var credentials = userInfo.Split(':'); + options.HttpCredentials = new HttpCredentials + { + Username = credentials[0], + Password = credentials[1] + }; + } + } + + var page = _playwrightBrowser.NewPageAsync(options).Sync(); _context = page.Context; Cookies = new Cookies(_context); _context.SetDefaultTimeout(10000); - } + } - private string PlaywrightBrowserChannel(Browser browser) + private string PlaywrightBrowserChannel(Browser browser) { if (browser == Browser.Chrome) return "chrome"; @@ -200,22 +220,10 @@ public void CancelPrompt(string text, DriverScope scope, Action trigger) public void Visit(string url, Scope scope) { - string userInfo = new Uri(url).UserInfo; - if (string.IsNullOrEmpty(userInfo)) - { - _context.SetExtraHTTPHeadersAsync(new Dictionary { - { "Authorization", string.Empty } - }).Sync(); - } else { - var base64EncodedAuthenticationString = Convert.ToBase64String(Encoding.ASCII.GetBytes(userInfo)); - _context.SetExtraHTTPHeadersAsync(new Dictionary { - { "Authorization", "Basic " + base64EncodedAuthenticationString } - }).Sync(); - } IResponse response = PlaywrightPage(scope).GotoAsync(url).Sync(); if (response != null && response.Status != 200) { - throw new Exception("Failed to load page"); + throw new Exception("Failed to load page"); } } diff --git a/src/Coypu/Drivers/Selenium/SeleniumWebDriver.cs b/src/Coypu/Drivers/Selenium/SeleniumWebDriver.cs index ceff279e..977a1682 100644 --- a/src/Coypu/Drivers/Selenium/SeleniumWebDriver.cs +++ b/src/Coypu/Drivers/Selenium/SeleniumWebDriver.cs @@ -22,7 +22,7 @@ public class SeleniumWebDriver : IDriver private IWebDriver _webDriver; private readonly WindowHandleFinder _windowHandleFinder; - public SeleniumWebDriver(Browser browser, bool headless) + public SeleniumWebDriver(Browser browser, bool headless, string _appHost = null) : this(new DriverFactory().NewWebDriver(browser, headless), browser) { } protected SeleniumWebDriver(IWebDriver webDriver,