@angular/cdk
Version:
Angular Material Component Development Kit
310 lines (304 loc) • 11.7 kB
JavaScript
import { __awaiter } from 'tslib';
import { TestKey, _getTextWithExcludedElements, HarnessEnvironment } from '@angular/cdk/testing';
import { Key, browser, Button, by, element } from 'protractor';
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/** Maps the `TestKey` constants to Protractor's `Key` constants. */
const keyMap = {
[TestKey.BACKSPACE]: Key.BACK_SPACE,
[TestKey.TAB]: Key.TAB,
[TestKey.ENTER]: Key.ENTER,
[TestKey.SHIFT]: Key.SHIFT,
[TestKey.CONTROL]: Key.CONTROL,
[TestKey.ALT]: Key.ALT,
[TestKey.ESCAPE]: Key.ESCAPE,
[TestKey.PAGE_UP]: Key.PAGE_UP,
[TestKey.PAGE_DOWN]: Key.PAGE_DOWN,
[TestKey.END]: Key.END,
[TestKey.HOME]: Key.HOME,
[TestKey.LEFT_ARROW]: Key.ARROW_LEFT,
[TestKey.UP_ARROW]: Key.ARROW_UP,
[TestKey.RIGHT_ARROW]: Key.ARROW_RIGHT,
[TestKey.DOWN_ARROW]: Key.ARROW_DOWN,
[TestKey.INSERT]: Key.INSERT,
[TestKey.DELETE]: Key.DELETE,
[TestKey.F1]: Key.F1,
[TestKey.F2]: Key.F2,
[TestKey.F3]: Key.F3,
[TestKey.F4]: Key.F4,
[TestKey.F5]: Key.F5,
[TestKey.F6]: Key.F6,
[TestKey.F7]: Key.F7,
[TestKey.F8]: Key.F8,
[TestKey.F9]: Key.F9,
[TestKey.F10]: Key.F10,
[TestKey.F11]: Key.F11,
[TestKey.F12]: Key.F12,
[TestKey.META]: Key.META
};
/** Converts a `ModifierKeys` object to a list of Protractor `Key`s. */
function toProtractorModifierKeys(modifiers) {
const result = [];
if (modifiers.control) {
result.push(Key.CONTROL);
}
if (modifiers.alt) {
result.push(Key.ALT);
}
if (modifiers.shift) {
result.push(Key.SHIFT);
}
if (modifiers.meta) {
result.push(Key.META);
}
return result;
}
/** A `TestElement` implementation for Protractor. */
class ProtractorElement {
constructor(element) {
this.element = element;
}
blur() {
return __awaiter(this, void 0, void 0, function* () {
return browser.executeScript('arguments[0].blur()', this.element);
});
}
clear() {
return __awaiter(this, void 0, void 0, function* () {
return this.element.clear();
});
}
click(...args) {
return __awaiter(this, void 0, void 0, function* () {
yield this._dispatchClickEventSequence(args);
});
}
rightClick(...args) {
return __awaiter(this, void 0, void 0, function* () {
yield this._dispatchClickEventSequence(args, Button.RIGHT);
});
}
focus() {
return __awaiter(this, void 0, void 0, function* () {
return browser.executeScript('arguments[0].focus()', this.element);
});
}
getCssValue(property) {
return __awaiter(this, void 0, void 0, function* () {
return this.element.getCssValue(property);
});
}
hover() {
return __awaiter(this, void 0, void 0, function* () {
return browser.actions()
.mouseMove(yield this.element.getWebElement())
.perform();
});
}
mouseAway() {
return __awaiter(this, void 0, void 0, function* () {
return browser.actions()
.mouseMove(yield this.element.getWebElement(), { x: -1, y: -1 })
.perform();
});
}
sendKeys(...modifiersAndKeys) {
return __awaiter(this, void 0, void 0, function* () {
const first = modifiersAndKeys[0];
let modifiers;
let rest;
if (typeof first !== 'string' && typeof first !== 'number') {
modifiers = first;
rest = modifiersAndKeys.slice(1);
}
else {
modifiers = {};
rest = modifiersAndKeys;
}
const modifierKeys = toProtractorModifierKeys(modifiers);
const keys = rest.map(k => typeof k === 'string' ? k.split('') : [keyMap[k]])
.reduce((arr, k) => arr.concat(k), [])
// Key.chord doesn't work well with geckodriver (mozilla/geckodriver#1502),
// so avoid it if no modifier keys are required.
.map(k => modifierKeys.length > 0 ? Key.chord(...modifierKeys, k) : k);
return this.element.sendKeys(...keys);
});
}
text(options) {
return __awaiter(this, void 0, void 0, function* () {
if (options === null || options === void 0 ? void 0 : options.exclude) {
return browser.executeScript(_getTextWithExcludedElements, this.element, options.exclude);
}
return this.element.getText();
});
}
getAttribute(name) {
return __awaiter(this, void 0, void 0, function* () {
return browser.executeScript(`return arguments[0].getAttribute(arguments[1])`, this.element, name);
});
}
hasClass(name) {
return __awaiter(this, void 0, void 0, function* () {
const classes = (yield this.getAttribute('class')) || '';
return new Set(classes.split(/\s+/).filter(c => c)).has(name);
});
}
getDimensions() {
return __awaiter(this, void 0, void 0, function* () {
const { width, height } = yield this.element.getSize();
const { x: left, y: top } = yield this.element.getLocation();
return { width, height, left, top };
});
}
getProperty(name) {
return __awaiter(this, void 0, void 0, function* () {
return browser.executeScript(`return arguments[0][arguments[1]]`, this.element, name);
});
}
setInputValue(value) {
return __awaiter(this, void 0, void 0, function* () {
return browser.executeScript(`arguments[0].value = arguments[1]`, this.element, value);
});
}
selectOptions(...optionIndexes) {
return __awaiter(this, void 0, void 0, function* () {
const options = yield this.element.all(by.css('option'));
const indexes = new Set(optionIndexes); // Convert to a set to remove duplicates.
if (options.length && indexes.size) {
// Reset the value so all the selected states are cleared. We can
// reuse the input-specific method since the logic is the same.
yield this.setInputValue('');
for (let i = 0; i < options.length; i++) {
if (indexes.has(i)) {
// We have to hold the control key while clicking on options so that multiple can be
// selected in multi-selection mode. The key doesn't do anything for single selection.
yield browser.actions().keyDown(Key.CONTROL).perform();
yield options[i].click();
yield browser.actions().keyUp(Key.CONTROL).perform();
}
}
}
});
}
matchesSelector(selector) {
return __awaiter(this, void 0, void 0, function* () {
return browser.executeScript(`
return (Element.prototype.matches ||
Element.prototype.msMatchesSelector).call(arguments[0], arguments[1])
`, this.element, selector);
});
}
isFocused() {
return __awaiter(this, void 0, void 0, function* () {
return this.element.equals(browser.driver.switchTo().activeElement());
});
}
dispatchEvent(name) {
return __awaiter(this, void 0, void 0, function* () {
return browser.executeScript(_dispatchEvent, name, this.element);
});
}
/** Dispatches all the events that are part of a click event sequence. */
_dispatchClickEventSequence(args, button) {
return __awaiter(this, void 0, void 0, function* () {
// Omitting the offset argument to mouseMove results in clicking the center.
// This is the default behavior we want, so we use an empty array of offsetArgs if no args are
// passed to this method.
const offsetArgs = args.length === 2 ? [{ x: args[0], y: args[1] }] : [];
yield browser.actions()
.mouseMove(yield this.element.getWebElement(), ...offsetArgs)
.click(button)
.perform();
});
}
}
/**
* Dispatches an event with a particular name and data to an element.
* Note that this needs to be a pure function, because it gets stringified by
* Protractor and is executed inside the browser.
*/
function _dispatchEvent(name, element) {
const event = document.createEvent('Event');
event.initEvent(name);
// This type has a string index signature, so we cannot access it using a dotted property access.
element['dispatchEvent'](event);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/** The default environment options. */
const defaultEnvironmentOptions = {
queryFn: (selector, root) => root.all(by.css(selector))
};
/** A `HarnessEnvironment` implementation for Protractor. */
class ProtractorHarnessEnvironment extends HarnessEnvironment {
constructor(rawRootElement, options) {
super(rawRootElement);
this._options = Object.assign(Object.assign({}, defaultEnvironmentOptions), options);
}
/** Creates a `HarnessLoader` rooted at the document root. */
static loader(options) {
return new ProtractorHarnessEnvironment(element(by.css('body')), options);
}
/** Gets the ElementFinder corresponding to the given TestElement. */
static getNativeElement(el) {
if (el instanceof ProtractorElement) {
return el.element;
}
throw Error('This TestElement was not created by the ProtractorHarnessEnvironment');
}
forceStabilize() {
return __awaiter(this, void 0, void 0, function* () { });
}
waitForTasksOutsideAngular() {
return __awaiter(this, void 0, void 0, function* () {
// TODO: figure out how we can do this for the protractor environment.
// https://github.com/angular/components/issues/17412
});
}
getDocumentRoot() {
return element(by.css('body'));
}
createTestElement(element) {
return new ProtractorElement(element);
}
createEnvironment(element) {
return new ProtractorHarnessEnvironment(element, this._options);
}
getAllRawElements(selector) {
return __awaiter(this, void 0, void 0, function* () {
const elementArrayFinder = this._options.queryFn(selector, this.rawRootElement);
const length = yield elementArrayFinder.count();
const elements = [];
for (let i = 0; i < length; i++) {
elements.push(elementArrayFinder.get(i));
}
return elements;
});
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export { ProtractorElement, ProtractorHarnessEnvironment };
//# sourceMappingURL=protractor.js.map