Protractor - Unable to loop every item by using ElemArrayFinder each - jasmine

I am using Protractor + Jasmine.
I have 2 elements (links) in a table, and I need to delete one after one - Or one-by-one. After I deleted the first item, the table will refresh and re-populated with the remaining elements (or links).
My code below only deleting the first element and exiting the code. I am unable to loop and delete all elements.
I am getting the total count correct.
element.all(by.xpath("//span[#class='abc']")).count().then(function (count)
{
element.all(by.xpath("//span[#class='abc']")).each(function (elem, index)
{
elem.getText().then(function (name)
{
console.log("NAME IS " + name);
var row = element(by.xpath('//span[contains(text(),"' + name + '")]/../../..'));
row.click();
var overFlow = element(by.xpath('//span[contains(text(),"' + name + '")]/../../..//*[#class="zzz"]'));
helper.clickElemWithJavascript(overFlow);
helper.scrollIntoView(deleteButton);
helper.clickElemWithJavascript(deleteButton);
})
})
}); //count

Promises chaining is one solution for this kind of issues.
I figured it out in this way and this is my approach:
I made these steps as a function.
I get the total count of elements using element.all().each(). This returns array of elements/array of values.
Using a For loop and length of the above array, calling the function (step 1) which has steps to delete Single element.
I followed Promises chaining. So unless the previous step was not finished, control flow will not execute the next step.
I am not familiar with Async and Await, so I followed the approach above.

Related

RxJs hot range observable

I'm trying to create a hot range observable. This means that when I have an observer observering the observable after a certain timeout, it should not receive the values that have already been published. I have created the following program:
import Rx from "rxjs/Rx";
var x = Rx.Observable.range(1,10).share()
x.subscribe(x => {
print('1: ' + x);
});
setTimeout(() => {
x.subscribe(x => {
print('2: ' + x);
});
}, 1000);
function print(x) {
const element = document.createElement('div');
element.innerText = x;
document.body.appendChild(element)
}
I expect this program to print 1 to 10, and then the second observable to print nothing, since the values 1 to 10 are produced within the first second. The expected output is shown below.
1: 1
1: 2
..
1:10
However, I see that it also prints all the values. Eventhough I have put the share() operator behind it. The output is shown below.
1: 1
..
1: 10
2: 1
..
2: 10
Can somebody explain this to me?
share returns an observable that's reference counted for subscriptions. When the reference count goes from zero to one, the shared observable subscribes to the source - in your case, to the range observable. And when the reference count drops back to zero, it unsubscribes from the source.
The key point in your snippet is that range emits it's values synchronously and then completes. And the completion effects an unsubscription from the shared observable and that sees the reference count drop back to zero - which sees the shared observable unsubscribe from its source.
If you replace share with publish you should see the behaviour you expected:
var x = Rx.Observable.range(1,10).publish();
x.subscribe(x => print('1: ' + x));
x.connect();
publish returns a ConnectableObservable which is not reference counted and provides a connect method that can be called to explicitly connect - i.e. subscribe - to the source.

Limit number of lines read by d3.csv or d3.text

When users of a web app upload a CSV, I want to display on screen a sample of the uploaded data. They could upload 2 to 20 million rows, so I want to limit the number being read by d3 (for speed) and displayed (for style) to, let's say, 100 rows.
Is this possible?
The documentation didn't make the answer apparent to me. I see that it says
An optional row conversion function may be specified to map and filter
row objects to a more-specific representation;
But I don't really understand these row conversion functions or other filters and if they can only be applied after the file is read, or if they can be used to limit the rows being read.
In your row (or accessor) function, use the index (the second argument) to limit the number of rows:
If a row conversion function is specified, the specified function is invoked for each row, being passed an object representing the current row (d), the index (i) starting at zero for the first non-header row, and the array of column names. (emphasis mine)
For instance, in the following example, I'm limiting the number of rows to 5, even if the CSV has 10 rows (I'm using a <pre> element to simulate the CSV because I can't upload a real CSV using the Stack snippet):
var data = d3.csvParse(d3.select("#csv").text(), row);
function row(d, i) {
if (i < 5) return d;
}
console.log("data length is " + data.length);
console.log("data is " + JSON.stringify(data));
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="csv">foo,bar
12,23
13,22
43,66
3,4
66,55
43,48
32,11
11,11
21,23
78,17</pre>
Have in mind that if the CSV has in fact 20 million rows, as you said, you'll still have to wait until all the file is downloaded. The row function only limits the data array created when you parse the CSV: it will not magically stop the download/parsing process when you get to a certain row.

Possibility of saving partial outputs from bulk iteration in Flink Dataset?

I am doing an iterative computation using flink dataset API.
But the result of each iteration is a part of my complete solution.
(If more details required: I am computing lattice nodes level-wise starting from top towards bottom in each iteration, see Formal Concept Analysis)
If I use flink dataset API with bulk iteration without saving my result, the code will look like below:
val start = env.fromElements((0, BitSet.empty))
val end = start.iterateWithTermination(size) { inp =>
val result = ObjData.mapPartition(new MyMapPartition).withBroadcastSet(inp, "concepts").groupBy(0).reduceGroup(new MyReduceGroup)
(result,result)
}
end.count()
But, if I try to write partial results within iteration (_.writeAsText()) or any action, I will get error:
org.apache.flink.api.common.InvalidProgramException: A data set that is part of an iteration was used as a sink or action. Did you forget to close the iteration?
The alternative without bulk iteration seems to be below:
var start = env.fromElements((0, BitSet.empty))
var count = 1L
var all = count
while (count > 0){
start = ObjData.mapPartition(new MyMapPartition).withBroadcastSet(start, "concepts").groupBy(0).reduceGroup(new MyReduceGroup)
count = start.count()
all = all + count
}
println("total nodes: " + all)
But this approach is exceptionally slow on smallest input data, iteration version takes <30 seconds and loop version takes >3 minutes.
I guess flink is not able to create optimal plan to execute the loop.
Any workaround I should try? Is some modification to flink is possible to be able to save partial results on hadoop etc.?
Unfortunately, it is not currently possible to output intermediate results from a bulk iteration. You can only output the final result at the end of the iteration.
Also, as you correctly noticed, Flink cannot efficiently unroll a while-loop or for-loop, so that won't work either.
If your intermediate results are not that big, one thing you can try is appending your intermediate results in the partial solution and then output everything in the end of the iteration. A similar approach is implemented in the TransitiveClosureNaive example, where paths discovered in an iteration are accumulated in the next partial solution.

How to return X elements [Selenium]?

A page loads 35.000 elements, which only the first 10 are of interest to me. Returning all elements makes the scraping extremely slow.
I only succeeded in either returning the first element with:
driver.find_element_by
Or returning all, 35.000 elements, with:
driver.find_elements_by
Anyone knows a way to return x amount of elements found?
Selenium does not provide a facility that allows returning only a slice of the .find_elements... calls. A general solution if you want to optimize things so that you do not need to have Selenium return every single element is perform the slice operation on the browser side, in JavaScript. I present this solution in this answer here. If you want to use XPath for selecting the DOM nodes, you could adapt the answer here to that, or you could use the method in another answer I've submitted.
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.example.com")
# We add 35000 paragraphs with class `test` to the page so that we can
# later show how to get the first 10 paragraphs of this class. Each
# paragraph is uniquely numbered.
driver.execute_script("""
var html = [];
for (var i = 0; i < 35000; ++i) {
html.push("<p class='test'>"+ i + "</p>");
}
document.body.innerHTML += html.join("");
""")
elements = driver.execute_script("""
return Array.prototype.slice.call(document.querySelectorAll("p.test"), 0, 10);
""")
# Verify that we got the first 10 elements by outputting the text they
# contain to the console. The loop here is for illustration purposes
# to show that the `elements` array contains what we want. In real
# code, if I wanted to process the text of the first 10 elements, I'd
# do what I show next.
for element in elements:
print element.text
# A better way to get the text of the first 10 elements. This results
# in 1 round-trip between this script and the browser. The loop above
# would take 10 round-trips.
print driver.execute_script("""
return Array.prototype.slice.call(document.querySelectorAll("p.test"), 0, 10)
.map(function (x) { return x.textContent; });;
""")
driver.quit()
The Array.prototype.slice.call rigmarole is needed because what document.querySelectorAll returns looks like an Array but is not actually an Array object. (It is a NodeList.) So it does not have a .slice method but you can pass it to Array's slice method.
Here is a significantly different approach presented as a different answer because some people will prefer this one to the other one I gave, or the other one to this one.
This one relies on using XPath to slice the results:
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.example.com")
# We add 35000 paragraphs with class `test` to the page so that we can
# later show how to get the first 10 paragraphs of this class. Each
# paragraph is uniquely numbered. These paragraphs are put into
# individual `div` to make sure they are not siblings of one
# another. (This prevents offering a naive XPath expression that would
# work only if they *are* siblings.)
driver.execute_script("""
var html = [];
for (var i = 0; i < 35000; ++i) {
html.push("<div><p class='test'>"+ i + "</p></div>");
}
document.body.innerHTML += html.join("");
""")
elements = driver.find_elements_by_xpath(
"(//p[#class='test'])[position() < 11]")
for element in elements:
print element.text
driver.quit()
Note that XPath uses 1-based indexes so < 11 is indeed the proper expression. The parentheses around the first part of the expression are absolutely necessary. With these parentheses, the [position() < 11] test checks the position each node has in the nodeset which is the result of the expression in parentheses. Without them, the position test would check the position of the nodes relative to their parents nodes, which would match all nodes because all <p> are at the first position in their respective <div>. (This is why I've added those <div> elements above: to show this problem.)
I would use this solution if I were already using XPath for my selection. Otherwise, if I were doing a search by CSS selector or by id I would not convert it to XPath only to perform the slice. I'd use the other method I've shown.

How do I sync RxJS updates so that intermediate values aren't passed through the stream?

In my system I have a source, two "steps" that map the source to a new value, and then a sum that combines those two steps to create a final value. The initial run through of this system works as I hoped, generating a single sum of 3.
var source = new Rx.BehaviorSubject(0);
var stepOne = source.map(function (value) {
return value + 1;
});
var stepTwo = source.map(function (value) {
return value + 2;
});
var sum = Rx.Observable.combineLatest(
stepOne,
stepTwo,
function (s1, s2) {
console.log('calc sum: ' + (s1 + s2));
return s1 + s2;
}).subscribe(function (sum) {
});
Outputs:
> calc sum: 3
But if I then put in a new value for source I get two results like this:
source.onNext(1);
> calc sum: 4
> calc sum: 5
The first is an intermediate result… as the new source value passes through one part of the system, and then I get the final result when all values have finished propagating.
So my questions is, what's the recommended way to configure things so that a new value pushed into source will pass through the system atomically and only generate one sum result?
Thanks!
That's how combineLatest works, it indeed is confusing since it allows these temporarily inconsistent states as you pointed out. The key thing to learn from combineLatest is that it emits a new item whenever any one of its sources emits a new item, and it does so partially, it doesn't have any sort of "waiting" mechanism.
In diagrams, http://rxmarbles.com/#combineLatest.
What you probably want is the zip operator. Zip waits for its inputs to emit items that match with each other. In other words, zip's output emits its n-th item once all the n-th items from all inputs have been emitted. It is ideal for this diamond case where you have source generating stepOne and stepTwo and you want to combine stepOne and stepTwo.
In diagrams, http://rxmarbles.com/#zip.
Keep in mind that zip assumes the inputs have the same frequency of emissions. In other cases, you might want to combine items from stepOne with stepTwo when they have a different frequency of emissions. Then you need to use combineLatest.

Resources