browser-monkey
Advanced tools
Comparing version 3.0.0-beta.11 to 3.0.0-beta.12
@@ -25,5 +25,8 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.matchers = exports.Mount = exports.IFrameMount = exports.Query = void 0; | ||
exports.matchers = exports.Mount = exports.IFrameMount = exports.Field = exports.Button = exports.createFinder = exports.Query = void 0; | ||
var Query_1 = require("./lib/Query"); | ||
Object.defineProperty(exports, "Query", { enumerable: true, get: function () { return Query_1.Query; } }); | ||
Object.defineProperty(exports, "createFinder", { enumerable: true, get: function () { return Query_1.createFinder; } }); | ||
Object.defineProperty(exports, "Button", { enumerable: true, get: function () { return Query_1.Button; } }); | ||
Object.defineProperty(exports, "Field", { enumerable: true, get: function () { return Query_1.Field; } }); | ||
var IFrameMount_1 = __importDefault(require("./lib/IFrameMount")); | ||
@@ -30,0 +33,0 @@ exports.IFrameMount = IFrameMount_1.default; |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -6,3 +6,2 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var polyfills_1 = require("./polyfills"); | ||
var normaliseText_1 = __importDefault(require("./normaliseText")); | ||
@@ -100,7 +99,9 @@ var keycode_1 = __importDefault(require("keycode")); | ||
var Dom = /** @class */ (function () { | ||
function Dom() { | ||
function Dom(_a) { | ||
var _b = _a === void 0 ? {} : _a, _c = _b.jsdom, jsdom = _c === void 0 ? window.navigator.userAgent.includes('jsdom') : _c; | ||
this.jsdom = jsdom; | ||
} | ||
Dom.prototype.enterText = function (element, text, _a) { | ||
var _this = this; | ||
var _b = (_a === void 0 ? {} : _a).incremental, incremental = _b === void 0 ? true : _b; | ||
var _b = _a === void 0 ? {} : _a, _c = _b.incremental, incremental = _c === void 0 ? true : _c; | ||
element.focus(); | ||
@@ -142,3 +143,6 @@ var enterText = function (text) { | ||
Dom.prototype.elementInnerText = function (element) { | ||
return normaliseText_1.default(element.innerText); | ||
var text = this.jsdom | ||
? element.textContent | ||
: element.innerText; | ||
return normaliseText_1.default(text); | ||
}; | ||
@@ -153,8 +157,7 @@ Dom.prototype.click = function (element) { | ||
var _this = this; | ||
var _b = (_a === void 0 ? {} : _a).visibleOnly, visibleOnly = _b === void 0 ? true : _b; | ||
var _b = _a === void 0 ? {} : _a, _c = _b.visibleOnly, visibleOnly = _c === void 0 ? true : _c; | ||
var children = Array.prototype.slice.call(element.querySelectorAll(selector)); | ||
children = visibleOnly | ||
return visibleOnly && !this.jsdom | ||
? children.filter(function (c) { return _this.elementVisible(c); }) | ||
: children; | ||
return children; | ||
}; | ||
@@ -233,7 +236,7 @@ Dom.prototype.elementVisible = function (element) { | ||
// @ts-ignore | ||
return new polyfills_1.MouseEvent(type, { bubbles: true, cancelable: true }); | ||
return new window.MouseEvent(type, { bubbles: true, cancelable: true }); | ||
} | ||
function createEvent(type, params) { | ||
if (params === void 0) { params = { bubbles: true, cancelable: false }; } | ||
return new Event(type, params); | ||
return new window.Event(type, params); | ||
} | ||
@@ -245,3 +248,3 @@ function matchKeyCode(text) { | ||
// @ts-ignore | ||
var event = new polyfills_1.KeyboardEvent(type, { bubbles: true, cancelable: true }); | ||
var event = new window.KeyboardEvent(type, { bubbles: true, cancelable: true }); | ||
var match = matchKeyCode(key); | ||
@@ -248,0 +251,0 @@ if (match) { |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -21,2 +21,5 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -27,17 +30,19 @@ exports.placeholder = exports.ariaLabelledBy = exports.ariaLabel = exports.labelFor = exports.label = exports.button = void 0; | ||
var matchers = __importStar(require("./matchers")); | ||
var Dom_1 = __importDefault(require("./Dom")); | ||
exports.button = { | ||
name: 'button', | ||
definition: function (query, name) { | ||
finder: function (query, name) { | ||
return query.findCss('button, input[type=button], input[type=submit], input[type=reset], a').containing(name); | ||
} | ||
}; | ||
exports.label = function (inputSelector) { return ({ | ||
var label = function (inputSelector) { return ({ | ||
name: 'label', | ||
definition: function (query, name) { | ||
finder: function (query, name) { | ||
return query.find('label').containing(name).find(inputSelector(query)); | ||
}, | ||
}); }; | ||
exports.label = label; | ||
exports.labelFor = { | ||
name: 'label-for', | ||
definition: function (query, name) { | ||
finder: function (query, name) { | ||
return query.find('label[for]').containing(name).map(function (label) { | ||
@@ -51,3 +56,3 @@ var id = label.getAttribute('for'); | ||
name: 'aria-label', | ||
definition: function (query, name) { | ||
finder: function (query, name) { | ||
return query.find('[aria-label]').filter(function (element) { | ||
@@ -61,3 +66,3 @@ var label = element.getAttribute('aria-label'); | ||
name: 'aria-labelledby', | ||
definition: function (query, name) { | ||
finder: function (query, name) { | ||
return query.find('[aria-labelledby]').filter(function (element) { | ||
@@ -67,3 +72,4 @@ var id = element.getAttribute('aria-labelledby'); | ||
if (labelElement) { | ||
return match_1.match(query.dom().elementInnerText(labelElement), name).isMatch; | ||
var dom = new Dom_1.default(); | ||
return match_1.match(dom.elementInnerText(labelElement), name).isMatch; | ||
} | ||
@@ -75,3 +81,3 @@ }, 'aria-label'); | ||
name: 'placeholder', | ||
definition: function (query, name) { | ||
finder: function (query, name) { | ||
return query.find(inputSelectors_1.withPlaceholders).containing(matchers.elementAttributes({ | ||
@@ -78,0 +84,0 @@ placeholder: name, |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -29,3 +31,3 @@ function __() { this.constructor = d; } | ||
function IFrameMount(url, _a) { | ||
var _b = (_a === void 0 ? {} : _a).resize, resize = _b === void 0 ? false : _b; | ||
var _b = _a === void 0 ? {} : _a, _c = _b.resize, resize = _c === void 0 ? false : _c; | ||
var _this = _super.call(this) || this; | ||
@@ -69,3 +71,4 @@ _this.url = url; | ||
IFrameMount.prototype.mount = function (query) { | ||
return query.scope(this._iframe).iframe(); | ||
query.setInput(this._iframe); | ||
return query.iframe(); | ||
}; | ||
@@ -72,0 +75,0 @@ return IFrameMount; |
@@ -21,3 +21,4 @@ "use strict"; | ||
Mount.prototype.mount = function (query) { | ||
return query.scope(this._mountDiv); | ||
query.setInput(this._mountDiv); | ||
return query; | ||
}; | ||
@@ -24,0 +25,0 @@ Mount.prototype.unmount = function () { |
module.exports.MouseEvent = (function () { | ||
try { | ||
new MouseEvent('click'); // eslint-disable-line | ||
return MouseEvent; // eslint-disable-line | ||
new window.MouseEvent('click'); | ||
return window.MouseEvent; | ||
} | ||
@@ -15,3 +15,3 @@ catch (e) { | ||
}; | ||
MouseEventPolyfill.prototype = Event.prototype; | ||
MouseEventPolyfill.prototype = window.Event.prototype; | ||
return MouseEventPolyfill; | ||
@@ -22,4 +22,4 @@ })(); | ||
try { | ||
new KeyboardEvent('keyup'); // eslint-disable-line | ||
return KeyboardEvent; // eslint-disable-line | ||
new window.KeyboardEvent('keyup'); | ||
return window.KeyboardEvent; | ||
} | ||
@@ -42,5 +42,5 @@ catch (e) { | ||
}; | ||
KeyboardEventPolyfill.prototype = Event.prototype; | ||
KeyboardEventPolyfill.prototype = window.Event.prototype; | ||
return KeyboardEventPolyfill; | ||
})(); | ||
//# sourceMappingURL=polyfills.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (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 __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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -57,8 +38,6 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
}; | ||
var __spreadArrays = (this && this.__spreadArrays) || function () { | ||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; | ||
for (var r = Array(s), k = 0, i = 0; i < il; i++) | ||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) | ||
r[k] = a[j]; | ||
return r; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
}; | ||
@@ -69,3 +48,3 @@ var __importDefault = (this && this.__importDefault) || function (mod) { | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Query = void 0; | ||
exports.Query = exports.Css = exports.createFinder = exports.Field = exports.Button = void 0; | ||
var ExecutedTransformPath_1 = require("./ExecutedTransformPath"); | ||
@@ -92,3 +71,10 @@ var ExecutedSimpleTransform_1 = require("./ExecutedSimpleTransform"); | ||
var match_1 = require("./match"); | ||
var fieldDefinitions = __importStar(require("./fieldDefinitions")); | ||
var Finder_1 = require("./Finder"); | ||
Object.defineProperty(exports, "createFinder", { enumerable: true, get: function () { return Finder_1.createFinder; } }); | ||
var Button_1 = require("./Button"); | ||
Object.defineProperty(exports, "Button", { enumerable: true, get: function () { return Button_1.Button; } }); | ||
var Field_1 = require("./Field"); | ||
Object.defineProperty(exports, "Field", { enumerable: true, get: function () { return Field_1.Field; } }); | ||
var Css_1 = require("./Css"); | ||
Object.defineProperty(exports, "Css", { enumerable: true, get: function () { return Css_1.Css; } }); | ||
var missing = {}; | ||
@@ -249,22 +235,3 @@ var Query = /** @class */ (function () { | ||
}, | ||
], | ||
buttons: [ | ||
fieldDefinitions.button, | ||
fieldDefinitions.label(function () { return inputSelectors_1.default.canBeClicked; }), | ||
fieldDefinitions.labelFor, | ||
fieldDefinitions.ariaLabel, | ||
fieldDefinitions.ariaLabelledBy, | ||
], | ||
fields: [ | ||
fieldDefinitions.label(function (query) { return query.inputSelector(); }), | ||
fieldDefinitions.labelFor, | ||
fieldDefinitions.ariaLabel, | ||
fieldDefinitions.ariaLabelledBy, | ||
fieldDefinitions.placeholder, | ||
], | ||
finders: { | ||
Field: function (q, value) { return q.findLabel(value); }, | ||
Button: function (q, value) { return q.findButton(value); }, | ||
Css: function (q, value) { return q.findCss(value); }, | ||
}, | ||
] | ||
} | ||
@@ -275,5 +242,2 @@ }; | ||
} | ||
Query.prototype.dom = function () { | ||
return this._dom; | ||
}; | ||
Object.defineProperty(Query.prototype, Symbol.toStringTag, { | ||
@@ -305,60 +269,2 @@ get: function () { | ||
}; | ||
Query.prototype.findButton = function (name) { | ||
return this.concat(this._options.definitions.buttons.map(function (_a) { | ||
var definition = _a.definition; | ||
return function (q) { | ||
return definition(q, name); | ||
}; | ||
})); | ||
}; | ||
Query.prototype.findLabel = function (name) { | ||
return this.concat(this._options.definitions.fields.map(function (_a) { | ||
var definition = _a.definition; | ||
return function (q) { | ||
return definition(q, name); | ||
}; | ||
})); | ||
}; | ||
Query.prototype.defineButtonFinder = function (name, definition) { | ||
if (!definition) { | ||
definition = name; | ||
name = undefined; | ||
} | ||
return this.clone(function (q) { return q._options.definitions.buttons.push({ | ||
name: name, | ||
definition: definition | ||
}); }); | ||
}; | ||
Query.prototype.undefineButtonFinder = function (name) { | ||
return this.clone(function (q) { | ||
var index = q._options.definitions.buttons.findIndex(function (def) { return def.name === name; }); | ||
if (index >= 0) { | ||
q._options.definitions.buttons.splice(index, 1); | ||
} | ||
else { | ||
throw new Error("field definition " + JSON.stringify(name) + " doesn't exist"); | ||
} | ||
}); | ||
}; | ||
Query.prototype.defineFieldFinder = function (name, definition) { | ||
if (!definition) { | ||
definition = name; | ||
name = undefined; | ||
} | ||
return this.clone(function (q) { return q._options.definitions.fields.push({ | ||
name: name, | ||
definition: definition | ||
}); }); | ||
}; | ||
Query.prototype.undefineFieldFinder = function (name) { | ||
return this.clone(function (q) { | ||
var index = q._options.definitions.fields.findIndex(function (def) { return def.name === name; }); | ||
if (index >= 0) { | ||
q._options.definitions.fields.splice(index, 1); | ||
} | ||
else { | ||
throw new Error("field definition " + JSON.stringify(name) + " doesn't exist"); | ||
} | ||
}); | ||
}; | ||
// TODO: try removing any | ||
@@ -504,4 +410,5 @@ Query.prototype.result = function () { | ||
}; | ||
Query.prototype.options = function (options) { | ||
return this.clone(function (q) { return extend_1.default(q._options, options); }); | ||
Query.prototype.setOptions = function (options) { | ||
extend_1.default(this._options, options); | ||
return this; | ||
}; | ||
@@ -568,8 +475,9 @@ Query.prototype.getOptions = function () { | ||
}; | ||
// TODO: why is this public? | ||
Query.prototype.input = function (value) { | ||
return this.clone(function (q) { return q._input = value; }); | ||
Query.prototype.setInput = function (elementOrArray) { | ||
var input = elementOrArray instanceof Array | ||
? elementOrArray | ||
: [elementOrArray]; | ||
this._input = input; | ||
}; | ||
// TODO: rename `input`/`getInput` to something better | ||
Query.prototype.getInput = function () { | ||
Query.prototype.input = function () { | ||
return this._input; | ||
@@ -582,3 +490,2 @@ }; | ||
this._options = extend_1.default({}, from._options); | ||
this._options.definitions = cloneDefinitions(from._options.definitions); | ||
}; | ||
@@ -623,5 +530,2 @@ Query.prototype.shouldHaveElements = function (count, message) { | ||
}; | ||
Query.prototype.clickButton = function (name) { | ||
return this.findButton(name).click(); | ||
}; | ||
Query.prototype.submit = function (selector) { | ||
@@ -658,5 +562,2 @@ var _this = this; | ||
}; | ||
Query.prototype.scope = function (element) { | ||
return this.input([element]); | ||
}; | ||
Query.prototype.mount = function (mount) { | ||
@@ -833,15 +734,2 @@ return mount.mount(this); | ||
}; | ||
Query.prototype.define = function (name, finderDefinition) { | ||
var _this = this; | ||
if (typeof finderDefinition === 'function') { | ||
this._options.definitions.finders[name] = finderDefinition; | ||
} | ||
else if (typeof finderDefinition === 'string') { | ||
this._options.definitions.finders[name] = function (q) { return q.find(finderDefinition); }; | ||
} | ||
else if (name.constructor === Object && finderDefinition === undefined) { | ||
Object.keys(name).forEach(function (key) { return _this.define(key, name[key]); }); | ||
} | ||
return this; | ||
}; | ||
Query.prototype.inputSelector = function () { | ||
@@ -876,4 +764,5 @@ return this._options.definitions.inputs.map(function (i) { return i.selector; }).filter(Boolean).join(','); | ||
}; | ||
Query.prototype.defineInput = function (inputDefinition) { | ||
Query.prototype.addInputDefinition = function (inputDefinition) { | ||
this._options.definitions.inputs.unshift(inputDefinition); | ||
return this; | ||
}; | ||
@@ -957,22 +846,11 @@ Query.prototype.containing = function (model) { | ||
Query.prototype.find = function (selector) { | ||
// name(arg1, arg2, ...) | ||
var match = /^\s*([$a-z_][0-9a-z_$]*)\s*(\((.*)\)\s*)?$/i.exec(selector); | ||
if (match) { | ||
var name_1 = match[1], value = match[3]; | ||
var finder = this._options.definitions.finders[name_1]; | ||
if (value !== undefined) { | ||
if (finder) { | ||
var func = new Function("return [" + value + "]"); | ||
var args = func(); | ||
return finder.apply(void 0, __spreadArrays([this], args)); | ||
} | ||
else { | ||
throw new Error('no such definition ' + name_1); | ||
} | ||
} | ||
else if (finder) { | ||
return finder(this); | ||
} | ||
var selectorString = selector.toString(); | ||
var finderInvocation = Finder_1.parseFinder(selectorString); | ||
if (finderInvocation) { | ||
var finder = finderInvocation.finder, _a = finderInvocation.args, args = _a === void 0 ? [] : _a; | ||
return Finder_1.callFinder.apply(void 0, __spreadArray([finder, this], args)); | ||
} | ||
return this.findCss(selector); | ||
else { | ||
return this.findCss(selectorString); | ||
} | ||
}; | ||
@@ -1079,14 +957,2 @@ Query.prototype.is = function (selector) { | ||
exports.Query = Query; | ||
function cloneDefinitions(definitions) { | ||
var result = {}; | ||
Object.keys(definitions).forEach(function (key) { | ||
if (definitions[key] instanceof Array) { | ||
result[key] = definitions[key].slice(); | ||
} | ||
else { | ||
result[key] = Object.assign({}, definitions[key]); | ||
} | ||
}); | ||
return result; | ||
} | ||
function isIframe(element) { | ||
@@ -1093,0 +959,0 @@ return element.contentWindow !== undefined; |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -1,2 +0,2 @@ | ||
import {Query} from './lib/Query' | ||
export {Query, createFinder, Button, Field} from './lib/Query' | ||
import IFrameMount from './lib/IFrameMount' | ||
@@ -7,3 +7,2 @@ import Mount from './lib/Mount' | ||
export { | ||
Query, | ||
IFrameMount, | ||
@@ -10,0 +9,0 @@ Mount, |
@@ -104,2 +104,8 @@ import {MouseEvent, KeyboardEvent} from './polyfills' | ||
export default class Dom { | ||
private jsdom: boolean | ||
public constructor({jsdom = window.navigator.userAgent.includes('jsdom')} = {}) { | ||
this.jsdom = jsdom | ||
} | ||
public enterText (element: HTMLInputElement, text: string | string[], {incremental = true} = {}): void { | ||
@@ -144,3 +150,7 @@ element.focus() | ||
public elementInnerText (element: HTMLElement): string { | ||
return normaliseText(element.innerText) | ||
const text = this.jsdom | ||
? element.textContent | ||
: element.innerText | ||
return normaliseText(text) | ||
} | ||
@@ -156,9 +166,7 @@ | ||
public querySelectorAll (element: HTMLElement, selector: string, {visibleOnly = true} = {}): HTMLElement[] { | ||
let children = Array.prototype.slice.call(element.querySelectorAll(selector)) | ||
const children = Array.prototype.slice.call(element.querySelectorAll(selector)) | ||
children = visibleOnly | ||
return visibleOnly && !this.jsdom | ||
? children.filter(c => this.elementVisible(c)) | ||
: children | ||
return children | ||
} | ||
@@ -246,7 +254,7 @@ | ||
// @ts-ignore | ||
return new MouseEvent(type, { bubbles: true, cancelable: true }) | ||
return new window.MouseEvent(type, { bubbles: true, cancelable: true }) | ||
} | ||
function createEvent (type, params = {bubbles: true, cancelable: false}): Event { | ||
return new Event(type, params) | ||
return new window.Event(type, params) | ||
} | ||
@@ -260,3 +268,3 @@ | ||
// @ts-ignore | ||
const event = new KeyboardEvent(type, { bubbles: true, cancelable: true }) | ||
const event = new window.KeyboardEvent(type, { bubbles: true, cancelable: true }) | ||
@@ -263,0 +271,0 @@ const match = matchKeyCode(key) |
@@ -5,6 +5,7 @@ import { Query } from './Query' | ||
import * as matchers from './matchers' | ||
import Dom from './Dom' | ||
export const button = { | ||
name: 'button', | ||
definition: (query: Query, name) => { | ||
finder: (query: Query, name) => { | ||
return query.findCss('button, input[type=button], input[type=submit], input[type=reset], a').containing(name) | ||
@@ -16,3 +17,3 @@ } | ||
name: 'label', | ||
definition: (query: Query, name) => { | ||
finder: (query: Query, name) => { | ||
return query.find('label').containing(name).find(inputSelector(query)) | ||
@@ -24,3 +25,3 @@ }, | ||
name: 'label-for', | ||
definition: (query: Query, name) => { | ||
finder: (query: Query, name) => { | ||
return query.find('label[for]').containing(name).map(label => { | ||
@@ -35,3 +36,3 @@ const id = label.getAttribute('for') | ||
name: 'aria-label', | ||
definition: (query: Query, name) => { | ||
finder: (query: Query, name) => { | ||
return query.find('[aria-label]').filter(element => { | ||
@@ -46,3 +47,3 @@ const label = element.getAttribute('aria-label') | ||
name: 'aria-labelledby', | ||
definition: (query: Query, name) => { | ||
finder: (query: Query, name) => { | ||
return query.find('[aria-labelledby]').filter(element => { | ||
@@ -52,3 +53,4 @@ const id = element.getAttribute('aria-labelledby') | ||
if (labelElement) { | ||
return match(query.dom().elementInnerText(labelElement), name).isMatch | ||
const dom = new Dom() | ||
return match(dom.elementInnerText(labelElement), name).isMatch | ||
} | ||
@@ -61,3 +63,3 @@ }, 'aria-label') | ||
name: 'placeholder', | ||
definition: (query: Query, name) => { | ||
finder: (query: Query, name) => { | ||
return query.find(withPlaceholders).containing(matchers.elementAttributes({ | ||
@@ -64,0 +66,0 @@ placeholder: name, |
@@ -101,4 +101,5 @@ import _debug from 'debug' | ||
mount (query: Query): Query { | ||
return query.scope(this._iframe).iframe() | ||
query.setInput(this._iframe) | ||
return query.iframe() | ||
} | ||
} |
@@ -27,3 +27,4 @@ import {Query} from './Query' | ||
public mount (query: Query): Query { | ||
return query.scope(this._mountDiv) | ||
query.setInput(this._mountDiv) | ||
return query | ||
} | ||
@@ -30,0 +31,0 @@ |
module.exports.MouseEvent = (function () { | ||
try { | ||
new MouseEvent('click') // eslint-disable-line | ||
return MouseEvent // eslint-disable-line | ||
new window.MouseEvent('click') | ||
return window.MouseEvent | ||
} catch (e) { | ||
@@ -33,3 +33,3 @@ // Need to polyfill - fall through | ||
MouseEventPolyfill.prototype = Event.prototype | ||
MouseEventPolyfill.prototype = window.Event.prototype | ||
@@ -42,4 +42,4 @@ return MouseEventPolyfill | ||
try { | ||
new KeyboardEvent('keyup') // eslint-disable-line | ||
return KeyboardEvent // eslint-disable-line | ||
new window.KeyboardEvent('keyup') | ||
return window.KeyboardEvent | ||
} catch (e) { | ||
@@ -76,5 +76,5 @@ // Need to polyfill - fall through | ||
KeyboardEventPolyfill.prototype = Event.prototype | ||
KeyboardEventPolyfill.prototype = window.Event.prototype | ||
return KeyboardEventPolyfill | ||
})() |
203
lib/Query.ts
@@ -23,4 +23,16 @@ import { ExecutedTransform } from './ExecutedTransform' | ||
import {match} from './match' | ||
import * as fieldDefinitions from './fieldDefinitions' | ||
import { | ||
Finder, | ||
callFinder, | ||
createFinder, | ||
parseFinder | ||
} from './Finder' | ||
import { Button } from './Button' | ||
import { Field } from './Field' | ||
import { Css } from './Css' | ||
export { MultiFinder } from './MultiFinder' | ||
export { Button, Field, createFinder, Css } | ||
type Transform = (elements: Array<HTMLElement>, executedTransforms: ExecutedTransform[]) => any | ||
@@ -41,17 +53,8 @@ type Action = (elements: Array<HTMLElement>, executedTransforms: ExecutedTransform[]) => void | ||
type FieldName = string | RegExp | ||
type FieldFinderDefinition = (query: Query, name: FieldName) => Query | ||
type FinderDefinition = (query: Query, ...any) => Query | ||
type LiteralModel = string | RegExp | boolean | ||
type FunctionModel = (query: Query) => void | ||
type Model = LiteralModel | FunctionModel | { [key: string]: Model } | Model[] | ||
export type Model = LiteralModel | FunctionModel | { [key: string]: Model } | Model[] | ||
interface Definitions { | ||
inputs: InputDefinition[] | ||
buttons: ({name: string, definition: FieldFinderDefinition})[] | ||
fields: ({name: string, definition: FieldFinderDefinition})[] | ||
finders: { | ||
[key: string]: FinderDefinition | ||
} | ||
} | ||
@@ -64,3 +67,3 @@ | ||
private _options: Options | ||
private _input: [HTMLElement] | ||
private _input: HTMLElement[] | ||
private _actionExecuted = false | ||
@@ -221,24 +224,6 @@ private _action: Action | ||
}, | ||
], | ||
buttons: [ | ||
fieldDefinitions.button, | ||
fieldDefinitions.label(() => inputSelectors.canBeClicked), | ||
fieldDefinitions.labelFor, | ||
fieldDefinitions.ariaLabel, | ||
fieldDefinitions.ariaLabelledBy, | ||
], | ||
fields: [ | ||
fieldDefinitions.label(query => query.inputSelector()), | ||
fieldDefinitions.labelFor, | ||
fieldDefinitions.ariaLabel, | ||
fieldDefinitions.ariaLabelledBy, | ||
fieldDefinitions.placeholder, | ||
], | ||
finders: { | ||
Field: (q: Query, value) => q.findLabel(value), | ||
Button: (q: Query, value) => q.findButton(value), | ||
Css: (q: Query, value) => q.findCss(value), | ||
}, | ||
] | ||
} | ||
} | ||
this._dom = new Dom() | ||
@@ -249,6 +234,2 @@ | ||
public dom() { | ||
return this._dom | ||
} | ||
public get [Symbol.toStringTag](): string { | ||
@@ -258,3 +239,3 @@ return 'Query'; | ||
public transform (transform: Transform): Query { | ||
private transform (transform: Transform): Query { | ||
return this.clone(clone => clone._transforms.push(transform)) | ||
@@ -274,3 +255,3 @@ } | ||
public action (action: Action): Query { | ||
private action (action: Action): Query { | ||
if (this._action) { | ||
@@ -285,64 +266,2 @@ throw new Error('can only have one action') | ||
public findButton (name: FieldName): Query { | ||
return this.concat(this._options.definitions.buttons.map(({definition}) => { | ||
return (q: Query): Query => { | ||
return definition(q, name) | ||
} | ||
})) | ||
} | ||
public findLabel (name: string): Query { | ||
return this.concat(this._options.definitions.fields.map(({definition}) => { | ||
return (q: Query): Query => { | ||
return definition(q, name) | ||
} | ||
})) | ||
} | ||
public defineButtonFinder (name: string | FieldFinderDefinition, definition?: FieldFinderDefinition): Query { | ||
if (!definition) { | ||
definition = name as FieldFinderDefinition | ||
name = undefined | ||
} | ||
return this.clone(q => q._options.definitions.buttons.push({ | ||
name: name as string, | ||
definition | ||
})) | ||
} | ||
public undefineButtonFinder (name: string): Query { | ||
return this.clone(q => { | ||
const index = q._options.definitions.buttons.findIndex(def => def.name === name) | ||
if (index >= 0) { | ||
q._options.definitions.buttons.splice(index, 1) | ||
} else { | ||
throw new Error(`field definition ${JSON.stringify(name)} doesn't exist`) | ||
} | ||
}) | ||
} | ||
public defineFieldFinder (name: string | FieldFinderDefinition, definition?: FieldFinderDefinition): Query { | ||
if (!definition) { | ||
definition = name as FieldFinderDefinition | ||
name = undefined | ||
} | ||
return this.clone(q => q._options.definitions.fields.push({ | ||
name: name as string, | ||
definition | ||
})) | ||
} | ||
public undefineFieldFinder (name: string): Query { | ||
return this.clone(q => { | ||
const index = q._options.definitions.fields.findIndex(def => def.name === name) | ||
if (index >= 0) { | ||
q._options.definitions.fields.splice(index, 1) | ||
} else { | ||
throw new Error(`field definition ${JSON.stringify(name)} doesn't exist`) | ||
} | ||
}) | ||
} | ||
// TODO: try removing any | ||
@@ -511,4 +430,5 @@ public result (): any { | ||
public options (options: Options): Query { | ||
return this.clone(q => extend(q._options, options)) | ||
public setOptions (options: Options): this { | ||
extend(this._options, options) | ||
return this | ||
} | ||
@@ -574,9 +494,11 @@ | ||
// TODO: why is this public? | ||
public input (value): Query { | ||
return this.clone(q => q._input = value) | ||
public setInput (elementOrArray: HTMLElement | HTMLElement[]) { | ||
const input: HTMLElement[] = elementOrArray instanceof Array | ||
? elementOrArray | ||
: [elementOrArray] | ||
this._input = input | ||
} | ||
// TODO: rename `input`/`getInput` to something better | ||
public getInput (): [HTMLElement] { | ||
public input (): HTMLElement[] { | ||
return this._input | ||
@@ -592,3 +514,2 @@ } | ||
this._options = extend({}, from._options) | ||
this._options.definitions = cloneDefinitions(from._options.definitions) | ||
} | ||
@@ -635,6 +556,2 @@ | ||
public clickButton (name: FieldName): Query { | ||
return this.findButton(name).click() | ||
} | ||
public submit (selector?: string): Query { | ||
@@ -669,6 +586,2 @@ return this.optionalSelector(selector) | ||
public scope (element: HTMLElement): Query { | ||
return this.input([element]) | ||
} | ||
public mount (mount: {mount: (query: Query) => Query}): Query { | ||
@@ -832,15 +745,3 @@ return mount.mount(this) | ||
public define (name: string | Object, finderDefinition?: FinderDefinition | string): this { | ||
if (typeof finderDefinition === 'function') { | ||
this._options.definitions.finders[name as string] = finderDefinition | ||
} else if (typeof finderDefinition === 'string') { | ||
this._options.definitions.finders[name as string] = q => q.find(finderDefinition) | ||
} else if (name.constructor === Object && finderDefinition === undefined) { | ||
Object.keys(name).forEach(key => this.define(key, name[key])) | ||
} | ||
return this | ||
} | ||
private inputSelector (): string { | ||
public inputSelector (): string { | ||
return this._options.definitions.inputs.map(i => i.selector).filter(Boolean).join(',') | ||
@@ -881,4 +782,5 @@ } | ||
public defineInput (inputDefinition: InputDefinition): void { | ||
public addInputDefinition (inputDefinition: InputDefinition): this { | ||
this._options.definitions.inputs.unshift(inputDefinition) | ||
return this | ||
} | ||
@@ -975,24 +877,13 @@ | ||
public find (selector: string): Query { | ||
// name(arg1, arg2, ...) | ||
const match = /^\s*([$a-z_][0-9a-z_$]*)\s*(\((.*)\)\s*)?$/i.exec(selector) | ||
public find (selector: string | Finder): Query { | ||
const selectorString = selector.toString() | ||
if (match) { | ||
const [, name,, value] = match | ||
const finder = this._options.definitions.finders[name] | ||
const finderInvocation = parseFinder(selectorString) | ||
if (value !== undefined) { | ||
if (finder) { | ||
const func = new Function(`return [${value}]`) | ||
const args = func() | ||
return finder(this, ...args) | ||
} else { | ||
throw new Error('no such definition ' + name) | ||
} | ||
} else if (finder) { | ||
return finder(this) | ||
} | ||
if (finderInvocation) { | ||
const {finder, args = []} = finderInvocation | ||
return callFinder(finder, this, ...args) | ||
} else { | ||
return this.findCss(selectorString) | ||
} | ||
return this.findCss(selector) | ||
} | ||
@@ -1097,16 +988,2 @@ | ||
function cloneDefinitions(definitions: Definitions): Definitions { | ||
const result = {} | ||
Object.keys(definitions).forEach(function (key) { | ||
if (definitions[key] instanceof Array) { | ||
result[key] = definitions[key].slice() | ||
} else { | ||
result[key] = Object.assign({}, definitions[key]) | ||
} | ||
}) | ||
return result as Definitions | ||
} | ||
function isIframe (element: HTMLElement): element is HTMLIFrameElement { | ||
@@ -1113,0 +990,0 @@ return (element as HTMLIFrameElement).contentWindow !== undefined |
{ | ||
"name": "browser-monkey", | ||
"version": "3.0.0-beta.11", | ||
"version": "3.0.0-beta.12", | ||
"description": "reliable dom testing", | ||
@@ -14,10 +14,14 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"test": "yarn test-electron-mocha && eslint .", | ||
"test": "yarn test-electron-mocha && yarn test-mocha && yarn test-karma && yarn test-jest && eslint .", | ||
"test-karma": "karma start --single-run", | ||
"test-electron-mocha": "yarn electron-mocha test/**/*Spec.{js,ts}", | ||
"test-electron-mocha": "yarn electron-mocha test/*Spec.{js,ts} test/mount/*Spec.{js,ts}", | ||
"test-electron-mocha-watch": "rg --files | entr yarn test-electron-mocha", | ||
"electron-mocha": "electron-mocha --disable-site-isolation-trials --full-trace --color --main electron/foreignIframe.js -r ts-node/register --renderer", | ||
"mocha": "mocha -r test/register.js", | ||
"test-mocha": "yarn mocha test/*Spec.{js,ts}", | ||
"test-jest": "yarn jest", | ||
"watch-types": "tsc -w --noEmit", | ||
"mocha": "TEST_JSDOM=true mocha -r test/register.js -r test/jsdom.js", | ||
"prepare": "tsc -p tsconfig.build.json && ./export-mounts.js && node -r ./HyperdomMount.js -r ./ReactMount.js -e '1'", | ||
"docs": "yarn build-docs && docsify serve --no-open --port 3003 ./docs-dist", | ||
"watch-docs": "ls docs/*.md | entr yarn build-docs", | ||
"docs": "yarn build-docs && yarn docsify serve --no-open --port 3003 ./docs-dist", | ||
"watch-docs": "ls docs/*.md | entr -r yarn docs", | ||
"build-docs": "rm -rf ./docs-dist && cp -r ./docs ./docs-dist && codesandbox-example-links --output-dir=./docs-dist ./docs/*.md", | ||
@@ -29,27 +33,29 @@ "publish-docs": "yarn build-docs && gh-pages -t -d docs-dist" | ||
"devDependencies": { | ||
"@babel/core": "^7.12.3", | ||
"@babel/core": "^7.14.3", | ||
"@babel/polyfill": "^7.12.1", | ||
"@babel/preset-env": "^7.12.1", | ||
"@babel/preset-react": "^7.12.5", | ||
"@babel/register": "^7.12.1", | ||
"@types/mocha": "^8.0.3", | ||
"@typescript-eslint/eslint-plugin": "^4.6.1", | ||
"@typescript-eslint/parser": "^4.6.1", | ||
"@babel/preset-env": "^7.14.4", | ||
"@babel/preset-react": "^7.13.13", | ||
"@babel/register": "^7.13.16", | ||
"@types/mocha": "^8.2.2", | ||
"@typescript-eslint/eslint-plugin": "^4.25.0", | ||
"@typescript-eslint/parser": "^4.25.0", | ||
"assert": "latest", | ||
"babel-loader": "^8.1.0", | ||
"chai": "4.2.0", | ||
"babel-loader": "^8.2.2", | ||
"chai": "4.3.4", | ||
"codesandbox-example-links": "^1.1.0", | ||
"electron": "12.0.0", | ||
"docsify-cli": "^4.4.3", | ||
"electron": "13.0.1", | ||
"electron-mocha": "^10.0.0", | ||
"eslint": "^7.12.1", | ||
"eslint-config-standard": "^16.0.1", | ||
"eslint-plugin-import": "^2.22.1", | ||
"eslint-plugin-mocha": "^8.0.0", | ||
"eslint": "^7.27.0", | ||
"eslint-config-standard": "^16.0.3", | ||
"eslint-plugin-import": "^2.23.4", | ||
"eslint-plugin-mocha": "^9.0.0", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^4.2.1", | ||
"eslint-plugin-standard": "^4.0.2", | ||
"eslint-plugin-promise": "^5.1.0", | ||
"eslint-plugin-standard": "^5.0.0", | ||
"express": "^4.16.4", | ||
"gh-pages": "^3.1.0", | ||
"gh-pages": "^3.2.0", | ||
"hyperdom": "^2.1.0", | ||
"karma": "5.2.3", | ||
"jest": "^27.0.3", | ||
"karma": "6.3.2", | ||
"karma-browserstack-launcher": "https://github.com/karma-runner/karma-browserstack-launcher", | ||
@@ -65,20 +71,21 @@ "karma-chrome-launcher": "3.1.0", | ||
"karma-webpack": "https://github.com/rahcusa/karma-webpack", | ||
"mocha": "8.2.1", | ||
"mocha": "8.4.0", | ||
"process": "latest", | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1", | ||
"ts-loader": "^8.0.9", | ||
"ts-node": "^9.0.0", | ||
"webpack": "^5.4.0", | ||
"webpack-cli": "^4.2.0" | ||
"react": "^17.0.2", | ||
"react-dom": "^17.0.2", | ||
"ts-jest": "^27.0.2", | ||
"ts-loader": "^9.2.2", | ||
"ts-node": "^10.0.0", | ||
"webpack": "^5.38.1", | ||
"webpack-cli": "^4.7.0" | ||
}, | ||
"dependencies": { | ||
"debug": "^4.2.0", | ||
"debug": "^4.3.1", | ||
"hobostyle": "1.0.0", | ||
"iframe-resizer": "^4.2.11", | ||
"iframe-resizer": "^4.3.2", | ||
"keycode": "^2.2.0", | ||
"lowscore": "^1.12.1", | ||
"object-inspect": "1.8.0", | ||
"object-inspect": "1.10.3", | ||
"pluralize": "^8.0.0", | ||
"typescript": "^4.0.5" | ||
"typescript": "^4.3.2" | ||
}, | ||
@@ -110,3 +117,11 @@ "standard": { | ||
}, | ||
"homepage": "https://github.com/featurist/browser-monkey" | ||
"homepage": "https://github.com/featurist/browser-monkey", | ||
"jest": { | ||
"testMatch": [ | ||
"<rootDir>/test/jest/**.test.ts" | ||
], | ||
"transform": { | ||
"^.+\\.(ts|tsx)$": "ts-jest" | ||
} | ||
} | ||
} |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -1,3 +0,1 @@ | ||
/* global location */ | ||
const createTestDiv = require('../../lib/createTestDiv') | ||
@@ -8,6 +6,8 @@ const pathUtils = require('path') | ||
import Dom from '../../lib/Dom' | ||
import {Query} from '../../lib/Query' | ||
import { Query } from '../../lib/Query' | ||
const object = require('lowscore/object') | ||
import inspect from 'object-inspect' | ||
const testJSDOM = process.env.TEST_JSDOM | ||
export class DomAssembly { | ||
@@ -21,2 +21,7 @@ private delayedOperations: number | ||
public static domCanHaveFocus = !testJSDOM | ||
public static domHasInnerText = !testJSDOM | ||
public static domHasVisibility = !testJSDOM | ||
public static domCanLoadIFrames = !testJSDOM | ||
public constructor () { | ||
@@ -39,3 +44,3 @@ this.delayedOperations = 0 | ||
return browserMonkey.options({ | ||
browserMonkey.setOptions({ | ||
retry: (fn) => { | ||
@@ -60,2 +65,3 @@ if (this._normalRetry) { | ||
}) | ||
return browserMonkey | ||
} | ||
@@ -77,3 +83,3 @@ | ||
public static localUrl (path): string { | ||
return location.protocol === 'file:' | ||
return window.location.protocol === 'file:' | ||
? 'file://' + pathUtils.join(pathUtils.join(__dirname, '..'), path) | ||
@@ -80,0 +86,0 @@ : '/base/test/' + path |
import {DomAssembly} from './assemblies/DomAssembly' | ||
import {expect} from 'chai' | ||
import {Query} from '../lib/Query' | ||
import {Query, Button as OriginalButton, MultiFinder} from '../lib/Query' | ||
@@ -8,2 +8,3 @@ describe('buttons', function () { | ||
let browser: Query | ||
let Button: MultiFinder | ||
@@ -13,2 +14,3 @@ beforeEach(function () { | ||
browser = assembly.browserMonkey() | ||
Button = OriginalButton.clone() | ||
}) | ||
@@ -23,3 +25,3 @@ | ||
const elements = browser.findButton(label).result() | ||
const elements = browser.find(Button(label)).result() | ||
const expected = assembly.find('.expected') | ||
@@ -33,3 +35,3 @@ expect(expected, 'no `.expected` element found').to.exist | ||
const elements = browser.findButton(label).result() | ||
const elements = browser.find(Button(label)).result() | ||
expect(elements).to.eql([]) | ||
@@ -52,2 +54,9 @@ } | ||
it('can recognise an input of type submit with exact value', function () { | ||
assertButtonFound( | ||
'<input type="submit" value="Login" class=expected />', | ||
'Login' | ||
) | ||
}) | ||
it('can recognise an input of type button with exact value', function () { | ||
@@ -105,3 +114,3 @@ assertButtonFound( | ||
it('can find a checkbox by its aria-label', () => { | ||
it('can find a checkbox by its aria-labelledby', () => { | ||
assertButtonFound( | ||
@@ -119,3 +128,3 @@ ` | ||
const elements = browser.findButton('Logi').result() | ||
const elements = browser.find(Button('Logi')).result() | ||
expect(elements).to.eql([]) | ||
@@ -127,3 +136,3 @@ }) | ||
const elements = browser.findButton('Login').result() | ||
const elements = browser.find(Button('Login')).result() | ||
expect(elements).to.eql([button]) | ||
@@ -135,3 +144,3 @@ }) | ||
const elements = browser.findButton('Logi').result() | ||
const elements = browser.find(Button('Logi')).result() | ||
expect(elements).to.eql([]) | ||
@@ -145,5 +154,5 @@ }) | ||
const query = browser.defineButtonFinder((query, name) => query.find('div.button').containing(name)) | ||
Button.addFinder((query, name) => query.find('div.button').containing(name)) | ||
const elements = query.findButton('Login').result() | ||
const elements = browser.find(Button('Login')).result() | ||
expect(elements).to.eql([button]) | ||
@@ -156,5 +165,5 @@ }) | ||
const query = browser.defineButtonFinder((query, name) => query.find('div.button').containing(name)) | ||
Button.addFinder((query, name) => query.find('div.button').containing(name)) | ||
const elements = query.findButton('Login').result() | ||
const elements = browser.find(Button('Login')).result() | ||
expect(elements).to.eql([button]) | ||
@@ -164,2 +173,18 @@ }) | ||
describe('removing button finders', function() { | ||
it('remove button finder no longer find buttons', function() { | ||
assembly.insertHtml('<div class="button">Login</div>') | ||
Button.addFinder('div.button', (query, name) => query.find('div.button').containing(name)) | ||
let elements = browser.find(Button('Login')).result() | ||
expect(elements.length).to.eql(1) | ||
Button.removeFinder('div.button') | ||
elements = browser.find(Button('Login')).result() | ||
expect(elements.length).to.eql(0) | ||
}) | ||
}) | ||
describe('clicking a button', () => { | ||
@@ -177,24 +202,24 @@ async function assertCanClickButton(html, action): Promise<void> { | ||
it('can click a button', async () => { | ||
await assertCanClickButton('<button class="target">Login</button>', () => browser.clickButton('Login')) | ||
await assertCanClickButton('<button class="target">Login</button>', () => browser.click(Button('Login'))) | ||
}) | ||
it('can find and click a button', async () => { | ||
await assertCanClickButton('<button class="target">Login</button>', () => browser.find('Button("Login")').click()) | ||
await assertCanClickButton('<button class="target">Login</button>', () => browser.find(Button("Login")).click()) | ||
}) | ||
it('can click a button with selector', async () => { | ||
await assertCanClickButton('<button class="target">Login</button>', () => browser.click('Button("Login")')) | ||
await assertCanClickButton('<button class="target">Login</button>', () => browser.click(Button("Login"))) | ||
}) | ||
it('can click a defined button', async () => { | ||
const query = browser.defineButtonFinder((query, name) => query.find('div.button').containing(name)) | ||
await assertCanClickButton('<div class="target button">Login</div>', () => query.click('Button("Login")')) | ||
Button.addFinder((query, name) => query.find('div.button').containing(name)) | ||
await assertCanClickButton('<div class="target button">Login</div>', () => browser.click(Button("Login"))) | ||
}) | ||
it('throws if the button cannot be found to click', async () => { | ||
const query = browser.defineButtonFinder((query, name) => query.find('div.button').containing(name)) | ||
Button.addFinder((query, name) => query.find('div.button').containing(name)) | ||
assembly.insertHtml('<button class="target">Login</button>') | ||
await assembly.assertRejection(query.clickButton('Logout'), "expected 1 element, found 0") | ||
await assembly.assertRejection(browser.click(Button('Logout')), "expected 1 element, found 0") | ||
}) | ||
}) | ||
}) |
import { expect } from 'chai' | ||
import { DomAssembly } from './assemblies/DomAssembly' | ||
import {Query} from '../lib/Query' | ||
import {Query, createFinder} from '../lib/Query' | ||
describe('define', function () { | ||
let assembly | ||
let browser: Query | ||
let query: Query | ||
beforeEach(function () { | ||
assembly = new DomAssembly() | ||
browser = assembly.browserMonkey() | ||
query = assembly.browserMonkey() | ||
}) | ||
@@ -19,17 +19,13 @@ | ||
it('can define a field', () => { | ||
browser.define('Hello', q => q.transform(() => 'hello')) | ||
assembly.insertHtml('<div class=hello>bye</div>') | ||
const Hello = createFinder(q => q.find('.hello')) | ||
expect(browser.find('Hello').result()).to.equal('hello') | ||
expect(query.find(Hello).result()).to.eql(assembly.findAll('.hello')) | ||
}) | ||
it('can define a field with arguments', () => { | ||
let args | ||
it('can define', () => { | ||
assembly.insertHtml('<div class=hello>bye</div>') | ||
const Hello = createFinder('.hello') | ||
browser.define('Hello', (q, arg1, arg2) => q.transform(() => { | ||
args = [arg1, arg2] | ||
return `hello ${arg1} ${arg2}` | ||
})) | ||
expect(browser.find('Hello("one", 2)').result()).to.equal('hello one 2') | ||
expect(args).to.eql(['one', 2]) | ||
expect(query.find(Hello).result()).to.eql(assembly.findAll('.hello')) | ||
}) | ||
@@ -42,7 +38,9 @@ | ||
`) | ||
browser.define('Flash', (q, flashType) => q.find(`.flash-${flashType}`)) | ||
const Flash = createFinder((q, flashType) => q.find(`.flash-${flashType}`)) | ||
await browser.shouldContain({ | ||
'Flash("success")': 'Success!', | ||
'Flash("alert")': /Fail/, | ||
const a = 'success' | ||
await query.shouldContain({ | ||
[Flash(a)]: 'Success!', | ||
[Flash("alert")]: /Fail/, | ||
}) | ||
@@ -52,10 +50,6 @@ }) | ||
describe('definition not found', () => { | ||
it('with arguments: throws an error if the definition is not found', () => { | ||
expect(() => browser.find('Hello("one", 2)')).to.throw('no such definition Hello') | ||
}) | ||
it('without arguments: assumes that it is CSS', () => { | ||
expect(() => browser.find('Hello').shouldExist().result()).to.throw("expected one or more elements, found 0 (found: find('Hello') [0])") | ||
expect(() => query.find('Hello').shouldExist().result()).to.throw("expected one or more elements, found 0 (found: find('Hello') [0])") | ||
}) | ||
}) | ||
}) |
@@ -95,27 +95,55 @@ import {DomAssembly} from './assemblies/DomAssembly' | ||
describe('innerText', () => { | ||
it('normalises innerText removing extra spaces at the end of lines', () => { | ||
const element = assembly.insertHtml(` | ||
<div> | ||
first | ||
line | ||
<br/> | ||
second | ||
line | ||
</div> | ||
`) | ||
if (DomAssembly.domHasInnerText) { | ||
describe('innerText', () => { | ||
it('normalises innerText removing extra spaces at the end of lines', () => { | ||
const element = assembly.insertHtml(` | ||
<div> | ||
first | ||
line | ||
<br/> | ||
second | ||
line | ||
</div> | ||
`) | ||
expect(assembly.dom.elementInnerText(element)).to.equal('first line\nsecond line') | ||
expect(assembly.dom.elementInnerText(element)).to.equal('first line\nsecond line') | ||
}) | ||
it('normalises innerText removing extra spaces between words', () => { | ||
const element = assembly.insertHtml(` | ||
<div> | ||
two words | ||
</div> | ||
`) | ||
expect(assembly.dom.elementInnerText(element)).to.equal('two words') | ||
}) | ||
}) | ||
} else { | ||
describe('innerText', () => { | ||
it('normalises innerText removing extra spaces at the end of lines', () => { | ||
const element = assembly.insertHtml(` | ||
<div> | ||
first | ||
line | ||
<br/> | ||
second | ||
line | ||
</div> | ||
`) | ||
it('normalises innerText removing extra spaces between words', () => { | ||
const element = assembly.insertHtml(` | ||
<div> | ||
two words | ||
</div> | ||
`) | ||
expect(assembly.dom.elementInnerText(element)).to.equal('first\nline\n\nsecond\nline') | ||
}) | ||
expect(assembly.dom.elementInnerText(element)).to.equal('two words') | ||
it('normalises innerText removing extra spaces between words', () => { | ||
const element = assembly.insertHtml(` | ||
<div> | ||
two words | ||
</div> | ||
`) | ||
expect(assembly.dom.elementInnerText(element)).to.equal('two words') | ||
}) | ||
}) | ||
}) | ||
} | ||
@@ -438,45 +466,47 @@ describe('clicking', () => { | ||
describe('visibility', () => { | ||
it('when element is visible it returns true', () => { | ||
const element = assembly.insertHtml('<div>hi</div>') | ||
if (DomAssembly.domHasVisibility) { | ||
describe('visibility', () => { | ||
it('when element is visible it returns true', () => { | ||
const element = assembly.insertHtml('<div>hi</div>') | ||
expect(assembly.dom.elementVisible(element)).to.equal(true) | ||
}) | ||
expect(assembly.dom.elementVisible(element)).to.equal(true) | ||
}) | ||
it('when element is visible but empty returns true', () => { | ||
const element = assembly.insertHtml('<div></div>') | ||
it('when element is visible but empty returns true', () => { | ||
const element = assembly.insertHtml('<div></div>') | ||
expect(assembly.dom.elementVisible(element)).to.equal(true) | ||
}) | ||
expect(assembly.dom.elementVisible(element)).to.equal(true) | ||
}) | ||
it('when element is display:none it returns false', () => { | ||
const element = assembly.insertHtml('<div style="display: none">hi</div>') | ||
it('when element is display:none it returns false', () => { | ||
const element = assembly.insertHtml('<div style="display: none">hi</div>') | ||
expect(assembly.dom.elementVisible(element)).to.equal(false) | ||
}) | ||
expect(assembly.dom.elementVisible(element)).to.equal(false) | ||
}) | ||
it('when element is visible but parent is not', () => { | ||
assembly.insertHtml('<div style="display: none"><div id="child">hi</div></div>') | ||
it('when element is visible but parent is not', () => { | ||
assembly.insertHtml('<div style="display: none"><div id="child">hi</div></div>') | ||
const element = assembly.find('#child') | ||
const element = assembly.find('#child') | ||
expect(assembly.dom.elementVisible(element)).to.equal(false) | ||
}) | ||
expect(assembly.dom.elementVisible(element)).to.equal(false) | ||
}) | ||
it('when element is option and select is visible, returns true', () => { | ||
assembly.insertHtml('<select><option id="option">1</option><select>') | ||
it('when element is option and select is visible, returns true', () => { | ||
assembly.insertHtml('<select><option id="option">1</option><select>') | ||
const element = assembly.find('#option') | ||
const element = assembly.find('#option') | ||
expect(assembly.dom.elementVisible(element)).to.equal(true) | ||
}) | ||
expect(assembly.dom.elementVisible(element)).to.equal(true) | ||
}) | ||
it('when element is option and select is not visible, returns false', () => { | ||
assembly.insertHtml('<select style="display: none"><option id="option">1</option><select>') | ||
it('when element is option and select is not visible, returns false', () => { | ||
assembly.insertHtml('<select style="display: none"><option id="option">1</option><select>') | ||
const element = assembly.find('#option') | ||
const element = assembly.find('#option') | ||
expect(assembly.dom.elementVisible(element)).to.equal(false) | ||
expect(assembly.dom.elementVisible(element)).to.equal(false) | ||
}) | ||
}) | ||
}) | ||
} | ||
@@ -483,0 +513,0 @@ describe('matches', function () { |
@@ -51,3 +51,5 @@ import {DomAssembly} from './assemblies/DomAssembly' | ||
function assertBrowserHasFocus (): void { | ||
expect(document.hasFocus(), 'the browser must be in focus for this test!').to.equal(true) | ||
if (DomAssembly.domCanHaveFocus) { | ||
expect(document.hasFocus(), 'the browser must be in focus for this test!').to.equal(true) | ||
} | ||
} | ||
@@ -54,0 +56,0 @@ |
import {DomAssembly} from './assemblies/DomAssembly' | ||
import {expect} from 'chai' | ||
import {Query} from '../lib/Query' | ||
import {Query, Field as OriginalField} from '../lib/Query' | ||
@@ -8,2 +8,3 @@ describe('labels', function () { | ||
let browser: Query | ||
let Field | ||
@@ -13,2 +14,3 @@ beforeEach(function () { | ||
browser = assembly.browserMonkey() | ||
Field = OriginalField.clone() | ||
}) | ||
@@ -47,3 +49,3 @@ | ||
`, | ||
'Field("Feature Enabled")' | ||
Field("Feature Enabled") | ||
) | ||
@@ -61,3 +63,3 @@ }) | ||
`, | ||
'Field("Feature Enabled")' | ||
Field("Feature Enabled") | ||
) | ||
@@ -80,3 +82,3 @@ }) | ||
`, | ||
'Field(/Favourite Colour/)' | ||
Field(/Favourite Colour/) | ||
) | ||
@@ -94,3 +96,3 @@ }) | ||
`, | ||
'Field("Feature Enabled")' | ||
Field("Feature Enabled") | ||
) | ||
@@ -108,3 +110,3 @@ }) | ||
`, | ||
'Field("Feature Enabled")' | ||
Field("Feature Enabled") | ||
) | ||
@@ -122,3 +124,3 @@ }) | ||
`, | ||
'Field("Feature")' | ||
Field("Feature") | ||
) | ||
@@ -136,3 +138,3 @@ }) | ||
`, | ||
'Field(/Feature/)' | ||
Field(/Feature/) | ||
) | ||
@@ -149,3 +151,3 @@ }) | ||
`, | ||
'Field("Search")' | ||
Field("Search") | ||
) | ||
@@ -160,3 +162,3 @@ }) | ||
`, | ||
'Field(/sea/i)' | ||
Field(/sea/i) | ||
) | ||
@@ -171,3 +173,3 @@ }) | ||
`, | ||
'Field("Search")' | ||
Field("Search") | ||
) | ||
@@ -183,3 +185,3 @@ }) | ||
`, | ||
'Field("Search")' | ||
Field("Search") | ||
) | ||
@@ -195,3 +197,3 @@ }) | ||
`, | ||
'Field(/sea/i)' | ||
Field(/sea/i) | ||
) | ||
@@ -207,3 +209,3 @@ }) | ||
`, | ||
'Field("Search")' | ||
Field("Search") | ||
) | ||
@@ -219,3 +221,3 @@ }) | ||
`, | ||
'Field("Search")' | ||
Field("Search") | ||
) | ||
@@ -232,3 +234,3 @@ }) | ||
`, | ||
'Field("Search")' | ||
Field("Search") | ||
) | ||
@@ -243,3 +245,3 @@ }) | ||
`, | ||
'Field(/sea/i)' | ||
Field(/sea/i) | ||
) | ||
@@ -265,3 +267,3 @@ }) | ||
const found = browser.find('Field("Feature Enabled")').result() | ||
const found = browser.find(Field("Feature Enabled")).result() | ||
@@ -273,10 +275,12 @@ expect(found).to.eql(expected) | ||
it('can define a new way of finding labels', () => { | ||
const query = browser.defineFieldFinder((query, label) => query.findCss(`[data-label=${JSON.stringify(label)}]`)) | ||
Field.addFinder((query, label) => ( | ||
query.find(`[data-label=${JSON.stringify(label)}]`) | ||
)) | ||
assertFoundElementByLabel( | ||
query, | ||
browser, | ||
` | ||
<div class="result" data-label="Search"/> | ||
`, | ||
'Field("Search")' | ||
Field("Search") | ||
) | ||
@@ -286,21 +290,21 @@ }) | ||
it('can add and remove a label definition by name', async () => { | ||
const query = browser.defineFieldFinder('data-label', (query, label) => query.findCss(`[data-label=${JSON.stringify(label)}]`)) | ||
Field.addFinder('data-label', (query, label) => query.findCss(`[data-label=${JSON.stringify(label)}]`)) | ||
assertFoundElementByLabel( | ||
query, | ||
browser, | ||
` | ||
<div class="result" data-label="Search"/> | ||
`, | ||
'Field("Search")' | ||
Field("Search") | ||
) | ||
const without = query.undefineFieldFinder('data-label') | ||
Field.removeFinder('data-label') | ||
await without.find('Field("Search")').shouldNotExist().result() | ||
await browser.find(Field("Search")).shouldNotExist().result() | ||
}) | ||
it("throws if we try to undefine a label that doesn't exist", async () => { | ||
expect(() => browser.undefineFieldFinder('data-label')).to.throw("doesn't exist") | ||
expect(() => Field.removeFinder('data-label')).to.throw("doesn't exist") | ||
}) | ||
}) | ||
}) |
import {DomAssembly} from './assemblies/DomAssembly' | ||
import {expect} from 'chai' | ||
import { Query } from '../lib/Query' | ||
import { Query, Button } from '../lib/Query' | ||
@@ -121,33 +121,38 @@ describe('find', () => { | ||
describe('iframes', () => { | ||
it('can search into iframes', async () => { | ||
const iframe = browser.iframe('iframe') | ||
if (DomAssembly.domCanLoadIFrames) { | ||
describe('iframes', () => { | ||
it('can search into iframes', async () => { | ||
const iframe = browser.iframe('iframe') | ||
assembly.useNormalRetry() | ||
assembly.eventuallyInsertHtml(`<iframe src="${DomAssembly.localUrl('page1.html')}"/>`) | ||
assembly.useNormalRetry() | ||
assembly.eventuallyInsertHtml(`<iframe src="${DomAssembly.localUrl('page1.html')}"/>`) | ||
await iframe.clickButton('page 2') | ||
await iframe.shouldContain({h1: 'Page 2'}) | ||
await iframe.click(Button('page 2')) | ||
await iframe.shouldContain({h1: 'Page 2'}) | ||
}) | ||
}) | ||
}) | ||
} | ||
describe('visibility', () => { | ||
it('should not find an element that is visually hidden', () => { | ||
assembly.insertHtml('<div class="element">hello <span style="display:none;">world</span></div>') | ||
if (DomAssembly.domHasVisibility) { | ||
describe('visibility', () => { | ||
it('should not find an element that is visually hidden', () => { | ||
assembly.insertHtml('<div class="element">hello <span style="display:none;">world</span></div>') | ||
return browser.find('.element > span').shouldNotExist() | ||
}) | ||
return browser.find('.element > span').shouldNotExist() | ||
}) | ||
it('should find an element that is visually hidden when visibleOnly = false', () => { | ||
assembly.insertHtml('<div class="element">hello <span style="display:none;">world</span></div>') | ||
it('should find an element that is visually hidden when visibleOnly = false', () => { | ||
assembly.insertHtml('<div class="element">hello <span style="display:none;">world</span></div>') | ||
return browser.options({ visibleOnly: false }).find('.element > span').shouldExist() | ||
}) | ||
browser.setOptions({ visibleOnly: false }) | ||
return browser.find('.element > span').shouldExist() | ||
}) | ||
it('should find elements that are visually hidden because of how html renders them', () => { | ||
assembly.insertHtml('<select><option>First</option><option>Second</option></select>') | ||
it('should find elements that are visually hidden because of how html renders them', () => { | ||
assembly.insertHtml('<select><option>First</option><option>Second</option></select>') | ||
return browser.find('select option').shouldContain(['First', 'Second']) | ||
return browser.find('select option').shouldContain(['First', 'Second']) | ||
}) | ||
}) | ||
}) | ||
} | ||
}) |
import {expect} from 'chai' | ||
import {DomAssembly} from './assemblies/DomAssembly' | ||
import {Query} from '../lib/Query' | ||
import Dom from '../lib/Dom' | ||
@@ -8,2 +9,3 @@ describe('query', () => { | ||
let browser: Query | ||
let dom: Dom | ||
@@ -13,2 +15,3 @@ beforeEach(() => { | ||
browser = assembly.browserMonkey() | ||
dom = new Dom() | ||
}) | ||
@@ -35,7 +38,10 @@ | ||
it('returns a new Browser Monkey object without modifying the current one', () => { | ||
expect(browser.options({timeout: 400}).getOptions().timeout).to.equal(400) | ||
browser.setOptions({timeout: 400}) | ||
expect(browser.getOptions().timeout).to.equal(400) | ||
}) | ||
it('overrides previously set option', () => { | ||
expect(browser.options({timeout: 400}).options({timeout: 4000}).getOptions().timeout).to.equal(4000) | ||
browser.setOptions({timeout: 400}) | ||
browser.setOptions({timeout: 4000}) | ||
expect(browser.getOptions().timeout).to.equal(4000) | ||
}) | ||
@@ -267,24 +273,31 @@ }) | ||
// transform() has been moved to private | ||
// describe('input', () => { | ||
// it('input sets the input used in transform', async () => { | ||
// const query = browser | ||
// .input('a') | ||
// .transform(x => `input: ${x}`) | ||
// expect(query.result()).to.eql('input: a') | ||
// }) | ||
// }) | ||
describe('input', () => { | ||
it('input sets the input used in transform', async () => { | ||
const query = browser | ||
.input('a') | ||
.transform(x => `input: ${x}`) | ||
it('when input is one element, sets the input to an array of one', () => { | ||
browser.setInput(document.body) | ||
expect(query.result()).to.eql('input: a') | ||
expect(browser.input()).to.eql([document.body]) | ||
}) | ||
}) | ||
describe('scope', () => { | ||
it('when scope is one element, sets the input to an array of one', () => { | ||
const query = browser | ||
.scope(document.body) | ||
it('when input is an array of elements, sets the input to that array', () => { | ||
const array = [document.body] | ||
browser.setInput(array) | ||
expect(query.getInput()).to.eql([document.body]) | ||
expect(browser.input()).to.eq(array) | ||
}) | ||
it('scope can be passed in to constructor', () => { | ||
it('input can be passed in to constructor', () => { | ||
const query = new Query(document.body) | ||
expect(query.getInput()).to.eql([document.body]) | ||
expect(query.input()).to.eql([document.body]) | ||
}) | ||
@@ -297,3 +310,3 @@ }) | ||
.expect(elements => { | ||
expect(elements.some(element => element.innerText.includes('hello'))).to.equal(true) | ||
expect(elements.some(element => dom.elementInnerText(element).includes('hello'))).to.equal(true) | ||
}) | ||
@@ -312,3 +325,3 @@ .then() | ||
.expect(elements => { | ||
expect(elements.some(element => element.innerText.includes('hello')), 'expected to see hello').to.equal(true) | ||
expect(elements.some(element => dom.elementInnerText(element).includes('hello')), 'expected to see hello').to.equal(true) | ||
}) | ||
@@ -325,20 +338,21 @@ .then() | ||
describe('transform', () => { | ||
it('can map all the elements', async () => { | ||
const contacts = browser | ||
.find('.name') | ||
.transform(names => { | ||
return names.map(contact => contact.innerText).join(', ') | ||
}) | ||
.expect(x => expect(x).to.not.be.empty) | ||
.then() | ||
// Moved to private | ||
// describe('transform', () => { | ||
// it('can map all the elements', async () => { | ||
// const contacts = browser | ||
// .find('.name') | ||
// .transform(names => { | ||
// return names.map(contact => contact.innerText).join(', ') | ||
// }) | ||
// .expect(x => expect(x).to.not.be.empty) | ||
// .then() | ||
assembly.eventuallyInsertHtml(` | ||
<div class="name">Sally</div> | ||
<div class="name">Bob</div> | ||
`) | ||
// assembly.eventuallyInsertHtml(` | ||
// <div class="name">Sally</div> | ||
// <div class="name">Bob</div> | ||
// `) | ||
expect(await contacts).to.eql('Sally, Bob') | ||
}) | ||
}) | ||
// expect(await contacts).to.eql('Sally, Bob') | ||
// }) | ||
// }) | ||
@@ -350,3 +364,3 @@ describe('filter', () => { | ||
.filter(contact => { | ||
return (contact.querySelector('.name') as HTMLElement).innerText === 'Sally' | ||
return dom.elementInnerText(contact.querySelector('.name') as HTMLElement) === 'Sally' | ||
}) | ||
@@ -371,64 +385,62 @@ .shouldHaveElements(1) | ||
// `map` has been moved to private | ||
// describe('map', () => { | ||
// it('can map elements', async () => { | ||
// const contacts = browser | ||
// .find('.contact') | ||
// .map(contact => { | ||
// return contact.querySelector('.name') | ||
// }) | ||
// .shouldExist() | ||
// .then() | ||
describe('map', () => { | ||
it('can map elements', async () => { | ||
const contacts = browser | ||
.find('.contact') | ||
.map(e => e.querySelector('.name')) | ||
.shouldExist() | ||
.then() | ||
// assembly.eventuallyInsertHtml(` | ||
// <div class="contact"> | ||
// <div class="name">Sally</div> | ||
// <div class="address">32 Yellow Drive</div> | ||
// </div> | ||
// <div class="contact"> | ||
// <div class="name">Bob</div> | ||
// <div class="address">32 Red Drive</div> | ||
// </div> | ||
// `) | ||
assembly.eventuallyInsertHtml(` | ||
<div class="contact"> | ||
<div class="name">Sally</div> | ||
<div class="address">32 Yellow Drive</div> | ||
</div> | ||
<div class="contact"> | ||
<div class="name">Bob</div> | ||
<div class="address">32 Red Drive</div> | ||
</div> | ||
`) | ||
// expect(await contacts).to.eql(assembly.findAll('.name')) | ||
// }) | ||
// }) | ||
expect(await contacts).to.eql(assembly.findAll('.name')) | ||
}) | ||
}) | ||
describe('actions', () => { | ||
it('actions are only executed once', async () => { | ||
let actionExecuted = 0 | ||
// Moved to private | ||
// describe('actions', () => { | ||
// it('actions are only executed once', async () => { | ||
// let actionExecuted = 0 | ||
assembly.insertHtml(` | ||
<div>A</div> | ||
`) | ||
// assembly.insertHtml(` | ||
// <div>A</div> | ||
// `) | ||
const action = browser.find('div').action(function () { | ||
actionExecuted++ | ||
}) | ||
// const action = browser.find('div').action(function () { | ||
// actionExecuted++ | ||
// }) | ||
await action | ||
expect(actionExecuted).to.equal(1) | ||
await action | ||
expect(actionExecuted).to.equal(1) | ||
}) | ||
// await action | ||
// expect(actionExecuted).to.equal(1) | ||
// await action | ||
// expect(actionExecuted).to.equal(1) | ||
// }) | ||
it('actions return the element or elements they acted on', async () => { | ||
const divA = assembly.insertHtml(` | ||
<div>A</div> | ||
`) | ||
const divB = assembly.insertHtml(` | ||
<div>B</div> | ||
`) | ||
// it('actions return the element or elements they acted on', async () => { | ||
// const divA = assembly.insertHtml(` | ||
// <div>A</div> | ||
// `) | ||
// const divB = assembly.insertHtml(` | ||
// <div>B</div> | ||
// `) | ||
let givenElements | ||
const action = browser.find('div').action(function (els) { | ||
givenElements = els | ||
}) | ||
// let givenElements | ||
// const action = browser.find('div').action(function (els) { | ||
// givenElements = els | ||
// }) | ||
const elements = await action | ||
expect(elements).to.eql([divA, divB]) | ||
expect(givenElements).to.eql([divA, divB]) | ||
}) | ||
}) | ||
// const elements = await action | ||
// expect(elements).to.eql([divA, divB]) | ||
// expect(givenElements).to.eql([divA, divB]) | ||
// }) | ||
// }) | ||
@@ -435,0 +447,0 @@ describe('errors', () => { |
import {DomAssembly} from './assemblies/DomAssembly' | ||
import Dom from '../lib/Dom' | ||
import {expect} from 'chai' | ||
import {Query} from '../lib/Query' | ||
import {Query, createFinder} from '../lib/Query' | ||
@@ -8,5 +9,7 @@ describe('set', function () { | ||
let browser: Query | ||
let dom: Dom | ||
beforeEach(function () { | ||
assembly = new DomAssembly() | ||
dom = new Dom() | ||
browser = assembly.browserMonkey() | ||
@@ -45,3 +48,3 @@ }) | ||
const selectedItem = assembly.find('select').selectedOptions[0] | ||
expect(selectedItem.innerText).to.equal('Two') | ||
expect(dom.elementInnerText(selectedItem)).to.equal('Two') | ||
}) | ||
@@ -62,3 +65,3 @@ | ||
const selectedItem = assembly.find('select').selectedOptions[0] | ||
expect(selectedItem.innerText).to.equal('Two') | ||
expect(dom.elementInnerText(selectedItem)).to.equal('Two') | ||
}) | ||
@@ -307,7 +310,7 @@ | ||
'.street': streetQuery => { | ||
streetQuery.shouldHaveElements(1).result()[0].innerText = 'hi' | ||
streetQuery.shouldHaveElements(1).result()[0].innerHTML = 'hi' | ||
} | ||
}) | ||
expect(assembly.find('.street').innerText).to.equal('hi') | ||
expect(dom.elementInnerText(assembly.find('.street'))).to.equal('hi') | ||
}) | ||
@@ -355,3 +358,3 @@ }) | ||
const selectedItem = assembly.find('select').selectedOptions[0] | ||
expect(selectedItem.innerText).to.equal('Three') | ||
expect(dom.elementInnerText(selectedItem)).to.equal('Three') | ||
}) | ||
@@ -369,8 +372,8 @@ }) | ||
browser.define('phone', b => b.find('.phone')) | ||
browser.define('firstName', b => b.find('.first-name')) | ||
const phone = createFinder('.phone') | ||
const firstName = createFinder('.first-name') | ||
await browser.set({ | ||
phone: '123123123', | ||
firstName: 'Barry' | ||
[phone]: '123123123', | ||
[firstName]: 'Barry' | ||
}) | ||
@@ -390,7 +393,7 @@ | ||
browser.define('form', (b, name) => b.find('* [name=' + JSON.stringify(name) + ']')) | ||
const form = createFinder((b, name) => b.find('* [name=' + JSON.stringify(name) + ']')) | ||
await browser.set({ | ||
'form("phone")': '123123123', | ||
'form("firstname")': 'Barry' | ||
[form("phone")]: '123123123', | ||
[form("firstname")]: 'Barry' | ||
}) | ||
@@ -397,0 +400,0 @@ |
import {DomAssembly} from './assemblies/DomAssembly' | ||
import {Query} from '../lib/Query' | ||
import {Query, Button} from '../lib/Query' | ||
describe('buttons', function () { | ||
describe('shouldAppearAfter shouldDisappearAfter', function () { | ||
let assembly | ||
@@ -25,3 +25,3 @@ let browser: Query | ||
await browser.find('.element').shouldAppearAfter(() => browser.clickButton('Show')) | ||
await browser.find('.element').shouldAppearAfter(() => browser.click(Button('Show'))) | ||
}) | ||
@@ -35,3 +35,3 @@ | ||
await assembly.assertRejection( | ||
browser.find('.element').shouldAppearAfter(() => browser.clickButton('Show')), | ||
browser.find('.element').shouldAppearAfter(() => browser.click(Button('Show'))), | ||
'expected one or more elements, found 0' | ||
@@ -47,3 +47,3 @@ ) | ||
await assembly.assertRejection( | ||
browser.find('.element').shouldAppearAfter(() => browser.clickButton('Show')), | ||
browser.find('.element').shouldAppearAfter(() => browser.click(Button('Show'))), | ||
'expected no elements' | ||
@@ -65,3 +65,3 @@ ) | ||
await browser.find('.element').shouldDisappearAfter(() => browser.clickButton('Show')) | ||
await browser.find('.element').shouldDisappearAfter(() => browser.click(Button('Show'))) | ||
}) | ||
@@ -76,3 +76,3 @@ | ||
await assembly.assertRejection( | ||
browser.find('.element').shouldDisappearAfter(() => browser.clickButton('Show')), | ||
browser.find('.element').shouldDisappearAfter(() => browser.click(Button('Show'))), | ||
'expected no elements, found 1' | ||
@@ -87,3 +87,3 @@ ) | ||
await assembly.assertRejection( | ||
browser.find('.element').shouldDisappearAfter(() => browser.clickButton('Show')), | ||
browser.find('.element').shouldDisappearAfter(() => browser.click(Button('Show'))), | ||
'expected one or more elements, found 0' | ||
@@ -90,0 +90,0 @@ ) |
import {DomAssembly} from './assemblies/DomAssembly' | ||
import BrowserMonkeyAssertionError from '../lib/BrowserMonkeyAssertionError' | ||
import {elementAttributes} from '../lib/matchers' | ||
import {Query} from '../lib/Query' | ||
import {Query, createFinder} from '../lib/Query' | ||
import Dom from '../lib/Dom' | ||
@@ -9,2 +10,3 @@ describe('shouldContain', function () { | ||
let browser: Query | ||
let dom: Dom | ||
@@ -14,2 +16,3 @@ beforeEach(function () { | ||
browser = assembly.browserMonkey() | ||
dom = new Dom() | ||
}) | ||
@@ -450,3 +453,3 @@ | ||
'.content': query => { | ||
if (!/Content/.test(query.elementResult().innerText)) { | ||
if (!/Content/.test(dom.elementInnerText(query.elementResult()))) { | ||
throw new BrowserMonkeyAssertionError('asdf') | ||
@@ -469,3 +472,3 @@ } | ||
'.content': query => { | ||
if (/Content/.test(query.elementResult().innerText)) { | ||
if (/Content/.test(dom.elementInnerText(query.elementResult()))) { | ||
throw new BrowserMonkeyAssertionError('asdf', {actual: 'error actual', expected: 'error expected'}) | ||
@@ -599,6 +602,6 @@ } | ||
browser.define('Header', q => q.find('h1')) | ||
const Header = createFinder(q => q.find('h1')) | ||
await browser.shouldContain({ | ||
Header: 'Title', | ||
[Header]: 'Title', | ||
'.content': 'The Content' | ||
@@ -616,6 +619,6 @@ }) | ||
browser.define('Header', 'h1') | ||
const Header = createFinder('h1') | ||
await browser.shouldContain({ | ||
Header: 'Title', | ||
[Header]: 'Title', | ||
'.content': 'The Content' | ||
@@ -625,21 +628,2 @@ }) | ||
it('can define a several fields using an object', async () => { | ||
assembly.insertHtml(` | ||
<div> | ||
<h1>Title</h1> | ||
<div class="content">The Content</div> | ||
</div> | ||
`) | ||
browser.define({ | ||
Header: 'h1', | ||
Content: q => q.find('.content'), | ||
}) | ||
await browser.shouldContain({ | ||
Header: 'Title', | ||
Content: 'The Content' | ||
}) | ||
}) | ||
it('can define a section by its contents', async () => { | ||
@@ -657,3 +641,3 @@ assembly.insertHtml(` | ||
browser.define('Section', (query, value) => { | ||
const Section = createFinder((query, value) => { | ||
return query.find('section').containing({h1: value}) | ||
@@ -663,3 +647,3 @@ }) | ||
await browser.shouldContain({ | ||
'Section(/S.* A/)': { | ||
[Section(/S.* A/)]: { | ||
'.content': 'Section A Content' | ||
@@ -669,33 +653,3 @@ } | ||
}) | ||
it('can define a several hierarchical fields using finders', async () => { | ||
assembly.insertHtml(` | ||
<div> | ||
<h1>Title</h1> | ||
<div class="content"> | ||
<div class="title">title</div> | ||
<div class="body"> | ||
body | ||
</div> | ||
</div> | ||
</div> | ||
`) | ||
browser.define({ | ||
Title: 'h1', | ||
Content: q => q.find('.content').define({ | ||
Title: '.title', | ||
Body: '.body' | ||
}), | ||
}) | ||
await browser.shouldContain({ | ||
Title: 'Title', | ||
Content: { | ||
Title: 'title', | ||
Body: 'body' | ||
} | ||
}) | ||
}) | ||
}) | ||
}) |
import {DomAssembly} from './assemblies/DomAssembly' | ||
import {expect} from 'chai' | ||
import {Query} from '../lib/Query' | ||
import {Query, Button} from '../lib/Query' | ||
@@ -75,3 +75,3 @@ describe('submit', function () { | ||
`, | ||
() => browser.clickButton('ok') | ||
() => browser.click(Button('ok')) | ||
) | ||
@@ -98,3 +98,3 @@ }) | ||
`, | ||
() => browser.clickButton('ok') | ||
() => browser.click(Button('ok')) | ||
) | ||
@@ -101,0 +101,0 @@ }) |
@@ -11,3 +11,4 @@ import {expect} from 'chai' | ||
assembly = new DomAssembly() | ||
browser = assembly.browserMonkey().scope(document.body) | ||
browser = assembly.browserMonkey() | ||
browser.setInput(document.body) | ||
}) | ||
@@ -14,0 +15,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
382596
140
8071
0
46
+ Addedobject-inspect@1.10.3(transitive)
- Removedobject-inspect@1.8.0(transitive)
Updateddebug@^4.3.1
Updatediframe-resizer@^4.3.2
Updatedobject-inspect@1.10.3
Updatedtypescript@^4.3.2