/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
    if (value !== null && value !== void 0) {
        if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
        var dispose, inner;
        if (async) {
            if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
            dispose = value[Symbol.asyncDispose];
        }
        if (dispose === void 0) {
            if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
            dispose = value[Symbol.dispose];
            if (async) inner = dispose;
        }
        if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
        if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
        env.stack.push({ value: value, dispose: dispose, async: async });
    }
    else if (async) {
        env.stack.push({ async: true });
    }
    return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
    return function (env) {
        function fail(e) {
            env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
            env.hasError = true;
        }
        var r, s = 0;
        function next() {
            while (r = env.stack.pop()) {
                try {
                    if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
                    if (r.dispose) {
                        var result = r.dispose.call(r.value);
                        if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
                    }
                    else s |= 1;
                }
                catch (e) {
                    fail(e);
                }
            }
            if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
            if (env.hasError) throw env.error;
        }
        return next();
    };
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
import fs from 'fs';
import path from 'path';
import { test, expect, daemonFolder } from './cli-fixtures';
import { killProcessGroup } from '../config/commonFixtures';
import playwright from '../../packages/playwright-core';
test('list', async ({ cli, server }) => {
    const { output: emptyOutput } = await cli('list');
    expect(emptyOutput).toContain('(no browsers)');
    await cli('open', server.HELLO_WORLD);
    const { output: listOutput } = await cli('list');
    expect(listOutput).toContain('### Browsers');
    expect(listOutput).toContain('- default:');
});
test('close', async ({ cli, server }) => {
    await cli('open', server.HELLO_WORLD);
    const { output } = await cli('close');
    expect(output).toContain(`Browser 'default' closed`);
    const { output: listOutput } = await cli('list');
    expect(listOutput).toContain('(no browsers)');
});
test('close named session', async ({ cli, server }) => {
    await cli('-s', 'mysession', 'open', server.HELLO_WORLD);
    const { output } = await cli('-s', 'mysession', 'close');
    expect(output).toContain(`Browser 'mysession' closed`);
});
test('close non-running session', async ({ cli }) => {
    const { output } = await cli('-s', 'nonexistent', 'close');
    expect(output).toContain(`Browser 'nonexistent' is not open.`);
});
test('close-all', async ({ cli, server }) => {
    await cli('-s', 'session1', 'open', server.HELLO_WORLD);
    await cli('-s', 'session2', 'open', server.HELLO_WORLD);
    const { output: listBefore } = await cli('list');
    expect(listBefore).toContain('session1');
    expect(listBefore).toContain('session2');
    await cli('close-all');
    const { output: listAfter } = await cli('list');
    expect(listAfter).not.toContain('session1');
});
test('delete-data', async ({ cli, server, mcpBrowserNormalized }) => {
    await cli('open', server.HELLO_WORLD, '--persistent');
    const dataDir = path.resolve(await daemonFolder(), 'ud-default-' + mcpBrowserNormalized);
    expect(fs.existsSync(dataDir)).toBe(true);
    const { output } = await cli('delete-data');
    expect(output).toContain(`Deleted user data for browser 'default'.`);
    expect(fs.existsSync(dataDir)).toBe(false);
});
test('delete-data named session', async ({ cli, server, mcpBrowserNormalized }) => {
    await cli('-s', 'mysession', 'open', server.HELLO_WORLD, '--persistent');
    const dataDir = path.resolve(await daemonFolder(), 'ud-mysession-' + mcpBrowserNormalized);
    expect(fs.existsSync(dataDir)).toBe(true);
    const { output } = await cli('-s', 'mysession', 'delete-data');
    expect(output).toContain(`Deleted user data for browser 'mysession'.`);
    expect(fs.existsSync(dataDir)).toBe(false);
});
test('delete-data non-existent session', async ({ cli }) => {
    const { output } = await cli('-s', 'nonexistent', 'delete-data');
    expect(output).toContain(`No user data found for browser 'nonexistent'.`);
});
test('session stops when browser exits', async ({ cli, server }) => {
    await cli('open', server.HELLO_WORLD);
    const { output: listBefore } = await cli('list');
    expect(listBefore).toContain('default');
    // Close the browser - this will cause the daemon to exit so the command may fail
    await cli('run-code', '() => page.context().browser().close()').catch(() => { });
    await cli('close');
    const { output: listAfter } = await cli('list');
    expect(listAfter).toContain('(no browsers)');
});
test('session reopen with different config', async ({ cli, server }, testInfo) => {
    const config = { browser: { contextOptions: { viewport: { width: 700, height: 500 } } } };
    const configPath = testInfo.outputPath('config.json');
    await fs.promises.writeFile(configPath, JSON.stringify(config, null, 2));
    {
        await cli('open', server.HELLO_WORLD, '--config=' + configPath);
        const { output } = await cli('eval', 'window.innerWidth + "x" + window.innerHeight');
        expect(output).toContain('700x500');
    }
    {
        // Reopen without config should use default viewport
        await cli('open', server.HELLO_WORLD);
        const { output } = await cli('eval', 'window.innerWidth + "x" + window.innerHeight');
        expect(output).toContain('1280x720');
    }
});
test('workspace isolation - sessions in different workspaces are isolated', async ({ cli, server }, testInfo) => {
    // Create two separate workspaces with their own daemon dirs
    const workspace1 = testInfo.outputPath('workspace1');
    const workspace2 = testInfo.outputPath('workspace2');
    await fs.promises.mkdir(workspace1, { recursive: true });
    await fs.promises.mkdir(workspace2, { recursive: true });
    await cli('install', { cwd: workspace1 });
    await cli('install', { cwd: workspace2 });
    expect(fs.existsSync(path.join(workspace1, '.playwright'))).toBe(true);
    expect(fs.existsSync(path.join(workspace2, '.playwright'))).toBe(true);
    // Open sessions in both workspaces
    await cli('open', server.HELLO_WORLD, { cwd: workspace1 });
    await cli('open', server.HELLO_WORLD, { cwd: workspace2 });
    const { output: list1 } = await cli('list', { cwd: workspace1 });
    expect(list1).toContain('default');
    const { output: list2 } = await cli('list', { cwd: workspace2 });
    expect(list2).toContain(' default');
    await cli('close', { cwd: workspace1 });
    const { output: list1After } = await cli('list', { cwd: workspace1 });
    expect(list1After).not.toContain('### Browsers');
    const { output: list2After } = await cli('list', { cwd: workspace2 });
    expect(list2After).toContain('default');
    await cli('close', { cwd: workspace2 });
});
test('list --all lists sessions from all workspaces', async ({ cli, server }, testInfo) => {
    // Create two separate workspaces with their own daemon dirs
    const workspace1 = testInfo.outputPath('workspace1');
    const workspace2 = testInfo.outputPath('workspace2');
    const workspace3 = testInfo.outputPath('workspace3');
    await fs.promises.mkdir(workspace1, { recursive: true });
    await fs.promises.mkdir(workspace2, { recursive: true });
    await fs.promises.mkdir(workspace3, { recursive: true });
    await cli('install', { cwd: workspace1 });
    await cli('install', { cwd: workspace2 });
    await cli('install', { cwd: workspace3 });
    await cli('-s', 'session1', 'open', server.HELLO_WORLD, { cwd: workspace1 });
    await cli('-s', 'session2', 'open', server.HELLO_WORLD, { cwd: workspace2 });
    const session3 = await cli('-s', 'session3', 'open', server.HELLO_WORLD, { cwd: workspace3 });
    // List all sessions from workspace1
    const { output: allList } = await cli('list', '--all', { cwd: workspace1 });
    // Should include both workspace folders and sessions
    expect(allList).toContain('/:');
    expect(allList).toContain('session1');
    expect(allList).toContain('..' + path.sep + 'workspace2:');
    expect(allList).toContain('session2');
    expect(allList).toContain('..' + path.sep + 'workspace3:');
    expect(allList).toContain('session3');
    const rootDir = test.info().outputPath('daemon');
    const dirs = await fs.promises.readdir(rootDir);
    const getSessionFiles = async () => (await Promise.all(dirs.map(dir => fs.promises.readdir(path.join(rootDir, dir))))).flat();
    const sessionFilesBefore = await getSessionFiles();
    expect(sessionFilesBefore).toContain('session1.session');
    expect(sessionFilesBefore).toContain('session2.session');
    expect(sessionFilesBefore).toContain('session3.session');
    await cli('-s', 'session1', 'close', { cwd: workspace1 });
    const { output: listTwo } = await cli('list', '--all', { cwd: workspace2 });
    expect(listTwo).not.toContain('workspace1');
    expect(listTwo).not.toContain('session1');
    expect(listTwo).toContain('/:');
    expect(listTwo).toContain('session2');
    expect(listTwo).toContain('workspace3');
    expect(listTwo).toContain('session3');
    const sessionFilesAfterClose = await getSessionFiles();
    expect(sessionFilesAfterClose).not.toContain('session1.session');
    expect(sessionFilesAfterClose).toContain('session2.session');
    expect(sessionFilesAfterClose).toContain('session3.session');
    killProcessGroup(session3.daemonPid);
    const { output: listOne } = await cli('list', '--all', { cwd: workspace2 });
    expect(listOne).not.toContain('workspace1');
    expect(listOne).not.toContain('session1');
    expect(listOne).toContain('/:');
    expect(listOne).toContain('session2');
    expect(listOne).not.toContain('workspace3');
    expect(listOne).not.toContain('session3');
    const sessionFilesAfterList = await getSessionFiles();
    expect(sessionFilesAfterList).not.toContain('session1.session');
    expect(sessionFilesAfterList).toContain('session2.session');
    expect(sessionFilesAfterList).not.toContain('session3.session');
});
test('newer client with older daemon is compatible', async ({ cli, server }) => {
    await cli('open', server.HELLO_WORLD);
    const { exitCode } = await cli('eval', '1+1', { env: { PLAYWRIGHT_CLI_VERSION_FOR_TEST: '9.9.9' } });
    expect(exitCode).toBe(0);
});
test('older client with newer daemon fails with version mismatch error', async ({ cli, server }) => {
    await cli('open', server.HELLO_WORLD);
    const { output, error, exitCode } = await cli('eval', '1+1', { env: { PLAYWRIGHT_CLI_VERSION_FOR_TEST: '0.0.1' } });
    expect(exitCode).not.toBe(0);
    const fullOutput = output + error;
    expect(fullOutput).toContain('Client is v0.0.1');
    expect(fullOutput).toContain('playwright-cli open');
    expect(fullOutput).toContain('to restart the browser session');
});
test('older client with newer daemon - named session includes session name in error', async ({ cli, server }) => {
    await cli('-s', 'mysession', 'open', server.HELLO_WORLD);
    const { output, error, exitCode } = await cli('-s', 'mysession', 'eval', '1+1', { env: { PLAYWRIGHT_CLI_VERSION_FOR_TEST: '0.0.1' } });
    expect(exitCode).not.toBe(0);
    const fullOutput = output + error;
    expect(fullOutput).toContain('Client is v0.0.1');
    expect(fullOutput).toContain(`session 'mysession'`);
    expect(fullOutput).toContain('playwright-cli -s=mysession open');
});
test('older client with newer daemon - list shows incompatible warning', async ({ cli, server }) => {
    await cli('open', server.HELLO_WORLD);
    const { output } = await cli('list', { env: { PLAYWRIGHT_CLI_VERSION_FOR_TEST: '0.0.1' } });
    expect(output).toContain('### Browsers');
    expect(output).toContain('- default:');
    expect(output).toContain('[incompatible please re-open]');
});
test.describe('browser server', () => {
    test.beforeEach(async ({ mcpBrowser }, testInfo) => {
        test.skip(!['chrome', 'chromium', 'webkit', 'firefox'].includes(mcpBrowser));
        process.env.PLAYWRIGHT_SERVER_REGISTRY = testInfo.outputPath('registry');
    });
    test('list browser servers', async ({ cli, mcpBrowser }) => {
        const env_1 = { stack: [], error: void 0, hasError: false };
        try {
            const browserName = mcpBrowser.replace('chrome', 'chromium');
            const browser = __addDisposableResource(env_1, await playwright[browserName].launch({ headless: true }), true);
            await browser.bind('foobar', { workspaceDir: 'workspace1' });
            const { output } = await cli('list', '--all');
            expect(output).toBe(`### Browser servers available for attach
workspace1:
- browser "foobar":
  - browser: ${ /* FIX browser._options */mcpBrowser.replace('chrome', 'chromium')}
  - version: ${version}
  - data-dir: <in-memory>
  - run \`playwright-cli attach "foobar"\` to attach`);
        }
        catch (e_1) {
            env_1.error = e_1;
            env_1.hasError = true;
        }
        finally {
            const result_1 = __disposeResources(env_1);
            if (result_1)
                await result_1;
        }
    });
    test('attach to browser server', async ({ cli, mcpBrowser }) => {
        const env_2 = { stack: [], error: void 0, hasError: false };
        try {
            const browserName = mcpBrowser.replace('chrome', 'chromium');
            const browser = __addDisposableResource(env_2, await playwright[browserName].launch({ headless: true }), true);
            await browser.bind('foobar', { workspaceDir: 'workspace1' });
            const page = await browser.newPage();
            await page.setContent('<title>My Page</title>');
            const { output: openOutput } = await cli('attach', 'foobar');
            expect(openOutput).toContain('### Session `foobar` created, attached to `foobar`.');
            expect(openOutput).toContain('Run commands with: playwright-cli --s=foobar <command>');
            const { output: listOutput } = await cli('list', '--all');
            expect(listOutput).toBe(`### Browsers
/:
- foobar:
  - status: open
  - browser-type: ${mcpBrowser.replace('chrome', 'chromium')} (attached)

### Browser servers available for attach
workspace1:
- browser "foobar":
  - browser: ${mcpBrowser.replace('chrome', 'chromium')}
  - version: ${version}
  - data-dir: <in-memory>
  - run \`playwright-cli attach "foobar"\` to attach`);
        }
        catch (e_2) {
            env_2.error = e_2;
            env_2.hasError = true;
        }
        finally {
            const result_2 = __disposeResources(env_2);
            if (result_2)
                await result_2;
        }
    });
    test('fail to attach to browser server without contexts', async ({ cli, mcpBrowser }) => {
        const env_3 = { stack: [], error: void 0, hasError: false };
        try {
            const browserName = mcpBrowser.replace('chrome', 'chromium');
            const browser = __addDisposableResource(env_3, await playwright[browserName].launch({ headless: true }), true);
            await browser.bind('foobar', { workspaceDir: 'workspace1' });
            const { error } = await cli('attach', 'foobar');
            expect(error).toContain('Error: unable to connect to a browser that does not have any contexts');
        }
        catch (e_3) {
            env_3.error = e_3;
            env_3.hasError = true;
        }
        finally {
            const result_3 = __disposeResources(env_3);
            if (result_3)
                await result_3;
        }
    });
    test('attach with session alias', async ({ cli, mcpBrowser }) => {
        const env_4 = { stack: [], error: void 0, hasError: false };
        try {
            const browserName = mcpBrowser.replace('chrome', 'chromium');
            const browser = __addDisposableResource(env_4, await playwright[browserName].launch({ headless: true }), true);
            await browser.bind('foobar', { workspaceDir: 'workspace1' });
            const page = await browser.newPage();
            await page.setContent('<title>Alias Page</title>');
            const { output: openOutput } = await cli('attach', 'foobar', '--session=mybrowser');
            expect(openOutput).toContain('### Session `mybrowser` created, attached to `foobar`.');
            expect(openOutput).toContain('Run commands with: playwright-cli --s=mybrowser <command>');
            await cli('-s', 'mybrowser', 'close');
        }
        catch (e_4) {
            env_4.error = e_4;
            env_4.hasError = true;
        }
        finally {
            const result_4 = __disposeResources(env_4);
            if (result_4)
                await result_4;
        }
    });
    test('detach from browser server', async ({ cli, mcpBrowser }) => {
        const env_5 = { stack: [], error: void 0, hasError: false };
        try {
            const browserName = mcpBrowser.replace('chrome', 'chromium');
            const browser = __addDisposableResource(env_5, await playwright[browserName].launch({ headless: true }), true);
            await browser.newPage();
            await browser.bind('foobar', { workspaceDir: 'workspace1' });
            const { output: openOutput } = await cli('attach', 'foobar');
            expect(openOutput).toContain('Session `foobar` created, attached to `foobar`');
            await cli('-s', 'foobar', 'close');
            const { output: listOutput } = await cli('list', '--all');
            expect(listOutput).toBe(`### Browser servers available for attach
workspace1:
- browser \"foobar\":
  - browser: ${ /* FIX browser._options */mcpBrowser.replace('chrome', 'chromium')}
  - version: ${version}
  - data-dir: <in-memory>
  - run \`playwright-cli attach \"foobar\"\` to attach`);
        }
        catch (e_5) {
            env_5.error = e_5;
            env_5.hasError = true;
        }
        finally {
            const result_5 = __disposeResources(env_5);
            if (result_5)
                await result_5;
        }
    });
});
const version = 'v' + require('../../packages/playwright-core/package.json').version;
//# sourceMappingURL=cli-session.spec.js.map