codeceptjs
Advanced tools
Comparing version 0.3.1 to 0.3.2
@@ -21,2 +21,7 @@ #!/usr/bin/env node | ||
program.command('list [path]') | ||
.alias('sh') | ||
.description('List all actions for I.') | ||
.action(require('../lib/command/list')); | ||
program.command('generate test [path]') | ||
@@ -23,0 +28,0 @@ .alias('gt') |
@@ -0,1 +1,9 @@ | ||
## 0.3.2 | ||
* Added `codeceptjs list` command which shows all available methods of `I` object. | ||
* [Protractor][SeleniumWebdriver] fixed closing browser instances | ||
* [Protractor][SeleniumWebdriver] `doubleClick` method added | ||
* [WebDriverIO][Protractor][SeleniumWebdriver] `doubleClick` method to locate clickable elements by text, `context` option added. | ||
* Fixed using assert in generator without yields #89 | ||
## 0.3.1 | ||
@@ -2,0 +10,0 @@ |
@@ -73,2 +73,3 @@ 'use strict'; | ||
global.by = require('protractor').By; | ||
global.element = require('protractor').element; | ||
this.driverProvider = require('protractor/built/driverProviders/'+this.options.driver)(this.options); | ||
@@ -105,15 +106,5 @@ this.driverProvider.setupEnv(); | ||
_after() { | ||
return this.browser.quit().then(() => { | ||
this.browser.driver = null; | ||
this.browser = null; | ||
}); | ||
return this.browser.quit(); | ||
} | ||
_failed(test) { | ||
let fileName = test.name.replace(/ /g, '_') + '.failed.png'; | ||
this.debug('Screenshot has been saved to ' + path.join(global.output_dir, fileName)); | ||
return this.saveScreenshot(fileName); | ||
} | ||
_withinBegin(locator) { | ||
@@ -215,2 +206,5 @@ withinStore.elFn = this.browser.findElement; | ||
/** | ||
* Moves to url | ||
*/ | ||
moveTo(path) { | ||
@@ -220,2 +214,7 @@ return this.browser.setLocation(path); | ||
/** | ||
* Reloads page | ||
* | ||
* *Angular specific* | ||
*/ | ||
refresh() { | ||
@@ -225,2 +224,5 @@ return this.browser.refresh(); | ||
/** | ||
* Injects Angular module | ||
*/ | ||
haveModule(modName, fn) { | ||
@@ -230,2 +232,5 @@ return this.browser.addMockModule(modName, fn); | ||
/** | ||
* Resets Angualr module | ||
*/ | ||
resetModule(modName) { | ||
@@ -243,145 +248,2 @@ if (!modName) { | ||
function *findCheckable(client, locator) { | ||
let matchedLocator = guessLocator(locator); | ||
if (matchedLocator) { | ||
return client.findElements(matchedLocator); | ||
} | ||
let literal = xpathLocator.literal(locator); | ||
let byText = xpathLocator.combine([ | ||
`.//input[@type = 'checkbox' or @type = 'radio'][(@id = //label[contains(normalize-space(string(.)), ${literal})]/@for) or @placeholder = ${literal}]`, | ||
`.//label[contains(normalize-space(string(.)), ${literal})]//input[@type = 'radio' or @type = 'checkbox']` | ||
]); | ||
let els = yield client.findElements(by.xpath(byText)); | ||
if (els.length) { | ||
return els; | ||
} | ||
let byName = `.//input[@type = 'checkbox' or @type = 'radio'][@name = ${literal}]`; | ||
els = yield client.findElements(by.xpath(byName)); | ||
if (els.length) { | ||
return els; | ||
} | ||
return yield client.findElements(by.css(locator)); | ||
} | ||
function *findFields(client, locator) { | ||
let matchedLocator = guessLocator(locator); | ||
if (matchedLocator) { | ||
return client.findElements(matchedLocator); | ||
} | ||
let literal = xpathLocator.literal(locator); | ||
let byLabelEquals = xpathLocator.combine([ | ||
`.//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')][((./@name = ${literal}) or ./@id = //label[normalize-space(string(.)) = ${literal}]/@for or ./@placeholder = ${literal})]`, | ||
`.//label[normalize-space(string(.)) = ${literal}]//.//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]` | ||
]); | ||
let els = yield client.findElements(by.xpath(byLabelEquals)); | ||
if (els.length) { | ||
return els; | ||
} | ||
let byLabelContains = xpathLocator.combine([ | ||
`.//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')][(((./@name = ${literal}) or ./@id = //label[contains(normalize-space(string(.)), ${literal})]/@for) or ./@placeholder = ${literal})]`, | ||
`.//label[contains(normalize-space(string(.)), ${literal})]//.//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]` | ||
]); | ||
els = yield client.findElements(by.xpath(byLabelContains)); | ||
if (els.length) { | ||
return els; | ||
} | ||
let byName = `.//*[self::input | self::textarea | self::select][@name = ${literal}]`; | ||
els = yield client.findElements(by.xpath(byName)); | ||
if (els.length) { | ||
return els; | ||
} | ||
return yield client.findElements(by.css(locator)); | ||
} | ||
function proceedSee(assertType, text, context) { | ||
let description, locator; | ||
if (!context) { | ||
if (this.context === this.options.rootElement) { | ||
locator = guessLocator(this.context) || by.css(this.context); | ||
description = 'web application'; | ||
} else { | ||
locator = null; | ||
description = 'current context ' + this.context; | ||
} | ||
} else { | ||
locator = guessLocator(context) || by.css(context); | ||
description = 'element ' + context; | ||
} | ||
return this.browser.findElement(locator).getText().then(function (source) { | ||
return stringIncludes(description)[assertType](text, source); | ||
}); | ||
} | ||
function *proceedSeeInField(assertType, field, value) { | ||
let els = yield co(findFields(this.browser, field)); | ||
if (!els.length) { | ||
throw new Error(`Field ${field} not found by name|text|CSS|XPath`); | ||
} | ||
let el = els[0]; | ||
let tag = yield el.getTagName(); | ||
let fieldVal = yield el.getAttribute('value'); | ||
if (tag == 'select') { | ||
// locate option by values and check them | ||
let text = yield el.findElement(by.xpath(`./option[@value=${xpathLocator.literal(fieldVal)}]`)).getText(); | ||
return equals('select option by ' + field)[assertType](value, text); | ||
} | ||
return stringIncludes('field by ' + field)[assertType](value, fieldVal); | ||
} | ||
function *proceedIsChecked(assertType, option) { | ||
return co(findCheckable(this.browser, option)).then((els) => { | ||
if (!els.length) { | ||
throw new Error(`Option ${option} not found by name|text|CSS|XPath`); | ||
} | ||
let elsSelected = []; | ||
els.forEach(function (el) { | ||
elsSelected.push(el.isSelected()); | ||
}); | ||
return Promise.all(elsSelected).then(function(values) { | ||
let selected = values.reduce((prev, cur) => prev || cur) | ||
return truth(`checkable ${option}`, 'to be checked')[assertType](selected); | ||
}); | ||
}); | ||
} | ||
function *findClickable(matcher, locator) { | ||
let l = guessLocator(locator); | ||
if (guessLocator(locator)) { | ||
return matcher.findElement(l); | ||
} | ||
let literal = xpathLocator.literal(locator); | ||
let narrowLocator = xpathLocator.combine([ | ||
`.//a[normalize-space(.)=${literal}]`, | ||
`.//button[normalize-space(.)=${literal}]`, | ||
`.//a/img[normalize-space(@alt)=${literal}]/ancestor::a`, | ||
`.//input[./@type = 'submit' or ./@type = 'image' or ./@type = 'button'][normalize-space(@value)=${literal}]` | ||
]); | ||
let els = yield matcher.findElements(by.xpath(narrowLocator)); | ||
if (els.length) { | ||
return els[0]; | ||
} | ||
let wideLocator = xpathLocator.combine([ | ||
`.//a[./@href][((contains(normalize-space(string(.)), ${literal})) or .//img[contains(./@alt, ${literal})])]`, | ||
`.//input[./@type = 'submit' or ./@type = 'image' or ./@type = 'button'][contains(./@value, ${literal})]`, | ||
`.//input[./@type = 'image'][contains(./@alt, ${literal})]`, | ||
`.//button[contains(normalize-space(string(.)), ${literal})]`, | ||
`.//input[./@type = 'submit' or ./@type = 'image' or ./@type = 'button'][./@name = ${literal}]`, | ||
`.//button[./@name = ${literal}]` | ||
]); | ||
els = yield matcher.findElements(by.xpath(wideLocator)); | ||
if (els.length) { | ||
return els[0]; | ||
} | ||
if (isXPath(locator)) { | ||
return matcher.findElement(by.xpath(locator)); | ||
} | ||
return matcher.findElement(by.css(locator)); | ||
} | ||
function guessLocator(locator) { | ||
@@ -388,0 +250,0 @@ if (!locator) { |
@@ -151,4 +151,8 @@ 'use strict'; | ||
*/ | ||
doubleClick(locator) { | ||
return this.browser.findElement(guessLocator(locator)).then((el) => el.doubleClick()); | ||
doubleClick(locator, context) { | ||
let matcher = this.browser; | ||
if (context) { | ||
matcher = matcher.findElement(guessLocator(context) || by.css(context)); | ||
} | ||
return co(findClickable(matcher, locator)).then((el) => this.browser.actions().doubleClick(el).perform()); | ||
} | ||
@@ -730,2 +734,3 @@ | ||
`.//button[contains(normalize-space(string(.)), ${literal})]`, | ||
`.//label[contains(normalize-space(string(.)), ${literal})]`, | ||
`.//input[./@type = 'submit' or ./@type = 'image' or ./@type = 'button'][./@name = ${literal}]`, | ||
@@ -732,0 +737,0 @@ `.//button[./@name = ${literal}]` |
@@ -304,4 +304,15 @@ 'use strict'; | ||
*/ | ||
doubleClick(locator) { | ||
return this.browser.doubleClick(withStrictLocator(locator)); | ||
doubleClick(locator, context) { | ||
let client = this.browser; | ||
if (context) { | ||
client = client.element(context); | ||
} | ||
return findClickable(client, locator).then(function (res) { | ||
if (!res.value || res.value.length === 0) { | ||
if (typeof(locator) === "object") locator = JSON.stringify(locator); | ||
throw new Error(`Clickable element ${locator.toString()} was not found by text|CSS|XPath`); | ||
} | ||
let elem = res.value[0]; | ||
return this.moveTo(elem.ELEMENT).doDoubleClick(); | ||
}); | ||
} | ||
@@ -308,0 +319,0 @@ |
@@ -28,5 +28,9 @@ 'use strict'; | ||
let res = testFn.apply(test, getInjectedArguments(testFn)); | ||
if (isGenerator(testFn)) { | ||
res.next(); // running test | ||
try { | ||
res.next(); // running test | ||
} catch (err) { | ||
done(err); | ||
return test; | ||
} | ||
recorder.catch(); // catching possible errors in promises | ||
@@ -33,0 +37,0 @@ let resumeTest = function () { |
{ | ||
"name": "codeceptjs", | ||
"version": "0.3.1", | ||
"version": "0.3.2", | ||
"description": "Modern Era Aceptance Testing Framework for NodeJS", | ||
@@ -5,0 +5,0 @@ "homepage": "http://codecept.io", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
39
141737
4136