Acme-CPANModulesBundle-Import-MojoliciousAdvent-2018
view release on metacpan or search on metacpan
devdata/https_mojolicious.io_blog_2018_12_07_openapi_ view on Meta::CPAN
title: "MetaCPAN API"
# common path shared throughout the API
basePath: "/v1"
</code></pre>
<h4>Defining an Endpoint</h4>
<p>Each of the paths available to the API are defined within the paths object.</p>
<pre><code>paths:
# The path to the endpoint
/search/web:
# The HTTP method that the endpoint accepts
get:
# A unique identifier for the method
operationId: search_web
# This attribute points to the name of the class in the appliction
# and the method to call separated by `#`
x-mojo-to: Search#web
# A description of the API Endpoint
summary: Perform API search in the same fashion as the Web UI
</code></pre>
devdata/https_mojolicious.io_blog_2018_12_07_openapi_ view on Meta::CPAN
<p>There are times that a property of an object might be <code>null</code>. In the MetaCPAN API the favourite count may either be an integer representing how many people have favourited the distribution, or <code>null</code>. Using a list for the pro...
<pre><code>favorites:
type:
- "integer"
- "null"
</code></pre>
<h3>The MetaCPAN Specification</h3>
<p>The entire specification doesnâÂÂt need to be complete in order to get OpenAPI up and running. When documenting an existing API, itâÂÂs possible to with one portion of the API. With MetaCPAN we started with the search endpoints.</p>
<p>The <a href="https://github.com/metacpan/metacpan-api/blob/master/root/static/v1.yml">spec file can be viewed here</a> and the <a href="https://fastapi.metacpan.org/static/index.html">API documentation here</a></p>
<h2>Further Reading</h2>
<p>The <a href="https://github.com/OAI/OpenAPI-Specification">OpenAPI Specification repository</a> includes full documentation and many examples of varying levels of details.</p>
<p>The <a href="https://openapi-map.apihandyman.io">OpenAPI Map</a> is an interactive site to aid in working with the OpenAPI Specification.</p>
</section>
devdata/https_mojolicious.io_blog_2018_12_20_testing-dancer_ view on Meta::CPAN
<p>but saves a lot of typing.
Next we load the necessary testing libraries.
Then make an instance of <code>Test::Mojo</code> composed with the <code>PSGI</code> role and make a new instance that points to the app we want to test.</p>
<pre><code>use Test::More;
use Test::Mojo;
my $t = Test::Mojo->with_roles('+PSGI')->new('app.psgi');
</code></pre>
<p>With that out of the way, on to the tests!
In our first tests we'll focus on the plain text endpoint <code>/text</code>.</p>
<pre><code>$t->get_ok('/text')
->status_is(200)
->content_type_like(qr[text/plain])
->content_is('hello world');
</code></pre>
<p>Each of the above method calls is a test.
The first, <code>get_ok</code>, builds a transaction and requests the resource.
Since the url is relative, it is handled by the app (if we wanted we could request and web resource too using a fully qualified url).
devdata/https_mojolicious.io_blog_2018_12_20_testing-dancer_ view on Meta::CPAN
<p>The next test is similar but this one uses the standard <a href="https://mojolicious.org/perldoc/Mojo/UserAgent">Mojo::UserAgent</a> style request generation to build a query string naming Santa for our greeting.
The tests are all the same except of course that it checks that the content greets Santa.</p>
<pre><code>$t->get_ok('/text', form => { name => 'santa' })
->status_is(200)
->content_type_like(qr[text/plain])
->content_is('hello santa');
</code></pre>
<p>Moving on we request the data endpoint, both without and with a query, then similarly test the responses.</p>
<pre><code>$t->get_ok('/data')
->status_is(200)
->content_type_like(qr[application/json])
->json_is('/hello' => 'world');
$t->post_ok('/data' => form => { name => 'rudolph' })
->status_is(200)
->content_type_like(qr[application/json])
->json_is('/hello' => 'rudolph');
</code></pre>
<p>You can see we use the <code>json_is</code> method to test the responses.
Now, the test could have been <code>->json_is({hello => 'rudolph'})</code> if had wanted to test the entire document.
By passing a <a href="https://mojolicious.org/perldoc/Mojo/JSON/Pointer">JSON Pointer</a> I can inspect only the portions I'm interested in.</p>
<p>Finally I'm going to test the HTML endpoint.
As I said above, the result resists easy parsing.
We want to test the <code>dd</code> tag contents that follows a <code>dt</code> tag with the id <code>hello</code>, all inside a <code>dl</code> tag with the id <code>data</code>.
That would be a monstrous regexp (hehe).
However it is a piece of cake using <a href="https://mojolicious.org/perldoc/Mojo/DOM/CSS">CSS Selectors</a>.</p>
<pre><code>$t->get_ok('/html')
->status_is(200)
->content_type_like(qr[text/html])
->text_is('dl#data dt#hello + dd', 'world');
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
title => 'Higher Order Promises',
day => 3,
author => 'brain d foy',
},
],
status => 200,
);
});
</code></pre>
<p>As a sidenote, you may have to allow <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">Cross Origin Resource Sharing (CORS)</a> if the Angular app throws an error while accessing the mojo API endpoint.
In that case you may want to make use of the <a href="https://mojolicious.org/perldoc/Mojolicious/#before_dispatch"><code>before_dispatch</code></a> app hook:</p>
<pre><code>$self->hook(before_dispatch => sub {
my $c = shift;
$c->res->headers->header('Access-Control-Allow-Origin' => '*');
});
</code></pre>
<p>But please note, in a real-world application <code>*</code> is defeating the security feature.</p>
( run in 0.380 second using v1.01-cache-2.11-cpan-27979f6cc8f )