diff --git a/index.js b/index.js index 06c94e4..3e4b6ee 100644 --- a/index.js +++ b/index.js @@ -59,6 +59,22 @@ function validateString(stringtoValidate) { } } +/** + * Calls a function once the control flow is idle + * @param {webdriver.promise.ControlFlow} flow The Web Driver control flow + * @param {!Function} fn The function to call + */ +function callWhenIdle(flow, fn) { + if (flow.isIdle()) { + fn(); + } else { + flow.once(webdriver.promise.ControlFlow.EventType.IDLE, function() { + fn(); + }); + } +} + + /** * Wraps a function so it runs inside a webdriver.promise.ControlFlow and * waits for the flow to complete before continuing. @@ -78,30 +94,38 @@ function wrapInControlFlow(flow, globalFn, fnName) { flow.execute(function controlFlowExecute() { return new webdriver.promise.Promise(function(fulfill, reject) { + function wrappedReject(err) { + var wrappedErr = new Error(err); + reject(wrappedErr); + } if (async) { // If testFn is async (it expects a done callback), resolve the promise of this // test whenever that callback says to. Any promises returned from testFn are // ignored. var proxyDone = fulfill; - proxyDone.fail = function(err) { - var wrappedErr = new Error(err); - reject(wrappedErr); - }; + proxyDone.fail = wrappedReject; testFn(proxyDone); } else { // Without a callback, testFn can return a promise, or it will // be assumed to have completed synchronously. - fulfill(testFn()); + var ret = testFn(); + if (webdriver.promise.isPromise(ret)) { + ret.then(fulfill, wrappedReject); + } else { + fulfill(ret); + } } }, flow); - }, 'Run ' + fnName + description + ' in control flow').then(seal(done), function(err) { - if (!err) { - err = new Error('Unknown Error'); - err.stack = ''; + }, 'Run ' + fnName + description + ' in control flow').then( + callWhenIdle.bind(null, flow, done), function(err) { + if (!err) { + err = new Error('Unknown Error'); + err.stack = ''; + } + err.stack = err.stack + '\nFrom asynchronous test: \n' + driverError.stack; + callWhenIdle(flow, done.fail.bind(done, err)); } - err.stack = err.stack + '\nFrom asynchronous test: \n' + driverError.stack; - done.fail(err); - }); + ); }; } diff --git a/spec/adapterSpec.js b/spec/adapterSpec.js index 6fce99e..9dcbbaf 100644 --- a/spec/adapterSpec.js +++ b/spec/adapterSpec.js @@ -242,4 +242,24 @@ describe('webdriverJS Jasmine adapter', function() { expect(spec3.description).toBe('test3'); }); }); + + describe('should handle returning native promises', () => { + var currentTest = null; + + it('test A', () => { + currentTest = 'A'; + return new Promise((resolve) => { + setTimeout(() => { + fakeDriver.sleep(100).then(() => { + expect(currentTest).toBe('A'); + }); + resolve(); + }, 100); + }); + }); + + it('test B', () => { + currentTest = 'B'; + }); + }); });