Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

browser-monkey

Package Overview
Dependencies
Maintainers
3
Versions
87
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

browser-monkey - npm Package Compare versions

Comparing version 3.0.0-beta.11 to 3.0.0-beta.12

dist/lib/Button.js

5

dist/index.js

@@ -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;

2

dist/lib/BrowserMonkeyAssertionError.js

@@ -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
})()

@@ -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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc