"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtensionTestRig = exports.TestRig = void 0;
const assert_1 = __importDefault(require("assert"));
const path_1 = __importDefault(require("path"));
const index_js_1 = require("../cdp/index.js");
const engine_js_1 = require("./engine.js");
const extension_js_1 = require("./extension.js");
const index_js_2 = require("./mocks/index.js");
const index_js_3 = require("./model/index.js");
const index_js_4 = require("./services/index.js");
class UnexpectedSuccessError extends Error {
    constructor() {
        super(...arguments);
        this.code = 'UnexpectedSuccess';
    }
}
class TestRig {
    constructor() {
        this.chromePort = Number(process.env.CHROME_PORT) || 9123;
        this.chromeAddress = process.env.CHROME_ADDRESS ?? '127.0.0.1';
        this.chromePath = process.env.CHROME_PATH ?? undefined;
        this.chromeArgs = process.env.CHROME_ARGS ?? '';
        this.engine = new engine_js_1.Engine();
        this.launcher = new index_js_1.ChromeLauncher({
            chromeAddress: this.chromeAddress,
            chromePort: this.chromePort,
            chromePath: this.chromePath,
            userDataDir: path_1.default.resolve(process.cwd(), '.tmp/chromedata'),
            args: this.getChromeArgs(),
        });
    }
    getChromeArgs() {
        return [
            `--proxy-server=http://localhost:${this.proxy.getProxyPort()}`,
            ...this.chromeArgs.split(/\s+/).filter(Boolean),
        ];
    }
    getChromeAdditionalArgs() {
        return [];
    }
    setupEngine() {
        this.engine.container.bind(index_js_2.FlowServiceMock).toSelf().inSingletonScope();
        this.engine.container.rebind(index_js_4.FlowService).toService(index_js_2.FlowServiceMock);
    }
    async beforeAll() {
        await this.launcher.launch();
    }
    async afterAll() {
        await this.launcher.shutdown(1000);
    }
    async beforeEach() {
        this.engine = new engine_js_1.Engine();
        this.setupEngine();
        await this.engine.startSession();
        await this.browser.connect();
        await this.openNewTab();
    }
    async afterEach() {
        await this.engine.finishSession();
        await this.closeTab();
        await this.browser.disconnect();
    }
    get browser() {
        return this.engine.get(index_js_4.BrowserService);
    }
    get page() {
        return this.browser.page;
    }
    get flow() {
        return this.engine.get(index_js_2.FlowServiceMock);
    }
    get proxy() {
        return this.engine.get(index_js_4.ProxyService);
    }
    get playwright() {
        return this.engine.get(index_js_4.PlaywrightService);
    }
    async openNewTab() {
        this.browserContextId = (await this.browser.createBrowserContext()).browserContextId;
        const tab = await this.browser.newTab(this.browserContextId);
        await this.browser.attach(tab.target.targetId);
        for (const other of this.browser.attachedTargets()) {
            if (other.targetId !== tab.target.targetId) {
                other.close();
            }
        }
    }
    async closeTab() {
        const { page } = this;
        page.close();
        if (page.target.browserContextId) {
            await this.browser.disposeBrowserContext(page.target.browserContextId);
        }
        this.browser.detach();
    }
    createScript(spec) {
        return new index_js_3.Script(this.engine, spec);
    }
    createScriptWithActions(actions) {
        return this.createScript({
            name: 'test',
            contexts: [{ type: 'main', actions }],
        });
    }
    createPipeline(pipes) {
        const script = this.createScript({});
        const context = script.getMainContext();
        const def = context.definitions.insert({
            type: 'definition',
            pipeline: pipes,
        }, 0);
        return def.pipeline;
    }
    async runPipes(pipes) {
        const pipeline = this.createPipeline(pipes);
        return this.runPipeline(pipeline);
    }
    async runPipeline(pipeline) {
        const inputSet = await pipeline.$action.resolveScope();
        return await pipeline.selectAll(inputSet, pipeline.$action.createCtx());
    }
    async runActions(actions) {
        const script = this.createScriptWithActions(actions);
        await script.runAll();
    }
    async assertError(code, asyncFn) {
        try {
            await asyncFn();
            throw new UnexpectedSuccessError();
        }
        catch (err) {
            assert_1.default.equal(err.code, code);
            return err;
        }
    }
}
exports.TestRig = TestRig;
class ExtensionTestRig extends TestRig {
    constructor(extensionDir) {
        super();
        this.extensionDir = extensionDir;
    }
    setupExtension() { }
    get container() {
        return this.extension.container;
    }
    async beforeAll() {
        await super.beforeAll();
    }
    async beforeEach() {
        this.engine = new engine_js_1.Engine();
        this.setupEngine();
        this.extension = await extension_js_1.Extension.load(this.extensionDir);
        this.engine.addExtension(this.extension);
        this.setupExtension();
        await this.engine.startSession();
        await this.browser.connect();
        await this.openNewTab();
    }
}
exports.ExtensionTestRig = ExtensionTestRig;
//# sourceMappingURL=rig.js.map