browser-monkey
Advanced tools
Comparing version 3.0.0-beta.3 to 3.0.0-beta.4
@@ -10,2 +10,4 @@ import { ExecutedTransform } from './ExecutedTransform' | ||
public executedTransforms: ExecutedTransformPath | ||
public duration: number | ||
public retries: number | ||
@@ -43,3 +45,7 @@ public constructor (message, { | ||
public renderError (): string { | ||
return `${this.description}${this.executedTransforms.transforms.length ? ` (found: ${this.executedTransforms.renderError()})`: ''}` | ||
const stats = this.duration !== undefined && this.retries !== undefined | ||
? ` [waited ${this.duration}ms, retried ${this.retries} times]` | ||
: '' | ||
return `${this.description}${stats}${this.executedTransforms.transforms.length ? ` (found: ${this.executedTransforms.renderError()})`: ''}` | ||
} | ||
@@ -46,0 +52,0 @@ } |
import { ExecutedTransform } from './ExecutedTransform' | ||
import inspect from 'object-inspect' | ||
export class ExecutedContainingTransform extends ExecutedTransform { | ||
public model: any | ||
public failingActuals: any[] | ||
public constructor (value: any, model: any) { | ||
public constructor (value: any, model: any, failingActuals: any[]) { | ||
super(value) | ||
this.model = model | ||
this.failingActuals = failingActuals | ||
} | ||
public renderError (): string { | ||
return `containing(${this.model ? '...' + this.model.renderError() : ''}) [${this.value.length}]` | ||
return `containing(${this.failingActuals ? inspect({expected: this.model, actual: this.failingActuals}) : inspect(this.model)}) [${this.value.length}]` | ||
} | ||
} |
const settable = | ||
'input:not([type]), ' + | ||
'input[type=text], ' + | ||
'input[type=hidden], ' + | ||
'input[type=email], ' + | ||
@@ -5,0 +6,0 @@ 'input[type=password], ' + |
421
lib/Query.ts
@@ -12,12 +12,12 @@ import { ExecutedTransform } from './ExecutedTransform' | ||
import toExecutedTransform from './toExecutedTransform' | ||
const pluralize = require('pluralize') | ||
const extend = require('lowscore/extend') | ||
import pluralize from 'pluralize' | ||
import extend from 'lowscore/extend' | ||
import retry from './retry' | ||
const inspect = require('object-inspect') | ||
const uniq = require('lowscore/uniq') | ||
import inspect from 'object-inspect' | ||
import uniq from 'lowscore/uniq' | ||
const debug = require('debug')('browser-monkey') | ||
const inputSelectors = require('./inputSelectors') | ||
const object = require('lowscore/object') | ||
const range = require('lowscore/range') | ||
const flatten = require('lowscore/flatten') | ||
import inputSelectors from './inputSelectors' | ||
import object from 'lowscore/object' | ||
import range from 'lowscore/range' | ||
import flatten from 'lowscore/flatten' | ||
import {match} from './match' | ||
@@ -28,18 +28,24 @@ import * as matchers from './matchers' | ||
type Action = (elements: any, executedTransforms: ExecutedTransform[]) => void | ||
interface FieldType { | ||
value?: (query: Query) => Query | ||
interface InputDefinition { | ||
values?: (query: Query) => Query | ||
setter?: (query: Query, value: any) => Query | ||
valueAsserter?: (query: Query, expected: any) => Query | ||
valueAsserters?: (query: Query, expected: any) => Query | ||
} | ||
type LabelName = string | RegExp | ||
type LabelDefinition = <Q extends Query>(query: Q, name: LabelName) => Q | ||
type FieldDefinition = <Q extends Query>(query: Q, ...any) => Q | ||
type Match = { | ||
isMatch: boolean, | ||
actual: any, | ||
expected: any, | ||
} | ||
type FieldName = string | RegExp | ||
type FieldFinderDefinition = <Q extends Query>(query: Q, name: FieldName) => Q | ||
type FinderDefinition = <Q extends Query>(query: Q, ...any) => Q | ||
interface Definitions { | ||
fieldTypes: FieldType[] | ||
button: LabelDefinition[] | ||
label: ({name: string, definition: LabelDefinition})[] | ||
fields: { | ||
[key: string]: FieldDefinition | ||
inputs: InputDefinition[] | ||
buttons: FieldFinderDefinition[] | ||
fields: ({name: string, definition: FieldFinderDefinition})[] | ||
finders: { | ||
[key: string]: FinderDefinition | ||
} | ||
@@ -67,3 +73,3 @@ } | ||
definitions: { | ||
fieldTypes: [ | ||
inputs: [ | ||
{ | ||
@@ -73,3 +79,3 @@ setter: (query, value) => { | ||
.is('input[type=checkbox]') | ||
.expectOneElement() | ||
.shouldHaveElements(1) | ||
.transform(([checkbox]) => { | ||
@@ -87,7 +93,6 @@ if (typeof value !== 'boolean') { | ||
}, | ||
value: (query) => { | ||
values: (query) => { | ||
return query | ||
.is('input[type=checkbox]') | ||
.expectOneElement() | ||
.transform(([checkbox]) => { | ||
.map((checkbox) => { | ||
return query._dom.checked(checkbox) | ||
@@ -101,3 +106,3 @@ }) | ||
.is('select') | ||
.expectOneElement('expected to be select element') | ||
.shouldHaveElements(1, 'expected to be select element') | ||
.findCss('option') | ||
@@ -107,3 +112,3 @@ .filter(o => { | ||
}, `option with text or value ${JSON.stringify(value)}`) | ||
.expectOneElement(`expected one option element with text or value ${JSON.stringify(value)}`) | ||
.shouldHaveElements(1, `expected one option element with text or value ${JSON.stringify(value)}`) | ||
.transform(([option]) => { | ||
@@ -117,12 +122,13 @@ return () => { | ||
}, | ||
valueAsserter: (query, expected) => { | ||
valueAsserters: (query, expected) => { | ||
return query | ||
.is('select') | ||
.expectOneElement('expected to be select element') | ||
.transform(([select]) => { | ||
.map((select) => { | ||
return () => { | ||
const value = select.value | ||
if (match(expected, value).isMatch) { | ||
return | ||
const matchValue = match(expected, value) | ||
if (matchValue.isMatch) { | ||
return matchValue | ||
} | ||
@@ -133,18 +139,27 @@ | ||
const actual = query._dom.elementInnerText(selectedOption) | ||
if (match(expected, actual).isMatch) { | ||
return | ||
const matchText = match(expected, actual) | ||
if (matchText.isMatch) { | ||
return matchText | ||
} else { | ||
this.error('expected ' + inspect(actual) + ' or ' + inspect(value) + ' to equal ' + inspect(expected), { actual, expected }) | ||
return { | ||
isMatch: false, | ||
actual, | ||
expected, | ||
} | ||
} | ||
} | ||
this.error('expected ' + inspect(value) + ' to equal ' + inspect(expected), { actual: value, expected }) | ||
return { | ||
isMatch: false, | ||
actual: value, | ||
expected, | ||
} | ||
} | ||
}) | ||
}, | ||
value: (query) => { | ||
values: (query) => { | ||
return query | ||
.is('select') | ||
.expectOneElement('expected to be select element') | ||
.transform(([select]) => { | ||
.map((select) => { | ||
const selectedOption = select.options[select.selectedIndex] | ||
@@ -159,3 +174,3 @@ return selectedOption && query._dom.elementInnerText(selectedOption) | ||
.is(inputSelectors.settable) | ||
.expectOneElement() | ||
.shouldHaveElements(1) | ||
.transform(([element]) => { | ||
@@ -171,4 +186,4 @@ if (typeof value !== 'string') { | ||
}, | ||
value: (query) => { | ||
return query.is(inputSelectors.gettable).expectOneElement().transform(([input]) => { | ||
values: (query) => { | ||
return query.is(inputSelectors.gettable).map((input) => { | ||
return input.value | ||
@@ -179,4 +194,4 @@ }) | ||
{ | ||
value: (query) => { | ||
return query.expectOneElement().transform(([element]) => { | ||
values: (query) => { | ||
return query.map((element) => { | ||
return query._dom.elementInnerText(element) | ||
@@ -187,3 +202,3 @@ }) | ||
], | ||
button: [ | ||
buttons: [ | ||
(query, name) => { | ||
@@ -193,3 +208,3 @@ return query.findCss('button, input[type=button], input[type=submit], input[type=reset], a').containing(name) | ||
], | ||
label: [ | ||
fields: [ | ||
{ | ||
@@ -240,4 +255,4 @@ name: 'label', | ||
], | ||
fields: { | ||
Label: (q, value) => q.findLabel(value), | ||
finders: { | ||
Field: (q, value) => q.findLabel(value), | ||
Button: (q, value) => q.findButton(value), | ||
@@ -282,4 +297,4 @@ Css: (q, value) => q.findCss(value), | ||
public findButton (name: LabelName): this { | ||
return this.concat(this._options.definitions.button.map(definition => { | ||
public findButton (name: FieldName): this { | ||
return this.concat(this._options.definitions.buttons.map(definition => { | ||
return (q: Query): Query => { | ||
@@ -292,3 +307,3 @@ return definition(q, name) | ||
public findLabel (name: string): this { | ||
return this.concat(this._options.definitions.label.map(({definition}) => { | ||
return this.concat(this._options.definitions.fields.map(({definition}) => { | ||
return (q: Query): Query => { | ||
@@ -300,22 +315,38 @@ return definition(q, name) | ||
public defineButtonType (definition: LabelDefinition): this { | ||
return this.clone(q => q._options.definitions.button.push(definition)) | ||
public defineButtonFinder (name: string | FieldFinderDefinition, definition: FieldFinderDefinition): this { | ||
if (!definition) { | ||
definition = name as FieldFinderDefinition | ||
name = undefined | ||
} | ||
return this.clone(q => q._options.definitions.buttons.push(definition)) | ||
} | ||
public defineLabelType (name: string | LabelDefinition, definition?: LabelDefinition): this { | ||
public undefineButtonFinder (name: string): this { | ||
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): this { | ||
if (!definition) { | ||
definition = name as LabelDefinition | ||
definition = name as FieldFinderDefinition | ||
name = undefined | ||
} | ||
return this.clone(q => q._options.definitions.label.push({name: name as string, definition})) | ||
return this.clone(q => q._options.definitions.fields.push({name: name as string, definition})) | ||
} | ||
public undefineLabelType (name: string): this { | ||
public undefineFieldFinder (name: string): this { | ||
return this.clone(q => { | ||
const index = q._options.definitions.label.findIndex(def => def.name === name) | ||
const index = q._options.definitions.fields.findIndex(def => def.name === name) | ||
if (index >= 0) { | ||
q._options.definitions.label.splice(index, 1) | ||
q._options.definitions.fields.splice(index, 1) | ||
} else { | ||
throw new Error(`label definition ${JSON.stringify(name)} doesn't exist`) | ||
throw new Error(`field definition ${JSON.stringify(name)} doesn't exist`) | ||
} | ||
@@ -506,6 +537,14 @@ }) | ||
let retries = 0 | ||
const startTime = new Date() | ||
const promise = Promise.resolve(retry(() => { | ||
retries++ | ||
return this.execute().value | ||
})).catch(error => { | ||
if (error instanceof BrowserMonkeyAssertionError) { | ||
error.retries = retries | ||
error.duration = new Date() - startTime | ||
error.rewriteMessage() | ||
if (debug.enabled) { | ||
@@ -568,8 +607,6 @@ debug('assertion error', error.message) | ||
public expectNoElements (message?: string): this { | ||
public shouldHaveElements (count: number, message?: string): this { | ||
return this.expect(elements => { | ||
expectElements(elements) | ||
if (elements.length !== 0) { | ||
this.error(message || 'expected no elements, found ' + elements.length) | ||
if (elements.length !== count) { | ||
this.error(message || `expected ${count} ${pluralize('elements', count)}, found ` + elements.length) | ||
} | ||
@@ -579,8 +616,6 @@ }) | ||
public expectOneElement (message?: string): this { | ||
public shouldExist (message?: string): this { | ||
return this.expect(elements => { | ||
expectElements(elements) | ||
if (elements.length !== 1) { | ||
this.error(message || 'expected just one element, found ' + elements.length) | ||
if (elements.length < 1) { | ||
this.error(message || 'expected one or more elements, found ' + elements.length) | ||
} | ||
@@ -590,16 +625,6 @@ }) | ||
public elementResult (): HTMLElement { | ||
return this.expectOneElement().result()[0] | ||
} | ||
public elementsResult (): HTMLElement { | ||
return this.expectSomeElements().result() | ||
} | ||
public expectSomeElements (message?: string): this { | ||
public shouldNotExist (message?: string): this { | ||
return this.expect(elements => { | ||
expectElements(elements) | ||
if (elements.length < 1) { | ||
this.error(message || 'expected one or more elements, found ' + elements.length) | ||
if (elements.length !== 0) { | ||
this.error(message || 'expected no elements, found ' + elements.length) | ||
} | ||
@@ -609,14 +634,12 @@ }) | ||
public expectLength (length: number): this { | ||
return this.expect(elements => { | ||
expectElements(elements) | ||
public elementResult (): HTMLElement { | ||
return this.shouldHaveElements(1).result()[0] | ||
} | ||
if (elements.length !== length) { | ||
this.error(`expected ${length} elements, found ` + elements.length) | ||
} | ||
}) | ||
public elementsResult (): HTMLElement { | ||
return this.shouldExist().result() | ||
} | ||
public click (selector?: string): this { | ||
return this.optionalSelector(selector).expectOneElement().action(([element]) => { | ||
return this.optionalSelector(selector).shouldHaveElements(1).action(([element]) => { | ||
debug('click', element) | ||
@@ -627,3 +650,3 @@ this._dom.click(element) | ||
public clickButton (name: LabelName): this { | ||
public clickButton (name: FieldName): this { | ||
return this.findButton(name).click() | ||
@@ -634,3 +657,3 @@ } | ||
return this.optionalSelector(selector) | ||
.expectOneElement() | ||
.shouldHaveElements(1) | ||
.expect(([element]) => { | ||
@@ -654,3 +677,3 @@ if (!element.form) { | ||
return this.optionalSelector(selector) | ||
.expectOneElement() | ||
.shouldHaveElements(1) | ||
.is(inputSelectors.settable) | ||
@@ -704,3 +727,3 @@ .action(([element]) => { | ||
value: (query, model): ActualExpected => { | ||
const setter = query.setter(model).result() | ||
const setter = query.shouldHaveElements(1).setter(model).result() | ||
setters.push(() => setter()) | ||
@@ -714,3 +737,3 @@ return { | ||
expectOne: (query): ActualExpected => { | ||
query.expectOneElement().result() | ||
query.shouldHaveElements(1).result() | ||
return { | ||
@@ -740,10 +763,2 @@ actual: {}, | ||
public shouldExist (): this { | ||
return this.expectSomeElements() | ||
} | ||
public shouldNotExist (): this { | ||
return this.expectNoElements() | ||
} | ||
public async shouldAppearAfter (action: () => void): Promise<void> { | ||
@@ -772,3 +787,3 @@ await this.shouldNotExist() | ||
try { | ||
query.expectOneElement().result() | ||
query.shouldHaveElements(1).result() | ||
return {actual: {}, expected: {}} | ||
@@ -789,36 +804,9 @@ } catch (e) { | ||
value: (query, model): ActualExpected => { | ||
let valueAsserter | ||
const match = query.matchValue(model) | ||
try { | ||
valueAsserter = query.valueAsserter(model).result() | ||
} catch (e) { | ||
if (e instanceof BrowserMonkeyAssertionError) { | ||
isError = true | ||
return { | ||
actual: e, | ||
expected: model, | ||
} | ||
} else { | ||
throw e | ||
} | ||
if (!match.isMatch) { | ||
isError = true | ||
} | ||
try { | ||
valueAsserter() | ||
} catch (e) { | ||
if (e instanceof BrowserMonkeyAssertionError) { | ||
isError = true | ||
return { | ||
actual: e.actual, | ||
expected: e.expected, | ||
} | ||
} else { | ||
throw e | ||
} | ||
} | ||
return { | ||
actual: model, | ||
expected: model, | ||
} | ||
return match | ||
}, | ||
@@ -858,2 +846,5 @@ | ||
return this.transform(elements => { | ||
if (elements.length <= index) { | ||
this.error(`index(${index}) where there are only ${elements.length} elements`) | ||
} | ||
return new ExecutedSimpleTransform([elements[index]], 'index ' + index) | ||
@@ -863,8 +854,8 @@ }) | ||
public define (name: string, fieldDefinition): this { | ||
if (typeof fieldDefinition === 'function') { | ||
this._options.definitions.fields[name] = fieldDefinition | ||
} else if (typeof fieldDefinition === 'string') { | ||
this._options.definitions.fields[name] = q => q.find(fieldDefinition) | ||
} else if (name.constructor === Object && fieldDefinition === undefined) { | ||
public define (name: string, finderDefinition): this { | ||
if (typeof finderDefinition === 'function') { | ||
this._options.definitions.finders[name] = finderDefinition | ||
} else if (typeof finderDefinition === 'string') { | ||
this._options.definitions.finders[name] = q => q.find(finderDefinition) | ||
} else if (name.constructor === Object && finderDefinition === undefined) { | ||
Object.keys(name).forEach(key => this.define(key, name[key])) | ||
@@ -876,24 +867,36 @@ } | ||
private setter (model): this { | ||
return this.firstOf(this._options.definitions.fieldTypes.filter(def => def.setter).map(def => { | ||
return query => def.setter(query, model) | ||
private setter (value): this { | ||
return this.firstOf(this._options.definitions.inputs.filter(def => def.setter).map(def => { | ||
return query => def.setter(query, value) | ||
})) | ||
} | ||
private valueAsserter (expected: any): this { | ||
return this.firstOf(this._options.definitions.fieldTypes.filter(def => def.value).map(def => { | ||
return query => def.valueAsserter | ||
? def.valueAsserter(query, expected) | ||
: def.value(query).transform(actual => { | ||
return () => { | ||
if (!match(actual, expected).isMatch) { | ||
this.error('expected ' + inspect(actual) + ' to equal ' + inspect(expected), { actual, expected }) | ||
} | ||
} | ||
private valueAsserters (expected: any): this { | ||
return this.transform(elements => { | ||
const definitions = this._options.definitions.inputs.filter(def => def.values || def.valueAsserters) | ||
const asserters = elements.map(element => { | ||
const queryOfOneElement = this.resolve([element]) | ||
const firstAsserterForElement = definitions.map(def => { | ||
const definitionAsserters = def.valueAsserters | ||
? def.valueAsserters(queryOfOneElement, expected) | ||
: def.values(queryOfOneElement).transform(actuals => { | ||
return actuals.map(actual => () => { | ||
return match(actual, expected) | ||
}) | ||
}) | ||
return definitionAsserters.result()[0] | ||
}) | ||
})) | ||
return firstAsserterForElement.find(Boolean) | ||
}).filter(Boolean) | ||
return asserters | ||
}) | ||
} | ||
public defineFieldType (fieldTypeDefinition: FieldType): void { | ||
this._options.definitions.fieldTypes.unshift(fieldTypeDefinition) | ||
public defineInput (inputDefinition: InputDefinition): void { | ||
this._options.definitions.inputs.unshift(inputDefinition) | ||
} | ||
@@ -908,10 +911,10 @@ | ||
value: (query, value): ActualExpected => { | ||
const valueAsserter = query.valueAsserter(value).result() | ||
valueAsserter() | ||
value: (query, model): ActualExpected => { | ||
const match = query.matchValue(model) | ||
return { | ||
actual: value, | ||
expected: value | ||
if (!match.isMatch) { | ||
isError = true | ||
} | ||
return match | ||
}, | ||
@@ -933,14 +936,26 @@ | ||
let lastError | ||
let lastSuccess | ||
let isError | ||
const failingActuals = [] | ||
const matchingElements = [] | ||
const matchingElements = elements.filter(element => { | ||
elements.forEach(element => { | ||
try { | ||
const clone = this.resolve([element]) | ||
lastSuccess = new ExecutedSimpleTransform(clone.mapModel(model, actions)) | ||
return true | ||
isError = false | ||
const match = clone.mapModel(model, actions) | ||
if (isError) { | ||
failingActuals.push(match.actual) | ||
} else { | ||
matchingElements.push(element) | ||
} | ||
} catch (e) { | ||
if (e instanceof BrowserMonkeyAssertionError) { | ||
lastError = new ExecutedTransformError(e) | ||
return false | ||
failingActuals.push({ | ||
isMatch: false, | ||
actual: e.actual, | ||
expected: e.expected, | ||
}) | ||
} else { | ||
@@ -952,10 +967,26 @@ throw e | ||
return new ExecutedContainingTransform(matchingElements, lastSuccess ? lastSuccess : lastError) | ||
return new ExecutedContainingTransform(matchingElements, model, matchingElements.length ? undefined : failingActuals) | ||
}) | ||
} | ||
public value (): this { | ||
return this.firstOf(this._options.definitions.fieldTypes.filter(def => def.value).map(def => { | ||
return query => def.value(query) | ||
})) | ||
public values (): this { | ||
return this.transform(elements => { | ||
const definitions = this._options.definitions.inputs.filter(def => def.values) | ||
const values = elements.map(element => { | ||
const queryOfOneElement = this.resolve([element]) | ||
const value = definitions.map(def => { | ||
const values = def.values(queryOfOneElement).transform(actuals => { | ||
return actuals | ||
}).result() | ||
return values | ||
}).filter(vs => vs.length).map(vs => vs[0])[0] | ||
return value | ||
}) | ||
return values | ||
}) | ||
} | ||
@@ -965,3 +996,2 @@ | ||
const findElements = this.transform(elements => { | ||
expectElements(elements) | ||
return new ExecutedSimpleTransform(flatten(elements.map(element => { | ||
@@ -981,3 +1011,3 @@ return this._dom.querySelectorAll(element, selector, this._options) | ||
const [, name,, value] = match | ||
const finder = this._options.definitions.fields[name] | ||
const finder = this._options.definitions.finders[name] | ||
@@ -1019,2 +1049,24 @@ if (value !== undefined) { | ||
private matchValue(model: any): Match { | ||
const valueAsserters = this.valueAsserters(model).result() | ||
const results = valueAsserters.map(valueAsserter => valueAsserter()) | ||
const success = results.find(r => r.isMatch) | ||
if (success) { | ||
return success | ||
} else { | ||
const actual = results.length === 1 | ||
? results[0].actual | ||
: results.length === 0 | ||
? undefined | ||
: results.map(r => r.actual) | ||
return { | ||
isMatch: false, | ||
actual, | ||
expected: model, | ||
} | ||
} | ||
} | ||
private mapModel (model: any, actions: Actions): any { | ||
@@ -1061,3 +1113,3 @@ const map = (query: Query, model: any): any => { | ||
} else { | ||
return actions.value(query.expectOneElement(), model) | ||
return actions.value(query, model) | ||
} | ||
@@ -1070,8 +1122,2 @@ } | ||
function expectElements (elements): void { | ||
if (!isArrayOfHTMLElements(elements)) { | ||
throw new BrowserMonkeyAssertionError('expected an array of HTML elements') | ||
} | ||
} | ||
function cloneDefinitions(definitions: Definitions): Definitions { | ||
@@ -1104,9 +1150,2 @@ const result = {} | ||
function isArrayOfHTMLElements (elements): boolean { | ||
return elements instanceof Array && | ||
elements.every(element => { | ||
return isHTMLElement(element) | ||
}) | ||
} | ||
type Retry = <T>(fn: () => T, options?: {timeout?: number, interval?: number}) => Promise<T> | ||
@@ -1113,0 +1152,0 @@ |
{ | ||
"name": "browser-monkey", | ||
"version": "3.0.0-beta.3", | ||
"version": "3.0.0-beta.4", | ||
"description": "reliable dom testing", | ||
@@ -24,9 +24,9 @@ "main": "dist/index.js", | ||
"devDependencies": { | ||
"@babel/core": "^7.2.2", | ||
"@babel/polyfill": "^7.2.5", | ||
"@babel/preset-env": "^7.2.3", | ||
"@babel/preset-react": "^7.0.0", | ||
"@babel/preset-typescript": "^7.8.3", | ||
"@babel/register": "^7.0.0", | ||
"@types/jquery": "^3.3.31", | ||
"@babel/core": "^7.10.4", | ||
"@babel/polyfill": "^7.10.4", | ||
"@babel/preset-env": "^7.10.4", | ||
"@babel/preset-react": "^7.10.4", | ||
"@babel/preset-typescript": "^7.10.4", | ||
"@babel/register": "^7.10.4", | ||
"@types/jquery": "^3.5.0", | ||
"@types/mocha": "^5.2.7", | ||
@@ -33,0 +33,0 @@ "@types/react": "^16.9.19", |
@@ -8,6 +8,6 @@ /* global location */ | ||
const { expect } = require('chai') | ||
const inspect = require('object-inspect') | ||
import Dom from '../../lib/Dom' | ||
import {Query} from '../../lib/Query' | ||
const object = require('lowscore/object') | ||
import inspect from 'object-inspect' | ||
@@ -144,8 +144,12 @@ export class DomAssembly { | ||
public assertRejection (promise: Promise<any>, expectedMessage): Promise<void> { | ||
public assertRejection (promise: Promise<any>, expectedMessage, {assertMetrics = false} = {}): Promise<void> { | ||
return promise.then(() => { | ||
throw new Error('expected rejection ' + JSON.stringify(expectedMessage)) | ||
throw new Error('expected rejection ' + inspect(expectedMessage)) | ||
}, e => { | ||
if (e.message.indexOf(expectedMessage) === -1) { | ||
throw new Error('expected error message ' + inspect(e.message) + ' to include ' + inspect(expectedMessage)) | ||
const message = assertMetrics | ||
? e.message | ||
: e.message.replace(/ \[waited \d+ms, retried \d+ times\]/, '') | ||
if (expectedMessage instanceof RegExp ? !expectedMessage.test(message) : message.indexOf(expectedMessage) === -1) { | ||
throw new Error('expected error message ' + inspect(message) + ' to include ' + inspect(expectedMessage)) | ||
} | ||
@@ -152,0 +156,0 @@ }) |
@@ -19,3 +19,3 @@ const {DomAssembly} = require('./DomAssembly') | ||
const element = assembly.insertHtml('<div class="a"/>') | ||
const [found] = await browser.find('.a').expectOneElement() | ||
const [found] = await browser.find('.a').shouldHaveElements(1) | ||
expect(found).to.equal(element) | ||
@@ -25,3 +25,3 @@ }) | ||
it('can eventually insert html before searching', async () => { | ||
const promise = browser.find('.a').expectOneElement().then() | ||
const promise = browser.find('.a').shouldHaveElements(1).then() | ||
const element = assembly.eventuallyInsertHtml('<div class="a"/>') | ||
@@ -33,3 +33,3 @@ const [found] = await promise | ||
it('can eventually insert html after searching', async () => { | ||
const found = browser.find('.a').expectOneElement().then() | ||
const found = browser.find('.a').shouldHaveElements(1).then() | ||
const element = assembly.eventuallyInsertHtml('<div class="a"/>') | ||
@@ -41,4 +41,4 @@ expect((await found)[0]).to.equal(await element) | ||
const promise = Promise.all([ | ||
browser.find('.a').expectOneElement().then(), | ||
browser.find('.a').expectOneElement().then() | ||
browser.find('.a').shouldHaveElements(1).then(), | ||
browser.find('.a').shouldHaveElements(1).then() | ||
]) | ||
@@ -45,0 +45,0 @@ const element = assembly.eventuallyInsertHtml('<div class="a"/>') |
@@ -64,3 +64,3 @@ import {DomAssembly} from './assemblies/DomAssembly' | ||
const query = browser.defineButtonType((query, name) => query.find('div.button').containing(name)) | ||
const query = browser.defineButtonFinder((query, name) => query.find('div.button').containing(name)) | ||
@@ -75,3 +75,3 @@ const elements = query.findButton('Login').result() | ||
const query = browser.defineButtonType((query, name) => query.find('div.button').containing(name)) | ||
const query = browser.defineButtonFinder((query, name) => query.find('div.button').containing(name)) | ||
@@ -107,3 +107,3 @@ const elements = query.findButton('Login').result() | ||
it('can click a defined button', async () => { | ||
const query = browser.defineButtonType((query, name) => query.find('div.button').containing(name)) | ||
const query = browser.defineButtonFinder((query, name) => query.find('div.button').containing(name)) | ||
await assertCanClickButton('<div class="target button">Login</div>', () => query.click('Button("Login")')) | ||
@@ -113,7 +113,7 @@ }) | ||
it('throws if the button cannot be found to click', async () => { | ||
const query = browser.defineButtonType((query, name) => query.find('div.button').containing(name)) | ||
const query = browser.defineButtonFinder((query, name) => query.find('div.button').containing(name)) | ||
assembly.insertHtml('<button class="target">Login</button>') | ||
await assembly.assertRejection(query.clickButton('Logout'), "expected just one element, found 0") | ||
await assembly.assertRejection(query.clickButton('Logout'), "expected 1 element, found 0") | ||
}) | ||
}) | ||
}) |
@@ -67,2 +67,3 @@ import {DomAssembly} from './assemblies/DomAssembly' | ||
<div class="title">Title</div> | ||
<div class="title">ax</div> | ||
<div class="body">Body</div> | ||
@@ -80,2 +81,16 @@ </div> | ||
it('matches when it matches one of several child elements', () => { | ||
assembly.insertHtml(` | ||
<div class="result correct"> | ||
<div class="title">Title</div> | ||
<div class="title">Other</div> | ||
<div class="body">Body</div> | ||
</div> | ||
`) | ||
const results = browser.find('.result').containing({'.title': 'Title'}).result() | ||
const expected = assembly.findAll('.correct') | ||
expect(results).to.eql(expected) | ||
}) | ||
it("shows why it couldn't find the element", () => { | ||
@@ -96,4 +111,4 @@ assembly.insertHtml(` | ||
expect(() => | ||
browser.find('.result').containing({'.title': 'Title', '.body': 'None'}).expectOneElement().result() | ||
).to.throw(`expected just one element, found 0 (found: path(find('.result') [3], containing(...expected just one element, found 0 (found: find('.title') [0])) [0]))`) | ||
browser.find('.result').containing({'.title': 'Title', '.body': 'None'}).shouldHaveElements(1).result() | ||
).to.throw(`expected 1 element, found 0 (found: path(find('.result') [3], containing({ expected: { '.title': 'Title', '.body': 'None' }, actual: [ { '.title': 'Title', '.body': undefined }, { '.title': 'Title', '.body': 'Body' }, { '.title': undefined, '.body': 'Body' } ] }) [0]))`) | ||
}) | ||
@@ -148,6 +163,6 @@ }) | ||
browser.find('.result').containing(result => result.find('.body').shouldExist()).find('.title').expectOneElement().result() | ||
browser.find('.result').containing(result => result.find('.body').shouldExist()).find('.title').shouldHaveElements(1).result() | ||
expect(() => | ||
browser.find('.result').containing(result => result.find('.body').shouldExist()).find('.title').expectOneElement().result() | ||
).to.throw(`expected just one element, found 0 (found: path(find('.result') [3], containing(...path(find('.body') [1])) [2], find('.title') [0]))`) | ||
browser.find('.result').containing(result => result.find('.body').shouldExist()).find('.title').shouldHaveElements(1).result() | ||
).to.throw(`expected 1 element, found 0 (found: path(find('.result') [3], containing(...path(find('.body') [1])) [2], find('.title') [0]))`) | ||
}) | ||
@@ -169,6 +184,6 @@ | ||
expect(() => | ||
browser.find('.result').containing(result => result.find('.body').shouldExist()).find('.title').expectOneElement().result() | ||
).to.throw(`expected just one element, found 0 (found: path(find('.result') [3], containing(...expected one or more elements, found 0 (found: find('.body') [0])) [0], find('.title') [0])`) | ||
browser.find('.result').containing(result => result.find('.body').shouldExist()).find('.title').shouldHaveElements(1).result() | ||
).to.throw(`expected 1 element, found 0 (found: path(find('.result') [3], containing(...expected one or more elements, found 0 (found: find('.body') [0])) [0], find('.title') [0])`) | ||
}) | ||
}) | ||
}) |
@@ -32,3 +32,3 @@ import {DomAssembly} from './assemblies/DomAssembly' | ||
query.find(label).expectNoElements().result() | ||
query.find(label).shouldNotExist().result() | ||
} | ||
@@ -46,3 +46,3 @@ | ||
`, | ||
'Label("Feature Enabled")' | ||
'Field("Feature Enabled")' | ||
) | ||
@@ -60,3 +60,3 @@ }) | ||
`, | ||
'Label("Feature Enabled")' | ||
'Field("Feature Enabled")' | ||
) | ||
@@ -74,3 +74,3 @@ }) | ||
`, | ||
'Label("Feature Enabled")' | ||
'Field("Feature Enabled")' | ||
) | ||
@@ -88,3 +88,3 @@ }) | ||
`, | ||
'Label("Feature")' | ||
'Field("Feature")' | ||
) | ||
@@ -102,3 +102,3 @@ }) | ||
`, | ||
'Label(/Feature/)' | ||
'Field(/Feature/)' | ||
) | ||
@@ -115,3 +115,3 @@ }) | ||
`, | ||
'Label("Search")' | ||
'Field("Search")' | ||
) | ||
@@ -126,3 +126,3 @@ }) | ||
`, | ||
'Label(/sea/i)' | ||
'Field(/sea/i)' | ||
) | ||
@@ -137,3 +137,3 @@ }) | ||
`, | ||
'Label("Search")' | ||
'Field("Search")' | ||
) | ||
@@ -149,3 +149,3 @@ }) | ||
`, | ||
'Label("Search")' | ||
'Field("Search")' | ||
) | ||
@@ -161,3 +161,3 @@ }) | ||
`, | ||
'Label(/sea/i)' | ||
'Field(/sea/i)' | ||
) | ||
@@ -173,3 +173,3 @@ }) | ||
`, | ||
'Label("Search")' | ||
'Field("Search")' | ||
) | ||
@@ -185,3 +185,3 @@ }) | ||
`, | ||
'Label("Search")' | ||
'Field("Search")' | ||
) | ||
@@ -198,3 +198,3 @@ }) | ||
`, | ||
'Label("Search")' | ||
'Field("Search")' | ||
) | ||
@@ -209,3 +209,3 @@ }) | ||
`, | ||
'Label(/sea/i)' | ||
'Field(/sea/i)' | ||
) | ||
@@ -231,3 +231,3 @@ }) | ||
const found = browser.find('Label("Feature Enabled")').result() | ||
const found = browser.find('Field("Feature Enabled")').result() | ||
@@ -239,3 +239,3 @@ expect(found).to.eql(expected) | ||
it('can define a new way of finding labels', () => { | ||
const query = browser.defineLabelType((query, label) => query.findCss(`[data-label=${JSON.stringify(label)}]`)) | ||
const query = browser.defineFieldFinder((query, label) => query.findCss(`[data-label=${JSON.stringify(label)}]`)) | ||
@@ -247,3 +247,3 @@ assertFoundElementByLabel( | ||
`, | ||
'Label("Search")' | ||
'Field("Search")' | ||
) | ||
@@ -253,3 +253,3 @@ }) | ||
it('can add and remove a label definition by name', async () => { | ||
const query = browser.defineLabelType('data-label', (query, label) => query.findCss(`[data-label=${JSON.stringify(label)}]`)) | ||
const query = browser.defineFieldFinder('data-label', (query, label) => query.findCss(`[data-label=${JSON.stringify(label)}]`)) | ||
@@ -261,14 +261,14 @@ assertFoundElementByLabel( | ||
`, | ||
'Label("Search")' | ||
'Field("Search")' | ||
) | ||
const without = query.undefineLabelType('data-label') | ||
const without = query.undefineFieldFinder('data-label') | ||
await without.find('Label("Search")').expectNoElements().result() | ||
await without.find('Field("Search")').shouldNotExist().result() | ||
}) | ||
it("throws if we try to undefine a label that doesn't exist", async () => { | ||
expect(() => browser.undefineLabelType('data-label')).to.throw("doesn't exist") | ||
expect(() => browser.undefineFieldFinder('data-label')).to.throw("doesn't exist") | ||
}) | ||
}) | ||
}) |
@@ -19,3 +19,3 @@ import {expect} from 'chai' | ||
it('can find an element by DOM selector', async () => { | ||
const selectedElementPromise = browserMonkey.find('.test').expectOneElement().then() | ||
const selectedElementPromise = browserMonkey.find('.test').shouldHaveElements(1).then() | ||
@@ -42,3 +42,3 @@ const insertedElementPromise = assembly.eventuallyInsertHtml( | ||
describe('expectNoElements', () => { | ||
describe('shouldNotExist', () => { | ||
it('passes when there are no elements found', async () => { | ||
@@ -54,3 +54,3 @@ assembly.insertHtml(` | ||
.find('.contact') | ||
.expectNoElements() | ||
.shouldNotExist() | ||
.then() | ||
@@ -77,3 +77,3 @@ | ||
.find('.contact') | ||
.expectNoElements() | ||
.shouldNotExist() | ||
.then() | ||
@@ -86,59 +86,59 @@ | ||
describe('expectOneElement', () => { | ||
it('when there is one element, returns it', async () => { | ||
const contacts = browserMonkey | ||
.find('.contact') | ||
.expectOneElement() | ||
.then() | ||
describe('shouldHaveElements', () => { | ||
describe('when 1', () => { | ||
it('when there is one element, returns it', async () => { | ||
const contacts = browserMonkey | ||
.find('.contact') | ||
.shouldHaveElements(1) | ||
.then() | ||
assembly.eventuallyInsertHtml(` | ||
<div class="contact"> | ||
<div class="name">Sally</div> | ||
<div class="address">32 Yellow Drive</div> | ||
</div> | ||
`) | ||
assembly.eventuallyInsertHtml(` | ||
<div class="contact"> | ||
<div class="name">Sally</div> | ||
<div class="address">32 Yellow Drive</div> | ||
</div> | ||
`) | ||
expect(await contacts).to.eql([assembly.find('.contact:nth-child(1)')]) | ||
}) | ||
expect(await contacts).to.eql([assembly.find('.contact:nth-child(1)')]) | ||
}) | ||
it('when there is more than one element, throws an error', async () => { | ||
const contacts = browserMonkey | ||
.find('.contact') | ||
.expectOneElement() | ||
.then() | ||
it('when there is more than one element, throws an error', async () => { | ||
const contacts = browserMonkey | ||
.find('.contact') | ||
.shouldHaveElements(1) | ||
.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> | ||
`) | ||
await assembly.assertRejection(contacts, 'expected just one element, found 2') | ||
}) | ||
await assembly.assertRejection(contacts, 'expected 1 element, found 2') | ||
}) | ||
it('when there no elements, throws an error', async () => { | ||
const contacts = browserMonkey | ||
.find('.contact') | ||
.expectOneElement() | ||
.then() | ||
it('when there no elements, throws an error', async () => { | ||
const contacts = browserMonkey | ||
.find('.contact') | ||
.shouldHaveElements(1) | ||
.then() | ||
assembly.eventuallyInsertHtml(` | ||
<div class="title"></div> | ||
<div class="title"></div> | ||
`) | ||
assembly.eventuallyInsertHtml(` | ||
<div class="title"></div> | ||
<div class="title"></div> | ||
`) | ||
await assembly.assertRejection(contacts, 'expected just one element, found 0') | ||
await assembly.assertRejection(contacts, 'expected 1 element, found 0') | ||
}) | ||
}) | ||
}) | ||
describe('expectLength', () => { | ||
it('asserts list of one element has one element', async () => { | ||
it('asserts list of two elements has two elements', async () => { | ||
const items = browserMonkey | ||
.find('li ul') | ||
.expectLength(2) | ||
.shouldHaveElements(2) | ||
.then() | ||
@@ -156,6 +156,6 @@ | ||
it('asserts list of one element has one element', async () => { | ||
it('fails when a list of two element is asserted to have three elements', async () => { | ||
const items = browserMonkey | ||
.find('li ul') | ||
.expectLength(3) | ||
.shouldHaveElements(3) | ||
.then() | ||
@@ -195,3 +195,3 @@ | ||
.find('.title') | ||
.elementResult()).to.throw('expected just one element, found 2') | ||
.elementResult()).to.throw('expected 1 element, found 2') | ||
}) | ||
@@ -205,3 +205,3 @@ | ||
.find('.title') | ||
.elementResult()).to.throw('expected just one element, found 0') | ||
.elementResult()).to.throw('expected 1 element, found 0') | ||
}) | ||
@@ -236,7 +236,7 @@ }) | ||
describe('expectSomeElements', () => { | ||
describe('shouldExist', () => { | ||
it('when there are one or more elements, selects them', async () => { | ||
const contacts = browserMonkey | ||
.find('.contact') | ||
.expectSomeElements() | ||
.shouldExist() | ||
.then() | ||
@@ -261,3 +261,3 @@ | ||
.find('.contact') | ||
.expectSomeElements() | ||
.shouldExist() | ||
.then() | ||
@@ -355,3 +355,3 @@ | ||
}) | ||
.expectOneElement() | ||
.shouldHaveElements(1) | ||
.then() | ||
@@ -381,3 +381,3 @@ | ||
}) | ||
.expectSomeElements() | ||
.shouldExist() | ||
.then() | ||
@@ -443,3 +443,3 @@ | ||
.find('.name') | ||
.expectOneElement() | ||
.shouldHaveElements(1) | ||
.then() | ||
@@ -457,3 +457,3 @@ | ||
await assembly.assertRejection(name, "expected just one element, found 0 (found: path(find('.container') [1], find('.contact') [2], find('.name') [0]))") | ||
await assembly.assertRejection(name, "expected 1 element, found 0 (found: path(find('.container') [1], find('.contact') [2], find('.name') [0]))") | ||
}) | ||
@@ -496,3 +496,3 @@ }) | ||
b => b.find('.b') | ||
]).find('.child').expectSomeElements() | ||
]).find('.child').shouldExist() | ||
@@ -503,7 +503,19 @@ return assembly.assertRejection(promise, "expected one or more elements, found 0 (found: path(concat(find('.a') [1], find('.b') [1]) [2], find('.child') [0])") | ||
describe('errors', () => { | ||
it('throws error with wait duration and retry count', async () => { | ||
assembly.insertHtml(` | ||
<div class="a">A</div> | ||
`) | ||
const promise = browserMonkey.find('.b').shouldExist() | ||
return assembly.assertRejection(promise, /expected one or more elements, found 0 \[waited \d+ms, retried 1 times\]/, {assertMetrics: true}) | ||
}) | ||
}) | ||
describe('firstOf', () => { | ||
it('finds the first of two or more queries', async () => { | ||
const promise = browserMonkey.firstOf([ | ||
b => b.find('.a').expectSomeElements(), | ||
b => b.find('.b').expectSomeElements() | ||
b => b.find('.a').shouldExist(), | ||
b => b.find('.b').shouldExist() | ||
]).then() | ||
@@ -523,4 +535,4 @@ | ||
const promise = browserMonkey.find('.content').firstOf([ | ||
b => b.find('.a').expectSomeElements(), | ||
b => b.find('.b').expectSomeElements() | ||
b => b.find('.a').shouldExist(), | ||
b => b.find('.b').shouldExist() | ||
]) | ||
@@ -536,3 +548,3 @@ | ||
b => b.find('.a'), | ||
b => b.find('.b').expectSomeElements() | ||
b => b.find('.b').shouldExist() | ||
]) | ||
@@ -547,4 +559,4 @@ | ||
const promise = browserMonkey.detect({ | ||
a: q => q.find('.a').expectSomeElements(), | ||
b: q => q.find('.b').expectSomeElements() | ||
a: q => q.find('.a').shouldExist(), | ||
b: q => q.find('.b').shouldExist() | ||
}).then() | ||
@@ -566,4 +578,4 @@ | ||
const promise = browserMonkey.find('.content').detect({ | ||
a: b => b.find('.a').expectSomeElements(), | ||
b: b => b.find('.b').expectSomeElements() | ||
a: b => b.find('.a').shouldExist(), | ||
b: b => b.find('.b').shouldExist() | ||
}) | ||
@@ -579,3 +591,3 @@ | ||
a: b => b.find('.a'), | ||
b: b => b.find('.b').expectSomeElements() | ||
b: b => b.find('.b').shouldExist() | ||
}) | ||
@@ -582,0 +594,0 @@ |
@@ -164,3 +164,3 @@ import {DomAssembly} from './assemblies/DomAssembly' | ||
}, | ||
}), "expected just one element, found 2 (found: path(find('.address') [1], find('.street') [2]))") | ||
}), "expected 1 element, found 2 (found: path(find('.address') [1], find('.street') [2]))") | ||
}) | ||
@@ -278,3 +278,3 @@ | ||
'.street': streetQuery => { | ||
streetQuery.expectOneElement().result()[0].innerText = 'hi' | ||
streetQuery.shouldHaveElements(1).result()[0].innerText = 'hi' | ||
} | ||
@@ -301,3 +301,3 @@ }) | ||
}) | ||
await assembly.assertRejection(promise, "expected just one element, found 0 (found: path(find('form') [1], find('.street') [0]))") | ||
await assembly.assertRejection(promise, "expected 1 element, found 0 (found: path(find('form') [1], find('.street') [0]))") | ||
@@ -304,0 +304,0 @@ expect(assembly.find('.phone').value).to.equal('') |
@@ -29,2 +29,29 @@ import {DomAssembly} from './assemblies/DomAssembly' | ||
it('can assert html element when there are more than one', async () => { | ||
assembly.insertHtml(` | ||
<span class="address">12 Hapless Boulevard</span> | ||
<span class="address">54 Harvard St</span> | ||
`) | ||
await browser.shouldContain({ | ||
'.address': '12 Hapless Boulevard', | ||
}) | ||
}) | ||
it('fails to assert html element when there are more than one', async () => { | ||
assembly.insertHtml(` | ||
<span class="address">12 Boulevard Ave</span> | ||
<span class="address">54 Harvard St</span> | ||
`) | ||
await assembly.assertExpectedActual(browser, { | ||
'.address': '12 Hapless Boulevard', | ||
}, { | ||
'.address': [ | ||
'12 Boulevard Ave', | ||
'54 Harvard St', | ||
], | ||
}) | ||
}) | ||
it('can assert text inputs', async () => { | ||
@@ -59,3 +86,3 @@ assembly.insertHtml(` | ||
}, { | ||
'.address': "Error: expected just one element, found 0 (found: find('.address') [0])", | ||
'.address': undefined, | ||
}) | ||
@@ -192,3 +219,3 @@ }) | ||
'h1': 'Title', | ||
'.content': "Error: expected just one element, found 0 (found: find('.content') [0])" | ||
'.content': undefined, | ||
}) | ||
@@ -216,3 +243,3 @@ }) | ||
'h1': 'Title', | ||
'.content': "Error: expected just one element, found 0 (found: path(find('.result') [2], index 0 [1], find('.content') [0]))" | ||
'.content': undefined, | ||
}, | ||
@@ -251,3 +278,3 @@ 'The Content' | ||
'h1': 'Title', | ||
'.content': "Error: expected just one element, found 0 (found: find('.content') [0])" | ||
'.content': "Error: expected 1 element, found 0 (found: find('.content') [0])" | ||
}) | ||
@@ -254,0 +281,0 @@ }) |
@@ -20,4 +20,4 @@ import {expect} from 'chai' | ||
const value = browser.find('.element').expectOneElement().value().result() | ||
expect(value).to.equal(expectedValue) | ||
const value = browser.find('.element').shouldHaveElements(1).values().result() | ||
expect(value).to.eql(expectedValue) | ||
} | ||
@@ -27,3 +27,3 @@ | ||
it('can get value of input', () => { | ||
assertValue('<input class="element" type="text" value="the value">', 'the value') | ||
assertValue('<input class="element" type="text" value="the value">', ['the value']) | ||
}) | ||
@@ -34,3 +34,3 @@ }) | ||
it('returns the innerHTML', () => { | ||
assertValue('<div class="element">this is the inner text</div>', 'this is the inner text') | ||
assertValue('<div class="element">this is the inner text</div>', ['this is the inner text']) | ||
}) | ||
@@ -41,7 +41,7 @@ }) | ||
it('when checked, returns true', () => { | ||
assertValue('<input class="element" type="checkbox" checked />', true) | ||
assertValue('<input class="element" type="checkbox" checked />', [true]) | ||
}) | ||
it('when unchecked, returns false', () => { | ||
assertValue('<input class="element" type="checkbox" />', false) | ||
assertValue('<input class="element" type="checkbox" />', [false]) | ||
}) | ||
@@ -53,4 +53,4 @@ | ||
const value = browser.find('.element').expectOneElement().value().result() | ||
expect(value).to.equal('indeterminate') | ||
const values = browser.find('.element').shouldHaveElements(1).values().result() | ||
expect(values).to.eql(['indeterminate']) | ||
}) | ||
@@ -68,3 +68,3 @@ }) | ||
`, | ||
'two' | ||
['two'] | ||
) | ||
@@ -71,0 +71,0 @@ }) |
Sorry, the diff of this file is too big to display
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
11502
3
1139103
64