Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions bin/lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ class CommandRegistry {
}
}

class NavigationRedirects extends Map {
#waiters = new Map();
fulfilled(pageId) { return new Promise(resolve => this.#waiters.set(pageId, resolve)); }
markFulfilled(pageId) {
this.#waiters.get(pageId)?.();
this.#waiters.delete(pageId);
}
}

class BaseHandler {
constructor(deps = {}) { Object.assign(this, deps); }
validateResource(resourceMap, resourceId, resourceType) {
Expand All @@ -190,7 +199,7 @@ class BaseHandler {
return { handleId };
}
async executeWithRegistry(registry, method, ...args) { return await registry.execute(method, ...args); }
async followNavigationRedirects(pageId, page, action) {
async followNavigationRedirects(pageId, page, action, settlesOnRedirect = false) {
let nextAction = action;
let redirectCount = 0;
let result;
Expand All @@ -199,7 +208,10 @@ class BaseHandler {
this.navigationRedirects.delete(pageId);

try {
result = await nextAction();
// from Playwright 1.64 only goto() settles on the redirect's 204; a goto() to the same url before it does fails with net::ERR_ABORTED
result = await (settlesOnRedirect
? nextAction()
: Promise.race([nextAction(), this.navigationRedirects.fulfilled(pageId)]));
} catch (error) {
if (!this.navigationRedirects.has(pageId)) throw error;
}
Expand All @@ -212,6 +224,7 @@ class BaseHandler {
throw new Error(`Too many navigation redirects for page ${pageId}`);
}
nextAction = () => page.goto(target);
settlesOnRedirect = true;
}
}
}
Expand Down Expand Up @@ -330,5 +343,5 @@ const logger = new Logger();

module.exports = {
logger, ErrorHandler, LspFraming, sendFramedResponse,
CommandRegistry, BaseHandler, PromiseUtils, FrameUtils, RouteUtils,
CommandRegistry, NavigationRedirects, BaseHandler, PromiseUtils, FrameUtils, RouteUtils,
};
3 changes: 2 additions & 1 deletion bin/lib/handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,8 @@ class PageHandler extends BaseHandler {
const gotoResponse = await this.followNavigationRedirects(
command.pageId,
page,
() => page.goto(command.url, command.options)
() => page.goto(command.url, command.options),
true
);
return { response: this.serializeResponse(gotoResponse) };
}
Expand Down
5 changes: 3 additions & 2 deletions bin/playwright-server.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const {chromium, firefox, webkit, request} = require('playwright');
const { logger, ErrorHandler, LspFraming, sendFramedResponse, CommandRegistry, BaseHandler } = require('./lib/core');
const { logger, ErrorHandler, LspFraming, sendFramedResponse, CommandRegistry, NavigationRedirects, BaseHandler } = require('./lib/core');
const { APIRequestHandler, ContextHandler, PageHandler, LocatorHandler, InteractionHandler, FrameHandler, JSHandleHandler, SelectorsHandler, VideoHandler } = require('./lib/handlers');
const { globalCoordinator } = require('./lib/coordination');

Expand All @@ -20,7 +20,7 @@ class PlaywrightServer extends BaseHandler {
this.dialogs = new Map();
this.elementHandles = new Map();
this.contextThrottling = new Map();
this.navigationRedirects = new Map();
this.navigationRedirects = new NavigationRedirects();
this.servers = new Map();
this.videos = new Map();
this.apiContexts = new Map();
Expand Down Expand Up @@ -148,6 +148,7 @@ class PlaywrightServer extends BaseHandler {
if (!this.pages.has(info.contextId)) throw new Error('Navigation redirects require a page route');
this.navigationRedirects.set(info.contextId, command.url);
await route.fulfill({ status: 204, headers: command.options?.headers });
this.navigationRedirects.markFulfilled(info.contextId);
}

async continueRoute(route, info, command) {
Expand Down
14 changes: 14 additions & 0 deletions tests/Functional/Network/RouteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,20 @@ public function testCanRedirectNavigationRequestAfterClick(): void
$this->assertSame($baseUrl.'/page-2.html', $this->page->url());
}

public function testCanRedirectNavigationRequestAfterFormSubmit(): void
{
$baseUrl = $this->getBaseUrl();
$this->goto('/index.html');
$this->page->evaluate("document.body.innerHTML = '<form method=\"post\" action=\"/login\"><button>Log in</button></form>'");
$this->page->route('**/login', static function (Route $route) use ($baseUrl): void {
$route->redirectNavigationRequest($baseUrl.'/page-2.html');
});

$this->page->locator('button')->click();

$this->assertSame($baseUrl.'/page-2.html', $this->page->url());
}

public function testCanRedirectNavigationRequestAfterReload(): void
{
$baseUrl = $this->getBaseUrl();
Expand Down
Loading