/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import assert from 'node:assert';
import { describe, it } from 'node:test';
import { listPages, newPage, closePage, selectPage, navigatePage, resizePage, handleDialog, } from '../../src/tools/pages.js';
import { withMcpContext } from '../utils.js';
describe('pages', () => {
    describe('list_pages', () => {
        it('list pages', async () => {
            await withMcpContext(async (response, context) => {
                await listPages.handler({ params: {} }, response, context);
                assert.ok(response.includePages);
            });
        });
    });
    describe('new_page', () => {
        it('create a page', async () => {
            await withMcpContext(async (response, context) => {
                assert.strictEqual(context.getPageByIdx(0), context.getSelectedPage());
                await newPage.handler({ params: { url: 'about:blank' } }, response, context);
                assert.strictEqual(context.getPageByIdx(1), context.getSelectedPage());
                assert.ok(response.includePages);
            });
        });
    });
    describe('close_page', () => {
        it('closes a page', async () => {
            await withMcpContext(async (response, context) => {
                const page = await context.newPage();
                assert.strictEqual(context.getPageByIdx(1), context.getSelectedPage());
                assert.strictEqual(context.getPageByIdx(1), page);
                await closePage.handler({ params: { pageIdx: 1 } }, response, context);
                assert.ok(page.isClosed());
                assert.ok(response.includePages);
            });
        });
        it('cannot close the last page', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await closePage.handler({ params: { pageIdx: 0 } }, response, context);
                assert.deepStrictEqual(response.responseLines[0], `The last open page cannot be closed. It is fine to keep it open.`);
                assert.ok(response.includePages);
                assert.ok(!page.isClosed());
            });
        });
    });
    describe('select_page', () => {
        it('selects a page', async () => {
            await withMcpContext(async (response, context) => {
                await context.newPage();
                assert.strictEqual(context.getPageByIdx(1), context.getSelectedPage());
                await selectPage.handler({ params: { pageIdx: 0 } }, response, context);
                assert.strictEqual(context.getPageByIdx(0), context.getSelectedPage());
                assert.ok(response.includePages);
            });
        });
        it('selects a page and keeps it focused in the background', async () => {
            await withMcpContext(async (response, context) => {
                await context.newPage();
                assert.strictEqual(context.getPageByIdx(1), context.getSelectedPage());
                assert.strictEqual(await context.getPageByIdx(0).evaluate(() => document.hasFocus()), false);
                await selectPage.handler({ params: { pageIdx: 0 } }, response, context);
                assert.strictEqual(context.getPageByIdx(0), context.getSelectedPage());
                assert.strictEqual(await context.getPageByIdx(0).evaluate(() => document.hasFocus()), true);
                assert.ok(response.includePages);
            });
        });
    });
    describe('navigate_page', () => {
        it('navigates to correct page', async () => {
            await withMcpContext(async (response, context) => {
                await navigatePage.handler({ params: { url: 'data:text/html,<div>Hello MCP</div>' } }, response, context);
                const page = context.getSelectedPage();
                assert.equal(await page.evaluate(() => document.querySelector('div')?.textContent), 'Hello MCP');
                assert.ok(response.includePages);
            });
        });
        it('throws an error if the page was closed not by the MCP server', async () => {
            await withMcpContext(async (response, context) => {
                const page = await context.newPage();
                assert.strictEqual(context.getPageByIdx(1), context.getSelectedPage());
                assert.strictEqual(context.getPageByIdx(1), page);
                await page.close();
                try {
                    await navigatePage.handler({ params: { url: 'data:text/html,<div>Hello MCP</div>' } }, response, context);
                    assert.fail('should not reach here');
                }
                catch (err) {
                    assert.strictEqual(err.message, 'The selected page has been closed. Call list_pages to see open pages.');
                }
            });
        });
        it('go back', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await page.goto('data:text/html,<div>Hello MCP</div>');
                await navigatePage.handler({ params: { type: 'back' } }, response, context);
                assert.equal(await page.evaluate(() => document.location.href), 'about:blank');
                assert.ok(response.includePages);
            });
        });
        it('go forward', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await page.goto('data:text/html,<div>Hello MCP</div>');
                await page.goBack();
                await navigatePage.handler({ params: { type: 'forward' } }, response, context);
                assert.equal(await page.evaluate(() => document.querySelector('div')?.textContent), 'Hello MCP');
                assert.ok(response.includePages);
            });
        });
        it('reload', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await page.goto('data:text/html,<div>Hello MCP</div>');
                await navigatePage.handler({ params: { type: 'reload' } }, response, context);
                assert.equal(await page.evaluate(() => document.location.href), 'data:text/html,<div>Hello MCP</div>');
                assert.ok(response.includePages);
            });
        });
        it('go forward with error', async () => {
            await withMcpContext(async (response, context) => {
                await navigatePage.handler({ params: { type: 'forward' } }, response, context);
                assert.ok(response.responseLines
                    .at(0)
                    ?.startsWith('Unable to navigate forward in the selected page:'));
                assert.ok(response.includePages);
            });
        });
        it('go back with error', async () => {
            await withMcpContext(async (response, context) => {
                await navigatePage.handler({ params: { type: 'back' } }, response, context);
                assert.ok(response.responseLines
                    .at(0)
                    ?.startsWith('Unable to navigate back in the selected page:'));
                assert.ok(response.includePages);
            });
        });
    });
    describe('resize', () => {
        it('create a page', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                const resizePromise = page.evaluate(() => {
                    return new Promise(resolve => {
                        window.addEventListener('resize', resolve, { once: true });
                    });
                });
                await resizePage.handler({ params: { width: 700, height: 500 } }, response, context);
                await resizePromise;
                const dimensions = await page.evaluate(() => {
                    return [window.innerWidth, window.innerHeight];
                });
                assert.deepStrictEqual(dimensions, [700, 500]);
            });
        });
    });
    describe('dialogs', () => {
        it('can accept dialogs', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                const dialogPromise = new Promise(resolve => {
                    page.on('dialog', () => {
                        resolve();
                    });
                });
                page.evaluate(() => {
                    alert('test');
                });
                await dialogPromise;
                await handleDialog.handler({
                    params: {
                        action: 'accept',
                    },
                }, response, context);
                assert.strictEqual(context.getDialog(), undefined);
                assert.strictEqual(response.responseLines[0], 'Successfully accepted the dialog');
            });
        });
        it('can dismiss dialogs', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                const dialogPromise = new Promise(resolve => {
                    page.on('dialog', () => {
                        resolve();
                    });
                });
                page.evaluate(() => {
                    alert('test');
                });
                await dialogPromise;
                await handleDialog.handler({
                    params: {
                        action: 'dismiss',
                    },
                }, response, context);
                assert.strictEqual(context.getDialog(), undefined);
                assert.strictEqual(response.responseLines[0], 'Successfully dismissed the dialog');
            });
        });
        it('can dismiss already dismissed dialog dialogs', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                const dialogPromise = new Promise(resolve => {
                    page.on('dialog', dialog => {
                        resolve(dialog);
                    });
                });
                page.evaluate(() => {
                    alert('test');
                });
                const dialog = await dialogPromise;
                await dialog.dismiss();
                await handleDialog.handler({
                    params: {
                        action: 'dismiss',
                    },
                }, response, context);
                assert.strictEqual(context.getDialog(), undefined);
                assert.strictEqual(response.responseLines[0], 'Successfully dismissed the dialog');
            });
        });
    });
});
