chore(roll): roll Playwright to 1.26.0-beta-1662762342000 (#2306)

This commit is contained in:
Max Schmitt
2022-09-12 20:33:06 +02:00
committed by GitHub
parent 57605ce7f9
commit d51994452a
15 changed files with 301 additions and 50 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->106.0.5249.21<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Chromium <!-- GEN:chromium-version -->106.0.5249.30<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| WebKit <!-- GEN:webkit-version -->16.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->104.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<AssemblyVersion>1.25.0</AssemblyVersion>
<PackageVersion>$(AssemblyVersion)-next-2</PackageVersion>
<DriverVersion>1.26.0-alpha-1662365984000</DriverVersion>
<DriverVersion>1.26.0-beta-1662762342000</DriverVersion>
<ReleaseVersion>$(AssemblyVersion)</ReleaseVersion>
<FileVersion>$(AssemblyVersion)</FileVersion>
<NoDefaultExcludes>true</NoDefaultExcludes>
@@ -51,86 +51,183 @@ namespace Microsoft.Playwright.Tests.Assertions
StringAssert.Contains("LocatorAssertions.ToBeCheckedAsync with timeout 300ms", exception.Message);
}
[PlaywrightTest("playwright-test/playwright.expect.spec.ts", "should support toBeEditable, toBeEnabled, toBeDisabled, toBeEmpty")]
public async Task ShouldSupportToBeEditableToBeEnabledToBeDisabledToBeEmpty()
[PlaywrightTest("playwright-test/playwright.expect.spec.ts", "should support toBeEditable")]
public async Task ShouldSupportToBeEditable()
{
{
// default
await Page.SetContentAsync("<input></input>");
await Expect(Page.Locator("input")).ToBeEditableAsync();
var locator = Page.Locator("input");
await Expect(locator).ToBeEditableAsync();
}
{
// with not
await Page.SetContentAsync("<input readonly></input>");
var locator = Page.Locator("input");
await Expect(locator).Not.ToBeEditableAsync();
}
{
// with editable:true
await Page.SetContentAsync("<input></input>");
var locator = Page.Locator("input");
await Expect(locator).ToBeEditableAsync(new() { Editable = true });
}
{
// with editable:false
await Page.SetContentAsync("<input readonly></input>");
var locator = Page.Locator("input");
await Expect(locator).ToBeEditableAsync(new() { Editable = false });
}
{
// with not and editable:false
await Page.SetContentAsync("<input></input>");
var locator = Page.Locator("input");
await Expect(locator).Not.ToBeEditableAsync(new() { Editable = false });
}
}
[PlaywrightTest("playwright-test/playwright.expect.spec.ts", "should support toBeEnabled")]
public async Task ShouldSupportToBeEnabled()
{
{
// default
await Page.SetContentAsync("<button>Text</button>");
await Expect(Page.Locator("button")).ToBeEnabledAsync();
}
{
await Page.SetContentAsync("<button disabled>Text</button>");
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => Expect(Page.Locator("button")).ToBeEnabledAsync(new() { Timeout = 500 }));
StringAssert.Contains("Locator expected to be enabled", exception.Message);
StringAssert.Contains("LocatorAssertions.ToBeEnabledAsync with timeout 500ms", exception.Message);
}
{
await Page.SetContentAsync("<button disabled>Text</button>");
var locator = Page.Locator("button");
await locator.EvaluateAsync("e => setTimeout(() => { e.removeAttribute('disabled') }, 500);");
await Expect(locator).ToBeEnabledAsync();
}
{
// with enabled:true
await Page.SetContentAsync("<button>Text</button>");
var locator = Page.Locator("button");
await locator.EvaluateAsync("e => setTimeout(() => { e.setAttribute('disabled', '') }, 500);");
await Expect(locator).ToBeEnabledAsync(new() { Enabled = true });
}
{
// with enabled:false
await Page.SetContentAsync("<button disabled>Text</button>");
var locator = Page.Locator("button");
await Expect(locator).ToBeEnabledAsync(new() { Enabled = false });
}
{
// failed
await Page.SetContentAsync("<button disabled>Text</button>");
var locator = Page.Locator("button");
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => Expect(locator).ToBeEnabledAsync(new() { Timeout = 1000 }));
StringAssert.Contains("selector resolved to <button disabled>Text</button>", exception.Message);
// extra checks
StringAssert.Contains("Locator expected to be enabled", exception.Message);
StringAssert.Contains("LocatorAssertions.ToBeEnabledAsync with timeout 1000ms", exception.Message);
}
{
// eventually
await Page.SetContentAsync("<button disabled>Text</button>");
var locator = Page.Locator("button");
await locator.EvaluateAsync("e => setTimeout(() => e.removeAttribute('disabled'), 500);");
await Expect(locator).ToBeEnabledAsync();
}
{
// eventually with not
await Page.SetContentAsync("<button>Text</button>");
var locator = Page.Locator("button");
await locator.EvaluateAsync("e => setTimeout(() => e.setAttribute('disabled', ''), 500);");
await Expect(locator).Not.ToBeEnabledAsync();
}
{
// with not and enabled:false
await Page.SetContentAsync("<button>Text</button>");
var locator = Page.Locator("button");
await Expect(locator).Not.ToBeEnabledAsync(new() { Enabled = false });
}
{
// toBeDisabled
await Page.SetContentAsync("<button disabled>Text</button>");
var locator = Page.Locator("button");
await Expect(locator).ToBeDisabledAsync();
}
{
await Page.SetContentAsync("<input></input>");
var locator = Page.Locator("input");
await Expect(locator).ToBeEmptyAsync();
}
{
await Page.SetContentAsync("<input value=text></input>");
var locator = Page.Locator("input");
await Expect(locator).Not.ToBeEmptyAsync();
}
}
[PlaywrightTest("playwright-test/playwright.expect.spec.ts", "should support toBeVisible, toBeHidden")]
[PlaywrightTest("playwright-test/playwright.expect.spec.ts", "should support toBeVisible")]
public async Task ShouldSupportToBeVisibleToBeHidden()
{
{
// default
await Page.SetContentAsync("<input></input>");
var locator = Page.Locator("input");
await Expect(locator).ToBeVisibleAsync();
}
{
// with not
await Page.SetContentAsync("<button style=\"display: none\"></button>");
var locator = Page.Locator("button");
await Expect(locator).Not.ToBeVisibleAsync();
}
{
// with visible:true
await Page.SetContentAsync("<button>hello</button>");
var locator = Page.Locator("button");
await Expect(locator).ToBeVisibleAsync(new() { Visible = true });
}
{
// with visible:false
await Page.SetContentAsync("<button hidden>hello</button>");
var locator = Page.Locator("button");
await Expect(locator).ToBeVisibleAsync(new() { Visible = false });
}
{
// with not and visible:false
await Page.SetContentAsync("<button>hello</button>");
var locator = Page.Locator("button");
await Expect(locator).Not.ToBeVisibleAsync(new() { Visible = false });
}
{
// eventually
await Page.SetContentAsync("<div></div>");
var locator = Page.Locator("span");
await Page.EvalOnSelectorAsync("div", "e => setTimeout(() => e.innerHTML = e.innerHTML + '<span>Hello</span>', 500);");
await Expect(locator).ToBeVisibleAsync();
}
{
// eventually with not
await Page.SetContentAsync("<div><span>Hello</span></div>");
var locator = Page.Locator("span");
await Page.EvalOnSelectorAsync("span", "span => setTimeout(() => span.textContent = '', 500);");
await Expect(locator).Not.ToBeVisibleAsync();
}
{
// fail
await Page.SetContentAsync("<button style=\"display: none\"></button>");
var locator = Page.Locator("button");
await Expect(locator).ToBeHiddenAsync();
}
{
await Page.SetContentAsync("<div></div>");
var locator = Page.Locator("div");
await Expect(locator).ToBeHiddenAsync();
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => Expect(locator).ToBeVisibleAsync(new() { Timeout = 1000 }));
StringAssert.Contains("selector resolved to <button></button>", exception.Message);
}
{
// fail with not
await Page.SetContentAsync("<input></input>");
var locator = Page.Locator("input");
await Expect(locator).Not.ToBeHiddenAsync();
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => Expect(locator).Not.ToBeVisibleAsync(new() { Timeout = 1000 }));
StringAssert.Contains("selector resolved to <input/>", exception.Message);
}
}
[PlaywrightTest("playwright-test/playwright.expect.spec.ts", "should support ToBeEmpty")]
public async Task ShouldSupportToBeEmpty()
{
{
// toBeEmpty input
await Page.SetContentAsync("<input></input>");
var locator = Page.Locator("input");
await Expect(locator).ToBeEmptyAsync();
}
{
// not.toBeEmpty
await Page.SetContentAsync("<input value=hello></input>");
var locator = Page.Locator("input");
await Expect(locator).Not.ToBeEmptyAsync();
}
{
// toBeEmpty div
await Page.SetContentAsync("<div style=\"width: 50; height: 50px\"></div>");
var locator = Page.Locator("div");
await Expect(locator).ToBeEmptyAsync();
}
}
+95
View File
@@ -253,5 +253,100 @@ namespace Microsoft.Playwright.Tests
}
await response.DisposeAsync();
}
[PlaywrightTest("global-fetch.spec.ts", "should not fail on empty body with encoding")]
public async Task ShouldNotFailOnEmptyBodyWithEncoding()
{
var request = await Playwright.APIRequest.NewContextAsync();
foreach (var method in new[] { "head", "put" })
{
foreach (var encoding in new[] { "br", "gzip", "deflate" })
{
Server.SetRoute("/empty.html", (ctx) =>
{
ctx.Response.StatusCode = 200;
ctx.Response.Headers.Add("Content-Encoding", encoding);
ctx.Response.Headers.Add("Content-Type", "text/plain");
return Task.CompletedTask;
});
var response = await request.NameToMethod(method)(Server.EmptyPage, null);
Assert.AreEqual(200, response.Status);
Assert.AreEqual(0, (await response.BodyAsync()).Length);
}
}
await request.DisposeAsync();
}
[PlaywrightTest("global-fetch.spec.ts", "should return body for failing requests")]
public async Task ShouldReturnBodyForFailingRequests()
{
var request = await Playwright.APIRequest.NewContextAsync();
foreach (var method in new[] { "head", "put", "trace" })
{
Server.SetRoute("/empty.html", async (ctx) =>
{
ctx.Response.StatusCode = 404;
ctx.Response.Headers.Add("Content-Length", "10");
ctx.Response.Headers.Add("Content-Type", "text/plain");
await ctx.Response.WriteAsync("Not found.");
});
var response = await request.FetchAsync(Server.EmptyPage, new() { Method = method });
Assert.AreEqual(404, response.Status);
// HEAD response returns empty body in node http module.
Assert.AreEqual(method == "head" ? "" : "Not found.", await response.TextAsync());
}
await request.DisposeAsync();
}
[PlaywrightTest("global-fetch.spec.ts", "should throw an error when maxRedirects is exceeded")]
public async Task ShouldThrowAnErrorWhenMaxRedirectsIsExceeded()
{
Server.SetRedirect("/a/redirect1", "/b/c/redirect2");
Server.SetRedirect("/b/c/redirect2", "/b/c/redirect3");
Server.SetRedirect("/b/c/redirect3", "/b/c/redirect4");
Server.SetRedirect("/b/c/redirect4", "/simple.json");
var request = await Playwright.APIRequest.NewContextAsync();
foreach (var method in new[] { "GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH" })
{
foreach (var maxRedirects in new[] { 1, 2, 3 })
{
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => request.FetchAsync($"{Server.Prefix}/a/redirect1", new() { Method = method, MaxRedirects = maxRedirects }));
StringAssert.Contains("Max redirect count exceeded", exception.Message);
}
}
await request.DisposeAsync();
}
[PlaywrightTest("global-fetch.spec.ts", "should not follow redirects when maxRedirects is set to 0")]
public async Task ShouldNotFollowRedirectsWhenMaxRedirectsIsSetTo0()
{
Server.SetRedirect("/a/redirect1", "/b/c/redirect2");
Server.SetRedirect("/b/c/redirect2", "/simple.json");
var request = await Playwright.APIRequest.NewContextAsync();
foreach (var method in new[] { "GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH" })
{
var response = await request.FetchAsync($"{Server.Prefix}/a/redirect1", new() { Method = method, MaxRedirects = 0 });
Assert.AreEqual("/b/c/redirect2", response.Headers["location"]);
Assert.AreEqual(302, response.Status);
}
await request.DisposeAsync();
}
[PlaywrightTest("global-fetch.spec.ts", "should throw an error when maxRedirects is less than 0")]
public async Task ShouldThrowAnErrorWhenMaxRedirectsIsLessThan0()
{
Server.SetRedirect("/a/redirect1", "/b/c/redirect2");
Server.SetRedirect("/b/c/redirect2", "/simple.json");
var request = await Playwright.APIRequest.NewContextAsync();
foreach (var method in new[] { "GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH" })
{
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => request.FetchAsync($"{Server.Prefix}/a/redirect1", new() { Method = method, MaxRedirects = -1 }));
StringAssert.Contains("'maxRedirects' should be greater than or equal to '0'", exception.Message);
}
await request.DisposeAsync();
}
}
}
@@ -84,6 +84,11 @@ namespace Microsoft.Playwright
/// DevTools Protocol.
/// </para>
/// <para>The default browser context is accessible via <see cref="IBrowser.Contexts"/>.</para>
/// <code>
/// var browser = await playwright.Chromium.ConnectOverCDPAsync("http://localhost:9222");<br/>
/// var defaultContext = browser.Contexts[0];<br/>
/// var page = defaultContext.Pages[0];
/// </code>
/// </summary>
/// <remarks>
/// <para>
@@ -53,9 +53,10 @@ namespace Microsoft.Playwright
/// <br/>
/// namespace PlaywrightTests;<br/>
/// <br/>
/// [TestFixture]<br/>
/// public class ExampleTests : PageTest<br/>
/// {<br/>
/// [Test]<br/>
/// [PlaywrightTest]<br/>
/// public async Task StatusBecomesSubmitted()<br/>
/// {<br/>
/// // ..<br/>
@@ -53,9 +53,10 @@ namespace Microsoft.Playwright
/// <br/>
/// namespace PlaywrightTests;<br/>
/// <br/>
/// [TestFixture]<br/>
/// public class ExampleTests : PageTest<br/>
/// {<br/>
/// [Test]<br/>
/// [PlaywrightTest]<br/>
/// public async Task NavigatetoLoginPage()<br/>
/// {<br/>
/// // ..<br/>
@@ -52,9 +52,10 @@ namespace Microsoft.Playwright
/// <br/>
/// namespace PlaywrightTests;<br/>
/// <br/>
/// [TestFixture]<br/>
/// public class ExampleTests : PageTest<br/>
/// {<br/>
/// [Test]<br/>
/// [PlaywrightTest]<br/>
/// public async Task StatusBecomesSubmitted()<br/>
/// {<br/>
/// await Page.Locator("#submit-button").ClickAsync();<br/>
@@ -57,6 +57,7 @@ namespace Microsoft.Playwright
Form = clone.Form;
Headers = clone.Headers;
IgnoreHTTPSErrors = clone.IgnoreHTTPSErrors;
MaxRedirects = clone.MaxRedirects;
Method = clone.Method;
Multipart = clone.Multipart;
Params = clone.Params;
@@ -125,6 +126,16 @@ namespace Microsoft.Playwright
[JsonPropertyName("ignoreHTTPSErrors")]
public bool? IgnoreHTTPSErrors { get; set; }
/// <summary>
/// <para>
/// Maximum number of request redirects that will be followed automatically. An error
/// will be thrown if the number is exceeded. Defaults to <c>20</c>. Pass <c>0</c> to
/// not follow redirects.
/// </para>
/// </summary>
[JsonPropertyName("maxRedirects")]
public int? MaxRedirects { get; set; }
/// <summary>
/// <para>
/// If set changes the fetch method (e.g. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT">PUT</a>
@@ -50,9 +50,13 @@ namespace Microsoft.Playwright
return;
}
Editable = clone.Editable;
Timeout = clone.Timeout;
}
[JsonPropertyName("editable")]
public bool? Editable { get; set; }
/// <summary><para>Time to retry the assertion for.</para></summary>
[JsonPropertyName("timeout")]
public float? Timeout { get; set; }
@@ -50,9 +50,13 @@ namespace Microsoft.Playwright
return;
}
Enabled = clone.Enabled;
Timeout = clone.Timeout;
}
[JsonPropertyName("enabled")]
public bool? Enabled { get; set; }
/// <summary><para>Time to retry the assertion for.</para></summary>
[JsonPropertyName("timeout")]
public float? Timeout { get; set; }
@@ -51,11 +51,15 @@ namespace Microsoft.Playwright
}
Timeout = clone.Timeout;
Visible = clone.Visible;
}
/// <summary><para>Time to retry the assertion for.</para></summary>
[JsonPropertyName("timeout")]
public float? Timeout { get; set; }
[JsonPropertyName("visible")]
public bool? Visible { get; set; }
}
}
+12 -1
View File
@@ -75,6 +75,16 @@ namespace Microsoft.Playwright.Core
public async Task<IAPIResponse> FetchAsync(string url, APIRequestContextOptions options = null)
{
options ??= new APIRequestContextOptions();
if (options.MaxRedirects != null && options.MaxRedirects < 0)
{
throw new PlaywrightException("'maxRedirects' should be greater than or equal to '0'");
}
if (new[] { options.DataByte, options.DataObject, options.DataString, options.Form, options.Multipart }.Count(x => x != null) > 1)
{
throw new PlaywrightException("Only one of 'data', 'form' or 'multipart' can be specified");
}
var queryParams = new Dictionary<string, string>();
if (options.Params != null)
{
@@ -113,7 +123,8 @@ namespace Microsoft.Playwright.Core
(FormData)options.Multipart,
options.Timeout,
options?.FailOnStatusCode,
options?.IgnoreHTTPSErrors).ConfigureAwait(false);
options?.IgnoreHTTPSErrors,
options?.MaxRedirects).ConfigureAwait(false);
}
private bool IsJsonContentType(IDictionary<string, string> headers)
+18 -3
View File
@@ -46,17 +46,32 @@ namespace Microsoft.Playwright.Core
public Task ToBeDisabledAsync(LocatorAssertionsToBeDisabledOptions options = null) => ExpectTrueAsync("to.be.disabled", "Locator expected to be disabled", ConvertToFrameExpectOptions(options));
public Task ToBeEditableAsync(LocatorAssertionsToBeEditableOptions options = null) => ExpectTrueAsync("to.be.editable", "Locator expected to be editable", ConvertToFrameExpectOptions(options));
public Task ToBeEditableAsync(LocatorAssertionsToBeEditableOptions options = null)
{
var editable = options == null || options.Editable == null || options.Editable == true;
var editableString = editable ? "editable" : "read-only";
return ExpectTrueAsync(editable ? "to.be.editable" : "to.be.readonly", $"Locator expected to be {editableString}", ConvertToFrameExpectOptions(options));
}
public Task ToBeEmptyAsync(LocatorAssertionsToBeEmptyOptions options = null) => ExpectTrueAsync("to.be.empty", "Locator expected to be empty", ConvertToFrameExpectOptions(options));
public Task ToBeEnabledAsync(LocatorAssertionsToBeEnabledOptions options = null) => ExpectTrueAsync("to.be.enabled", "Locator expected to be enabled", ConvertToFrameExpectOptions(options));
public Task ToBeEnabledAsync(LocatorAssertionsToBeEnabledOptions options = null)
{
var enabled = options == null || options.Enabled == null || options.Enabled == true;
var enabledString = enabled ? "enabled" : "disabled";
return ExpectTrueAsync(enabled ? "to.be.enabled" : "to.be.disabled", $"Locator expected to be {enabledString}", ConvertToFrameExpectOptions(options));
}
public Task ToBeFocusedAsync(LocatorAssertionsToBeFocusedOptions options = null) => ExpectTrueAsync("to.be.focused", "Locator expected to be focused", ConvertToFrameExpectOptions(options));
public Task ToBeHiddenAsync(LocatorAssertionsToBeHiddenOptions options = null) => ExpectTrueAsync("to.be.hidden", "Locator expected to be hidden", ConvertToFrameExpectOptions(options));
public Task ToBeVisibleAsync(LocatorAssertionsToBeVisibleOptions options = null) => ExpectTrueAsync("to.be.visible", "Locator expected to be visible", ConvertToFrameExpectOptions(options));
public Task ToBeVisibleAsync(LocatorAssertionsToBeVisibleOptions options = null)
{
var visible = options == null || options.Visible == null || options.Visible == true;
var visibleString = visible ? "visible" : "hidden";
return ExpectTrueAsync(visible ? "to.be.visible" : "to.be.hidden", $"Locator expected to be {visibleString}", ConvertToFrameExpectOptions(options));
}
private Task ExpectTrueAsync(string expression, string message, FrameExpectOptions options)
{
@@ -50,7 +50,8 @@ namespace Microsoft.Playwright.Transport.Channels
FormData multipartData,
float? timeout,
bool? failOnStatusCode,
bool? ignoreHTTPSErrors)
bool? ignoreHTTPSErrors,
int? maxRedirects)
{
var message = new Dictionary<string, object>
{
@@ -58,6 +59,7 @@ namespace Microsoft.Playwright.Transport.Channels
["method"] = method,
["failOnStatusCode"] = failOnStatusCode,
["ignoreHTTPSErrors"] = ignoreHTTPSErrors,
["maxRedirects"] = maxRedirects,
["timeout"] = timeout,
["params"] = parameters?.ToProtocol(),
["headers"] = headers?.ToProtocol(),