Why page.$$eval and evaluate return undefined - puppeteer

Let's say I will go to google.com then fetch all a tags inside the page, so I write something as below
await page
.goto ("https://google.com")
.then (() => page.$$eval ("a", xs => xs.length))
.then (console.log)
this will print a number that's greater than 0, which means that xs is an array full of <a> html elements. Good
However once I change it to the following
await page
.goto ("https://google.com")
.then (() => page.$$eval ("a", xs => xs))
.then (console.log)
it returns undefined ??? this is weird and confusing why would it return undefined it doesn't make any sense
is this a bug or something !

Related

Using the data retrieved, create an array using the map method to return just the title of every item and print the result in the console

Using the data retrieved, create an array using the map method to return just the title of every item and print the result in the console.
Code:
fetch('https://jsonplaceholder.typicode.com/todos').then(response => response.json()).then(data => {console.log(data)})
fetch('https://jsonplaceholder.typicode.com/todos').then(response => response.json()).then(data => {console.log(data)})
Using the data retrieved, create an array using the map method to return just the title of every item and print the result in the console.
fetch('https://jsonplaceholder.typicode.com/todos').then(response => response.json()).then(data => {
data.map((elem) => {
return elem.title
})
})
You store the result (of data.map) in whatever variable you like (it returns an array)
Basically just returning the title of the object using Map().

RxJs Interval with takeUntil to publish last value

I have some code which polls until a task is complete
See below
this.simulationStatus =
interval(2000).pipe(
switchMap(
() => from(this.simulationService.getSimulationStatus(this.route.snapshot.paramMap.get('jobId')))),
takeUntil(this.stopPoll),
tap(simulation => {
if (simulation && simulation.complete) {
if (this.stopCount == 1) {
// Get once after complete
this.stopPoll.next(true);
}
this.stopCount++;
}
})
);
I have tried using takeUntil and takeWhile the problem is that that the last value is never published once the task is complete.
To get around this I have to include the tap method to with the stopPoll subject and incrementing the stopCount to get the last value.
So the above works but just feels a bit messy, I'm sure there must be a better way of achieving this?
I would have expected takeUntil to publish the last value or have an override to tell it to e.g takeUntil(observable, {publishLast: true})
BTW Update, the observable is subscribed to by an Angular 6 template
Thanks in advance
One thing you can do is use a custom takeWhile-like operator like this:
const completeWith = <T>(predicate: (arg: T) => boolean) => (
source: Observable<T>,
) =>
new Observable<T>(observer =>
source.subscribe(
value => {
observer.next(value);
if (predicate(value)) {
observer.complete();
}
},
error => observer.error(error),
() => observer.complete(),
),
);
It doesn't seem like a good idea to see it as a variation of takeWhite because it's not just taking values while a condition holds, but also emits an extra value.
It might be that a more elegant solution would be make the simulation status observable emit two kinds of values: next notifications and completion notifications, similarly to how materialize/dematerialize operators work.
This has in the meantime been implemented in rxjs as takeWhile(condition, ?inclusive):
timer(0, 10).pipe(
takeWhile((x) => x < 3, true)
)
emits 0, 1, 2, 3
You can also create subject and emit using next() if you want to complete the observable.
this.stopPoll: Subject<any> = new Subject<any>();
If you want to do complete the subscription. you can call this.stopPoll.next(true);
you can access the data in subscribe()
this.simulationStatus.subscribe(success=>{}, failure=>{}, complete=>{});

Printing an HTML page header is different when saved in a var?

this works fine:
print $cgi->header({-type => "text/html", -expires => "now"}),
$cgi->start_html({-title => "TEST PAGE",
-style => [{-type => "text/css", -src =>"one.css"},
{-type => "text/css", -src =>"calendar.css"}],
-script => [
{-type => "text/javascript", -src => "main.js"},
]}),
$cgi->start_form({-name => "test", -autocomplete => "off"});
but if instead I try:
my $html= $cgi->header({-type => "text/html", -expires => "now"}),
$cgi->start_html({-title => "TEST PAGE",
-style => [{-type => "text/css", -src =>"one.css"},
{-type => "text/css", -src =>"calendar.css"}],
-script => [
{-type => "text/javascript", -src => "main.js"},
]}),
$cgi->start_form({-name => "test", -autocomplete => "off"});
print $html;
The HTML is then displayed on the page instead of rendered? Why would saving all the HTML in a var then printing that var produce a different result than printing directly? It's difficult to capture what's different because of the subtle differences like capturing a \n\n ..
Do I have to sprint that header into the var or something?
Thanks!
Why would saving all the HTML in a var then printing that var produce a different result than printing directly?
For the same reason that
print 'foo', 'bar'; # outputs foobar
is different than
my $foo = 'foo', 'bar';
print $foo; # outputs foo
print takes a list and outputs all the elements separated by $, (undef by default).
The comma operator in scalar context evaluates its left operand, throws away the result, evaluates its right operand, and returns that value. So my $foo = 'foo', 'bar' assigns the string foo to $foo and returns the string bar.
Also note that the HTML generation functions in CGI.pm are deprecated:
HTML Generation functions should no longer be used
All HTML generation functions within CGI.pm are no longer being maintained. Any issues, bugs, or patches will be rejected unless they relate to fundamentally broken page rendering.
The rationale for this is that the HTML generation functions of CGI.pm are an obfuscation at best and a maintenance nightmare at worst. You should be using a template engine for better separation of concerns. See CGI::Alternatives for an example of using CGI.pm with the Template::Toolkit module.
These functions, and perldoc for them, are considered deprecated, they are no longer being maintained and no fixes or features for them will be accepted.

Yii x-editable on CGridView: not stopping screen update when success returns error

When json response sends response.success == false, I can see the console log showing me the error, but x-editable seems that doesn't catch the return, and the value in the screen is changed to the new one I had introduced, although it has not been really saved. Is there something wrong?
Here is piece of the CGridView code I use:
'class' => 'editable.EditableColumn',
'editable' => array(
'model' => $model,
'params' => array('YII_CSRF_TOKEN' => Yii::app()->request->csrfToken),
'url' => $this->createUrl('user/update'),
'success' => 'js: function(response, newValue) {
if(!response.success)
console.log(response.msg);
return response.msg;
}',
'options' => array(
'ajaxOptions' => array('dataType' => 'json')
),
)
EDIT 1:
Ok, I have been working on that, and I have found which is the problem. It seems that the javascript function I put on success is not working properly.
The if statement is catching correctly the response, but the return value is not being sended correctly. I explain: if I put a literal like that: return "test return"; the value is returned correctly, but if I put return response.msg; nothing is sended.
Of course, response.msg is not empty and contains the String message correctly.
Ok, I have been working on that and I found my stupid mistake... I was returning msg as array and I had to do this:
return response.msg[index];
Where index is where the message is stored.
It was really embarrassing losing time with that...

Mojolicious Tests: How to get the input value using css-selectors

I am writing a test for a Mojolicious Application, which sends some HTML form data and then checks, if they show up in the subsequent get request.
$t->post_ok('/intern/offer/edit' => form => {
'angebotsdatum' => '2014-02-22',
'gastname' => 'Hansi Hinterseer',
'einmalkosten' => '128.00',
'tage' => '9',
'ankunft' => '2014-01-01',
'gesamtpreis' => '764.00',
'abfahrt' => '2014-01-10',
'tagespreis' => '70.71',
'apartments_id' => 'HAG28',
'id' => '1',
'aufenthaltspreis' => '636.39'
}
)
->status_is(200)
->content_like( qr/Angbot bearbeiten/ )
;
$t->get_ok('/intern/offer/edit/1')
->status_is(200)
->text_like('html body h2' => qr/Intern - Angebote/ )
->text_like('html body h3' => qr/Angbot bearbeiten/ )
->text_is('html body form div#adatum label' => 'Angebotsdatum:' )
->text_is('html body form div#adatum input#angebotsdatum value' => '2014-02-22' )
;
Unfortunately the last test for the value of the input element fails, since the returned value is always empty. The test for the form-label (here 'Angebotsdatum:') succeeds.
How can I select and get back the input-elements value from a HTML-form?
The HTML-code of the form is:
<div id="adatum">
<label>Angebotsdatum:</label>
<input type="text" name="angebotsdatum" value="2014-02-22" id="angebotsdatum">
</div>
And this is the test-output:
# Failed test 'exact match for selector "html body form div\#adatum input[name=angebotsdatum] value"'
# at t/1210-workflow_booking.t line 80.
# got: ''
# expected: '2014-02-22'
So we can see clearly, that the CSS-selector returns the empty value.
From the Test::Mojo
The text_is - Checks text content of the CSS selectors first
matching HTML/XML element for exact match with at in Mojo::DOM.
The at method
Find first element in DOM structure matching the CSS selector and
return it as a Mojo::DOM object or return undef if none could be
found. All selectors from "SELECTORS" in Mojo::DOM::CSS are supported.
And the
html body form div#adatum input#angebotsdatum value
^^^^^^ - this isn't valid
IMHO, isn't valid CSS selector.
You can try the next (shortened) selector:
div#adatum > input[value="2014-02-22"]
so find the element <input> what has an attribute equal to 2014-02-22.
E[foo="bar"]
An E element whose foo attribute value is exactly equal to bar.
More info Mojo::DOM::CSS#SELECTORS
So, it is enough test the existence of the element exactly with the wanted value:
->element_exists('input[value="2014-02-22"]', '...');
Ps: I'm not an very experienced Mojo developer, so ...
input#angebotsdatum means you are looking for an <input> element with an id=angebotsdatum attribute, but what you want to look for is a name=angebotsdatum attribute. So I think the last test should look something like
->text_is('html body form div#adatum input[name=angebotsdatum] value' => ...)