chromium/third_party/blink/web_tests/fast/forms/resources/common.js

function $(id) {
    return document.getElementById(id);
}

function createFormControlDataSet() {
    // A list of labelable elements resides in http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#category-label
    var formControlClassNames = [
        'HTMLButtonElement',
        'HTMLDataListElement',
        'HTMLFieldSetElement',
        'HTMLInputElement',
        'HTMLLabelElement',
        'HTMLLegendElement',
        'HTMLMeterElement',
        'HTMLObjectElement',
        'HTMLOptGroupElement',
        'HTMLOptionElement',
        'HTMLOutputElement',
        'HTMLProgressElement',
        'HTMLSelectElement',
        'HTMLTextAreaElement'
    ];
    var formControlDataSet = {};
    for (var i = 0; i < formControlClassNames.length; i++) {
        var className = formControlClassNames[i];
        var tagName = className.toLowerCase().substring(4, className.length - 7);
        var element = document.createElement(tagName);
        formControlDataSet[tagName] = {
            inputType: null,
            isLabelable: true,
            isSupported: element.toString() == '[object ' + className + ']',
            name: tagName,
            tagName: tagName,
        };
    }
    formControlDataSet.datalist.isLabelable = false;
    formControlDataSet.fieldset.isLabelable = false;
    formControlDataSet.label.isLabelable = false;
    formControlDataSet.legend.isLabelable = false;
    formControlDataSet.object.isLabelable = false;
    formControlDataSet.optgroup.isLabelable = false;
    formControlDataSet.option.isLabelable = false;

    // Input type names reside in http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html
    var inputTypeNames = [
        'button',
        'checkbox',
        'color',
        'date',
        'datetime',
        'datetime-local',
        'email',
        'file',
        'hidden',
        'image',
        'month',
        'number',
        'password',
        'radio',
        'range',
        'reset',
        'search',
        'submit',
        'tel',
        'text',
        'time',
        'url',
        'week',
    ];
    for (var i = 0; i < inputTypeNames.length; i++) {
        var typeName = inputTypeNames[i];
        var name = typeName + 'Type';
        var element = document.createElement('input');
        element.type = typeName;
        formControlDataSet[name] = {
            inputType: typeName,
            isLabelable: true,
            isSupported: element.type == typeName,
            name: name,
            tagName: 'input',
      };
    }
    formControlDataSet.hiddenType.isLabelable = false;

    return formControlDataSet;
}

function getAbsoluteRect(element) {
    var rect = element.getBoundingClientRect();
    rect.top += document.scrollingElement.scrollTop;
    rect.bottom += document.scrollingElement.scrollTop;
    rect.left += document.scrollingElement.scrollLeft;
    rect.right += document.scrollingElement.scrollLeft;
    return rect;
}

function searchCancelButtonPosition(element) {
    var offset = cumulativeOffset(element);
    var pos = {};
    pos.x = offset[0] + element.offsetWidth - 9;
    pos.y = offset[1] + element.offsetHeight / 2;
    return pos;
}

function rtlSearchCancelButtonPosition(element) {
    var offset = cumulativeOffset(element);
    var pos = {};
    pos.x = offset[0] + 9;
    pos.y = offset[1] + element.offsetHeight / 2;
    return pos;
}

function mouseMoveToIndexInListbox(index, listboxId) {
    var listbox = document.getElementById(listboxId);
    var itemHeight = Math.floor(listbox.offsetHeight / listbox.size);
    var border = 1;
    var y = border + index * itemHeight;
    if (window.eventSender)
        eventSender.mouseMoveTo(listbox.offsetLeft + border, listbox.offsetTop + y - window.pageYOffset);
}

function getUserAgentShadowTextContent(element) {
    return internals.shadowRoot(element).textContent;
};

function cumulativeOffset(element) {
    var x = 0;
    var y = 0;
    var parentFrame = element.ownerDocument.defaultView.frameElement;
    if (parentFrame) {
        var parentFrameOffset = cumulativeOffset(parentFrame);
        x = parentFrameOffset[0];
        y = parentFrameOffset[1];
    }
    if (element.parentNode) {
        do {
            x += element.offsetLeft || 0;
            y += element.offsetTop  || 0;
            element = element.offsetParent;
        } while (element);
    }
    return [x, y];
}

function elementCenterPosition(element) {
    var offset = cumulativeOffset(element);
    var centerX = offset[0] + element.offsetWidth / 2;
    var centerY = offset[1] + element.offsetHeight / 2;
    return [centerX, centerY];
}

function hoverOverElement(element) {
    var center = elementCenterPosition(element);
    eventSender.mouseMoveTo(center[0], center[1]);
}

function clickElement(element) {
    hoverOverElement(element);
    eventSender.mouseDown();
    eventSender.mouseUp();
}

function pressElement(element) {
    hoverOverElement(element);
    eventSender.mouseDown();
}

function traverseNextNode(node, stayWithin) {
    var nextNode = node.firstChild;
    if (nextNode)
        return nextNode;

    if (stayWithin && node === stayWithin)
        return null;

    nextNode = node.nextSibling;
    if (nextNode)
        return nextNode;

    nextNode = node;
    while (nextNode && !nextNode.nextSibling && (!stayWithin || !nextNode.parentNode || nextNode.parentNode !== stayWithin))
        nextNode = nextNode.parentNode;
    if (!nextNode)
        return null;

    return nextNode.nextSibling;
}

function getElementByPseudoId(root, pseudoId) {
    if (!window.internals)
        return null;
    var node = root;
    while (node) {
        if (node.nodeType === Node.ELEMENT_NODE && internals.shadowPseudoId(node) === pseudoId)
            return node;
        node = traverseNextNode(node, root);
    }
    return null;
}

function doneLater() {
    setTimeout(function() {
        testRunner.notifyDone();
    }, 0);
}

function waitUntilLoadedAndAutofocused(callback) {
    var loaded = false;
    var autofocused = false;
    // Use doneLater() because some rendering tests need repaint after focus.
    callback  = callback || doneLater;
    // Does both of waitUntilDone and jsTestIsAsync because we want to support
    // tests with/without js-test.js.
    testRunner.waitUntilDone();
    window.jsTestIsAsync = true;
    window.addEventListener('load', function() {
        loaded = true;
        if (autofocused)
            callback();
    }, false);
    document.addEventListener('focusin', function() {
        if (internals.hasAutofocusRequest(document))
            return;
        if (autofocused)
            return;
        autofocused = true;
        if (loaded)
            callback();
    }, false);
}

function sendString(str) {
    if (!window.eventSender) {
        console.log('Require eventSender.');
        return;
    }
    for (var i = 0; i < str.length; ++i) {
        var key = str.charAt(i);
        if (key == '\n')
            key = 'Enter';
        eventSender.keyDown(key);
    }
}