"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InputAction = void 0;
const index_js_1 = require("../model/index.js");
const util = __importStar(require("../util/index.js"));
class InputAction extends index_js_1.Action {
    constructor() {
        super(...arguments);
        this.optional = false;
        this.checkAndRetry = true;
        this.useClick = true;
        this.useClear = true;
        this.useFocus = true;
        this.useBlur = true;
        this.useEnter = false;
        this.maskInput = false;
        this.delay = 0;
    }
    async exec() {
        const ctx = this.createCtx();
        await this.retry(async () => {
            const el = await this.selectSingle(this.pipeline, this.optional, ctx);
            if (el) {
                await el.assertElement('Input only works on HTML elements');
                util.checkType(el.value, ['string', 'number']);
                await this.attemptInput(el, String(el.value));
                await ctx.takeDebugScreenshot('input');
            }
            else {
                this.$runtime.bypassed = true;
            }
        });
    }
    async attemptInput(el, value, attempt = 5) {
        if (attempt <= 0) {
            return;
        }
        await el.remote.getStablePoint();
        await el.tooltip('input');
        if (this.maskInput) {
            await el.evaluateJson(el => {
                el.style.webkitTextSecurity = 'disc';
            }, this);
        }
        await el.remote.typeText(value, {
            click: this.useClick,
            clear: this.useClear,
            focus: this.useFocus,
            blur: this.useBlur,
            enter: this.useEnter,
            delay: this.delay,
            parallel: this.delay === 0,
        });
        const { value: actualValue } = await el.getInfo(true);
        const valueMatches = !util.strEquals(actualValue, value, { onlyAlphaNumeric: true });
        if (this.checkAndRetry && valueMatches) {
            await new Promise(r => setTimeout(r, 500));
            await this.attemptInput(el, value, attempt - 1);
        }
    }
}
InputAction.$type = 'Page.input';
InputAction.$icon = 'fas fa-i-cursor';
InputAction.$help = `
Types text into DOM element.

The pipeline should resolve to a single element.
The value of the element must be a string — it will be sent to the DOM node as a series of keyboard events.

In order to handle keyboard events properly the element must receive focus.
There are multiple ways of setting the focus, the most reliable way which works in most cases is
to simply click on the element. For simplicity, this action includes a Use Click parameter
which does everything the Click does prior to sending the keyboard events.

However, there are edge cases when performing a click is undesirable (e.g. click opens a popup).
To address these cases there are few more parameters listed below which allow alternative focusing techniques.
Those are to be used at one's own discretion, as they are tightly coupled to website's internal implementation
details and are susceptible to even slightest changes.

The exact algorithm is as follows:

- the scope element is resolved from parent (#document by default)
- the pipeline is executed with scope element as its input set,
  expecting a single element in the output set and a string or number value
- the element is scrolled into view
- if Use Click is enabled, a subset of Click algorithm is performed on the element
- if Clear input is enabled, the entire text is selected and Backspace keystroke is sent to the webpage,
  causing the input to become clear
- a series of keystrokes is sent to the element as emulated keyboard events
- if Press Enter is enabled, an Enter keystroke is sent to the webpage
- if Use Blur is enabled, a synthetic \`blur\` event is triggered on the element via client-side JavaScript
- the screenshot is taken (if executed debug screenshots are enabled for the job)

### Parameters

- optional: if checked, the pipeline is allowed to return 0 elements in which case the action is bypassed,
  otherwise an error is thrown if pipeline returns 0 elements
- wait for stable box: after element is initially scrolled into view the action will wait for element's position
  to remain constant for a few frames; this is to prevent accidentally clicking at wrong location
  if the element is currently involved in an animation (e.g. smooth scrolling, carousels, etc.)
- check visibility: if unchecked, visibility check is bypassed (deprecated, incompatible with Use Click)
- use click: if checked, Click is used to focus the element
- use ticks: if checked, an small artificial delay is inserted between keystrokes; otherwise all keystrokes
  are sent simultaneously
- clear input: if checked, the text of the element is selected and cleared prior to typing text
- press Enter: if checked, an Enter keystroke is sent to the webpage after typing text
- use blur: if checked, a synthetic \`blur\` event is triggered on the element after typing
- mask input: if checked, the text of the element is masked so that the data is not shown in screenshot

### Use For

- typing text into text input fields
`;
__decorate([
    index_js_1.params.Pipeline(),
    __metadata("design:type", index_js_1.Pipeline)
], InputAction.prototype, "pipeline", void 0);
__decorate([
    index_js_1.params.Boolean(),
    __metadata("design:type", Boolean)
], InputAction.prototype, "optional", void 0);
__decorate([
    index_js_1.params.Boolean(),
    __metadata("design:type", Boolean)
], InputAction.prototype, "checkAndRetry", void 0);
__decorate([
    index_js_1.params.Boolean(),
    __metadata("design:type", Boolean)
], InputAction.prototype, "useClick", void 0);
__decorate([
    index_js_1.params.Boolean(),
    __metadata("design:type", Boolean)
], InputAction.prototype, "useClear", void 0);
__decorate([
    index_js_1.params.Boolean(),
    __metadata("design:type", Boolean)
], InputAction.prototype, "useFocus", void 0);
__decorate([
    index_js_1.params.Boolean(),
    __metadata("design:type", Boolean)
], InputAction.prototype, "useBlur", void 0);
__decorate([
    index_js_1.params.Boolean(),
    __metadata("design:type", Boolean)
], InputAction.prototype, "useEnter", void 0);
__decorate([
    index_js_1.params.Boolean(),
    __metadata("design:type", Boolean)
], InputAction.prototype, "maskInput", void 0);
__decorate([
    index_js_1.params.Number({
        min: 0,
        max: 600000
    }),
    __metadata("design:type", Number)
], InputAction.prototype, "delay", void 0);
exports.InputAction = InputAction;
//# sourceMappingURL=Page.input.js.map