我正在尝试再次运行e2e量角器测试Selenium Grid-Firefox,但是由于“浏览上下文已被丢弃”,因此继续遇到此错误。
堆栈跟踪的示例是:
× should have expected page elements #Smoke
- Failed: Browsing context has been discarded
at Object.throwDecodedError (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\error.js:514:15)
at parseHttpResponse (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\http.js:519:13)
at doSend.then.response (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\http.js:441:30)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
From: Task: Protractor.waitForAngular() - Locator: By(css selector, select[formControlName="pageType"])
at thenableWebDriverProxy.schedule (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
at ProtractorBrowser.executeAsyncScript_ (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\built\browser.js:425:28)
at angularAppRoot.then (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\built\browser.js:456:33)
at ManagedPromise.invokeCallback_ (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:1376:14)
at TaskQueue.execute_ (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:3084:14)
at TaskQueue.executeNext_ (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:3067:27)
at asyncRun (C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2927:27)
at C:\Users\User\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:668:7
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
From: Task: <anonymous>
奇怪的是,如果我更改测试代码的一部分,它将通过。这是测试样本
import Base from "../../common-pages/base.po";
describe('Edit Page', function () {
let pageName = "AutoQA Page " + base.now();
beforeAll(function (done) {
login = new Login();
login.login(login.userAdmin, login.password);
pages = new Pages();
let newPage = {
'pageName': pageName,
'pageKey': pageKey
};
pages.sendApiRequest('POST', pages.pagesEndpoint, newPage, 200);
done();
});
beforeEach(function (done) {
pages.goto(pages.url);
pages.searchPages(pageName);
pages.getFirstRecordInTable().click(); // this seems to be where context is discarded
form = new PageForm();
appliedPageType = form.getElementText(form.pageTypeField);
done();
});
it('test case #Smoke', function (done) {
// removed test code because it doesn't make it here
done();
});
});
上面的代码不起作用,但是如果我仅将pages.searchPages(pageName);
位更改为页面上的某些现有数据(如pages.searchPages("Existing Page A");
),它将按预期到达测试代码...
任何帮助将不胜感激。已经尝试了诸如将geckoversion强制为20.0的操作(我已经在s / o上看到了此问题,但没有用)
以下是与我相关的版本:
硒:3.141.59
壁虎驱动程序:v0.24.0
量角器:5.4.1
节点:8.11.4
这是来自geckodriver的调试日志:
1558383055692 Marionette DEBUG 0 <- [1,120,null,[{"element-6066-11e4-a52e-4f735466cecf":"9c8208bb-e666-484e-b565-716b11d93a08"},{"element-6066-11e4-a52e-4f735466 ... ecf":"5249171e-cbe6-4594-b06a-aac99ae6c777"},{"element-6066-11e4-a52e-4f735466cecf":"81bae4a4-f023-4a12-9348-8ba6169b5e60"}]]
1558383055692 webdriver::server DEBUG <- 200 OK {"value":[{"element-6066-11e4-a52e-4f735466cecf":"9c8208bb-e666-484e-b565-716b11d93a08"},{"element-6066-11e4-a52e-4f735466cecf":"0b6b9bcf-5247-4f70-ad1e-b7eadbaa5d4a"},{"element-6066-11e4-a52e-4f735466cecf":"d3a89d8b-54a2-4e15-a4fe-29ebae88905a"},{"element-6066-11e4-a52e-4f735466cecf":"5249171e-cbe6-4594-b06a-aac99ae6c777"},{"element-6066-11e4-a52e-4f735466cecf":"81bae4a4-f023-4a12-9348-8ba6169b5e60"}]}
1558383055705 webdriver::server DEBUG -> GET /session/db6b42c4-ef8d-485f-9aca-4b4951924089/element/9c8208bb-e666-484e-b565-716b11d93a08/text
1558383055706 Marionette DEBUG 0 -> [0,121,"WebDriver:GetElementText",{"id":"9c8208bb-e666-484e-b565-716b11d93a08"}]
1558383055711 Marionette DEBUG 0 <- [1,121,null,{"value":"AutoQA Page 1558383045962"}]
1558383055712 webdriver::server DEBUG <- 200 OK {"value":"AutoQA Page 1558383045962"}
1558383055723 webdriver::server DEBUG -> POST /session/db6b42c4-ef8d-485f-9aca-4b4951924089/execute/async {"script":"try { return (function anonymous() {\nfunction getNg1Hooks(selector, injectorPlease) {\n function tryEl(el) {\n try {\n if (!injectorPlease && angular.getTestability) {\n var $$testability = angular.getTestability(el);\n if ($$testability) {\n return {$$testability: $$testability};\n }\n } else {\n var $injector = angular.element(el).injector();\n if ($injector) {\n return {$injector: $injector};\n }\n }\n } catch(err) {}\n }\n function trySelector(selector) {\n var els = document.querySelectorAll(selector);\n for (var i = 0; i < els.length; i++) {\n var elHooks = tryEl(els[i]);\n if (elHooks) {\n return elHooks;\n }\n }\n }\n\n if (selector) {\n return trySelector(selector);\n } else if (window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__) {\n var $injector = window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__;\n var $$testability = null;\n try {\n $$testability = $injector.get('$$testability');\n } catch (e) {}\n return {$injector: $injector, $$testability: $$testability};\n } else {\n return tryEl(document.body) ||\n trySelector('[ng-app]') || trySelector('[ng\\\\:app]') ||\n trySelector('[ng-controller]') || trySelector('[ng\\\\:controller]');\n }\n}; return (function (rootSelector, callback) {\n\n try {\n // Wait for both angular1 testability and angular2 testability.\n\n var testCallback = callback;\n\n // Wait for angular1 testability first and run waitForAngular2 as a callback\n var waitForAngular1 = function(callback) {\n\n if (window.angular) {\n var hooks = getNg1Hooks(rootSelector);\n if (!hooks){\n callback(); // not an angular1 app\n }\n else{\n if (hooks.$$testability) {\n hooks.$$testability.whenStable(callback);\n } else if (hooks.$injector) {\n hooks.$injector.get('$browser')\n .notifyWhenNoOutstandingRequests(callback);\n } else if (!rootSelector) {\n throw new Error(\n 'Could not automatically find injector on page: \"' +\n window.location.toString() + '\". Consider using config.rootEl');\n } else {\n throw new Error(\n 'root element (' + rootSelector + ') has no injector.' +\n ' this may mean it is not inside ng-app.');\n }\n }\n }\n else {callback();} // not an angular1 app\n };\n\n // Wait for Angular2 testability and then run test callback\n var waitForAngular2 = function() {\n if (window.getAngularTestability) {\n if (rootSelector) {\n var testability = null;\n var el = document.querySelector(rootSelector);\n try{\n testability = window.getAngularTestability(el);\n }\n catch(e){}\n if (testability) {\n testability.whenStable(testCallback);\n return;\n }\n }\n\n // Didn't specify root element or testability could not be found\n // by rootSelector. This may happen in a hybrid app, which could have\n // more than one root.\n var testabilities = window.getAllAngularTestabilities();\n var count = testabilities.length;\n\n // No angular2 testability, this happens when\n // going to a hybrid page and going back to a pure angular1 page\n if (count === 0) {\n testCallback();\n return;\n }\n\n var decrement = function() {\n count--;\n if (count === 0) {\n testCallback();\n }\n };\n testabilities.forEach(function(testability) {\n testability.whenStable(decrement);\n });\n\n }\n else {testCallback();} // not an angular2 app\n };\n\n if (!(window.angular) && !(window.getAngularTestability)) {\n // no testability hook\n throw new Error(\n 'both angularJS testability and angular testability are undefined.' +\n ' This could be either ' +\n 'because this is a non-angular page or because your test involves ' +\n 'client-side navigation, which can interfere with Protractor\\'s ' +\n 'bootstrapping. See http://git.io/v4gXM for details');\n } else {waitForAngular1(waitForAngular2);} // Wait for angular1 and angular2\n // Testability hooks sequentially\n\n } catch (err) {\n callback(err.message);\n }\n\n}).apply(this, arguments);\n}).apply(this, arguments); }\ncatch(e) { throw (e instanceof Error) ? e : new Error(e); }","args":[""]}
1558383055725 Marionette DEBUG 0 -> [0,122,"WebDriver:ExecuteAsyncScript",{"args":[""],"script":"try { return (function anonymous() {\nfunction getNg1Hooks(selec ... }\n\n}).apply(this, arguments);\n}).apply(this, arguments); }\ncatch(e) { throw (e instanceof Error) ? e : new Error(e); }"}]
1558383055728 Marionette DEBUG 0 <- [1,122,null,{"value":null}]
1558383055728 webdriver::server DEBUG <- 200 OK {"value":null}
1558383055738 webdriver::server DEBUG -> POST /session/db6b42c4-ef8d-485f-9aca-4b4951924089/elements {"using":"css selector","value":".table-striped"}
1558383055739 Marionette DEBUG 0 -> [0,123,"WebDriver:FindElements",{"using":"css selector","value":".table-striped"}]
1558383055741 Marionette DEBUG 0 <- [1,123,null,[{"element-6066-11e4-a52e-4f735466cecf":"9b283ce7-4e06-46a4-ab94-776e4e52def8"}]]
1558383055742 webdriver::server DEBUG <- 200 OK {"value":[{"element-6066-11e4-a52e-4f735466cecf":"9b283ce7-4e06-46a4-ab94-776e4e52def8"}]}
1558383055752 webdriver::server DEBUG -> POST /session/db6b42c4-ef8d-485f-9aca-4b4951924089/element/9b283ce7-4e06-46a4-ab94-776e4e52def8/elements {"using":"css selector","value":"tbody > tr.d-flex > td"}
1558383055753 Marionette DEBUG 0 -> [0,124,"WebDriver:FindElements",{"element":"9b283ce7-4e06-46a4-ab94-776e4e52def8","using":"css selector","value":"tbody > tr.d-flex > td"}]
1558383055755 Marionette DEBUG 0 <- [1,124,null,[{"element-6066-11e4-a52e-4f735466cecf":"9c8208bb-e666-484e-b565-716b11d93a08"},{"element-6066-11e4-a52e-4f735466 ... ecf":"5249171e-cbe6-4594-b06a-aac99ae6c777"},{"element-6066-11e4-a52e-4f735466cecf":"81bae4a4-f023-4a12-9348-8ba6169b5e60"}]]
1558383055756 webdriver::server DEBUG <- 200 OK {"value":[{"element-6066-11e4-a52e-4f735466cecf":"9c8208bb-e666-484e-b565-716b11d93a08"},{"element-6066-11e4-a52e-4f735466cecf":"0b6b9bcf-5247-4f70-ad1e-b7eadbaa5d4a"},{"element-6066-11e4-a52e-4f735466cecf":"d3a89d8b-54a2-4e15-a4fe-29ebae88905a"},{"element-6066-11e4-a52e-4f735466cecf":"5249171e-cbe6-4594-b06a-aac99ae6c777"},{"element-6066-11e4-a52e-4f735466cecf":"81bae4a4-f023-4a12-9348-8ba6169b5e60"}]}
1558383055771 webdriver::server DEBUG -> POST /session/db6b42c4-ef8d-485f-9aca-4b4951924089/element/9c8208bb-e666-484e-b565-716b11d93a08/click {}
1558383055812 Marionette DEBUG 0 -> [0,125,"WebDriver:ElementClick",{"id":"9c8208bb-e666-484e-b565-716b11d93a08"}]
[Parent 79, Gecko_IOThread] WARNING: pipe error (76): Connection reset by peer: file /builds/worker/workspace/build/src/ipc/chromium/src/chrome/common/ipc_channel_posix.cc, line 349
2019-05-20T20:10:56.191328300Z
###!!! [Parent][MessageChannel] Error: (msgtype=0x1E0086,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv
2019-05-20T20:10:56.191359600Z
1558383056220 Marionette TRACE [19] Frame script loaded
1558383056220 Marionette TRACE [19] Frame script registered
A content process crashed and MOZ_CRASHREPORTER_SHUTDOWN is set, shutting down
1558383056259 Marionette TRACE [19] Check readyState uninitialized for about:blank
1558383056292 Marionette TRACE Received DOM event unload for [object XULDocument]
1558383056300 Marionette TRACE Received observer notification message-manager-disconnect
1558383056303 Marionette DEBUG 0 <- [1,125,null,{"value":null}]
1558383056311 webdriver::server DEBUG <- 200 OK {"value":null}
1558383056324 webdriver::server DEBUG -> POST /session/db6b42c4-ef8d-485f-9aca-4b4951924089/execute/async {"script":"try { return (function anonymous() {\nfunction getNg1Hooks(selector, injectorPlease) {\n function tryEl(el) {\n try {\n if (!injectorPlease && angular.getTestability) {\n var $$testability = angular.getTestability(el);\n if ($$testability) {\n return {$$testability: $$testability};\n }\n } else {\n var $injector = angular.element(el).injector();\n if ($injector) {\n return {$injector: $injector};\n }\n }\n } catch(err) {}\n }\n function trySelector(selector) {\n var els = document.querySelectorAll(selector);\n for (var i = 0; i < els.length; i++) {\n var elHooks = tryEl(els[i]);\n if (elHooks) {\n return elHooks;\n }\n }\n }\n\n if (selector) {\n return trySelector(selector);\n } else if (window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__) {\n var $injector = window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__;\n var $$testability = null;\n try {\n $$testability = $injector.get('$$testability');\n } catch (e) {}\n return {$injector: $injector, $$testability: $$testability};\n } else {\n return tryEl(document.body) ||\n trySelector('[ng-app]') || trySelector('[ng\\\\:app]') ||\n trySelector('[ng-controller]') || trySelector('[ng\\\\:controller]');\n }\n}; return (function (rootSelector, callback) {\n\n try {\n // Wait for both angular1 testability and angular2 testability.\n\n var testCallback = callback;\n\n // Wait for angular1 testability first and run waitForAngular2 as a callback\n var waitForAngular1 = function(callback) {\n\n if (window.angular) {\n var hooks = getNg1Hooks(rootSelector);\n if (!hooks){\n callback(); // not an angular1 app\n }\n else{\n if (hooks.$$testability) {\n hooks.$$testability.whenStable(callback);\n } else if (hooks.$injector) {\n hooks.$injector.get('$browser')\n .notifyWhenNoOutstandingRequests(callback);\n } else if (!rootSelector) {\n throw new Error(\n 'Could not automatically find injector on page: \"' +\n window.location.toString() + '\". Consider using config.rootEl');\n } else {\n throw new Error(\n 'root element (' + rootSelector + ') has no injector.' +\n ' this may mean it is not inside ng-app.');\n }\n }\n }\n else {callback();} // not an angular1 app\n };\n\n // Wait for Angular2 testability and then run test callback\n var waitForAngular2 = function() {\n if (window.getAngularTestability) {\n if (rootSelector) {\n var testability = null;\n var el = document.querySelector(rootSelector);\n try{\n testability = window.getAngularTestability(el);\n }\n catch(e){}\n if (testability) {\n testability.whenStable(testCallback);\n return;\n }\n }\n\n // Didn't specify root element or testability could not be found\n // by rootSelector. This may happen in a hybrid app, which could have\n // more than one root.\n var testabilities = window.getAllAngularTestabilities();\n var count = testabilities.length;\n\n // No angular2 testability, this happens when\n // going to a hybrid page and going back to a pure angular1 page\n if (count === 0) {\n testCallback();\n return;\n }\n\n var decrement = function() {\n count--;\n if (count === 0) {\n testCallback();\n }\n };\n testabilities.forEach(function(testability) {\n testability.whenStable(decrement);\n });\n\n }\n else {testCallback();} // not an angular2 app\n };\n\n if (!(window.angular) && !(window.getAngularTestability)) {\n // no testability hook\n throw new Error(\n 'both angularJS testability and angular testability are undefined.' +\n ' This could be either ' +\n 'because this is a non-angular page or because your test involves ' +\n 'client-side navigation, which can interfere with Protractor\\'s ' +\n 'bootstrapping. See http://git.io/v4gXM for details');\n } else {waitForAngular1(waitForAngular2);} // Wait for angular1 and angular2\n // Testability hooks sequentially\n\n } catch (err) {\n callback(err.message);\n }\n\n}).apply(this, arguments);\n}).apply(this, arguments); }\ncatch(e) { throw (e instanceof Error) ? e : new Error(e); }","args":[""]}
1558383056326 Marionette DEBUG 0 -> [0,126,"WebDriver:ExecuteAsyncScript",{"args":[""],"script":"try { return (function anonymous() {\nfunction getNg1Hooks(selec ... }\n\n}).apply(this, arguments);\n}).apply(this, arguments); }\ncatch(e) { throw (e instanceof Error) ? e : new Error(e); }"}]
1558383056327 Marionette DEBUG 0 <- [1,126,{"error":"no such window","message":"Browsing context has been discarded","stacktrace":"WebDriverError@chrome://marion ... et@chrome://marionette/content/server.js:236:8\n_onJSONObjectReady/<@chrome://marionette/content/transport.js:490:9\n"},null]
1558383056331 webdriver::server DEBUG <- 404 Not Found {"value":{"error":"no such window","message":"Browsing context has been discarded","stacktrace":"WebDriverError@chrome://marionette/content/error.js:179:5\nNoSuchWindowError@chrome://marionette/content/error.js:411:5\nassert.that/<@chrome://marionette/content/assert.js:418:13\nassert.open@chrome://marionette/content/assert.js:174:10\nGeckoDriver.prototype.execute_@chrome://marionette/content/driver.js:994:3\nGeckoDriver.prototype.executeAsyncScript@chrome://marionette/content/driver.js:975:24\ndespatch@chrome://marionette/content/server.js:291:20\nexecute@chrome://marionette/content/server.js:264:11\nonPacket/<@chrome://marionette/content/server.js:237:15\nonPacket@chrome://marionette/content/server.js:236:8\n_onJSONObjectReady/<@chrome://marionette/content/transport.js:490:9\n"}}
1558383056371 webdriver::server DEBUG -> POST /session/db6b42c4-ef8d-485f-9aca-4b4951924089/execute/async {"script":"try { return (function anonymous() {\nfunction getNg1Hooks(selector, injectorPlease) {\n function tryEl(el) {\n try {\n if (!injectorPlease && angular.getTestability) {\n var $$testability = angular.getTestability(el);\n if ($$testability) {\n return {$$testability: $$testability};\n }\n } else {\n var $injector = angular.element(el).injector();\n if ($injector) {\n return {$injector: $injector};\n }\n }\n } catch(err) {}\n }\n function trySelector(selector) {\n var els = document.querySelectorAll(selector);\n for (var i = 0; i < els.length; i++) {\n var elHooks = tryEl(els[i]);\n if (elHooks) {\n return elHooks;\n }\n }\n }\n\n if (selector) {\n return trySelector(selector);\n } else if (window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__) {\n var $injector = window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__;\n var $$testability = null;\n try {\n $$testability = $injector.get('$$testability');\n } catch (e) {}\n return {$injector: $injector, $$testability: $$testability};\n } else {\n return tryEl(document.body) ||\n trySelector('[ng-app]') || trySelector('[ng\\\\:app]') ||\n trySelector('[ng-controller]') || trySelector('[ng\\\\:controller]');\n }\n}; return (function (rootSelector, callback) {\n\n try {\n // Wait for both angular1 testability and angular2 testability.\n\n var testCallback = callback;\n\n // Wait for angular1 testability first and run waitForAngular2 as a callback\n var waitForAngular1 = function(callback) {\n\n if (window.angular) {\n var hooks = getNg1Hooks(rootSelector);\n if (!hooks){\n callback(); // not an angular1 app\n }\n else{\n if (hooks.$$testability) {\n hooks.$$testability.whenStable(callback);\n } else if (hooks.$injector) {\n hooks.$injector.get('$browser')\n .notifyWhenNoOutstandingRequests(callback);\n } else if (!rootSelector) {\n throw new Error(\n 'Could not automatically find injector on page: \"' +\n window.location.toString() + '\". Consider using config.rootEl');\n } else {\n throw new Error(\n 'root element (' + rootSelector + ') has no injector.' +\n ' this may mean it is not inside ng-app.');\n }\n }\n }\n else {callback();} // not an angular1 app\n };\n\n // Wait for Angular2 testability and then run test callback\n var waitForAngular2 = function() {\n if (window.getAngularTestability) {\n if (rootSelector) {\n var testability = null;\n var el = document.querySelector(rootSelector);\n try{\n testability = window.getAngularTestability(el);\n }\n catch(e){}\n if (testability) {\n testability.whenStable(testCallback);\n return;\n }\n }\n\n // Didn't specify root element or testability could not be found\n // by rootSelector. This may happen in a hybrid app, which could have\n // more than one root.\n var testabilities = window.getAllAngularTestabilities();\n var count = testabilities.length;\n\n // No angular2 testability, this happens when\n // going to a hybrid page and going back to a pure angular1 page\n if (count === 0) {\n testCallback();\n return;\n }\n\n var decrement = function() {\n count--;\n if (count === 0) {\n testCallback();\n }\n };\n testabilities.forEach(function(testability) {\n testability.whenStable(decrement);\n });\n\n }\n else {testCallback();} // not an angular2 app\n };\n\n if (!(window.angular) && !(window.getAngularTestability)) {\n // no testability hook\n throw new Error(\n 'both angularJS testability and angular testability are undefined.' +\n ' This could be either ' +\n 'because this is a non-angular page or because your test involves ' +\n 'client-side navigation, which can interfere with Protractor\\'s ' +\n 'bootstrapping. See http://git.io/v4gXM for details');\n } else {waitForAngular1(waitForAngular2);} // Wait for angular1 and angular2\n // Testability hooks sequentially\n\n } catch (err) {\n callback(err.message);\n }\n\n}).apply(this, arguments);\n}).apply(this, arguments); }\ncatch(e) { throw (e instanceof Error) ? e : new Error(e); }","args":[""]}
1558383056375 webdriver::server DEBUG Deleting session