Skip to content

Commit 4d9ac22

Browse files
0xlakshanOrKoN
andauthored
fix: support resize_page when browser window is maximized/fullscreenwindow state (#748)
Related Issue - [465](#465) ### Description This change make sure that the browser window is restored to a `normal` state before resizing the page. When the window is in `fullscreen` mode we have to set the state twice to match how Chrome CDP behaves. Tests cover window resizing for every available window states `type WindowState = 'normal' | 'minimized' | 'maximized' | 'fullscreen';` --------- Co-authored-by: Alex Rudenko <OrKoN@users.noreply.github.com>
1 parent 61f37d6 commit 4d9ac22

File tree

3 files changed

+145
-1
lines changed

3 files changed

+145
-1
lines changed

src/tools/pages.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,22 @@ export const resizePage = defineTool({
211211
handler: async (request, response, context) => {
212212
const page = context.getSelectedPage();
213213

214+
try {
215+
const browser = page.browser();
216+
const windowId = await page.windowId();
217+
218+
const bounds = await browser.getWindowBounds(windowId);
219+
220+
if (bounds.windowState === 'fullscreen') {
221+
// Have to call this twice on Ubuntu when the window is in fullscreen mode.
222+
await browser.setWindowBounds(windowId, {windowState: 'normal'});
223+
await browser.setWindowBounds(windowId, {windowState: 'normal'});
224+
} else if (bounds.windowState !== 'normal') {
225+
await browser.setWindowBounds(windowId, {windowState: 'normal'});
226+
}
227+
} catch {
228+
// Window APIs are not supported on all platforms
229+
}
214230
await page.resize({
215231
contentWidth: request.params.width,
216232
contentHeight: request.params.height,

tests/tools/pages.test.ts

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ describe('pages', () => {
214214
});
215215
});
216216
describe('resize', () => {
217-
it('create a page', async () => {
217+
it('resize the page', async () => {
218218
await withMcpContext(async (response, context) => {
219219
const page = context.getSelectedPage();
220220
const resizePromise = page.evaluate(() => {
@@ -228,12 +228,139 @@ describe('pages', () => {
228228
context,
229229
);
230230
await resizePromise;
231+
await page.waitForFunction(
232+
() => window.innerWidth === 700 && window.innerHeight === 500,
233+
);
231234
const dimensions = await page.evaluate(() => {
232235
return [window.innerWidth, window.innerHeight];
233236
});
234237
assert.deepStrictEqual(dimensions, [700, 500]);
235238
});
236239
});
240+
241+
it('resize when window state is normal', async () => {
242+
await withMcpContext(async (response, context) => {
243+
const page = context.getSelectedPage();
244+
const browser = page.browser();
245+
const windowId = await page.windowId();
246+
await browser.setWindowBounds(windowId, {windowState: 'normal'});
247+
248+
const {windowState} = await browser.getWindowBounds(windowId);
249+
assert.strictEqual(windowState, 'normal');
250+
251+
const resizePromise = page.evaluate(() => {
252+
return new Promise(resolve => {
253+
window.addEventListener('resize', resolve, {once: true});
254+
});
255+
});
256+
await resizePage.handler(
257+
{params: {width: 650, height: 450}},
258+
response,
259+
context,
260+
);
261+
await resizePromise;
262+
await page.waitForFunction(
263+
() => window.innerWidth === 650 && window.innerHeight === 450,
264+
);
265+
const dimensions = await page.evaluate(() => {
266+
return [window.innerWidth, window.innerHeight];
267+
});
268+
assert.deepStrictEqual(dimensions, [650, 450]);
269+
});
270+
});
271+
272+
it('resize when window state is minimized', async () => {
273+
await withMcpContext(async (response, context) => {
274+
const page = context.getSelectedPage();
275+
const browser = page.browser();
276+
const windowId = await page.windowId();
277+
await browser.setWindowBounds(windowId, {windowState: 'minimized'});
278+
279+
const {windowState} = await browser.getWindowBounds(windowId);
280+
assert.strictEqual(windowState, 'minimized');
281+
282+
const resizePromise = page.evaluate(() => {
283+
return new Promise(resolve => {
284+
window.addEventListener('resize', resolve, {once: true});
285+
});
286+
});
287+
await resizePage.handler(
288+
{params: {width: 750, height: 550}},
289+
response,
290+
context,
291+
);
292+
await resizePromise;
293+
await page.waitForFunction(
294+
() => window.innerWidth === 750 && window.innerHeight === 550,
295+
);
296+
const dimensions = await page.evaluate(() => {
297+
return [window.innerWidth, window.innerHeight];
298+
});
299+
assert.deepStrictEqual(dimensions, [750, 550]);
300+
});
301+
});
302+
303+
it('resize when window state is maximized', async () => {
304+
await withMcpContext(async (response, context) => {
305+
const page = context.getSelectedPage();
306+
const browser = page.browser();
307+
const windowId = await page.windowId();
308+
await browser.setWindowBounds(windowId, {windowState: 'maximized'});
309+
310+
const {windowState} = await browser.getWindowBounds(windowId);
311+
assert.strictEqual(windowState, 'maximized');
312+
313+
const resizePromise = page.evaluate(() => {
314+
return new Promise(resolve => {
315+
window.addEventListener('resize', resolve, {once: true});
316+
});
317+
});
318+
await resizePage.handler(
319+
{params: {width: 725, height: 525}},
320+
response,
321+
context,
322+
);
323+
await resizePromise;
324+
await page.waitForFunction(
325+
() => window.innerWidth === 725 && window.innerHeight === 525,
326+
);
327+
const dimensions = await page.evaluate(() => {
328+
return [window.innerWidth, window.innerHeight];
329+
});
330+
assert.deepStrictEqual(dimensions, [725, 525]);
331+
});
332+
});
333+
334+
it('resize when window state is fullscreen', async () => {
335+
await withMcpContext(async (response, context) => {
336+
const page = context.getSelectedPage();
337+
const browser = page.browser();
338+
const windowId = await page.windowId();
339+
await browser.setWindowBounds(windowId, {windowState: 'fullscreen'});
340+
341+
const {windowState} = await browser.getWindowBounds(windowId);
342+
assert.strictEqual(windowState, 'fullscreen');
343+
344+
const resizePromise = page.evaluate(() => {
345+
return new Promise(resolve => {
346+
window.addEventListener('resize', resolve, {once: true});
347+
});
348+
});
349+
await resizePage.handler(
350+
{params: {width: 850, height: 650}},
351+
response,
352+
context,
353+
);
354+
await resizePromise;
355+
await page.waitForFunction(
356+
() => window.innerWidth === 850 && window.innerHeight === 650,
357+
);
358+
const dimensions = await page.evaluate(() => {
359+
return [window.innerWidth, window.innerHeight];
360+
});
361+
assert.deepStrictEqual(dimensions, [850, 650]);
362+
});
363+
});
237364
});
238365

239366
describe('dialogs', () => {

tests/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export async function withBrowser(
5555
devtools: options.autoOpenDevTools ?? false,
5656
pipe: true,
5757
handleDevToolsAsPage: true,
58+
args: ['--screen-info={3840x2160}'],
5859
};
5960
const key = JSON.stringify(launchOptions);
6061

0 commit comments

Comments
 (0)