Delaying execution of protractor elementArrayFinder.map
If you call an map
ArrayFinder transport element function , it will immediately search the DOM for the elements that will render them, which is different from the behavior $$
that waits until the child elementArrayFinder is evaluated to find both the original element and its descendants.
The reason I need to defer the execution of the map function is to pre-define it in a file outside of my test file for the purpose of abstraction. The current attempt I have is:
Question.array = function(elementArrayFinder) {
function delayedPromise(executor) {
this.executor = executor;
}
delayedPromise.prototype.then = function(onFulfilled, onRejected) {
console.log('locating elements');
return (new Promise(this.executor)).then(onFulfilled, onRejected);
};
return new delayedPromise(function(resolve, reject) {
elementArrayFinder.map(function(omniTask) {
return new Question(omniTask);
}).then(resolve, reject);
});
};
This worked for a while, but when I restructured the test file today (and not the file containing this function, this function hasn't changed after a while), JavaScript had a memory issue related to this function:
<--- Last few GCs --->
133580 ms: Mark-sweep 1354.3 (1421.2) -> 1354.3 (1437.2) MB, 2608.1 / 0.0 ms [allocation failure] [GC in old space requested].
136052 ms: Mark-sweep 1354.3 (1437.2) -> 1354.3 (1437.2) MB, 2471.9 / 0.0 ms [allocation failure] [GC in old space requested].
138829 ms: Mark-sweep 1354.3 (1437.2) -> 1355.7 (1421.2) MB, 2775.8 / 0.0 ms [last resort gc].
141436 ms: Mark-sweep 1355.7 (1421.2) -> 1357.0 (1421.2) MB, 2606.6 / 0.0 ms [last resort gc].
<--- JS stacktrace --->
==== JS stack trace =========================================
Security context: 0x13c845cfb51 <JS Object>
1: enqueue [/Users/thasisclaus/omnistack/node_modules/selenium-webdriver/lib/promise.js:~2742] [pc=0x27de9185871b] (this=0x2b9531847931 <an EventEmitter with map 0x17526dabf9e9>,task=0x17b6b944f181 <a Deferred with map 0x17526dac0649>)
2: addCallback_ [/Users/thasisclaus/omnistack/node_modules/selenium-webdriver/lib/promise.js:~1328] [pc=0x27de919c1a75] (this=0x17b6b944eeb9 <a ManagedPro...
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
1: node::Abort() [/usr/local/bin/node]
2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/usr/local/bin/node]
3: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/local/bin/node]
4: v8::internal::Factory::NewFixedArray(int, v8::internal::PretenureFlag) [/usr/local/bin/node]
5: v8::internal::Handle<v8::internal::TypeFeedbackMetadata> v8::internal::TypeFeedbackMetadata::New<v8::internal::FeedbackVectorSpec>(v8::internal::Isolate*, v8::internal::FeedbackVectorSpec const*) [/usr/local/bin/node]
6: v8::internal::(anonymous namespace)::EnsureFeedbackVector(v8::internal::CompilationInfo*) [/usr/local/bin/node]
7: v8::internal::(anonymous namespace)::GenerateBaselineCode(v8::internal::CompilationInfo*) [/usr/local/bin/node]
8: v8::internal::(anonymous namespace)::GetUnoptimizedCodeCommon(v8::internal::CompilationInfo*) [/usr/local/bin/node]
9: v8::internal::Compiler::Compile(v8::internal::Handle<v8::internal::JSFunction>, v8::internal::Compiler::ClearExceptionFlag) [/usr/local/bin/node]
10: v8::internal::Accessors::FunctionLengthGetter(v8::Local<v8::Name>, v8::PropertyCallbackInfo<v8::Value> const&) [/usr/local/bin/node]
11: v8::internal::PropertyCallbackArguments::Call(void (*)(v8::Local<v8::Name>, v8::PropertyCallbackInfo<v8::Value> const&), v8::internal::Handle<v8::internal::Name>) [/usr/local/bin/node]
12: v8::internal::Object::GetPropertyWithAccessor(v8::internal::LookupIterator*) [/usr/local/bin/node]
13: v8::internal::Object::GetProperty(v8::internal::LookupIterator*) [/usr/local/bin/node]
14: v8::internal::Builtin_Impl_FunctionPrototypeBind(v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)0>, v8::internal::Isolate*) [/usr/local/bin/node]
15: v8::internal::Builtin_FunctionPrototypeBind(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
16: 0x27de909092a7
17: 0x27de9185871b
18: 0x27de919c1a75
19: 0x27de919c202c
20: 0x27de912d1b27
21: 0x27de90909895
22: 0x27de912dee53
>> FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
>> 1: node::Abort() [/usr/local/bin/node]
>> 2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/usr/local/bin/node]
>> 3: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/local/bin/node]
>> 4: v8::internal::Factory::NewFixedArray(int, v8::internal::PretenureFlag) [/usr/local/bin/node]
>> 5: v8::internal::Handle<v8::internal::TypeFeedbackMetadata> v8::internal::TypeFeedbackMetadata::New<v8::internal::FeedbackVectorSpec>(v8::internal::Isolate*, v8::internal::FeedbackVectorSpec const*) [/usr/local/bin/node]
>> 6: v8::internal::(anonymous namespace)::EnsureFeedbackVector(v8::internal::CompilationInfo*) [/usr/local/bin/node]
>> 7: v8::internal::(anonymous namespace)::GenerateBaselineCode(v8::internal::CompilationInfo*) [/usr/local/bin/node]
>> 8: v8::internal::(anonymous namespace)::GetUnoptimizedCodeCommon(v8::internal::CompilationInfo*) [/usr/local/bin/node]
>> 9: v8::internal::Compiler::Compile(v8::internal::Handle<v8::internal::JSFunction>, v8::internal::Compiler::ClearExceptionFlag) [/usr/local/bin/node]
>> 10: v8::internal::Accessors::FunctionLengthGetter(v8::Local<v8::Name>, v8::PropertyCallbackInfo<v8::Value> const&) [/usr/local/bin/node]
>> 11: v8::internal::PropertyCallbackArguments::Call(void (*)(v8::Local<v8::Name>, v8::PropertyCallbackInfo<v8::Value> const&), v8::internal::Handle<v8::internal::Name>) [/usr/local/bin/node]
>> 12: v8::internal::Object::GetPropertyWithAccessor(v8::internal::LookupIterator*) [/usr/local/bin/node]
>> 13: v8::internal::Object::GetProperty(v8::internal::LookupIterator*) [/usr/local/bin/node]
>> 14: v8::internal::Builtin_Impl_FunctionPrototypeBind(v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)0>, v8::internal::Isolate*) [/usr/local/bin/node]
>> 15: v8::internal::Builtin_FunctionPrototypeBind(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
>> 16: 0x27de909092a7
>> 17: 0x27de9185871b
>> 18: 0x27de919c1a75
>> 19: 0x27de919c202c
>> 20: 0x27de912d1b27
>> 21: 0x27de90909895
>> 22: 0x27de912dee53
The context in the test file I changed today is:
fit('Should have the right number of assignment questions initially', function(done) {
var done = browserHelper.strictDone(done),
self = this;
self.communityQuestions = self.myQuestions = [];
console.log(self.assignmentQuestions.length, self.communityQuestions.length, self.myQuestions.length)
assignmentPage.assignmentQuestions.then(function(assignmentQuestions) {
expect(assignmentQuestions.length).toEqual(self.assignmentQuestions.length);
assignmentPage.communityQuestionsTab.click();
assignmentPage.communityQuestions.then(function(communityQuestions) {
expect(communityQuestions.length).toEqual(self.communityQuestions.length);
assignmentPage.myQuestionsTab.click();
assignmentPage.myQuestions.then(function(myQuestions) {
console.log(myQuestions);
expect(myQuestions.length).toEqual(self.myQuestions.length);
done();
});
});
});
});
I don't know if the error is actually caused by a function or some external change that this function is encountering. Regardless, I think there is probably a better way to delay the map function, most likely by interacting directly with the Protractor control flow.
source to share
Even though I didn't return items with maps (I was returning objects built from items instead), I think it has something to do with this bug where the map is hanging: https://github.com/angular/protractor/issues/2227
To get around this, I just changed mine map
to reduce
and changed the passed function, which worked great.
I'm pretty sure this map
is one of the less updatable iterative functions of elementArrayFinder, because unlike reduce
lodash functions, it map
doesn't have the last argument, which is a collection, and therefore follows an outdated convention.
source to share