/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import assert from 'node:assert';
import { describe, it } from 'node:test';
import { evaluateScript } from '../../src/tools/script.js';
import { serverHooks } from '../server.js';
import { html, withMcpContext } from '../utils.js';
describe('script', () => {
    const server = serverHooks();
    describe('browser_evaluate_script', () => {
        it('evaluates', async () => {
            await withMcpContext(async (response, context) => {
                await evaluateScript.handler({ params: { function: String(() => 2 * 5) } }, response, context);
                const lineEvaluation = response.responseLines.at(2);
                assert.strictEqual(JSON.parse(lineEvaluation), 10);
            });
        });
        it('runs in selected page', async () => {
            await withMcpContext(async (response, context) => {
                await evaluateScript.handler({ params: { function: String(() => document.title) } }, response, context);
                let lineEvaluation = response.responseLines.at(2);
                assert.strictEqual(JSON.parse(lineEvaluation), '');
                const page = await context.newPage();
                await page.setContent(`
          <head>
            <title>New Page</title>
          </head>
        `);
                response.resetResponseLineForTesting();
                await evaluateScript.handler({ params: { function: String(() => document.title) } }, response, context);
                lineEvaluation = response.responseLines.at(2);
                assert.strictEqual(JSON.parse(lineEvaluation), 'New Page');
            });
        });
        it('work for complex objects', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await page.setContent(html `<script src="./scripts.js"></script> `);
                await evaluateScript.handler({
                    params: {
                        function: String(() => {
                            const scripts = Array.from(document.head.querySelectorAll('script')).map(s => ({ src: s.src, async: s.async, defer: s.defer }));
                            return { scripts };
                        }),
                    },
                }, response, context);
                const lineEvaluation = response.responseLines.at(2);
                assert.deepEqual(JSON.parse(lineEvaluation), {
                    scripts: [],
                });
            });
        });
        it('work for async functions', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await page.setContent(html `<script src="./scripts.js"></script> `);
                await evaluateScript.handler({
                    params: {
                        function: String(async () => {
                            await new Promise(res => setTimeout(res, 0));
                            return 'Works';
                        }),
                    },
                }, response, context);
                const lineEvaluation = response.responseLines.at(2);
                assert.strictEqual(JSON.parse(lineEvaluation), 'Works');
            });
        });
        it('work with one argument', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await page.setContent(html `<button id="test">test</button>`);
                await context.createTextSnapshot();
                await evaluateScript.handler({
                    params: {
                        function: String(async (el) => {
                            return el.id;
                        }),
                        args: [{ uid: '1_1' }],
                    },
                }, response, context);
                const lineEvaluation = response.responseLines.at(2);
                assert.strictEqual(JSON.parse(lineEvaluation), 'test');
            });
        });
        it('work with multiple args', async () => {
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await page.setContent(html `<button id="test">test</button>`);
                await context.createTextSnapshot();
                await evaluateScript.handler({
                    params: {
                        function: String((container, child) => {
                            return container.contains(child);
                        }),
                        args: [{ uid: '1_0' }, { uid: '1_1' }],
                    },
                }, response, context);
                const lineEvaluation = response.responseLines.at(2);
                assert.strictEqual(JSON.parse(lineEvaluation), true);
            });
        });
        it('work for elements inside iframes', async () => {
            server.addHtmlRoute('/iframe', html `<main><button>I am iframe button</button></main>`);
            server.addHtmlRoute('/main', html `<iframe src="/iframe"></iframe>`);
            await withMcpContext(async (response, context) => {
                const page = context.getSelectedPage();
                await page.goto(server.getRoute('/main'));
                await context.createTextSnapshot();
                await evaluateScript.handler({
                    params: {
                        function: String((element) => {
                            return element.textContent;
                        }),
                        args: [{ uid: '1_3' }],
                    },
                }, response, context);
                const lineEvaluation = response.responseLines.at(2);
                assert.strictEqual(JSON.parse(lineEvaluation), 'I am iframe button');
            });
        });
    });
});
