diff --git a/async/constants.js b/async/constants.js index afa7610..89cc933 100644 --- a/async/constants.js +++ b/async/constants.js @@ -7,6 +7,12 @@ exports.HOOKS = [ `afterEach`, `suite`, `test`, + `When`, + `Given`, + `Then`, + `After`, + `Before`, + `BeforeStep`, ]; // Commands here will have async added to them @@ -51,6 +57,8 @@ exports.JS_BUILT_IN = [ `Error`, `includes`, `trim`, + `trimStart`, + `trimEnd`, `constructor`, `toExponential`, `toFixed`, @@ -161,6 +169,8 @@ exports.JS_BUILT_IN = [ `toString`, `toTimeString`, `toUTCString`, + `DateTimeFormat`, + `format`, `valueOf`, `abs`, `acos`, @@ -172,6 +182,7 @@ exports.JS_BUILT_IN = [ `exp`, `floor`, `log`, + `error`, `max`, `min`, `pow`, @@ -185,7 +196,29 @@ exports.JS_BUILT_IN = [ `test`, `toSource`, `toString`, + `parse`, `parseInt`, `parseFloat`, `isNaN`, + `cwd`, + `find`, + `findIndex`, + `stringify`, + `resolve`, + `resolve2`, + `addAttachment`, + `addDescription`, + `encodeURIComponent`, + `decodeURIComponent`, + `base64Sync`, + `readFileSync`, + `writeFileSync`, + `existsSync`, + `querySelector`, + `fromFile`, + `then`, + `request`, + `from`, + `merge`, + `get`, ]; diff --git a/async/index.js b/async/index.js index b8a28a1..fee0176 100644 --- a/async/index.js +++ b/async/index.js @@ -271,12 +271,10 @@ module.exports = function transformer(file, api, opts) { name } }).replaceWith(path => { - const index = [`it`, `xit`, `test`, `describe`, `xdescribe`].includes(name) ? 1 : 0; - + const index = [`it`, `xit`, `test`, `describe`, `xdescribe`, `When`, `Given`, `Then`, `Before`, `BeforeStep`].includes(name) ? 1 : 0; if(path.value.arguments[index] && path.value.arguments[index].type === `ArrowFunctionExpression`) { path.value.arguments[index].async = true } - return path.value; }); }); @@ -470,9 +468,7 @@ module.exports = function transformer(file, api, opts) { if(EXCLUDE_METHODS.includes(path.value.key.name)) { return path.value; } - path.value.value.async = true; - return path.value; }); @@ -484,13 +480,12 @@ module.exports = function transformer(file, api, opts) { if(EXCLUDE_METHODS.includes(path.value.key.name)) { return path.value; } - path.value.async = true; return path.value; }); - // Set all function definitions to async + // Set all function definitions to async if await is present [`FunctionDeclaration`, `ArrowFunctionExpression`].forEach(name => { root.find(j[name]).replaceWith(path => { // Don't convert object literals @@ -507,6 +502,15 @@ module.exports = function transformer(file, api, opts) { return path.value; } + // If function has already been wrapped in a Promise then don't do anything + if( + path.parent.value.callee && + path.parent.value.callee.name === `Promise` + ) { + return path.value; + } + + path.value.async = true; return path.value; diff --git a/test/__fixtures__/async/source/spec.js b/test/__fixtures__/async/source/spec.js index f1b1d84..fe45a1e 100644 --- a/test/__fixtures__/async/source/spec.js +++ b/test/__fixtures__/async/source/spec.js @@ -160,3 +160,15 @@ const getColumns = (foo, bar) => { const foobar = () => ({ foo : 123 }); + +async function requestAsync() { + return new Promise(resolve => { + request({ + url: 'https://api.github.com', + method: 'POST', + headers: { + accept: 'application/json', + }, + }, (res) => resolve(res ? true : false)); + }); +} \ No newline at end of file diff --git a/test/__fixtures__/async/source/steps.js b/test/__fixtures__/async/source/steps.js new file mode 100644 index 0000000..fc73271 --- /dev/null +++ b/test/__fixtures__/async/source/steps.js @@ -0,0 +1,49 @@ +When('I click on the element {string}', (selector) => { + $(selector).click(); +}); + +When('I am open webDriverIO', () => { + browser.url('https://webdriver.io'); +}); + +Given(/^I switch to frame "([^"]*)?"$/, switchToFrame); + +Then( + /^I wait on element "([^"]*)?"(?: for (\d+)ms)*(?: to( not)* (be checked|be enabled|be selected|be displayed|contain a text|contain a value|exist|contain the text))*( "([^"]*)?")*$/, + { + wrapperOptions: { + retry: 3, + }, + }, + waitFor +); + +After((scenario) => { + if (scenario.result.status === 'SKIPPED') { + return true; + } + + if (scenario.result.status === 'PASSED' && failureObject === null) { + return true; + } + console.log('Save a screenshot'); + browser.saveScreenshot(filePath); +}); + +Before({ tags: '@NotMandatory' }, () => { + if (browser.params.featureContext === 'skip NotMandatory scenarios') { + return 'skipped'; + } + return true; + }); + +BeforeStep((feat) => { + const scenario = JSON.stringify(feat.pickle); + if (scenario && (scenario.includes('endif') || scenario.includes('else'))) { + return true; + } + if (browser.params.scenarioContext === 'skip next steps') { + return 'skipped'; + } + return true; +}); \ No newline at end of file diff --git a/test/__fixtures__/async/transformed/spec.js b/test/__fixtures__/async/transformed/spec.js index b186a0a..467dce3 100644 --- a/test/__fixtures__/async/transformed/spec.js +++ b/test/__fixtures__/async/transformed/spec.js @@ -164,3 +164,15 @@ const getColumns = async (foo, bar) => { const foobar = () => ({ foo : 123 }); + +async function requestAsync() { + return new Promise(resolve => { + request({ + url: 'https://api.github.com', + method: 'POST', + headers: { + accept: 'application/json', + }, + }, (res) => resolve(res ? true : false)); + }); +} \ No newline at end of file diff --git a/test/__fixtures__/async/transformed/steps.js b/test/__fixtures__/async/transformed/steps.js new file mode 100644 index 0000000..9ab539e --- /dev/null +++ b/test/__fixtures__/async/transformed/steps.js @@ -0,0 +1,49 @@ +When('I click on the element {string}', async selector => { + await $(selector).click(); +}); + +When('I am open webDriverIO', async () => { + await browser.url('https://webdriver.io'); +}); + +Given(/^I switch to frame "([^"]*)?"$/, switchToFrame); + +Then( + /^I wait on element "([^"]*)?"(?: for (\d+)ms)*(?: to( not)* (be checked|be enabled|be selected|be displayed|contain a text|contain a value|exist|contain the text))*( "([^"]*)?")*$/, + { + wrapperOptions: { + retry: 3, + }, + }, + waitFor +); + +After(async scenario => { + if (scenario.result.status === 'SKIPPED') { + return true; + } + + if (scenario.result.status === 'PASSED' && failureObject === null) { + return true; + } + console.log('Save a screenshot'); + await browser.saveScreenshot(filePath); +}); + +Before({ tags: '@NotMandatory' }, async () => { + if (browser.params.featureContext === 'skip NotMandatory scenarios') { + return 'skipped'; + } + return true; + }); + +BeforeStep((feat) => { + const scenario = JSON.stringify(feat.pickle); + if (scenario && (scenario.includes('endif') || scenario.includes('else'))) { + return true; + } + if (browser.params.scenarioContext === 'skip next steps') { + return 'skipped'; + } + return true; +}); \ No newline at end of file diff --git a/test/runner.js b/test/runner.js index ce3854b..2e238a1 100644 --- a/test/runner.js +++ b/test/runner.js @@ -38,7 +38,8 @@ const frameworkTests = { ], async: [ ['./spec.js', './spec.js'], - ['./page.js', './page.js'] + ['./page.js', './page.js'], + ['./steps.js', './steps.js'] ] } @@ -58,7 +59,10 @@ async function runTest (framework, tests, parser = 'babel') { [srcFile], { verbose: 2, - parser + parser, + printOptions : { + lineTerminator: '\n' + } } )