view release on metacpan or search on metacpan
devdata/https_mojolicious.io_blog_2017_12_05_day-5-your-apps-built-in-commands view on Meta::CPAN
260261262263264265266267268269270271272273274275276277278279280Because of that, headers are omitted from the output
unless
you pass <code>-v</code>.</p>
<p>Let&
#39;s see what it can do!
You can find the latest version of <code>IO::Socket::SSL</code> using the <a href=
"https://github.com/metacpan/metacpan-api/blob/master/docs/API-docs.md"
>Meta::CPAN JSON API</a>.
The response is parsed as JSON and only the <code>version</code> element is output.</p>
<pre><code>mojo get https://fastapi.metacpan.org/v1/module/IO::Socket::SSL /version
</code></pre>
<p>You can fetch the Perl headlines from reddit.
To
do
so we fetch the url (following redirects
with
<code>-r</code>), then we give it a <a href=
"http://mojolicious.org/perldoc/Mojo/DOM/CSS"
>CSS3 selector</a>, and
finally
extract the text from
each
found element.</p>
<pre><code>mojo get -r reddit.com/r/perl &
#39;p.title > a.title' text
</code></pre>
<p>How fun is that?!</p>
<ul>
<li>You can POST or PUT or DELETE data.</li>
<li>It handles HTTP basic authentication using <code>username:password@</code> in the URL.</li>
<li>You can submit forms, even
with
file uploads using the standard <code>
@filename
</code> syntax.</li>
devdata/https_mojolicious.io_blog_2017_12_09_day-9-the-best-way-to-test view on Meta::CPAN
306307308309310311312313314315316317318319320321322323324325326327328<p>These methods allow the (optional) first argument to be a <a href=
"http://mojolicious.org/perldoc/Mojo/JSON/Pointer"
>JSON Pointer</a> to
"
;dive in
"
; to the data structure.
Very handy
when
you only care about subsets of the data.</p>
<pre><code>
$t
-
>
;get_ok(&
#39;/santa_list/joel.json')
-
>
;json_is(&
#39;/status', 'nice');
</code></pre>
<p>Of course there are methods to test HTML responses.
Since it makes little sense to test the whole thing (and
if
you wanted to you could
use
<code>content_</code>), these take a <a href=
"http://mojolicious.org/perldoc/Mojo/DOM/CSS"
>CSS3 Selector</a> to narrow their focus in a similar manner to the JSON...
To inspect the textual portions of the HTML response,
use
the <code>text_</code> methods
with
a selector.
For other tests, there might not be text to test, or the value doesn&
#39;t matter.
For those cases there are <code>element_exists</code>, <code>element_exists_not</code>, and <code>element_count_is</code>, which, as their names indicate, take a selector and tries to find
if
or how many elements match it.
These really need a post of their own, but as a few examples</p>
<pre><code>
$t
-
>
;text_is(&
#39;div.main-content p:nth-of-type(2)', 'This is the third paragraph of the main-section of text');
$t
-
>
;element_exists(&
#39;img[src="kitten.jpg"]');
</code></pre>
<h2>Testing Websockets</h2>
<p>Websockets are an intersting challenge to test, however Test::Mojo makes them easy.
We&
#39;ve already seen that you open a websocket with <code>websocket_ok</code>.</p>
devdata/https_mojolicious.io_blog_2017_12_13_day-13-more-about-roles view on Meta::CPAN
146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177To
my
knowledge they all used Role::Tiny, but they had to roll their own composition mechanisms, presenting some barrier to
use
.</p>
<h2>Creating Roles</h2>
<p>A role itself looks like a class at first glance.
Rather than using the <code>-base</code> flag or specifying a parent class, a role uses the <code>-role</code> flag.
Once again, an optional <code>-signatures</code> flag is allowed too.</p>
<p>Let&
#39;s look at a (contrived) example.
Say we want to make a role that finds all the tags matching elements in a <a href=
"http://mojolicious.org/perldoc/Mojo/DOM"
>Mojo::DOM</a> based on a selector stored in an attribute.</p>
use
Mojo::Base -role;
requires &
#39;find';
has
custom_selector =
>
; &
#39;a';
sub
find_custom {
my
$self
=
shift
;
return
$self
-
>
;find(
$self
-
>
;custom_selector);
}
</code></pre>
<p>This example shows three interesting features.
First is that even though it is not a class, the
package
still gets Mojo::Base&
#39;s <a href="http://mojolicious.org/perldoc/Mojo/Base#has">has</a> keyword, used to make accessors for attributes.
Second is that a new keyword, <code>requires</code>,
has
been added, coming from <a href=
"https://metacpan.org/pod/Role::Tiny#requires"
>Role::Tiny</a>.
This keyword tells the role that it can only be composed into a class that provides a <code>find</code> method.
Consider the new <code>find_custom</code> method, since it uses <code>find</code>
if
the class it is composed into didn&
#39;t provide that method our new method couldn't behave as expected.</p>
<p>Indeed several keywords are imported from Role::Tiny including <code>
with
</code> to compose other roles and several method modifiers coming from <a href=
"https://metacpan.org/pod/Class::Method::Modifiers"
>Class::Method::Modifiers</a> (which is an ...
devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model view on Meta::CPAN
233234235236237238239240241242243244245246247248249250251252253254255256257258259260
-
>
;db
-
>
;insert(
&
#39;<span class="hljs-string">users</span>',
{name =
>
; <span class=
"hljs-type"
>
$name
</span>},
)-
>
;last_insert_id;
}
<span class=
"hljs-keyword"
>
sub
</span><span class=
"hljs-function"
>user</span> {
<span class=
"hljs-keyword"
>
my
</span> (<span class=
"hljs-type"
>
$self
</span>, <span class=
"hljs-type"
>
$name
</span>) = <span class=
"hljs-type"
>
@_
</span>;
<span class=
"hljs-keyword"
>
my
</span> <span class=
"hljs-type"
>
$sql
</span> =
<
;
<
;<span class=
"hljs-keyword"
>&
#39; SQL';</span>
select
user.id,
user.name,
(
select
json_group_array(item)
from (
select
json_object(
&
#39;id', items.id,
&
#39;title', items.title,
&
#39;url', items.url,
&
#39;purchased', items.purchased
) as item
from items
where items.user_id=user.id
)
) as items
from users user
devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model view on Meta::CPAN
266267268269270271272273274275276277278279280281282283284285286
-
>
;query(<span class=
"hljs-type"
>
$sql
</span>, <span class=
"hljs-type"
>
$name
</span>)
-
>
;expand(json =
>
; &
#39;<span class="hljs-string">items</span>')
-
>
;hash;
}
<span class=
"hljs-keyword"
>
sub
</span><span class=
"hljs-function"
>list_user_names</span> {
<span class=
"hljs-keyword"
>
my
</span> <span class=
"hljs-type"
>
$self
</span> = <span class=
"hljs-function"
>
shift
</span>;
<span class=
"hljs-keyword"
>
return
</span> <span class=
"hljs-type"
>
$self
</span><span class=
"hljs-type"
>
</span> -
>
;sqlite
-
>
;db
-
>
;<span class=
"hljs-function"
>
select
</span>(
&
#39;<span class="hljs-string">users</span>' => ['<span class="hljs-string">name</span>'],
<span class=
"hljs-function"
>
undef
</span>,
{-asc =
>
; &
#39;<span class="hljs-string">name</span>'},
)
-
>
;arrays
-
>
;<span class=
"hljs-function"
>
map
</span>(<span class=
"hljs-keyword"
>
sub
</span>{ <span class=
"hljs-variable"
>
$_
</span>-
>
;[0] });
}
<span class=
"hljs-keyword"
>
sub
</span><span class=
"hljs-function"
>add_item</span> {
<span class=
"hljs-keyword"
>
my
</span> (<span class=
"hljs-type"
>
$self
</span>, <span class=
"hljs-type"
>
$user
</span>, <span class=
"hljs-type"
>
$item
</span>) = <span class=
"hljs-type"
>
@_
</span>;
devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model view on Meta::CPAN
315316317318319320321322323324325326327328329330331332333334335
)-
>
;rows;
}
<span class=
"hljs-number"
>1</span>;
</code></pre>
<p><small>lib/Wishlist/Model.pm</small></p>
<p>This class define the ways that the application can alter the data in the database.
Rather than the familiar DBI methods like <code>selectrow_arrayref</code>, Mojo-Flavored DBI make a query and then ask
for
the result shape they want returned.
The user can ask
for
a row as a hash or an array.
They can also ask
for
and array of all thr rows, again as a hash or an array.
Sometimes there are other data you want rather than the actual results, like the <code>last_insert_id</code> or the number of <code>rows</code> affected.</p>
<p>Most of the methods are simple enough to employ the SQL::Abstract forms: add, update, remove, even listing the users.
However
for
getting a user we want to make a more complex <code>query</code> by hand.
It looks up the user row by name, and aggregates the items that user is wishing
for
as JSON.</p>
<p>Before fetching the results we
tell
Mojo::SQLite that we would like to expand the JSON back into Perl data transparently.
This <a href=
"https://metacpan.org/pod/Mojo::SQLite::Results#expand"
><code>expand</code></a> method differs slightly from the other flavors since SQLite doesn't have metadata to give Mojo::SQLite hints about which column to expand.
devdata/https_mojolicious.io_blog_2017_12_20_day-20-practical-testing view on Meta::CPAN
270271272273274275276277278279280281282283284285286287288289290done_testing;
</code></pre>
<p><small><a href=
"https://github.com/jberger/Wishlist/blob/blog_post/practical_testing/t/embed.t"
>t/embed.t</a></small></p>
<p>Because the template expects the result to be an object we have to build a tiny class to contain
our
mock results.
Also whenever you are mocking, it is important to check the input your mock received as well as the results that the calling code derives from your mock
return
value.</p>
<p>In the test you can also see some examples of how to
use
selectors to test
for
both text and attribute
values
.
The text test is especially important because it shows that the html value that I got back from the LinkEmbedder isn&
#39;t being escaped by the template and will render as HTML to the client.</p>
<p>A few more tests and some documentation and
our
application will really be taking final shape!</p>
</section>
<small><p><a href=
"https://commons.wikimedia.org/w/index.php?curid=11337658"
>Image</a> by Hawaii Volcano Observatory, USGS - <a class=
"external text"
href=
"http://hvo.wr.usgs.gov/kilauea/update/archive/2009/2009_Jun-Oct.html"
rel="nofol...
</small>
<p class=
"tags"
>
<span>Tagged in </span>:
devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack view on Meta::CPAN
152153154155156157158159160161162163164165166167168169170171<p>Mojo is an amazing toolkit
for
web development, as shown in previous
calendar entries, but using components of it can also solve problems in other
</section>
<section id=
"section-2"
>
<h2>Down By The Riverside</h2>
<p>First of all, we need the stream of data.
Initially, I used <code>tshark</code>
for
this, though another member of the OpenHMD team
built another application, OpenHMD-Dumper, which
has
both a device selection
interface and opens the device to
read
the packets, which makes this much
easier.
Doing so allows us to ask others who have HMDs to
send
us these logs, so we
can add driver support
for
devices none of the team have access to!
to capture and output the packet data.</p>
<pre><code>tshark -i usbmon1 -Y &
#39;usb.src == "1.22.1"' -T fields -e usb.capdata
</code></pre>
devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack view on Meta::CPAN
403404405406407408409410411412413414415416417418419420421422423424425426427various sizes
until
you see a (rough) sine wave, indicating you&
#39;ve got the
right offset and number of bytes
for
that part of the puzzle!</p>
<h2>Moving On To Greater Things</h2>
<p>This tool could easily be improved (and will be,
when
it is
next
called upon).
For example, both the extraction and fixing of the headers could be made into
commands, as demonstrated in
<p>It could also be made into a proper web application where the user can
select
the action they want to
do
and an animation shows the movement that is wanted
(not everyone is familiar
with
nautical terms
after
all!).
Perhaps even
with
a device
select
?
A UI that allows the user to
select
the offset, size and
unpack
method and
render the graphs as appropriate could cut down the
time
to analyse.
Better yet,
if
it could detect which combinations result in a rough sine wave,
it could narrow down and present the user
with
likely candidates
for
each
movement..</p>
<p>.. but those are improvements
for
another day!</p>
</section>
<small><p><a href=
"https://www.pexels.com/photo/sky-woman-clouds-girl-123335/"
>Image</a> by Bradley Hook, in the Public Domain.</p>
</small>