codeceptjs
Advanced tools
Comparing version 1.3.1 to 1.3.2
@@ -0,1 +1,12 @@ | ||
## 1.3.2 | ||
* Interactve Shell improvements for `pause()` | ||
* Added `next` command for **step-by-step debug** when using `pause()`. | ||
* Use `After(pause);` in a to start interactive console after last step. | ||
* [Puppeteer] Updated to Puppeteer 1.6.0 | ||
* Added `waitForRequest` to wait for network request. | ||
* Added `waitForResponse` to wait for network response. | ||
* Improved TypeScript definitions to support custom steps and page objects. By @xt1 | ||
* Fixed XPath detection to accept XPath which starts with `./` by @BenoitZugmeyer | ||
## 1.3.1 | ||
@@ -2,0 +13,0 @@ |
@@ -61,4 +61,14 @@ # Basics | ||
Interactive shell can be started outside test context by running | ||
To **debug test step-by-step** type `next` and press Enter. The next step will be executed and interactive shell will be shown again. | ||
To see all available commands press TAB two times to see list of all actions included in I. | ||
If a test is failing you can prevent browser from closing by putting `pause()` command into `After()` hook. This is very helpful to debug failing tests. This way you can keep the same session and try different actions on a page to get the idea what went wrong. | ||
```js | ||
After(pause); | ||
``` | ||
Interactive shell can be started outside the test context by running | ||
```bash | ||
@@ -65,0 +75,0 @@ codeceptjs shell |
@@ -1226,12 +1226,27 @@ const requireg = require('requireg'); | ||
```js | ||
I.waitForFunction(fn[, [args[, timeout]]) | ||
``` | ||
```js | ||
I.waitForFunction(() => window.requests == 0); | ||
I.waitForFunction(() => window.requests == 0, 5); // waits for 5 sec | ||
I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and wait for 5 sec | ||
``` | ||
@param function to be executed in browser context | ||
@param args arguments for function | ||
@param sec time seconds to wait, 1 by default | ||
*/ | ||
async waitForFunction(fn, sec = null) { | ||
async waitForFunction(fn, argsOrSec = null, sec = null) { | ||
let args = []; | ||
if (argsOrSec) { | ||
if (Array.isArray(argsOrSec)) { | ||
args = argsOrSec; | ||
} else if (typeof argsOrSec === 'number') { | ||
sec = argsOrSec; | ||
} | ||
} | ||
this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout; | ||
return this.browser.wait(fn); | ||
return this.browser.wait(fn, ...args); | ||
} | ||
@@ -1238,0 +1253,0 @@ |
@@ -55,3 +55,4 @@ # Configuration | ||
mocha: require('./mocha.conf.js') || {}, | ||
includes: { | ||
include: { | ||
I: './src/steps_file.js', | ||
loginPage: './src/pages/login_page', | ||
@@ -58,0 +59,0 @@ dashboardPage: new DashboardPage() |
@@ -839,4 +839,9 @@ # Nightmare | ||
```js | ||
I.waitForFunction(fn[, [args[, timeout]]) | ||
``` | ||
```js | ||
I.waitForFunction(() => window.requests == 0); | ||
I.waitForFunction(() => window.requests == 0, 5); // waits for 5 sec | ||
I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and wait for 5 sec | ||
``` | ||
@@ -847,3 +852,5 @@ | ||
- `function` to be executed in browser context | ||
- `args` arguments for function | ||
- `fn` | ||
- `argsOrSec` (optional, default `null`) | ||
- `sec` time seconds to wait, 1 by default | ||
@@ -850,0 +857,0 @@ |
@@ -1184,4 +1184,9 @@ # Protractor | ||
```js | ||
I.waitForFunction(fn[, [args[, timeout]]) | ||
``` | ||
```js | ||
I.waitForFunction(() => window.requests == 0); | ||
I.waitForFunction(() => window.requests == 0, 5); // waits for 5 sec | ||
I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and wait for 5 sec | ||
``` | ||
@@ -1192,5 +1197,6 @@ | ||
- `function` to be executed in browser context | ||
- `args` arguments for function | ||
- `fn` | ||
- `argsOrSec` (optional, default `null`) | ||
- `sec` time seconds to wait, 1 by default | ||
- `timeoutMsg` (optional, default `null`) | ||
@@ -1197,0 +1203,0 @@ ## waitForInvisible |
@@ -1167,4 +1167,9 @@ # Puppeteer | ||
```js | ||
I.waitForFunction(fn[, [args[, timeout]]) | ||
``` | ||
```js | ||
I.waitForFunction(() => window.requests == 0); | ||
I.waitForFunction(() => window.requests == 0, 5); // waits for 5 sec | ||
I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and wait for 5 sec | ||
``` | ||
@@ -1175,3 +1180,5 @@ | ||
- `function` to be executed in browser context | ||
- `args` arguments for function | ||
- `fn` | ||
- `argsOrSec` (optional, default `null`) | ||
- `sec` time seconds to wait, 1 by default | ||
@@ -1201,2 +1208,30 @@ | ||
## waitForRequest | ||
Waits for a network request. | ||
```js | ||
I.waitForRequest('http://example.com/resource'); | ||
I.waitForRequest(request => request.url() === 'http://example.com' && request.method() === 'GET'); | ||
``` | ||
**Parameters** | ||
- `urlOrPredicate` **Any** | ||
- `sec` **Any** | ||
## waitForResponse | ||
Waits for a network request. | ||
```js | ||
I.waitForResponse('http://example.com/resource'); | ||
I.waitForResponse(request => request.url() === 'http://example.com' && request.method() === 'GET'); | ||
``` | ||
**Parameters** | ||
- `urlOrPredicate` **Any** | ||
- `sec` **Any** | ||
## waitForText | ||
@@ -1203,0 +1238,0 @@ |
@@ -14,2 +14,6 @@ # WebDriverIO | ||
- `browser`: browser in which to perform testing. | ||
- `host`: (optional, default: localhost) - WebDriver host to connect. | ||
- `port`: (optional, default: 4444) - WebDriver port to connect. | ||
- `protocol`: (optional, default: http) - protocol for WebDriver server. | ||
- `path`: (optional, default: /wd/hub) - path to WebDriver server, | ||
- `restart`: (optional, default: true) - restart browser between tests. | ||
@@ -1306,4 +1310,9 @@ - `smartWait`: (optional) **enables [SmartWait](http://codecept.io/acceptance/#smartwait)**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000. | ||
```js | ||
I.waitForFunction(fn[, [args[, timeout]]) | ||
``` | ||
```js | ||
I.waitForFunction(() => window.requests == 0); | ||
I.waitForFunction(() => window.requests == 0, 5); // waits for 5 sec | ||
I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and wait for 5 sec | ||
``` | ||
@@ -1314,6 +1323,6 @@ | ||
- `function` to be executed in browser context | ||
- `args` arguments for function | ||
- `fn` | ||
- `sec` time seconds to wait, 1 by default | ||
Appium: support | ||
- `timeoutMsg` (optional, default `null`) | ||
- `argsOrSec` (optional, default `null`) | ||
- `sec` time seconds to wait, 1 by defaultAppium: support | ||
@@ -1320,0 +1329,0 @@ ## waitForInvisible |
@@ -148,2 +148,30 @@ # Page Object | ||
To use a Page Fragment within a Test Scenario just inject it into your Scenario: | ||
```js | ||
Scenario('failed_login', async (I, loginPage, modal) => { | ||
loginPage.sendForm('john@doe.com','wrong password'); | ||
I.waitForVisible(modal.root); | ||
within(modal.root, function () { | ||
I.see('Login failed'); | ||
}) | ||
}); | ||
``` | ||
To use a Page Fragment within a Page Object, you need to `require` it on top of the Page Object file: | ||
```js | ||
const I = actor(); | ||
const modal = require('../fragments/modal'); | ||
module.exports = { | ||
doStuff() { | ||
... | ||
modal.accept(); | ||
... | ||
} | ||
} | ||
``` | ||
## StepObjects | ||
@@ -150,0 +178,0 @@ |
@@ -12,19 +12,19 @@ const getConfig = require('./utils').getConfig; | ||
const template = ` | ||
type ICodeceptCallback = (i: CodeceptJS.{{I}}) => void; | ||
type ICodeceptCallback = (i: CodeceptJS.{{I}}{{callbackParams}}) => void; | ||
declare class FeatureConfig { | ||
retry(integer): FeatureConfig | ||
timeout(integer): FeatureConfig | ||
config(object): FeatureConfig | ||
config(string, object): FeatureConfig | ||
retry(times:number): FeatureConfig | ||
timeout(seconds:number): FeatureConfig | ||
config(config:object): FeatureConfig | ||
config(helperName:string, config:object): FeatureConfig | ||
} | ||
declare class ScenarioConfig { | ||
throws(any) : ScenarioConfig; | ||
throws(err:any) : ScenarioConfig; | ||
fails() : ScenarioConfig; | ||
retry(integer): ScenarioConfig | ||
timeout(integer): ScenarioConfig | ||
inject(object): ScenarioConfig | ||
config(object): ScenarioConfig | ||
config(string, object): ScenarioConfig | ||
retry(times:number): ScenarioConfig | ||
timeout(timeout:number): ScenarioConfig | ||
inject(inject:object): ScenarioConfig | ||
config(config:object): ScenarioConfig | ||
config(helperName:string, config:object): ScenarioConfig | ||
} | ||
@@ -43,23 +43,31 @@ | ||
declare class Locator implements ILocator { | ||
or(locator): Locator; | ||
find(locator): Locator; | ||
withChild(locator): Locator; | ||
find(locator): Locator; | ||
at(position): Locator; | ||
xpath?: string; | ||
css?: string; | ||
name?: string; | ||
value?: string; | ||
frame?: string; | ||
android?: string; | ||
ios?: string; | ||
or(locator:string): Locator; | ||
find(locator:string): Locator; | ||
withChild(locator:string): Locator; | ||
find(locator:string): Locator; | ||
at(position:number): Locator; | ||
first(): Locator; | ||
last(): Locator; | ||
inside(locator): Locator; | ||
before(locator): Locator; | ||
after(locator): Locator; | ||
withText(text): Locator; | ||
withAttr(attr): Locator; | ||
as(output): Locator; | ||
inside(locator:string): Locator; | ||
before(locator:string): Locator; | ||
after(locator:string): Locator; | ||
withText(locator:string): Locator; | ||
withAttr(locator:object): Locator; | ||
as(locator:string): Locator; | ||
} | ||
declare function actor(customSteps?: {}): CodeceptJS.{{I}}; | ||
declare function Feature(string: string, opts?: {}): FeatureConfig; | ||
declare function Scenario(string: string, callback: ICodeceptCallback): ScenarioConfig; | ||
declare function Scenario(string: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig; | ||
declare function xScenario(string: string, callback: ICodeceptCallback): ScenarioConfig; | ||
declare function xScenario(string: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig; | ||
declare function Feature(title: string, opts?: {}): FeatureConfig; | ||
declare function Scenario(title: string, callback: ICodeceptCallback): ScenarioConfig; | ||
declare function Scenario(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig; | ||
declare function xScenario(title: string, callback: ICodeceptCallback): ScenarioConfig; | ||
declare function xScenario(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig; | ||
declare function Data(data: any): any; | ||
@@ -74,8 +82,9 @@ declare function xData(data: any): any; | ||
declare function locate(selector: ILocator): Locator; | ||
declare function within(selector: string, callback: Function): Promise; | ||
declare function within(selector: ILocator, callback: Function): Promise; | ||
declare function session(selector: string, callback: Function): Promise; | ||
declare function session(selector: ILocator, callback: Function): Promise; | ||
declare function session(selector: string, config: any, callback: Function): Promise; | ||
declare function session(selector: ILocator, config: any, callback: Function): Promise; | ||
declare function within(selector: string, callback: Function): Promise<any>; | ||
declare function within(selector: ILocator, callback: Function): Promise<any>; | ||
declare function session(selector: string, callback: Function): Promise<any>; | ||
declare function session(selector: ILocator, callback: Function): Promise<any>; | ||
declare function session(selector: string, config: any, callback: Function): Promise<any>; | ||
declare function session(selector: ILocator, config: any, callback: Function): Promise<any>; | ||
declare function pause(): void; | ||
@@ -88,2 +97,3 @@ declare const codecept_helper: any; | ||
} | ||
{{exportPageObjects}} | ||
} | ||
@@ -96,2 +106,8 @@ | ||
const pageObjectTemplate = ` | ||
export interface {{name}} { | ||
{{methods}} | ||
} | ||
`; | ||
module.exports = function (genPath, options) { | ||
@@ -117,20 +133,29 @@ const configFile = options.config || genPath; | ||
const helper = helpers[name]; | ||
for (const action of methodsOfObject(helper)) { | ||
const actionAlias = container.translation() ? container.translation().actionAliasFor(action) : action; | ||
if (!actions[actionAlias]) { | ||
methods = methods.concat(toTypeDef(helper[action])); | ||
actions[actionAlias] = 1; | ||
} | ||
} | ||
methods = addAllMethodsInObject(helper, actions, methods, translations); | ||
} | ||
for (const name in suppportI) { | ||
if (actions[name]) { | ||
continue; | ||
} | ||
const actor = suppportI[name]; | ||
// const params = toTypeDef(actor); | ||
// methods.push(` ${(name)}: (${params}) => any; \n`); | ||
methods = addAllNamesInObject(suppportI, actions, methods); | ||
const supports = container.support(); // return all support objects | ||
const exportPageObjects = []; | ||
const callbackParams = []; | ||
for (const name in supports) { | ||
if (name === 'I') continue; | ||
callbackParams.push(`${name}:any`); | ||
const pageObject = supports[name]; | ||
const pageMethods = addAllMethodsInObject(pageObject, {}, []); | ||
let pageObjectExport = pageObjectTemplate.replace('{{methods}}', pageMethods.join('')); | ||
pageObjectExport = pageObjectExport.replace('{{name}}', name); | ||
exportPageObjects.push(pageObjectExport); | ||
} | ||
let definitionsTemplate = template.replace('{{methods}}', methods.join('')); | ||
definitionsTemplate = definitionsTemplate.replace(/\{\{I\}\}/g, container.translation().I); | ||
definitionsTemplate = definitionsTemplate.replace('{{exportPageObjects}}', exportPageObjects.join('\n')); | ||
if (callbackParams.length > 0) { | ||
definitionsTemplate = definitionsTemplate.replace('{{callbackParams}}', `, ${callbackParams.join(', ')}`); | ||
} else { | ||
definitionsTemplate = definitionsTemplate.replace('{{callbackParams}}', ''); | ||
} | ||
if (translations) { | ||
definitionsTemplate = definitionsTemplate.replace(/\{\{I\}\}/g, translations.I); | ||
} | ||
@@ -146,1 +171,35 @@ fs.writeFileSync(path.join(testsPath, 'steps.d.ts'), definitionsTemplate); | ||
}; | ||
function addAllMethodsInObject(supportObj, actions, methods, translations) { | ||
for (const action of methodsOfObject(supportObj)) { | ||
const actionAlias = translations ? translations.actionAliasFor(action) : action; | ||
if (!actions[actionAlias]) { | ||
methods.push(toTypeDef(supportObj[action])); | ||
actions[actionAlias] = 1; | ||
} | ||
} | ||
return methods; | ||
} | ||
function addAllNamesInObject(supportObj, actions, methods) { | ||
for (const name in supportObj) { | ||
if (actions[name]) { | ||
continue; | ||
} | ||
const actor = supportObj[name]; | ||
let params = toTypeDef(actor); | ||
if (params !== undefined) { | ||
if (params.indexOf(' : ') > 0) { | ||
if (params.indexOf(' (') > 0) { | ||
params = params.trim(); | ||
methods.push(` ${(name)}${params}\n`); | ||
} else { | ||
methods.push(`${params}`); | ||
} | ||
} else { | ||
methods.push(` ${(name)}: (${params}) => any; \n`); | ||
} | ||
} | ||
} | ||
return methods; | ||
} |
@@ -902,5 +902,13 @@ const requireg = require('requireg'); | ||
*/ | ||
async waitForFunction(fn, sec = null) { | ||
async waitForFunction(fn, argsOrSec = null, sec = null) { | ||
let args = []; | ||
if (argsOrSec) { | ||
if (Array.isArray(argsOrSec)) { | ||
args = argsOrSec; | ||
} else if (typeof argsOrSec === 'number') { | ||
sec = argsOrSec; | ||
} | ||
} | ||
this.browser.options.waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout; | ||
return this.browser.wait(fn); | ||
return this.browser.wait(fn, ...args); | ||
} | ||
@@ -907,0 +915,0 @@ |
@@ -1384,5 +1384,14 @@ let EC; | ||
*/ | ||
async waitForFunction(fn, sec = null, timeoutMsg = null) { | ||
async waitForFunction(fn, argsOrSec = null, sec = null) { | ||
let args = []; | ||
if (argsOrSec) { | ||
if (Array.isArray(argsOrSec)) { | ||
args = argsOrSec; | ||
} else if (typeof argsOrSec === 'number') { | ||
sec = argsOrSec; | ||
} | ||
} | ||
const aSec = sec || this.options.waitForTimeout; | ||
return this.browser.wait(() => this.browser.executeScript.call(this.browser, fn), aSec * 1000, timeoutMsg); | ||
return this.browser.wait(() => this.browser.executeScript.call(this.browser, fn, ...args), aSec * 1000); | ||
} | ||
@@ -1389,0 +1398,0 @@ |
@@ -170,3 +170,3 @@ const requireg = require('requireg'); | ||
} catch (e) { | ||
return ['puppeteer@^1.5.0']; | ||
return ['puppeteer@^1.6.0']; | ||
} | ||
@@ -509,3 +509,3 @@ } | ||
// Use manual mouse.move instead of .hover() so the offset can be added to the coordinates | ||
const { x, y } = await els[0]._visibleCenter(); | ||
const { x, y } = await els[0]._clickablePoint(); | ||
await this.page.mouse.move(x + offsetX, y + offsetY); | ||
@@ -570,3 +570,4 @@ return this._waitForAction(); | ||
assertElementExists(els, locator, 'Element'); | ||
const elementCoordinates = await els[0]._visibleCenter(); | ||
await els[0]._scrollIntoViewIfNeeded(); | ||
const elementCoordinates = await els[0]._clickablePoint(); | ||
x = elementCoordinates.x; | ||
@@ -1624,2 +1625,34 @@ y = elementCoordinates.y; | ||
/** | ||
* Waits for a network request. | ||
* | ||
* ```js | ||
* I.waitForRequest('http://example.com/resource'); | ||
* I.waitForRequest(request => request.url() === 'http://example.com' && request.method() === 'GET'); | ||
* ``` | ||
* | ||
* @param {*} urlOrPredicate | ||
* @param {*} sec | ||
*/ | ||
async waitForRequest(urlOrPredicate, sec = null) { | ||
const timeout = sec ? sec * 1000 : this.options.waitForTimeout; | ||
return this.page.waitForRequest(urlOrPredicate, { timeout }); | ||
} | ||
/** | ||
* Waits for a network request. | ||
* | ||
* ```js | ||
* I.waitForResponse('http://example.com/resource'); | ||
* I.waitForResponse(request => request.url() === 'http://example.com' && request.method() === 'GET'); | ||
* ``` | ||
* | ||
* @param {*} urlOrPredicate | ||
* @param {*} sec | ||
*/ | ||
async waitForResponse(urlOrPredicate, sec = null) { | ||
const timeout = sec ? sec * 1000 : this.options.waitForTimeout; | ||
return this.page.waitForResponse(urlOrPredicate, { timeout }); | ||
} | ||
/** | ||
* {{> ../webapi/switchTo }} | ||
@@ -1671,7 +1704,14 @@ */ | ||
*/ | ||
async waitForFunction(fn, sec = null) { | ||
const aSec = sec || this.options.waitForTimeout; | ||
const waitTimeout = aSec * 1000; | ||
async waitForFunction(fn, argsOrSec = null, sec = null) { | ||
let args = []; | ||
if (argsOrSec) { | ||
if (Array.isArray(argsOrSec)) { | ||
args = argsOrSec; | ||
} else if (typeof argsOrSec === 'number') { | ||
sec = argsOrSec; | ||
} | ||
} | ||
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout; | ||
const context = await this._getContext(); | ||
return context.waitForFunction(fn, { timeout: waitTimeout }); | ||
return context.waitForFunction(fn, { timeout: waitTimeout }, ...args); | ||
} | ||
@@ -1696,4 +1736,3 @@ | ||
console.log('This method will remove in CodeceptJS 1.4; use `waitForFunction` instead!'); | ||
const aSec = sec || this.options.waitForTimeout; | ||
const waitTimeout = aSec * 1000; | ||
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout; | ||
const context = await this._getContext(); | ||
@@ -1899,5 +1938,5 @@ return context.waitForFunction(fn, { timeout: waitTimeout }); | ||
// Note: Using private api ._visibleCenter becaues the .BoundingBox does not take into account iframe offsets! | ||
const dragSource = await src[0]._visibleCenter(); | ||
const dragDestination = await dst[0]._visibleCenter(); | ||
// Note: Using private api ._clickablePoint becaues the .BoundingBox does not take into account iframe offsets! | ||
const dragSource = await src[0]._clickablePoint(); | ||
const dragDestination = await dst[0]._clickablePoint(); | ||
@@ -2035,2 +2074,1 @@ // Drag start point | ||
} | ||
@@ -251,3 +251,3 @@ const cssToXPath = require('css-to-xpath'); | ||
function isXPath(locator) { | ||
return locator.substr(0, 2) === '//' || locator.substr(0, 3) === './/'; | ||
return locator.substr(0, 2) === '//' || locator.substr(0, 2) === './'; | ||
} | ||
@@ -254,0 +254,0 @@ |
@@ -43,3 +43,9 @@ const parser = require('parse-function')({ ecmaVersion: 2017 }); | ||
if (fn.name.indexOf('grab') === 0) { | ||
returnType = 'Promise'; | ||
if (fn.name.indexOf('BrowserLog') > 0 || fn.name.indexOf('ScrollPosition') > 0) { | ||
returnType = 'Promise<object>'; | ||
} | ||
if (fn.name.indexOf('Number') > 0) { | ||
returnType = 'Promise<number>'; | ||
} | ||
returnType = 'Promise<string>'; | ||
} | ||
@@ -62,2 +68,5 @@ return ` ${fn.name}(${params}) : ${returnType},\n`; | ||
case 'height': | ||
case 'offset': | ||
case 'offsetX': | ||
case 'offsetY': | ||
return ['number']; | ||
@@ -64,0 +73,0 @@ } |
const container = require('./container'); | ||
const recorder = require('./recorder'); | ||
const event = require('./event'); | ||
const output = require('./output'); | ||
@@ -12,2 +13,3 @@ const methodsOfObject = require('./utils').methodsOfObject; | ||
let finish; | ||
let next; | ||
@@ -17,24 +19,40 @@ /** | ||
*/ | ||
module.exports = function () { | ||
recorder.add('Start new session', () => { | ||
recorder.session.start('pause'); | ||
output.print(colors.yellow(' Interactive debug session started')); | ||
output.print(colors.yellow(' Use JavaScript syntax to try steps in action')); | ||
output.print(colors.yellow(` Press ${colors.bold('ENTER')} to continue`)); | ||
rl = readline.createInterface(process.stdin, process.stdout, completer); | ||
rl.on('line', parseInput); | ||
rl.on('close', () => { | ||
console.log('Exiting interactive shell....'); | ||
const pause = function () { | ||
next = false; | ||
// add listener to all next steps to provide next() functionality | ||
event.dispatcher.on(event.step.after, () => { | ||
recorder.add('Start next pause session', () => { | ||
if (!next) return; | ||
return pauseSession(); | ||
}); | ||
return new Promise(((resolve) => { | ||
finish = resolve; | ||
return askForStep(); | ||
})); | ||
}); | ||
recorder.add('Start new session', pauseSession); | ||
}; | ||
function pauseSession() { | ||
recorder.session.start('pause'); | ||
output.print(colors.yellow(' Interactive shell started')); | ||
output.print(colors.yellow(` Press ${colors.bold('ENTER')} to resume test`)); | ||
if (!next) { | ||
output.print(colors.yellow(' - Use JavaScript syntax to try steps in action')); | ||
output.print(colors.yellow(` - Press ${colors.bold('TAB')} twice to see all available commands`)); | ||
output.print(colors.yellow(` - Enter ${colors.bold('next')} to run the next step`)); | ||
} | ||
rl = readline.createInterface(process.stdin, process.stdout, completer); | ||
rl.on('line', parseInput); | ||
rl.on('close', () => { | ||
console.log('Exiting interactive shell....'); | ||
}); | ||
return new Promise(((resolve) => { | ||
finish = resolve; | ||
return askForStep(); | ||
})); | ||
} | ||
function parseInput(cmd) { | ||
rl.pause(); | ||
if (!cmd) { | ||
next = false; | ||
if (cmd === 'next') next = true; | ||
if (!cmd || cmd === 'next') { | ||
finish(); | ||
@@ -80,1 +98,3 @@ recorder.session.restore(); | ||
} | ||
module.exports = pause; |
{ | ||
"name": "codeceptjs", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"description": "Modern Era Acceptance Testing Framework for NodeJS", | ||
@@ -40,5 +40,5 @@ "keywords": [ | ||
"chalk": "^1.1.3", | ||
"commander": "^2.14.1", | ||
"commander": "^2.16.0", | ||
"css-to-xpath": "^0.1.0", | ||
"cucumber-expressions": "^6.0.0", | ||
"cucumber-expressions": "^6.0.1", | ||
"escape-string-regexp": "^1.0.3", | ||
@@ -51,5 +51,5 @@ "fn-args": "^3.0.0", | ||
"mocha": "^4.1.0", | ||
"parse-function": "^5.2.7", | ||
"parse-function": "^5.2.10", | ||
"promise-retry": "^1.1.1", | ||
"requireg": "^0.1.5", | ||
"requireg": "^0.1.8", | ||
"sprintf-js": "^1.1.1" | ||
@@ -59,12 +59,12 @@ }, | ||
"@types/inquirer": "^0.0.35", | ||
"@types/node": "^8.10.12", | ||
"@types/node": "^8.10.21", | ||
"chai": "^3.4.1", | ||
"chai-as-promised": "^5.2.0", | ||
"co-mocha": "^1.2", | ||
"documentation": "^4.0.0-beta1", | ||
"eslint": "^4.17.0", | ||
"eslint-config-airbnb-base": "^12.1.0", | ||
"eslint-plugin-import": "^2.8.0", | ||
"eslint-plugin-import": "^2.13.0", | ||
"faker": "^4.1.0", | ||
"gulp": "^3.9.1", | ||
"documentation": "^4.0.0-beta1", | ||
"gulp-documentation": "^2.2.0", | ||
@@ -74,11 +74,11 @@ "gulp-mustache": "^2.2.0", | ||
"nightmare": "^3.0.0", | ||
"nyc": "^11.5.0", | ||
"protractor": "^5.3.0", | ||
"puppeteer": "^1.5.0", | ||
"nyc": "^11.9.0", | ||
"protractor": "^5.3.2", | ||
"puppeteer": "^1.6.0", | ||
"rosie": "^1.6.0", | ||
"sinon": "^1.17.2", | ||
"sinon-chai": "^2.14.0", | ||
"typescript": "^2.8.3", | ||
"typescript": "^2.9.2", | ||
"unirest": "^0.5.1", | ||
"webdriverio": "^4.10.2", | ||
"webdriverio": "^4.13.1", | ||
"xmldom": "^0.1.27", | ||
@@ -85,0 +85,0 @@ "xpath": "0.0.27" |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
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
1159289
23957
Updatedcommander@^2.16.0
Updatedcucumber-expressions@^6.0.1
Updatedparse-function@^5.2.10
Updatedrequireg@^0.1.8