"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModelerCreatePage = void 0;
const test_1 = require("@playwright/test");
const ConnectorMarketplacePage_1 = require("./ConnectorMarketplacePage");
const sleep_1 = require("../../utils/sleep");
class ModelerCreatePage {
    page;
    generalPanel;
    taskDefinitionPanel;
    processIdInput;
    elemendIdInput;
    startEventElement;
    appendTaskButton;
    changeTypeButton;
    userTaskOption;
    serviceTaskOption;
    appendEndEventButton;
    dialog;
    startInstanceMainButton;
    deployAndRunMainButton;
    deployAndRunSubButton;
    viewProcessInstanceLink;
    nameInput;
    jobTypeInput;
    diagramBreadcrumb;
    renameDiagramNameButton;
    diagramNameInput;
    variableInput;
    embedFormButton;
    embedButton;
    newForm;
    deploySubButton;
    cancelButton;
    restConnectorOption;
    marketPlaceButton;
    clientIdTextbox;
    clientSecretTextbox;
    rememberCredentialsCheckbox;
    webhookMessageStartEventConnectorOption;
    webhookIdInput;
    implementationSection;
    implementationOptions;
    assignmentSection;
    priorityInput;
    secondElement;
    firstElement;
    thirdElement;
    appendElementButton;
    firstPlacedGateway;
    secondPlacedGateway;
    secondPlacedElement;
    appendPreButton;
    appendGatewayButton;
    parallelGatewayOption;
    connectToOtherElementButton;
    canvas;
    intermediateBoundaryEvent;
    intermediateWebhookConnectorOption;
    correlationKeyProcessInput;
    correlationKeyPayloadInput;
    playTab;
    continueToPlayButton;
    candidateUsersInput;
    assigneeInput;
    candidateGroupsInput;
    tenantIdInput;
    timerEventOption;
    timerEventSettings;
    timerType;
    timerValue;
    eighthPlacedElement;
    processIdSecondLocator;
    deployMenuItem;
    additionalActionsButton;
    closeModalButton;
    deployErrorMessage;
    implementTab;
    bpmnReplaceMenu;
    connectorsDocHandlingStartEventElement;
    startEventVariableInputWithThreeVariables;
    zeebeRestAddressVariable;
    variableAssignmentValueTextbox;
    zeebeSecretVariable;
    variableAssignmentValueTextboxSecondVariable;
    zeebeClientIdVariable;
    variableAssignmentValueTextboxThirdVariable;
    firstPlaceRESTConnector;
    authenticationPanel;
    oauthTokenEndpointInput;
    closeDetailsPanel;
    openDetailsPanel;
    constructor(page) {
        this.page = page;
        this.generalPanel = page.locator('[data-group-id="group-general"]');
        this.taskDefinitionPanel = page
            .locator('div')
            .filter({ hasText: /^Task definition$/ })
            .first();
        this.processIdInput = page.getByLabel('ID', { exact: true });
        this.elemendIdInput = page.getByLabel('ID', { exact: true });
        this.startEventElement = page.locator('.djs-hit').first();
        this.appendPreButton = page.locator('.djs-create-pad-icon > svg').first();
        this.appendTaskButton = page.getByTitle('Append task');
        this.changeTypeButton = page.getByRole('button', {
            name: 'Change element',
            exact: true,
        });
        this.userTaskOption = page
            .getByRole('listitem', { name: 'User task' })
            .locator('span')
            .first();
        this.serviceTaskOption = page.getByRole('listitem', { name: 'Service Task' });
        this.appendEndEventButton = page.getByTitle('Append end event');
        this.appendGatewayButton = page.getByTitle('append gateway');
        this.parallelGatewayOption = page.getByText('parallel gateway');
        this.dialog = page.getByRole('dialog');
        this.startInstanceMainButton = page.getByRole('button', {
            name: 'Run',
            exact: true,
        });
        this.deployAndRunMainButton = page.getByRole('button', {
            name: 'Deploy & run',
            exact: true,
        });
        this.deployAndRunSubButton = this.dialog.getByRole('button', {
            name: 'Deploy & run',
            exact: true,
        });
        this.viewProcessInstanceLink = page.getByRole('link', {
            name: 'View process instance',
        });
        this.nameInput = page.getByLabel('Name', { exact: true });
        this.jobTypeInput = page.getByRole('textbox', { name: /job type/i });
        this.diagramBreadcrumb = page.locator('[data-test="breadcrumb-diagram"]');
        this.renameDiagramNameButton = page.getByText('Rename');
        this.diagramNameInput = page.locator('[data-test="editable-input"]');
        this.variableInput = page.locator('[id="variables-json"]');
        this.embedFormButton = page.getByRole('button', { name: 'Link form' });
        this.embedButton = page.locator('[data-test="confirm-move"]');
        this.newForm = page.locator('[data-test="item-New form"]');
        this.continueToPlayButton = page.getByRole('button', { name: 'Continue' });
        this.deploySubButton = page
            .getByRole('dialog')
            .getByRole('button', { name: 'Deploy' });
        this.cancelButton = page.getByRole('button', { name: 'Cancel' });
        this.restConnectorOption = page.getByRole('listitem', {
            name: 'REST Outbound Connector',
        });
        this.marketPlaceButton = page.getByTitle('Browse Marketplace for more Connectors');
        this.clientIdTextbox = page.getByLabel('Client ID');
        this.clientSecretTextbox = page.getByLabel('Client secret');
        this.rememberCredentialsCheckbox = page.getByText('Remember credentials');
        this.webhookMessageStartEventConnectorOption = page.getByRole('listitem', {
            name: 'Webhook Message Start Event Connector',
            exact: true,
        });
        this.webhookIdInput = page.getByLabel('Webhook ID');
        this.firstElement = page.locator('.djs-element.djs-shape').nth(0);
        this.secondElement = page.locator('.djs-element.djs-shape').nth(1);
        this.thirdElement = page.locator('.djs-element.djs-shape').nth(2);
        this.implementationSection = page.locator('[data-group-id="group-userTaskImplementation"]');
        this.implementationOptions = page.locator('#bio-properties-panel-userTaskImplementation');
        this.assignmentSection = page.locator('[data-group-id="group-assignmentDefinition"]');
        this.priorityInput = page.getByRole('textbox', { name: 'priority' });
        this.appendElementButton = page
            .locator('[class="djs-context-pad open"]')
            .first();
        this.firstPlacedGateway = page
            .locator('[data-element-id*="Gateway"]')
            .first();
        this.secondPlacedGateway = page
            .locator('[data-element-id*="Gateway"]')
            .last();
        this.secondPlacedElement = page.locator('.djs-element.djs-shape').last();
        this.connectToOtherElementButton = page
            .getByLabel('Connect to other element')
            .locator('path');
        this.canvas = page.locator('rect').nth(1);
        this.intermediateBoundaryEvent = page.getByTitle('Append intermediate/boundary');
        this.intermediateWebhookConnectorOption = page.getByRole('listitem', {
            name: 'Webhook Intermediate Event Connector',
        });
        this.correlationKeyPayloadInput = page.getByLabel('Correlation key (payload)');
        this.correlationKeyProcessInput = page.getByLabel('Correlation key (process)');
        this.playTab = page.getByRole('tab', {
            name: 'Play',
        });
        this.candidateUsersInput = page.getByRole('textbox', {
            name: 'candidate users',
        });
        this.assigneeInput = page.getByRole('textbox', { name: 'assignee' });
        this.candidateGroupsInput = page.getByRole('textbox', {
            name: 'candidate groups',
        });
        this.tenantIdInput = page.getByLabel('Tenant ID (Optional)');
        this.timerEventOption = page.getByRole('listitem', {
            name: 'Timer intermediate catch event',
            exact: true,
        });
        this.timerEventSettings = page.getByText(/^Timer$/).first();
        this.timerType = page.getByLabel('Type');
        this.timerValue = page.getByLabel('Value');
        this.eighthPlacedElement = page
            .locator('g:nth-child(8) > .djs-element > .djs-hit')
            .first();
        this.processIdSecondLocator = page.getByLabel('Process ID');
        this.additionalActionsButton = page.getByRole('button', {
            name: 'Additional actions',
        });
        this.deployMenuItem = page.getByRole('menuitem', {
            name: 'Deploy',
        });
        this.closeModalButton = page
            .getByRole('dialog')
            .getByRole('button', { name: 'Close' });
        this.deployErrorMessage = page.getByText('The diagram failed to deploy & run');
        this.implementTab = page.getByRole('tab', { name: 'Implement' });
        this.bpmnReplaceMenu = page.getByTestId('bpmn-replace');
        this.connectorsDocHandlingStartEventElement = page.locator('g:nth-child(5) > .djs-element > .djs-hit');
        this.startEventVariableInputWithThreeVariables =
            page.getByText('Output mapping3');
        this.zeebeRestAddressVariable = page
            .locator('[data-test="properties-panel"]')
            .getByText('zeebeRestAdress');
        this.variableAssignmentValueTextbox = page.getByRole('textbox', {
            name: 'Variable assignment value',
        });
        this.zeebeSecretVariable = page
            .locator('[data-test="properties-panel"]')
            .getByText('zeebeSecret');
        this.variableAssignmentValueTextboxSecondVariable = page.locator('#bio-properties-panel-StartEvent_1-output-1-source div');
        this.zeebeClientIdVariable = page
            .locator('[data-test="properties-panel"]')
            .getByText('zeebeClientId');
        this.variableAssignmentValueTextboxThirdVariable = page.locator('#bio-properties-panel-StartEvent_1-output-2-source div');
        this.firstPlaceRESTConnector = page.locator('g:nth-child(2) > .djs-element > .djs-hit');
        this.authenticationPanel = page
            .locator('div')
            .filter({ hasText: /^Authentication$/ })
            .first();
        this.oauthTokenEndpointInput = page.getByLabel('OAuth 2.0 token endpoint');
        this.closeDetailsPanel = page.getByTitle('Close Details Panel');
        this.openDetailsPanel = page.getByTitle('Open Details Panel');
    }
    async deployProcessInstance(tenant = '') {
        await this.clickDeployButton();
        if (tenant.length > 0) {
            await this.clickTenantIdInput();
            await this.fillTenantIdInput(tenant);
        }
        await this.clickDeploySubButton();
        await (0, test_1.expect)(this.page.getByText('Process successfully deployed')).toBeVisible({
            timeout: 30000,
        });
        await this.clickCloseModalButton();
    }
    async clickCloseModalButton() {
        await this.closeModalButton.click({ timeout: 60000 });
    }
    // Function to model a simple Camunda User Task Diagram with or without a form
    async modelCamundaUserTaskDiagram(processName, processId = '', formName = '') {
        await (0, test_1.expect)(this.generalPanel).toBeVisible({
            timeout: 180000,
        });
        await this.enterDiagramName(processName);
        await (0, sleep_1.sleep)(1000);
        await this.clickCanvas();
        await this.clickGeneralPropertiesPanel();
        await this.assertNameInput(processName);
        await this.clickStartEventElement();
        if (processId.length > 0) {
            await this.clickStartEventElement();
            await this.clickGeneralPropertiesPanel();
            await this.clickIdInput();
            await this.fillIdInput(processId);
            await (0, sleep_1.sleep)(1000);
            await this.clickStartEventElement();
            try {
                await (0, test_1.expect)(this.appendElementButton).toBeVisible({ timeout: 1000 });
            }
            catch {
                await this.clickStartEventElement();
            }
        }
        await this.clickAppendElementButton();
        await this.clickAppendTaskButton();
        await this.clickChangeTypeButton();
        await this.clickUserTaskOption();
        await this.assertImplementationOption('zeebeUserTask');
        if (formName.length > 0) {
            await this.clickEmbedFormButton();
            await this.clickForm(formName);
            await this.clickEmbedButton();
        }
        await this.clickAppendElementButton();
        await this.clickAppendEndEventButton();
        await this.clickCanvas();
        await this.assertThreeElementsVisible();
    }
    async modelJobWorkerDiagram(processName) {
        await (0, test_1.expect)(this.generalPanel).toBeVisible({
            timeout: 120000,
        });
        await this.enterDiagramName(processName);
        await (0, sleep_1.sleep)(1000);
        await this.clickStartEventElement();
        await this.clickGeneralPropertiesPanel();
        await this.clickIdInput();
        await this.fillIdInput(processName);
        await this.assertNameInput(processName);
        await this.clickStartEventElement();
        await this.clickAppendElementButton();
        await this.clickAppendTaskButton();
        await this.clickChangeTypeButton();
        await this.clickUserTaskOption();
        await this.chooseImplementationOption('jobWorker');
        await this.clickAppendElementButton();
        await this.clickAppendEndEventButton();
        await this.clickCanvas();
        await this.assertThreeElementsVisible();
    }
    async assertThreeElementsVisible() {
        await (0, test_1.expect)(this.firstElement).toBeVisible({ timeout: 30000 });
        await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 30000 });
        await (0, test_1.expect)(this.thirdElement).toBeVisible({ timeout: 30000 });
    }
    async clickForm(name) {
        await this.page
            .locator(`[data-test="item-${name}"]`)
            .getByText(name)
            .click({ timeout: 90000 });
    }
    async runProcessInstance(variables = '', tenant = '') {
        await this.page.waitForTimeout(2000); // the canvas autosaves. This can take a second to save.
        const maxRetries = 3;
        for (let attempt = 0; attempt < maxRetries; attempt++) {
            try {
                await this.clickDeployAndRunMainButton();
                await (0, test_1.expect)(this.dialog).toBeVisible({
                    timeout: 30000,
                });
                if (variables.length > 0) {
                    await (0, test_1.expect)(this.variableInput).toBeVisible({
                        timeout: 60000,
                    });
                    await this.clickVariableInput();
                    await this.fillVariableInput(variables);
                }
                if (tenant.length > 0) {
                    await this.clickTenantIdInput();
                    await this.fillTenantIdInput(tenant);
                }
                await this.clickDeployAndRunSubButton();
                await (0, test_1.expect)(this.dialog).not.toBeVisible();
                await this.instanceStartedAssertion();
                return;
            }
            catch (error) {
                if (attempt < maxRetries - 1) {
                    console.warn(`Attempt ${attempt + 1} failed for deploy & run running process. Retrying...`);
                    await this.page.reload();
                    await (0, sleep_1.sleep)(10000);
                }
                else {
                    throw new Error(`Assertion failed after ${maxRetries} attempts`);
                }
            }
        }
    }
    async switchToPlay() {
        await (0, test_1.expect)(this.playTab).toBeVisible();
        await this.playTab.click();
    }
    async clickGeneralPropertiesPanel() {
        const isExpanded = (await this.generalPanel
            .locator('.bio-properties-panel-group-header open')
            .count()) > 0;
        if (!isExpanded) {
            await this.generalPanel.click({ timeout: 60000 });
        }
    }
    async clickIdInput() {
        try {
            await this.processIdInput.click();
        }
        catch {
            await this.processIdSecondLocator.click();
        }
    }
    async clickTaskDefinitionPropertiesPanel() {
        await this.taskDefinitionPanel.click();
    }
    async clickProcessIdInput() {
        await this.processIdInput.click();
    }
    async fillIdInput(id) {
        try {
            await this.processIdInput.fill(id);
            await (0, test_1.expect)(this.processIdInput).toHaveValue(id);
        }
        catch {
            await this.processIdSecondLocator.fill(id);
            await (0, test_1.expect)(this.processIdSecondLocator).toHaveValue(id);
        }
    }
    async clickElemendIdInput() {
        await this.elemendIdInput.click();
    }
    async fillElementIdInput(id) {
        await this.elemendIdInput.fill(id);
    }
    async clickStartEventElement() {
        await this.startEventElement.click();
    }
    async selectStartEventElement() {
        await this.startEventElement.click();
    }
    async clickAppendTaskButton() {
        await this.hoverOnLocator(this.appendPreButton);
        await this.appendTaskButton.click({ timeout: 90000 });
    }
    async hoverOnLocator(locator, selector = '.djs-create-pad-entry') {
        if (await this.page.locator(selector).first().isVisible()) {
            return;
        }
        await locator.waitFor({ state: 'visible' });
        await locator.hover({ timeout: 5000 });
        await this.page.waitForSelector(selector, { state: 'visible' });
    }
    async clickAppendGatewayButton() {
        await this.appendGatewayButton.click({ timeout: 90000 });
    }
    async clickChangeTypeButton() {
        try {
            await this.changeTypeButton.click({ timeout: 180000, force: true });
        }
        catch {
            await this.page.reload();
            if (await this.secondElement.isVisible({ timeout: 6000 })) {
                await this.secondElement.click({ timeout: 90000, force: true });
                await this.changeTypeButton.click({ timeout: 90000, force: true });
            }
            else {
                await this.firstElement.click({ timeout: 90000, force: true });
                await this.changeTypeButton.click({ timeout: 90000, force: true });
            }
        }
    }
    async clickUserTaskOption() {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    await this.userTaskOption.click({ timeout: 30000, force: true });
                }
                else {
                    await this.changeTypeButton.click({ force: true, timeout: 30000 });
                    await this.userTaskOption.click({ timeout: 30000, force: true });
                }
                return;
            }
            catch (error) {
                console.error(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to click the button after ${maxRetries} attempts.`);
    }
    async clickServiceTaskOption() {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    await this.serviceTaskOption.click({ timeout: 30000, force: true });
                }
                else {
                    await this.changeTypeButton.click({ force: true, timeout: 30000 });
                    await this.serviceTaskOption.click({ timeout: 30000, force: true });
                }
                return;
            }
            catch (error) {
                console.error(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to click the button after ${maxRetries} attempts.`);
    }
    async clickAppendEndEventButton(parentElement) {
        try {
            await this.appendEndEventButton.click();
        }
        catch (error) {
            await this.page.reload();
            const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
            await sleep(10000);
            if (parentElement == undefined) {
                await this.clickSecondPlacedElement();
            }
            else if (parentElement == 'parallelGateway') {
                await this.clickSecondPlacedGateway();
            }
            await this.hoverOnLocator(this.appendElementButton);
            await this.appendEndEventButton.click({ timeout: 30000 });
        }
    }
    async clickFirstPlacedElement() {
        await this.firstElement.click({ timeout: 90000 });
    }
    async clickSecondPlacedElement() {
        await this.secondPlacedElement.click({ timeout: 60000 });
    }
    async clickFirstPlacedGateway() {
        try {
            await this.firstPlacedGateway.click({ timeout: 3000 });
            await this.appendElementButton.isVisible({ timeout: 3000 });
        }
        catch (error) {
            await this.page.reload();
            await this.firstPlacedGateway.click({ timeout: 3000 });
        }
    }
    async clickSecondPlacedGateway() {
        try {
            await (0, test_1.expect)(this.secondPlacedGateway).toBeVisible({ timeout: 30000 });
            await this.secondPlacedGateway.click({ timeout: 3000 });
            await this.appendElementButton.isVisible({ timeout: 3000 });
        }
        catch (error) {
            await this.page.reload();
            await (0, test_1.expect)(this.secondPlacedGateway).toBeVisible({ timeout: 30000 });
            await this.secondPlacedGateway.click({ timeout: 3000 });
        }
    }
    async clickDeployAndRunMainButton() {
        await this.deployAndRunMainButton.click({ timeout: 30000 });
    }
    async clickDeployAndRunSubButton() {
        await this.deployAndRunSubButton.click({ timeout: 30000 });
    }
    async clickViewProcessInstanceLink() {
        await this.viewProcessInstanceLink.click({ timeout: 90000 });
    }
    async clickNameInput() {
        await this.nameInput.click();
    }
    async clickUserTask(id) {
        const priorityUserTask = this.page.locator(`[data-element-id="${id}"]`);
        await priorityUserTask.click({ timeout: 60000 });
    }
    async fillNameInput(name) {
        await this.nameInput.fill(name);
        await (0, test_1.expect)(this.nameInput).toHaveValue(name);
    }
    async clickJobTypeInput() {
        await this.jobTypeInput.click();
    }
    async fillJobTypeInput(name) {
        await this.jobTypeInput.fill(name);
    }
    async clickDiagramBreadcrumb() {
        await this.diagramBreadcrumb.click({ timeout: 60000 });
    }
    async clickEditDiagramNameButton() {
        await this.renameDiagramNameButton.click();
    }
    async enterDiagramName(name) {
        await this.diagramNameInput.fill(name, { timeout: 60000 });
        await this.diagramNameInput.press('Enter', { timeout: 60000 });
        await (0, sleep_1.sleep)(1000);
    }
    async clickVariableInput() {
        await this.variableInput.click();
    }
    async fillVariableInput(variable) {
        await this.variableInput.fill(variable);
    }
    async clickEmbedFormButton() {
        await this.embedFormButton.click({ timeout: 90000 });
    }
    async clickEmbedButton() {
        await this.embedButton.click();
    }
    async clickAdditionalActionsButton() {
        await (0, test_1.expect)(this.additionalActionsButton).toBeVisible({ timeout: 20000 });
        await this.additionalActionsButton.click({ timeout: 60000 });
    }
    async clickDeployMenuItem() {
        await (0, test_1.expect)(this.deployMenuItem).toBeVisible({ timeout: 20000 });
        await this.deployMenuItem.click({ timeout: 60000 });
    }
    async clickDeployButton() {
        await this.clickAdditionalActionsButton();
        await this.clickDeployMenuItem();
    }
    async clickDeploySubButton() {
        await this.deploySubButton.click({ timeout: 90000 });
    }
    async clickCancelButton() {
        await this.cancelButton.click();
    }
    async searchAndClickRestConnector() {
        await (0, test_1.expect)(this.restConnectorOption).toBeVisible({ timeout: 90000 });
        await this.restConnectorOption.click({ timeout: 90000 });
    }
    async clickRestConnectorOption() {
        const maxRetries = 4;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    // Panel already open from the caller (modelRestConnector in UtilitiesPage)
                    await this.searchAndClickRestConnector();
                }
                else if (retries === 1 || retries === 2) {
                    await this.secondElement.click({ timeout: 60000 });
                    await this.changeTypeButton.click({ force: true, timeout: 60000 });
                    await this.searchAndClickRestConnector();
                }
                else {
                    // Fourth attempt: install via marketplace in case connector is missing
                    await this.secondElement.click({ timeout: 60000 });
                    await this.changeTypeButton.click({ force: true, timeout: 60000 });
                    await this.clickMarketPlaceButton();
                    const marketplace = new ConnectorMarketplacePage_1.ConnectorMarketplacePage(this.page);
                    await marketplace.clickSearchForConnectorTextbox();
                    await (0, sleep_1.sleep)(5000);
                    await marketplace.fillSearchForConnectorTextbox('REST Connector');
                    await marketplace.downloadConnectorToProject();
                    // Marketplace closes the change-type panel; reopen it so the
                    // newly installed connector appears in the list.
                    await this.changeTypeButton.click({ force: true, timeout: 60000 });
                    await this.searchAndClickRestConnector();
                }
                return;
            }
            catch (error) {
                console.error(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to click the button after ${maxRetries} attempts.`);
    }
    async clickMarketPlaceButton() {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    await this.marketPlaceButton.click({ timeout: 30000 });
                }
                else {
                    await this.changeTypeButton.click({ force: true, timeout: 30000 });
                    await this.marketPlaceButton.click({ timeout: 30000 });
                }
                return;
            }
            catch (error) {
                console.error(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to click the button after ${maxRetries} attempts.`);
    }
    async completeDeploymentEndpointConfiguration() {
        await (0, test_1.expect)(this.clientIdTextbox).toBeVisible({ timeout: 60000 });
        await this.clientIdTextbox.click({ timeout: 30000 });
        await this.clientIdTextbox.fill('test', { timeout: 30000 });
        await this.clientSecretTextbox.click({ timeout: 30000 });
        await this.clientSecretTextbox.fill(process.env.DISTRO_QA_E2E_TESTS_KEYCLOAK_CLIENTS_SECRET);
        await this.rememberCredentialsCheckbox.click({ timeout: 30000 });
    }
    async completePlayConfiguration() {
        const timeout = 30000;
        let attempts = 0;
        const maxRetries = 2;
        while (attempts < maxRetries) {
            try {
                if (attempts > 0)
                    await this.switchToPlay(); // Call switchToPlay on subsequent attempts
                await this.continueToPlayButton.click({ timeout });
                await (0, test_1.expect)(this.page.getByText('Play environment is ready')).toBeVisible({ timeout: 90000 });
                return; // Exit if successful
            }
            catch (error) {
                if (attempts >= maxRetries - 1)
                    throw error;
                await this.page.reload();
                attempts++;
            }
        }
    }
    async clickWebhookMessageStartEventConnectorOption() {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    await this.webhookMessageStartEventConnectorOption.click({
                        timeout: 30000,
                    });
                }
                else {
                    await this.page.reload();
                    await this.changeTypeButton.click({ force: true, timeout: 30000 });
                    await this.webhookMessageStartEventConnectorOption.click({
                        timeout: 90000,
                    });
                }
                return;
            }
            catch (error) {
                console.error(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to click the button after ${maxRetries} attempts.`);
    }
    async clickWebhookIdInput() {
        await this.webhookIdInput.click();
    }
    async clearWebhookIdInput() {
        await this.webhookIdInput.clear();
    }
    async fillWebhookIdInput(webhookId) {
        await this.webhookIdInput.fill(webhookId);
    }
    async hoverOnStartEvent() {
        await this.hoverOnLocator(this.startEventElement, '.djs-context-pad');
    }
    async instanceStartedAssertion() {
        await (0, test_1.expect)(this.page.getByText('Instance started!')).toBeVisible({
            timeout: 30000,
        });
    }
    async assertImplementationOption(implementationType) {
        await this.expandImplementationOptionIfNecessary();
        (0, test_1.expect)(await this.implementationOptions.inputValue()).toEqual(implementationType);
    }
    async chooseImplementationOption(implementationType) {
        // Wait for implementation section to be attached and stable after task type change
        await this.implementationSection.waitFor({
            state: 'attached',
            timeout: 10000,
        });
        await this.implementationSection.click({ timeout: 30000 });
        if ((await this.implementationOptions.inputValue()) == implementationType) {
            console.log(`${implementationType} is already selected.`);
        }
        else {
            await this.implementationOptions.selectOption(implementationType);
        }
        await this.assertImplementationOption(implementationType);
    }
    async expandImplementationOptionIfNecessary() {
        const isExpanded = (await this.implementationSection
            .locator('.bio-properties-panel-group-header empty open')
            .count()) > 0;
        if (!isExpanded) {
            await this.implementationSection.click();
        }
    }
    async expandAssignmentSection() {
        const isExpanded = (await this.assignmentSection
            .locator('[data-group-id="group-assignmentDefinition"] .bio-properties-panel-group-header.open')
            .count()) > 0;
        if (!isExpanded) {
            await this.assignmentSection.click({ timeout: 60000 });
        }
    }
    async clickAppendElementButton() {
        for (let attempt = 1; attempt <= 3; attempt++) {
            try {
                await this.hoverOnLocator(this.appendPreButton);
                return; // Exit loop if successful
            }
            catch (error) {
                if (attempt === 3)
                    throw error; // Rethrow after 3 failed attempts
            }
        }
    }
    async clickParallelGatewayOption() {
        await this.parallelGatewayOption.click({ timeout: 90000 });
    }
    async clickConnectToOtherElementButton() {
        await this.connectToOtherElementButton.click({ timeout: 60000 });
    }
    async clickPriorityInput() {
        try {
            await this.priorityInput.click();
        }
        catch (error) {
            await this.assignmentSection.click({ timeout: 60000 });
            await this.priorityInput.click({ timeout: 60000 });
        }
    }
    async fillPriorityInput(priority) {
        await this.priorityInput.fill(priority, { timeout: 60000 });
        await (0, sleep_1.sleep)(1000);
    }
    async clickCanvas() {
        await this.canvas.click({ timeout: 60000 });
    }
    async addParallelUserTasks(numberOfTasks, taskName) {
        try {
            await this.clickAppendElementButton();
        }
        catch (error) {
            await this.page.reload();
            const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
            await sleep(10000);
            await this.clickFirstPlacedElement();
            await this.hoverOnLocator(this.appendElementButton);
        }
        await this.clickAppendGatewayButton();
        await this.clickChangeTypeButton();
        await this.clickParallelGatewayOption();
        await this.clickAppendElementButton();
        await this.clickAppendTaskButton();
        await this.clickChangeTypeButton();
        await this.clickUserTaskOption();
        await this.clickGeneralPropertiesPanel();
        await this.clickNameInput();
        await this.fillNameInput(taskName + '1');
        await this.clickIdInput();
        await this.fillIdInput(taskName + '1');
        await this.assertImplementationOption('zeebeUserTask');
        await this.clickAppendElementButton();
        await this.clickAppendGatewayButton();
        await this.clickChangeTypeButton();
        await this.clickParallelGatewayOption();
        for (let i = 2; i <= numberOfTasks; i++) {
            await this.clickFirstPlacedGateway();
            await this.clickAppendElementButton();
            await this.clickAppendTaskButton();
            await this.clickChangeTypeButton();
            await this.clickUserTaskOption();
            await this.clickNameInput();
            await this.fillNameInput(taskName + i);
            await this.clickIdInput();
            await this.fillIdInput(taskName + i);
            await this.assertImplementationOption('zeebeUserTask');
            await this.clickConnectToOtherElementButton();
            await this.clickSecondPlacedGateway();
            await this.clickCanvas();
        }
        await this.clickSecondPlacedGateway();
    }
    async setPriority(taskName, priority, numberOfTasks) {
        for (let i = 1; i <= numberOfTasks; i++) {
            const userTaskId = taskName + i;
            const priorityUserTask = this.page.locator(`g[data-element-id="${userTaskId}"]`);
            await priorityUserTask.click();
            await this.expandAssignmentSection();
            await this.clickPriorityInput();
            await this.fillPriorityInput(priority.toString());
            await (0, sleep_1.sleep)(5000);
            await this.clickCanvas();
            priority += 25;
        }
    }
    async clickIntermediateBoundaryEvent() {
        await this.intermediateBoundaryEvent.click({ timeout: 60000 });
    }
    async clickIntermediateWebhookConnectorOption() {
        const max = 3;
        for (let i = 0; i < max; i++) {
            try {
                await (0, test_1.expect)(this.intermediateWebhookConnectorOption).toBeVisible({
                    timeout: 30000,
                });
                await this.intermediateWebhookConnectorOption.click({ timeout: 30000 });
                return;
            }
            catch (err) {
                console.error(`clickIntermediateWebhookConnectorOption attempt ${i + 1} failed: ${err}`);
                if (i === max - 1)
                    throw err;
                await this.page.reload();
                await this.page.waitForLoadState('networkidle');
                // Wait for modeler canvas to render after reload before re-selecting
                await (0, test_1.expect)(this.secondElement).toBeVisible({ timeout: 60000 });
                await this.secondElement.click({ force: true, timeout: 30000 });
                await this.changeTypeButton.click({ force: true, timeout: 30000 });
            }
        }
    }
    async clickCorrelationKeyProcessInput() {
        await this.correlationKeyProcessInput.click({ timeout: 60000 });
    }
    async fillCorrelationKeyProcessInput(correlationKeyProcess) {
        await this.correlationKeyProcessInput.fill(correlationKeyProcess);
        await (0, test_1.expect)(this.page.getByText('Correlation key (process) must not be empty.')).not.toBeVisible({ timeout: 30000 });
    }
    async clickCorrelationKeyPayloadInput() {
        await this.correlationKeyPayloadInput.click({ timeout: 60000 });
    }
    async fillCorrelationKeyPayloadInput(correlationKeyPayload) {
        await this.correlationKeyPayloadInput.fill(correlationKeyPayload);
        await (0, test_1.expect)(this.page.getByText('Correlation key (payload) must not be empty.')).not.toBeVisible({ timeout: 30000 });
    }
    async selectUserTask(userTask) {
        await this.page.locator(`[data-element-id="${userTask}"]`).click();
    }
    async clickCandidateUsersInput() {
        await this.candidateUsersInput.click({ timeout: 60000 });
    }
    async fillCandidateUsersInput(candidateUser) {
        await this.candidateUsersInput.fill(candidateUser, { timeout: 60000 });
        await this.page.waitForTimeout(1000);
    }
    async clickCandidateGroupsInput() {
        await this.candidateGroupsInput.click({ timeout: 60000 });
    }
    async fillCandidateGroupsInput(candidateGroup) {
        await this.candidateGroupsInput.fill(candidateGroup, { timeout: 60000 });
        await (0, sleep_1.sleep)(1000);
    }
    async clickAssigneeInput() {
        await this.assigneeInput.click({ timeout: 60000 });
        await (0, sleep_1.sleep)(1000);
    }
    async fillAssigneeInput(name) {
        await this.assigneeInput.fill(name, { timeout: 60000 });
        await this.page.waitForTimeout(1000);
    }
    async clickTenantIdInput() {
        await (0, test_1.expect)(this.tenantIdInput).toBeVisible({ timeout: 60000 });
        await this.tenantIdInput.click({ timeout: 60000 });
    }
    async fillTenantIdInput(tenant) {
        await this.tenantIdInput.fill(tenant, { timeout: 60000 });
        await (0, sleep_1.sleep)(1000);
    }
    async clickTimerEventOption() {
        await this.timerEventOption.click();
    }
    async clickTimerEventSettings() {
        await this.timerEventSettings.click();
    }
    async selectTimerType(type) {
        await this.timerType.selectOption(type);
        await (0, test_1.expect)(this.page.getByText('Type must be defined.')).not.toBeVisible({
            timeout: 30000,
        });
    }
    async clickTimerValue() {
        await this.timerValue.click();
    }
    async fillTimerValue(value) {
        await this.timerValue.fill(value);
        await (0, test_1.expect)(this.page.getByText('Value must be defined.')).not.toBeVisible({ timeout: 30000 });
        await (0, sleep_1.sleep)(10000);
    }
    async clickEighthPlacedElement() {
        await this.eighthPlacedElement.click();
    }
    async assertNameInput(processName) {
        try {
            await (0, test_1.expect)(this.nameInput).toHaveValue(processName, { timeout: 2000 });
        }
        catch {
            await this.nameInput.click();
            await this.nameInput.fill(processName);
            // Press Enter to commit the name into the BPMN model before focus moves
            // away. Without this the value may not persist when the canvas element
            // is clicked next (properties panel re-renders discarding uncommitted edits).
            await this.nameInput.press('Enter');
        }
    }
    async switchToImplementTab() {
        await this.implementTab.click({ timeout: 30000 });
    }
    async clickStartEvent() {
        await this.startEventElement.click({ timeout: 30000 });
    }
    async clickContinueToPlay() {
        await this.continueToPlayButton.click({ timeout: 30000 });
    }
    async assertScenarioNameVisible(scenarioName) {
        await (0, test_1.expect)(this.page.getByTestId('instance-header').getByText(scenarioName)).toBeVisible();
    }
    async fillStartEventVariablesForDocHandling(zeebeUrl, zeebeClientId, zeebeClientSecret) {
        console.log(`URL: ${zeebeUrl}, ClientId: ${zeebeClientId}, Secret: ${zeebeClientSecret}`);
        (0, test_1.expect)(this.connectorsDocHandlingStartEventElement).toBeVisible({
            timeout: 60000,
        });
        await this.connectorsDocHandlingStartEventElement.click();
        (0, test_1.expect)(this.startEventVariableInputWithThreeVariables).toBeVisible({
            timeout: 60000,
        });
        await this.startEventVariableInputWithThreeVariables.click();
        await this.fillZeebeRestValue(zeebeUrl);
        await this.fillZeebeSecretValue(zeebeClientSecret);
        await this.fillZeebeClientId(zeebeClientId);
        await (0, sleep_1.sleep)(1000);
    }
    async fillZeebeClientId(clientId) {
        await this.zeebeClientIdVariable.click();
        await (0, test_1.expect)(this.variableAssignmentValueTextboxThirdVariable).toBeVisible({
            timeout: 60000,
        });
        await this.variableAssignmentValueTextboxThirdVariable.click();
        await (0, sleep_1.sleep)(1000);
        await this.variableAssignmentValueTextboxThirdVariable.fill('');
        await this.variableAssignmentValueTextboxThirdVariable.fill(clientId);
        await (0, test_1.expect)(this.variableAssignmentValueTextboxThirdVariable).toHaveText(clientId);
    }
    async fillZeebeSecretValue(zeebeSecret) {
        await this.zeebeSecretVariable.click();
        await (0, test_1.expect)(this.variableAssignmentValueTextboxSecondVariable).toBeVisible({
            timeout: 60000,
        });
        await this.variableAssignmentValueTextboxSecondVariable.click();
        await (0, sleep_1.sleep)(1000);
        await this.variableAssignmentValueTextboxSecondVariable.fill('');
        await this.variableAssignmentValueTextboxSecondVariable.fill(zeebeSecret);
        await (0, test_1.expect)(this.variableAssignmentValueTextboxSecondVariable).toHaveText(zeebeSecret);
    }
    async fillZeebeRestValue(zeebeUrl) {
        await this.zeebeRestAddressVariable.click();
        await (0, test_1.expect)(this.variableAssignmentValueTextbox).toBeVisible({
            timeout: 60000,
        });
        await this.variableAssignmentValueTextbox.click();
        await (0, sleep_1.sleep)(1000);
        await this.variableAssignmentValueTextbox.fill('');
        await this.variableAssignmentValueTextbox.fill(zeebeUrl);
        await (0, test_1.expect)(this.variableAssignmentValueTextbox).toHaveText(zeebeUrl);
    }
    async embedForm(formName) {
        await this.clickEmbedFormButton();
        await this.clickForm(formName);
        await this.clickEmbedButton();
    }
    async clickFirstPlaceRESTConnector() {
        await this.firstPlaceRESTConnector.click({ timeout: 60000 });
    }
    async setOAuthTokenEndpoint(elementToClick, endpoint, options) {
        const retries = options?.retries ?? 2;
        const settleMs = options?.settleMs ?? 250;
        const openPanel = options?.openPanel ?? false;
        await elementToClick.click({ timeout: 60000 });
        if (openPanel) {
            await this.clickOpenDetailsPanel();
        }
        await this.authenticationPanel.click({ timeout: 60000 });
        let lastError;
        for (let attempt = 1; attempt <= retries; attempt++) {
            try {
                await (0, test_1.expect)(this.oauthTokenEndpointInput).toBeVisible({ timeout: 3000 });
                await this.oauthTokenEndpointInput.click({ timeout: 3000 });
                await this.oauthTokenEndpointInput.fill(endpoint, { timeout: 30000 });
                return;
            }
            catch (err) {
                lastError = err;
                await this.authenticationPanel.click({ timeout: 60000 });
                await (0, sleep_1.sleep)(settleMs);
            }
        }
        throw new Error(`Failed to set OAuth 2.0 token endpoint after ${retries} attempt(s). Last error: ${String(lastError)}`);
    }
    async clickCloseDetailsPanel() {
        await this.closeDetailsPanel.click({ timeout: 30000 });
    }
    async clickOpenDetailsPanel() {
        await this.openDetailsPanel.click({ timeout: 30000 });
    }
}
exports.ModelerCreatePage = ModelerCreatePage;
