CINXE.COM

Test::Mojo - Testing Mojo

<!doctype html><html> <head> <link rel="apple-touch-icon" href="/mojolicious/touch-icon.png"> <link rel="apple-touch-icon" sizes="152x152" href="/mojolicious/touch-icon-152x152.png"> <link rel="apple-touch-icon" sizes="167x167" href="/mojolicious/touch-icon-167x167.png"> <link rel="apple-touch-icon" sizes="180x180" href="/mojolicious/touch-icon-180x180.png"> <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="Mojolicious" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Test::Mojo - Testing Mojo</title> <script src="/mojolicious/jquery/jquery.js"></script> <script src="/mojolicious/highlight.js/highlight.min.js"></script> <link href="/mojolicious/highlight.js/highlight-mojo-light.css" rel="stylesheet"> <script>hljs.initHighlightingOnLoad();</script> <script src="/mojolicious/bootstrap/bootstrap.js"></script> <link href="/mojolicious/bootstrap/bootstrap.css" rel="stylesheet"> <link href="/mojolicious/fontawesome/fontawesome.css" rel="stylesheet"> <link href="/app.css?v=3" rel="stylesheet"> <link href="/mojodocs.css" rel="stylesheet"> </head> <body><a id="toc"></a> <header> <nav class="navbar navbar-expand-lg navbar-dark mojobar"> <a href="https://mojolicious.org" id="mojobar-brand" class="navbar-brand"> <picture> <img src="/mojo/logo-white.png" srcset="/mojo/logo-white-2x.png 2x"> </picture> </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div id="navbarNav" class="collapse navbar-collapse"> <ul class="navbar-nav mr-auto"> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Documentation </a> <div class="dropdown-menu" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="https://docs.mojolicious.org">Overview</a> <div class="dropdown-divider"></div> <a class="dropdown-item" href="https://docs.mojolicious.org/Mojolicious/Guides/Tutorial">Tutorial</a> <a class="dropdown-item" href="https://docs.mojolicious.org/Mojolicious/Guides/Growing">Growing</a> <a class="dropdown-item" href="https://docs.mojolicious.org/Mojolicious/Guides/Routing">Routing</a> <a class="dropdown-item" href="https://docs.mojolicious.org/Mojolicious/Guides/Rendering">Rendering</a> <a class="dropdown-item" href="https://docs.mojolicious.org/Mojolicious/Guides/Testing">Testing</a> <a class="dropdown-item" href="https://docs.mojolicious.org/Mojolicious/Guides/Cookbook">Cookbook</a> <a class="dropdown-item" href="https://docs.mojolicious.org/Mojolicious/Guides/Contributing">Contributing</a> <a class="dropdown-item" href="https://docs.mojolicious.org/Mojolicious/Guides/FAQ">FAQ</a> <div class="dropdown-divider"></div> <a class="dropdown-item" href="https://docs.mojolicious.org#API">API</a> </div> </li> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="communityDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Community </a> <div class="dropdown-menu" aria-labelledby="communityDropdown"> <a class="dropdown-item" href="https://web.libera.chat/#mojo">IRC</a> <a class="dropdown-item" href="https://forum.mojolicious.org">Forum</a> <a class="dropdown-item" href="https://fosstodon.org/@mojolicious">Mastodon</a> <a class="dropdown-item" href="https://www.linkedin.com/groups/8963713/">LinkedIn</a> <a class="dropdown-item" href="https://github.com/mojolicious/mojo/wiki">Wiki</a> <a class="dropdown-item" href="https://metacpan.org/release/Mojolicious/">CPAN</a> </div> </li> <li class="nav-item"> <a class="nav-link" href="https://github.com/mojolicious/mojo/">Contribute on GitHub</a> </li> </ul> <a class="navbar-brand" href="https://mojojs.org"> <picture> <img src="/mojolicious/mojojs-white.png" srcset="/mojolicious/mojojs-white-2x.png 2x"> </picture> </a> <form action="https://www.google.com/cse" target="_blank" class="form-inline my-2 my-lg-0"> <input name="cx" type="hidden" value="014527573091551588235:pwfplkjpgbi"> <input name="ie" type="hidden" value="UTF-8"> <input name="q" placeholder="Search..." type="search"> </form> </div> </nav> </header> <div class="container-fluid"> <div class="row flex-wrap"> <aside class="col-sm-12 col-md-4 col-lg-2 mojo-sidebar"> <form class="mojo-version d-flex align-items-center"> <fieldset disabled> <input type="text" id="disabledTextInput" class="form-control" placeholder="v9.40"> </fieldset> </form> <ul> <li> <a href="#NAME"><b>NAME</b></a> </li> <li> <a href="#SYNOPSIS"><b>SYNOPSIS</b></a> </li> <li> <a href="#DESCRIPTION"><b>DESCRIPTION</b></a> </li> <li> <a href="#ATTRIBUTES"><b>ATTRIBUTES</b></a> <ul> <li><a href="#handler">handler</a></li> <li><a href="#message">message</a></li> <li><a href="#success">success</a></li> <li><a href="#tx">tx</a></li> <li><a href="#ua">ua</a></li> </ul> </li> <li> <a href="#METHODS"><b>METHODS</b></a> <ul> <li><a href="#app">app</a></li> <li><a href="#attr_is">attr_is</a></li> <li><a href="#attr_isnt">attr_isnt</a></li> <li><a href="#attr_like">attr_like</a></li> <li><a href="#attr_unlike">attr_unlike</a></li> <li><a href="#content_is">content_is</a></li> <li><a href="#content_isnt">content_isnt</a></li> <li><a href="#content_like">content_like</a></li> <li><a href="#content_type_is">content_type_is</a></li> <li><a href="#content_type_isnt">content_type_isnt</a></li> <li><a href="#content_type_like">content_type_like</a></li> <li><a href="#content_type_unlike">content_type_unlike</a></li> <li><a href="#content_unlike">content_unlike</a></li> <li><a href="#delete_ok">delete_ok</a></li> <li><a href="#element_count_is">element_count_is</a></li> <li><a href="#element_exists">element_exists</a></li> <li><a href="#element_exists_not">element_exists_not</a></li> <li><a href="#finish_ok">finish_ok</a></li> <li><a href="#finished_ok">finished_ok</a></li> <li><a href="#get_ok">get_ok</a></li> <li><a href="#head_ok">head_ok</a></li> <li><a href="#header_exists">header_exists</a></li> <li><a href="#header_exists_not">header_exists_not</a></li> <li><a href="#header_is">header_is</a></li> <li><a href="#header_isnt">header_isnt</a></li> <li><a href="#header_like">header_like</a></li> <li><a href="#header_unlike">header_unlike</a></li> <li><a href="#json_has">json_has</a></li> <li><a href="#json_hasnt">json_hasnt</a></li> <li><a href="#json_is">json_is</a></li> <li><a href="#json_like">json_like</a></li> <li><a href="#json_message_has">json_message_has</a></li> <li><a href="#json_message_hasnt">json_message_hasnt</a></li> <li><a href="#json_message_is">json_message_is</a></li> <li><a href="#json_message_like">json_message_like</a></li> <li><a href="#json_message_unlike">json_message_unlike</a></li> <li><a href="#json_unlike">json_unlike</a></li> <li><a href="#message_is">message_is</a></li> <li><a href="#message_isnt">message_isnt</a></li> <li><a href="#message_like">message_like</a></li> <li><a href="#message_ok">message_ok</a></li> <li><a href="#message_unlike">message_unlike</a></li> <li><a href="#new">new</a></li> <li><a href="#options_ok">options_ok</a></li> <li><a href="#or">or</a></li> <li><a href="#patch_ok">patch_ok</a></li> <li><a href="#post_ok">post_ok</a></li> <li><a href="#put_ok">put_ok</a></li> <li><a href="#request_ok">request_ok</a></li> <li><a href="#reset_session">reset_session</a></li> <li><a href="#send_ok">send_ok</a></li> <li><a href="#status_is">status_is</a></li> <li><a href="#status_isnt">status_isnt</a></li> <li><a href="#test">test</a></li> <li><a href="#text_is">text_is</a></li> <li><a href="#text_isnt">text_isnt</a></li> <li><a href="#text_like">text_like</a></li> <li><a href="#text_unlike">text_unlike</a></li> <li><a href="#websocket_ok">websocket_ok</a></li> </ul> </li> <li> <a href="#SEE-ALSO"><b>SEE ALSO</b></a> </li> </ul> </aside> <main class="col-sm-12 col-md-8 col-lg-10 py-md-3 pl-md-5 mojo-main"> <div class="mojo-docinfo"> <div> <div class="mojo-docnav"> <a class="nav-link" alt="API" href="https://docs.mojolicious.org#API"><i class="fas fa-book"></i></a> </div> Module: <a href="http://docs.mojolicious.org/Test">Test</a>::<a href="http://docs.mojolicious.org/Test/Mojo">Mojo</a> <div class="mojo-parent"> Parent: <a href="/Mojo/Base">Mojo::Base</a> </div> </div> </div> <div class="mojo-external"> <a class="btn btn-outline-secondary btn-sm" href="http://docs.mojolicious.org/Test/Mojo.txt" role="button"> Source </a> <a class="btn btn-outline-secondary btn-sm" href="https://metacpan.org/pod/Test::Mojo" role="button">CPAN</a> </div> <div class="mojo-perldoc"> <h1 id="NAME"><a class="permalink" href="#NAME">#</a><a href="#toc">NAME</a></h1> <p>Test::Mojo - Testing Mojo</p> <h1 id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">#</a><a href="#toc">SYNOPSIS</a></h1> <pre><code>use Test::More; use Test::Mojo; my $t = Test::Mojo-&gt;new(&#39;MyApp&#39;); # HTML/XML $t-&gt;get_ok(&#39;/welcome&#39;)-&gt;status_is(200)-&gt;text_is(&#39;div#message&#39; =&gt; &#39;Hello!&#39;); # JSON $t-&gt;post_ok(&#39;/search.json&#39; =&gt; form =&gt; {q =&gt; &#39;Perl&#39;}) -&gt;status_is(200) -&gt;header_is(&#39;Server&#39; =&gt; &#39;Mojolicious (Perl)&#39;) -&gt;header_isnt(&#39;X-Bender&#39; =&gt; &#39;Bite my shiny metal ass!&#39;) -&gt;json_is(&#39;/results/4/title&#39; =&gt; &#39;Perl rocks!&#39;) -&gt;json_like(&#39;/results/7/title&#39; =&gt; qr/Perl/); # WebSocket $t-&gt;websocket_ok(&#39;/echo&#39;) -&gt;send_ok(&#39;hello&#39;) -&gt;message_ok -&gt;message_is(&#39;echo: hello&#39;) -&gt;finish_ok; done_testing();</code></pre> <h1 id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">#</a><a href="#toc">DESCRIPTION</a></h1> <p><a href="http://docs.mojolicious.org/Test/Mojo">Test::Mojo</a> is a test user agent based on <a href="http://docs.mojolicious.org/Mojo/UserAgent">Mojo::UserAgent</a>, it is usually used together with <a href="http://docs.mojolicious.org/Test/More">Test::More</a> to test <a href="http://docs.mojolicious.org/Mojolicious">Mojolicious</a> applications. Just run your tests with <a href="http://docs.mojolicious.org/prove">prove</a>.</p> <pre><code class="nohighlight">$ prove -l -v $ prove -l -v t/foo.t</code></pre> <p>If it is not already defined, the <code>MOJO_LOG_LEVEL</code> environment variable will be set to <code>trace</code> or <code>fatal</code>, depending on the value of the <code>HARNESS_IS_VERBOSE</code> environment variable. And to make it esier to test HTTPS/WSS web services <a href="http://docs.mojolicious.org/Mojo/UserAgent#insecure">&quot;insecure&quot; in Mojo::UserAgent</a> will be activated by default for <a href="#ua">&quot;ua&quot;</a>.</p> <p>See <a href="http://docs.mojolicious.org/Mojolicious/Guides/Testing">Mojolicious::Guides::Testing</a> for more.</p> <h1 id="ATTRIBUTES"><a class="permalink" href="#ATTRIBUTES">#</a><a href="#toc">ATTRIBUTES</a></h1> <p><a href="http://docs.mojolicious.org/Test/Mojo">Test::Mojo</a> implements the following attributes.</p> <h2 id="handler"><a class="permalink" href="#handler">#</a><a href="#toc">handler</a></h2> <pre><code>my $cb = $t-&gt;handler; $t = $t-&gt;handler(sub {...});</code></pre> <p>A callback to connect <a href="http://docs.mojolicious.org/Test/Mojo">Test::Mojo</a> with <a href="http://docs.mojolicious.org/Test/More">Test::More</a>.</p> <pre><code>$t-&gt;handler(sub ($name, @args) { return Test::More-&gt;can($name)-&gt;(@args); });</code></pre> <h2 id="message"><a class="permalink" href="#message">#</a><a href="#toc">message</a></h2> <pre><code>my $msg = $t-&gt;message; $t = $t-&gt;message([text =&gt; $bytes]);</code></pre> <p>Current WebSocket message represented as an array reference containing the frame type and payload.</p> <pre><code># More specific tests use Mojo::JSON qw(decode_json); my $hash = decode_json $t-&gt;message-&gt;[1]; is ref $hash, &#39;HASH&#39;, &#39;right reference&#39;; is $hash-&gt;{foo}, &#39;bar&#39;, &#39;right value&#39;; # Test custom message $t-&gt;message([binary =&gt; $bytes]) -&gt;json_message_has(&#39;/foo/bar&#39;) -&gt;json_message_hasnt(&#39;/bar&#39;) -&gt;json_message_is(&#39;/foo/baz&#39; =&gt; {yada =&gt; [1, 2, 3]});</code></pre> <h2 id="success"><a class="permalink" href="#success">#</a><a href="#toc">success</a></h2> <pre><code>my $bool = $t-&gt;success; $t = $t-&gt;success($bool);</code></pre> <p>True if the last test was successful.</p> <pre><code># Build custom tests my $location_is = sub ($t, $value, $desc = &#39;&#39;) { $desc ||= &quot;Location: $value&quot;; local $Test::Builder::Level = $Test::Builder::Level + 1; return $t-&gt;success(is($t-&gt;tx-&gt;res-&gt;headers-&gt;location, $value, $desc)); }; $t-&gt;get_ok(&#39;/&#39;) -&gt;status_is(302) -&gt;$location_is(&#39;https://mojolicious.org&#39;) -&gt;or(sub { diag &#39;Must have been Joel!&#39; });</code></pre> <h2 id="tx"><a class="permalink" href="#tx">#</a><a href="#toc">tx</a></h2> <pre><code>my $tx = $t-&gt;tx; $t = $t-&gt;tx(Mojo::Transaction::HTTP-&gt;new);</code></pre> <p>Current transaction, usually a <a href="http://docs.mojolicious.org/Mojo/Transaction/HTTP">Mojo::Transaction::HTTP</a> or <a href="http://docs.mojolicious.org/Mojo/Transaction/WebSocket">Mojo::Transaction::WebSocket</a> object.</p> <pre><code># More specific tests is $t-&gt;tx-&gt;res-&gt;json-&gt;{foo}, &#39;bar&#39;, &#39;right value&#39;; ok $t-&gt;tx-&gt;res-&gt;content-&gt;is_multipart, &#39;multipart content&#39;; is $t-&gt;tx-&gt;previous-&gt;res-&gt;code, 302, &#39;right status&#39;;</code></pre> <h2 id="ua"><a class="permalink" href="#ua">#</a><a href="#toc">ua</a></h2> <pre><code>my $ua = $t-&gt;ua; $t = $t-&gt;ua(Mojo::UserAgent-&gt;new);</code></pre> <p>User agent used for testing, defaults to a <a href="http://docs.mojolicious.org/Mojo/UserAgent">Mojo::UserAgent</a> object.</p> <pre><code># Allow redirects $t-&gt;ua-&gt;max_redirects(10); $t-&gt;get_ok(&#39;/redirect&#39;)-&gt;status_is(200)-&gt;content_like(qr/redirected/); # Switch protocol from HTTP to HTTPS $t-&gt;ua-&gt;server-&gt;url(&#39;https&#39;); $t-&gt;get_ok(&#39;/secure&#39;)-&gt;status_is(200)-&gt;content_like(qr/secure/); # Use absolute URL for request with Basic authentication my $url = $t-&gt;ua-&gt;server-&gt;url-&gt;userinfo(&#39;sri:secr3t&#39;)-&gt;path(&#39;/secrets.json&#39;); $t-&gt;post_ok($url =&gt; json =&gt; {limit =&gt; 10}) -&gt;status_is(200) -&gt;json_is(&#39;/1/content&#39;, &#39;Mojo rocks!&#39;); # Customize all transactions (including followed redirects) $t-&gt;ua-&gt;on(start =&gt; sub ($ua, $tx) { $tx-&gt;req-&gt;headers-&gt;accept_language(&#39;en-US&#39;) }); $t-&gt;get_ok(&#39;/hello&#39;)-&gt;status_is(200)-&gt;content_like(qr/Howdy/);</code></pre> <h1 id="METHODS"><a class="permalink" href="#METHODS">#</a><a href="#toc">METHODS</a></h1> <p><a href="http://docs.mojolicious.org/Test/Mojo">Test::Mojo</a> inherits all methods from <a href="http://docs.mojolicious.org/Mojo/Base">Mojo::Base</a> and implements the following new ones.</p> <h2 id="app"><a class="permalink" href="#app">#</a><a href="#toc">app</a></h2> <pre><code>my $app = $t-&gt;app; $t = $t-&gt;app(Mojolicious-&gt;new);</code></pre> <p>Access application with <a href="http://docs.mojolicious.org/Mojo/UserAgent/Server#app">&quot;app&quot; in Mojo::UserAgent::Server</a>.</p> <pre><code># Change log level $t-&gt;app-&gt;log-&gt;level(&#39;fatal&#39;); # Test application directly is $t-&gt;app-&gt;defaults-&gt;{foo}, &#39;bar&#39;, &#39;right value&#39;; ok $t-&gt;app-&gt;routes-&gt;find(&#39;echo&#39;)-&gt;is_websocket, &#39;WebSocket route&#39;; my $c = $t-&gt;app-&gt;build_controller; ok $c-&gt;render(template =&gt; &#39;foo&#39;), &#39;rendering was successful&#39;; is $c-&gt;res-&gt;status, 200, &#39;right status&#39;; is $c-&gt;res-&gt;body, &#39;Foo!&#39;, &#39;right content&#39;; # Change application behavior $t-&gt;app-&gt;hook(before_dispatch =&gt; sub ($c) { $c-&gt;render(text =&gt; &#39;This request did not reach the router.&#39;) if $c-&gt;req-&gt;url-&gt;path-&gt;contains(&#39;/user&#39;); }); $t-&gt;get_ok(&#39;/user&#39;)-&gt;status_is(200)-&gt;content_like(qr/not reach the router/); # Extract additional information my $stash; $t-&gt;app-&gt;hook(after_dispatch =&gt; sub ($c) { $stash = $c-&gt;stash }); $t-&gt;get_ok(&#39;/hello&#39;)-&gt;status_is(200); is $stash-&gt;{foo}, &#39;bar&#39;, &#39;right value&#39;;</code></pre> <h2 id="attr_is"><a class="permalink" href="#attr_is">#</a><a href="#toc">attr_is</a></h2> <pre><code>$t = $t-&gt;attr_is(&#39;img.cat&#39;, &#39;alt&#39;, &#39;Grumpy cat&#39;); $t = $t-&gt;attr_is(&#39;img.cat&#39;, &#39;alt&#39;, &#39;Grumpy cat&#39;, &#39;right alt text&#39;);</code></pre> <p>Checks text content of attribute with <a href="http://docs.mojolicious.org/Mojo/DOM#attr">&quot;attr&quot; in Mojo::DOM</a> at the CSS selectors first matching HTML/XML element for exact match with <a href="http://docs.mojolicious.org/Mojo/DOM#at">&quot;at&quot; in Mojo::DOM</a>.</p> <h2 id="attr_isnt"><a class="permalink" href="#attr_isnt">#</a><a href="#toc">attr_isnt</a></h2> <pre><code>$t = $t-&gt;attr_isnt(&#39;img.cat&#39;, &#39;alt&#39;, &#39;Calm cat&#39;); $t = $t-&gt;attr_isnt(&#39;img.cat&#39;, &#39;alt&#39;, &#39;Calm cat&#39;, &#39;different alt text&#39;);</code></pre> <p>Opposite of <a href="#attr_is">&quot;attr_is&quot;</a>.</p> <h2 id="attr_like"><a class="permalink" href="#attr_like">#</a><a href="#toc">attr_like</a></h2> <pre><code>$t = $t-&gt;attr_like(&#39;img.cat&#39;, &#39;alt&#39;, qr/Grumpy/); $t = $t-&gt;attr_like(&#39;img.cat&#39;, &#39;alt&#39;, qr/Grumpy/, &#39;right alt text&#39;);</code></pre> <p>Checks text content of attribute with <a href="http://docs.mojolicious.org/Mojo/DOM#attr">&quot;attr&quot; in Mojo::DOM</a> at the CSS selectors first matching HTML/XML element for similar match with <a href="http://docs.mojolicious.org/Mojo/DOM#at">&quot;at&quot; in Mojo::DOM</a>.</p> <h2 id="attr_unlike"><a class="permalink" href="#attr_unlike">#</a><a href="#toc">attr_unlike</a></h2> <pre><code>$t = $t-&gt;attr_unlike(&#39;img.cat&#39;, &#39;alt&#39;, qr/Calm/); $t = $t-&gt;attr_unlike(&#39;img.cat&#39;, &#39;alt&#39;, qr/Calm/, &#39;different alt text&#39;);</code></pre> <p>Opposite of <a href="#attr_like">&quot;attr_like&quot;</a>.</p> <h2 id="content_is"><a class="permalink" href="#content_is">#</a><a href="#toc">content_is</a></h2> <pre><code>$t = $t-&gt;content_is(&#39;working!&#39;); $t = $t-&gt;content_is(&#39;working!&#39;, &#39;right content&#39;);</code></pre> <p>Check response content for exact match after retrieving it from <a href="http://docs.mojolicious.org/Mojo/Message#text">&quot;text&quot; in Mojo::Message</a>.</p> <h2 id="content_isnt"><a class="permalink" href="#content_isnt">#</a><a href="#toc">content_isnt</a></h2> <pre><code>$t = $t-&gt;content_isnt(&#39;working!&#39;); $t = $t-&gt;content_isnt(&#39;working!&#39;, &#39;different content&#39;);</code></pre> <p>Opposite of <a href="#content_is">&quot;content_is&quot;</a>.</p> <h2 id="content_like"><a class="permalink" href="#content_like">#</a><a href="#toc">content_like</a></h2> <pre><code>$t = $t-&gt;content_like(qr/working!/); $t = $t-&gt;content_like(qr/working!/, &#39;right content&#39;);</code></pre> <p>Check response content for similar match after retrieving it from <a href="http://docs.mojolicious.org/Mojo/Message#text">&quot;text&quot; in Mojo::Message</a>.</p> <h2 id="content_type_is"><a class="permalink" href="#content_type_is">#</a><a href="#toc">content_type_is</a></h2> <pre><code>$t = $t-&gt;content_type_is(&#39;text/html&#39;); $t = $t-&gt;content_type_is(&#39;text/html&#39;, &#39;right content type&#39;);</code></pre> <p>Check response <code>Content-Type</code> header for exact match.</p> <h2 id="content_type_isnt"><a class="permalink" href="#content_type_isnt">#</a><a href="#toc">content_type_isnt</a></h2> <pre><code>$t = $t-&gt;content_type_isnt(&#39;text/html&#39;); $t = $t-&gt;content_type_isnt(&#39;text/html&#39;, &#39;different content type&#39;);</code></pre> <p>Opposite of <a href="#content_type_is">&quot;content_type_is&quot;</a>.</p> <h2 id="content_type_like"><a class="permalink" href="#content_type_like">#</a><a href="#toc">content_type_like</a></h2> <pre><code>$t = $t-&gt;content_type_like(qr/text/); $t = $t-&gt;content_type_like(qr/text/, &#39;right content type&#39;);</code></pre> <p>Check response <code>Content-Type</code> header for similar match.</p> <h2 id="content_type_unlike"><a class="permalink" href="#content_type_unlike">#</a><a href="#toc">content_type_unlike</a></h2> <pre><code>$t = $t-&gt;content_type_unlike(qr/text/); $t = $t-&gt;content_type_unlike(qr/text/, &#39;different content type&#39;);</code></pre> <p>Opposite of <a href="#content_type_like">&quot;content_type_like&quot;</a>.</p> <h2 id="content_unlike"><a class="permalink" href="#content_unlike">#</a><a href="#toc">content_unlike</a></h2> <pre><code>$t = $t-&gt;content_unlike(qr/working!/); $t = $t-&gt;content_unlike(qr/working!/, &#39;different content&#39;);</code></pre> <p>Opposite of <a href="#content_like">&quot;content_like&quot;</a>.</p> <h2 id="delete_ok"><a class="permalink" href="#delete_ok">#</a><a href="#toc">delete_ok</a></h2> <pre><code>$t = $t-&gt;delete_ok(&#39;http://example.com/foo&#39;); $t = $t-&gt;delete_ok(&#39;/foo&#39;); $t = $t-&gt;delete_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; &#39;Content!&#39;); $t = $t-&gt;delete_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; form =&gt; {a =&gt; &#39;b&#39;}); $t = $t-&gt;delete_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; json =&gt; {a =&gt; &#39;b&#39;});</code></pre> <p>Perform a <code>DELETE</code> request and check for transport errors, takes the same arguments as <a href="http://docs.mojolicious.org/Mojo/UserAgent#delete">&quot;delete&quot; in Mojo::UserAgent</a>, except for the callback.</p> <h2 id="element_count_is"><a class="permalink" href="#element_count_is">#</a><a href="#toc">element_count_is</a></h2> <pre><code>$t = $t-&gt;element_count_is(&#39;div.foo[x=y]&#39;, 5); $t = $t-&gt;element_count_is(&#39;html body div&#39;, 30, &#39;thirty elements&#39;);</code></pre> <p>Checks the number of HTML/XML elements matched by the CSS selector with <a href="http://docs.mojolicious.org/Mojo/DOM#find">&quot;find&quot; in Mojo::DOM</a>.</p> <h2 id="element_exists"><a class="permalink" href="#element_exists">#</a><a href="#toc">element_exists</a></h2> <pre><code>$t = $t-&gt;element_exists(&#39;div.foo[x=y]&#39;); $t = $t-&gt;element_exists(&#39;html head title&#39;, &#39;has a title&#39;);</code></pre> <p>Checks for existence of the CSS selectors first matching HTML/XML element with <a href="http://docs.mojolicious.org/Mojo/DOM#at">&quot;at&quot; in Mojo::DOM</a>.</p> <pre><code># Check attribute values $t-&gt;get_ok(&#39;/login&#39;) -&gt;element_exists(&#39;label[for=email]&#39;) -&gt;element_exists(&#39;input[name=email][type=text][value*=&quot;example.com&quot;]&#39;) -&gt;element_exists(&#39;label[for=pass]&#39;) -&gt;element_exists(&#39;input[name=pass][type=password]&#39;) -&gt;element_exists(&#39;input[type=submit][value]&#39;);</code></pre> <h2 id="element_exists_not"><a class="permalink" href="#element_exists_not">#</a><a href="#toc">element_exists_not</a></h2> <pre><code>$t = $t-&gt;element_exists_not(&#39;div.foo[x=y]&#39;); $t = $t-&gt;element_exists_not(&#39;html head title&#39;, &#39;has no title&#39;);</code></pre> <p>Opposite of <a href="#element_exists">&quot;element_exists&quot;</a>.</p> <h2 id="finish_ok"><a class="permalink" href="#finish_ok">#</a><a href="#toc">finish_ok</a></h2> <pre><code>$t = $t-&gt;finish_ok; $t = $t-&gt;finish_ok(1000); $t = $t-&gt;finish_ok(1003 =&gt; &#39;Cannot accept data!&#39;);</code></pre> <p>Close WebSocket connection gracefully.</p> <h2 id="finished_ok"><a class="permalink" href="#finished_ok">#</a><a href="#toc">finished_ok</a></h2> <pre><code>$t = $t-&gt;finished_ok(1000);</code></pre> <p>Wait for WebSocket connection to be closed gracefully and check status.</p> <h2 id="get_ok"><a class="permalink" href="#get_ok">#</a><a href="#toc">get_ok</a></h2> <pre><code>$t = $t-&gt;get_ok(&#39;http://example.com/foo&#39;); $t = $t-&gt;get_ok(&#39;/foo&#39;); $t = $t-&gt;get_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; &#39;Content!&#39;); $t = $t-&gt;get_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; form =&gt; {a =&gt; &#39;b&#39;}); $t = $t-&gt;get_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; json =&gt; {a =&gt; &#39;b&#39;});</code></pre> <p>Perform a <code>GET</code> request and check for transport errors, takes the same arguments as <a href="http://docs.mojolicious.org/Mojo/UserAgent#get">&quot;get&quot; in Mojo::UserAgent</a>, except for the callback.</p> <pre><code># Run tests against remote host $t-&gt;get_ok(&#39;https://docs.mojolicious.org&#39;)-&gt;status_is(200); # Use relative URL for request with Basic authentication $t-&gt;get_ok(&#39;//sri:secr3t@/secrets.json&#39;) -&gt;status_is(200) -&gt;json_is(&#39;/1/content&#39;, &#39;Mojo rocks!&#39;); # Run additional tests on the transaction $t-&gt;get_ok(&#39;/foo&#39;)-&gt;status_is(200); is $t-&gt;tx-&gt;res-&gt;dom-&gt;at(&#39;input&#39;)-&gt;val, &#39;whatever&#39;, &#39;right value&#39;;</code></pre> <h2 id="head_ok"><a class="permalink" href="#head_ok">#</a><a href="#toc">head_ok</a></h2> <pre><code>$t = $t-&gt;head_ok(&#39;http://example.com/foo&#39;); $t = $t-&gt;head_ok(&#39;/foo&#39;); $t = $t-&gt;head_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; &#39;Content!&#39;); $t = $t-&gt;head_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; form =&gt; {a =&gt; &#39;b&#39;}); $t = $t-&gt;head_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; json =&gt; {a =&gt; &#39;b&#39;});</code></pre> <p>Perform a <code>HEAD</code> request and check for transport errors, takes the same arguments as <a href="http://docs.mojolicious.org/Mojo/UserAgent#head">&quot;head&quot; in Mojo::UserAgent</a>, except for the callback.</p> <h2 id="header_exists"><a class="permalink" href="#header_exists">#</a><a href="#toc">header_exists</a></h2> <pre><code>$t = $t-&gt;header_exists(&#39;ETag&#39;); $t = $t-&gt;header_exists(&#39;ETag&#39;, &#39;header exists&#39;);</code></pre> <p>Check if response header exists.</p> <h2 id="header_exists_not"><a class="permalink" href="#header_exists_not">#</a><a href="#toc">header_exists_not</a></h2> <pre><code>$t = $t-&gt;header_exists_not(&#39;ETag&#39;); $t = $t-&gt;header_exists_not(&#39;ETag&#39;, &#39;header is missing&#39;);</code></pre> <p>Opposite of <a href="#header_exists">&quot;header_exists&quot;</a>.</p> <h2 id="header_is"><a class="permalink" href="#header_is">#</a><a href="#toc">header_is</a></h2> <pre><code>$t = $t-&gt;header_is(ETag =&gt; &#39;&quot;abc321&quot;&#39;); $t = $t-&gt;header_is(ETag =&gt; &#39;&quot;abc321&quot;&#39;, &#39;right header&#39;);</code></pre> <p>Check response header for exact match.</p> <h2 id="header_isnt"><a class="permalink" href="#header_isnt">#</a><a href="#toc">header_isnt</a></h2> <pre><code>$t = $t-&gt;header_isnt(Etag =&gt; &#39;&quot;abc321&quot;&#39;); $t = $t-&gt;header_isnt(ETag =&gt; &#39;&quot;abc321&quot;&#39;, &#39;different header&#39;);</code></pre> <p>Opposite of <a href="#header_is">&quot;header_is&quot;</a>.</p> <h2 id="header_like"><a class="permalink" href="#header_like">#</a><a href="#toc">header_like</a></h2> <pre><code>$t = $t-&gt;header_like(ETag =&gt; qr/abc/); $t = $t-&gt;header_like(ETag =&gt; qr/abc/, &#39;right header&#39;);</code></pre> <p>Check response header for similar match.</p> <h2 id="header_unlike"><a class="permalink" href="#header_unlike">#</a><a href="#toc">header_unlike</a></h2> <pre><code>$t = $t-&gt;header_unlike(ETag =&gt; qr/abc/); $t = $t-&gt;header_unlike(ETag =&gt; qr/abc/, &#39;different header&#39;);</code></pre> <p>Opposite of <a href="#header_like">&quot;header_like&quot;</a>.</p> <h2 id="json_has"><a class="permalink" href="#json_has">#</a><a href="#toc">json_has</a></h2> <pre><code>$t = $t-&gt;json_has(&#39;/foo&#39;); $t = $t-&gt;json_has(&#39;/minibar&#39;, &#39;has a minibar&#39;);</code></pre> <p>Check if JSON response contains a value that can be identified using the given JSON Pointer with <a href="http://docs.mojolicious.org/Mojo/JSON/Pointer">Mojo::JSON::Pointer</a>.</p> <h2 id="json_hasnt"><a class="permalink" href="#json_hasnt">#</a><a href="#toc">json_hasnt</a></h2> <pre><code>$t = $t-&gt;json_hasnt(&#39;/foo&#39;); $t = $t-&gt;json_hasnt(&#39;/minibar&#39;, &#39;no minibar&#39;);</code></pre> <p>Opposite of <a href="#json_has">&quot;json_has&quot;</a>.</p> <h2 id="json_is"><a class="permalink" href="#json_is">#</a><a href="#toc">json_is</a></h2> <pre><code>$t = $t-&gt;json_is({foo =&gt; [1, 2, 3]}); $t = $t-&gt;json_is(&#39;/foo&#39; =&gt; [1, 2, 3]); $t = $t-&gt;json_is(&#39;/foo/1&#39; =&gt; 2, &#39;right value&#39;);</code></pre> <p>Check the value extracted from JSON response using the given JSON Pointer with <a href="http://docs.mojolicious.org/Mojo/JSON/Pointer">Mojo::JSON::Pointer</a>, which defaults to the root value if it is omitted.</p> <pre><code># Use an empty JSON Pointer to test the whole JSON response with a test description $t-&gt;json_is(&#39;&#39; =&gt; {foo =&gt; [1, 2, 3]}, &#39;right object&#39;);</code></pre> <h2 id="json_like"><a class="permalink" href="#json_like">#</a><a href="#toc">json_like</a></h2> <pre><code>$t = $t-&gt;json_like(&#39;/foo/1&#39; =&gt; qr/^\d+$/); $t = $t-&gt;json_like(&#39;/foo/1&#39; =&gt; qr/^\d+$/, &#39;right value&#39;);</code></pre> <p>Check the value extracted from JSON response using the given JSON Pointer with <a href="http://docs.mojolicious.org/Mojo/JSON/Pointer">Mojo::JSON::Pointer</a> for similar match.</p> <h2 id="json_message_has"><a class="permalink" href="#json_message_has">#</a><a href="#toc">json_message_has</a></h2> <pre><code>$t = $t-&gt;json_message_has(&#39;/foo&#39;); $t = $t-&gt;json_message_has(&#39;/minibar&#39;, &#39;has a minibar&#39;);</code></pre> <p>Check if JSON WebSocket message contains a value that can be identified using the given JSON Pointer with <a href="http://docs.mojolicious.org/Mojo/JSON/Pointer">Mojo::JSON::Pointer</a>.</p> <h2 id="json_message_hasnt"><a class="permalink" href="#json_message_hasnt">#</a><a href="#toc">json_message_hasnt</a></h2> <pre><code>$t = $t-&gt;json_message_hasnt(&#39;/foo&#39;); $t = $t-&gt;json_message_hasnt(&#39;/minibar&#39;, &#39;no minibar&#39;);</code></pre> <p>Opposite of <a href="#json_message_has">&quot;json_message_has&quot;</a>.</p> <h2 id="json_message_is"><a class="permalink" href="#json_message_is">#</a><a href="#toc">json_message_is</a></h2> <pre><code>$t = $t-&gt;json_message_is({foo =&gt; [1, 2, 3]}); $t = $t-&gt;json_message_is(&#39;/foo&#39; =&gt; [1, 2, 3]); $t = $t-&gt;json_message_is(&#39;/foo/1&#39; =&gt; 2, &#39;right value&#39;);</code></pre> <p>Check the value extracted from JSON WebSocket message using the given JSON Pointer with <a href="http://docs.mojolicious.org/Mojo/JSON/Pointer">Mojo::JSON::Pointer</a>, which defaults to the root value if it is omitted.</p> <h2 id="json_message_like"><a class="permalink" href="#json_message_like">#</a><a href="#toc">json_message_like</a></h2> <pre><code>$t = $t-&gt;json_message_like(&#39;/foo/1&#39; =&gt; qr/^\d+$/); $t = $t-&gt;json_message_like(&#39;/foo/1&#39; =&gt; qr/^\d+$/, &#39;right value&#39;);</code></pre> <p>Check the value extracted from JSON WebSocket message using the given JSON Pointer with <a href="http://docs.mojolicious.org/Mojo/JSON/Pointer">Mojo::JSON::Pointer</a> for similar match.</p> <h2 id="json_message_unlike"><a class="permalink" href="#json_message_unlike">#</a><a href="#toc">json_message_unlike</a></h2> <pre><code>$t = $t-&gt;json_message_unlike(&#39;/foo/1&#39; =&gt; qr/^\d+$/); $t = $t-&gt;json_message_unlike(&#39;/foo/1&#39; =&gt; qr/^\d+$/, &#39;different value&#39;);</code></pre> <p>Opposite of <a href="#json_message_like">&quot;json_message_like&quot;</a>.</p> <h2 id="json_unlike"><a class="permalink" href="#json_unlike">#</a><a href="#toc">json_unlike</a></h2> <pre><code>$t = $t-&gt;json_unlike(&#39;/foo/1&#39; =&gt; qr/^\d+$/); $t = $t-&gt;json_unlike(&#39;/foo/1&#39; =&gt; qr/^\d+$/, &#39;different value&#39;);</code></pre> <p>Opposite of <a href="#json_like">&quot;json_like&quot;</a>.</p> <h2 id="message_is"><a class="permalink" href="#message_is">#</a><a href="#toc">message_is</a></h2> <pre><code>$t = $t-&gt;message_is({binary =&gt; $bytes}); $t = $t-&gt;message_is({text =&gt; $bytes}); $t = $t-&gt;message_is(&#39;working!&#39;); $t = $t-&gt;message_is(&#39;working!&#39;, &#39;right message&#39;);</code></pre> <p>Check WebSocket message for exact match.</p> <h2 id="message_isnt"><a class="permalink" href="#message_isnt">#</a><a href="#toc">message_isnt</a></h2> <pre><code>$t = $t-&gt;message_isnt({binary =&gt; $bytes}); $t = $t-&gt;message_isnt({text =&gt; $bytes}); $t = $t-&gt;message_isnt(&#39;working!&#39;); $t = $t-&gt;message_isnt(&#39;working!&#39;, &#39;different message&#39;);</code></pre> <p>Opposite of <a href="#message_is">&quot;message_is&quot;</a>.</p> <h2 id="message_like"><a class="permalink" href="#message_like">#</a><a href="#toc">message_like</a></h2> <pre><code>$t = $t-&gt;message_like({binary =&gt; qr/$bytes/}); $t = $t-&gt;message_like({text =&gt; qr/$bytes/}); $t = $t-&gt;message_like(qr/working!/); $t = $t-&gt;message_like(qr/working!/, &#39;right message&#39;);</code></pre> <p>Check WebSocket message for similar match.</p> <h2 id="message_ok"><a class="permalink" href="#message_ok">#</a><a href="#toc">message_ok</a></h2> <pre><code>$t = $t-&gt;message_ok; $t = $t-&gt;message_ok(&#39;got a message&#39;);</code></pre> <p>Wait for next WebSocket message to arrive.</p> <pre><code># Wait for message and perform multiple tests on it $t-&gt;websocket_ok(&#39;/time&#39;) -&gt;message_ok -&gt;message_like(qr/\d+/) -&gt;message_unlike(qr/\w+/) -&gt;finish_ok;</code></pre> <h2 id="message_unlike"><a class="permalink" href="#message_unlike">#</a><a href="#toc">message_unlike</a></h2> <pre><code>$t = $t-&gt;message_unlike({binary =&gt; qr/$bytes/}); $t = $t-&gt;message_unlike({text =&gt; qr/$bytes/}); $t = $t-&gt;message_unlike(qr/working!/); $t = $t-&gt;message_unlike(qr/working!/, &#39;different message&#39;);</code></pre> <p>Opposite of <a href="#message_like">&quot;message_like&quot;</a>.</p> <h2 id="new"><a class="permalink" href="#new">#</a><a href="#toc">new</a></h2> <pre><code>my $t = Test::Mojo-&gt;new; my $t = Test::Mojo-&gt;new(&#39;MyApp&#39;); my $t = Test::Mojo-&gt;new(&#39;MyApp&#39;, {foo =&gt; &#39;bar&#39;}); my $t = Test::Mojo-&gt;new(Mojo::File-&gt;new(&#39;/path/to/myapp.pl&#39;)); my $t = Test::Mojo-&gt;new(Mojo::File-&gt;new(&#39;/path/to/myapp.pl&#39;), {foo =&gt; &#39;bar&#39;}); my $t = Test::Mojo-&gt;new(MyApp-&gt;new); my $t = Test::Mojo-&gt;new(MyApp-&gt;new, {foo =&gt; &#39;bar&#39;});</code></pre> <p>Construct a new <a href="http://docs.mojolicious.org/Test/Mojo">Test::Mojo</a> object. In addition to a class name or <a href="http://docs.mojolicious.org/Mojo/File">Mojo::File</a> object pointing to the application script, you can pass along a hash reference with configuration values that will be used to override the application configuration. The special configuration value <code>config_override</code> will be set in <a href="http://docs.mojolicious.org/Mojolicious#config">&quot;config&quot; in Mojolicious</a> as well, which is used to disable configuration plugins like <a href="http://docs.mojolicious.org/Mojolicious/Plugin/Config">Mojolicious::Plugin::Config</a>, <a href="http://docs.mojolicious.org/Mojolicious/Plugin/JSONConfig">Mojolicious::Plugin::JSONConfig</a> and <a href="http://docs.mojolicious.org/Mojolicious/Plugin/NotYAMLConfig">Mojolicious::Plugin::NotYAMLConfig</a> for tests.</p> <pre><code># Load application script relative to the &quot;t&quot; directory use Mojo::File qw(curfile); my $t = Test::Mojo-&gt;new(curfile-&gt;dirname-&gt;sibling(&#39;myapp.pl&#39;));</code></pre> <h2 id="options_ok"><a class="permalink" href="#options_ok">#</a><a href="#toc">options_ok</a></h2> <pre><code>$t = $t-&gt;options_ok(&#39;http://example.com/foo&#39;); $t = $t-&gt;options_ok(&#39;/foo&#39;); $t = $t-&gt;options_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; &#39;Content!&#39;); $t = $t-&gt;options_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; form =&gt; {a =&gt; &#39;b&#39;}); $t = $t-&gt;options_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; json =&gt; {a =&gt; &#39;b&#39;});</code></pre> <p>Perform a <code>OPTIONS</code> request and check for transport errors, takes the same arguments as <a href="http://docs.mojolicious.org/Mojo/UserAgent#options">&quot;options&quot; in Mojo::UserAgent</a>, except for the callback.</p> <h2 id="or"><a class="permalink" href="#or">#</a><a href="#toc">or</a></h2> <pre><code>$t = $t-&gt;or(sub {...});</code></pre> <p>Execute callback if the value of <a href="#success">&quot;success&quot;</a> is false.</p> <pre><code># Diagnostics $t-&gt;get_ok(&#39;/bad&#39;)-&gt;or(sub { diag &#39;Must have been Glen!&#39; }) -&gt;status_is(200)-&gt;or(sub { diag $t-&gt;tx-&gt;res-&gt;dom-&gt;at(&#39;title&#39;)-&gt;text });</code></pre> <h2 id="patch_ok"><a class="permalink" href="#patch_ok">#</a><a href="#toc">patch_ok</a></h2> <pre><code>$t = $t-&gt;patch_ok(&#39;http://example.com/foo&#39;); $t = $t-&gt;patch_ok(&#39;/foo&#39;); $t = $t-&gt;patch_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; &#39;Content!&#39;); $t = $t-&gt;patch_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; form =&gt; {a =&gt; &#39;b&#39;}); $t = $t-&gt;patch_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; json =&gt; {a =&gt; &#39;b&#39;});</code></pre> <p>Perform a <code>PATCH</code> request and check for transport errors, takes the same arguments as <a href="http://docs.mojolicious.org/Mojo/UserAgent#patch">&quot;patch&quot; in Mojo::UserAgent</a>, except for the callback.</p> <h2 id="post_ok"><a class="permalink" href="#post_ok">#</a><a href="#toc">post_ok</a></h2> <pre><code>$t = $t-&gt;post_ok(&#39;http://example.com/foo&#39;); $t = $t-&gt;post_ok(&#39;/foo&#39;); $t = $t-&gt;post_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; &#39;Content!&#39;); $t = $t-&gt;post_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; form =&gt; {a =&gt; &#39;b&#39;}); $t = $t-&gt;post_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; json =&gt; {a =&gt; &#39;b&#39;});</code></pre> <p>Perform a <code>POST</code> request and check for transport errors, takes the same arguments as <a href="http://docs.mojolicious.org/Mojo/UserAgent#post">&quot;post&quot; in Mojo::UserAgent</a>, except for the callback.</p> <pre><code># Test file upload my $upload = {foo =&gt; {content =&gt; &#39;bar&#39;, filename =&gt; &#39;baz.txt&#39;}}; $t-&gt;post_ok(&#39;/upload&#39; =&gt; form =&gt; $upload)-&gt;status_is(200); # Test JSON API $t-&gt;post_ok(&#39;/hello.json&#39; =&gt; json =&gt; {hello =&gt; &#39;world&#39;}) -&gt;status_is(200) -&gt;json_is({bye =&gt; &#39;world&#39;});</code></pre> <h2 id="put_ok"><a class="permalink" href="#put_ok">#</a><a href="#toc">put_ok</a></h2> <pre><code>$t = $t-&gt;put_ok(&#39;http://example.com/foo&#39;); $t = $t-&gt;put_ok(&#39;/foo&#39;); $t = $t-&gt;put_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; &#39;Content!&#39;); $t = $t-&gt;put_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; form =&gt; {a =&gt; &#39;b&#39;}); $t = $t-&gt;put_ok(&#39;/foo&#39; =&gt; {Accept =&gt; &#39;*/*&#39;} =&gt; json =&gt; {a =&gt; &#39;b&#39;});</code></pre> <p>Perform a <code>PUT</code> request and check for transport errors, takes the same arguments as <a href="http://docs.mojolicious.org/Mojo/UserAgent#put">&quot;put&quot; in Mojo::UserAgent</a>, except for the callback.</p> <h2 id="request_ok"><a class="permalink" href="#request_ok">#</a><a href="#toc">request_ok</a></h2> <pre><code>$t = $t-&gt;request_ok(Mojo::Transaction::HTTP-&gt;new);</code></pre> <p>Perform request and check for transport errors.</p> <pre><code># Request with custom method my $tx = $t-&gt;ua-&gt;build_tx(FOO =&gt; &#39;/test.json&#39; =&gt; json =&gt; {foo =&gt; 1}); $t-&gt;request_ok($tx)-&gt;status_is(200)-&gt;json_is({success =&gt; 1}); # Request with custom cookie my $tx = $t-&gt;ua-&gt;build_tx(GET =&gt; &#39;/account&#39;); $tx-&gt;req-&gt;cookies({name =&gt; &#39;user&#39;, value =&gt; &#39;sri&#39;}); $t-&gt;request_ok($tx)-&gt;status_is(200)-&gt;text_is(&#39;head &gt; title&#39; =&gt; &#39;Hello sri&#39;); # Custom WebSocket handshake my $tx = $t-&gt;ua-&gt;build_websocket_tx(&#39;/foo&#39;); $tx-&gt;req-&gt;headers-&gt;remove(&#39;User-Agent&#39;); $t-&gt;request_ok($tx)-&gt;message_ok-&gt;message_is(&#39;bar&#39;)-&gt;finish_ok;</code></pre> <h2 id="reset_session"><a class="permalink" href="#reset_session">#</a><a href="#toc">reset_session</a></h2> <pre><code>$t = $t-&gt;reset_session;</code></pre> <p>Reset user agent session.</p> <h2 id="send_ok"><a class="permalink" href="#send_ok">#</a><a href="#toc">send_ok</a></h2> <pre><code>$t = $t-&gt;send_ok({binary =&gt; $bytes}); $t = $t-&gt;send_ok({text =&gt; $bytes}); $t = $t-&gt;send_ok({json =&gt; {test =&gt; [1, 2, 3]}}); $t = $t-&gt;send_ok([$fin, $rsv1, $rsv2, $rsv3, $op, $payload]); $t = $t-&gt;send_ok($chars); $t = $t-&gt;send_ok($chars, &#39;sent successfully&#39;);</code></pre> <p>Send message or frame via WebSocket.</p> <pre><code># Send JSON object as &quot;Text&quot; message $t-&gt;websocket_ok(&#39;/echo.json&#39;) -&gt;send_ok({json =&gt; {test =&gt; &#39;I ♥ Mojolicious!&#39;}}) -&gt;message_ok -&gt;json_message_is(&#39;/test&#39; =&gt; &#39;I ♥ Mojolicious!&#39;) -&gt;finish_ok;</code></pre> <h2 id="status_is"><a class="permalink" href="#status_is">#</a><a href="#toc">status_is</a></h2> <pre><code>$t = $t-&gt;status_is(200); $t = $t-&gt;status_is(200, &#39;right status&#39;);</code></pre> <p>Check response status for exact match.</p> <h2 id="status_isnt"><a class="permalink" href="#status_isnt">#</a><a href="#toc">status_isnt</a></h2> <pre><code>$t = $t-&gt;status_isnt(200); $t = $t-&gt;status_isnt(200, &#39;different status&#39;);</code></pre> <p>Opposite of <a href="#status_is">&quot;status_is&quot;</a>.</p> <h2 id="test"><a class="permalink" href="#test">#</a><a href="#toc">test</a></h2> <pre><code>$t = $t-&gt;test(&#39;is&#39;, &#39;first value&#39;, &#39;second value&#39;, &#39;right value&#39;);</code></pre> <p>Call <a href="http://docs.mojolicious.org/Test/More">Test::More</a> functions through <a href="#handler">&quot;handler&quot;</a>, used to implement <a href="http://docs.mojolicious.org/Test/Mojo">Test::Mojo</a> roles. The result will be stored in <a href="#success">&quot;success&quot;</a>.</p> <h2 id="text_is"><a class="permalink" href="#text_is">#</a><a href="#toc">text_is</a></h2> <pre><code>$t = $t-&gt;text_is(&#39;div.foo[x=y]&#39; =&gt; &#39;Hello!&#39;); $t = $t-&gt;text_is(&#39;html head title&#39; =&gt; &#39;Hello!&#39;, &#39;right title&#39;);</code></pre> <p>Checks text content of the CSS selectors first matching HTML/XML element for exact match with <a href="http://docs.mojolicious.org/Mojo/DOM#at">&quot;at&quot; in Mojo::DOM</a>.</p> <h2 id="text_isnt"><a class="permalink" href="#text_isnt">#</a><a href="#toc">text_isnt</a></h2> <pre><code>$t = $t-&gt;text_isnt(&#39;div.foo[x=y]&#39; =&gt; &#39;Hello!&#39;); $t = $t-&gt;text_isnt(&#39;html head title&#39; =&gt; &#39;Hello!&#39;, &#39;different title&#39;);</code></pre> <p>Opposite of <a href="#text_is">&quot;text_is&quot;</a>.</p> <h2 id="text_like"><a class="permalink" href="#text_like">#</a><a href="#toc">text_like</a></h2> <pre><code>$t = $t-&gt;text_like(&#39;div.foo[x=y]&#39; =&gt; qr/Hello/); $t = $t-&gt;text_like(&#39;html head title&#39; =&gt; qr/Hello/, &#39;right title&#39;);</code></pre> <p>Checks text content of the CSS selectors first matching HTML/XML element for similar match with <a href="http://docs.mojolicious.org/Mojo/DOM#at">&quot;at&quot; in Mojo::DOM</a>.</p> <h2 id="text_unlike"><a class="permalink" href="#text_unlike">#</a><a href="#toc">text_unlike</a></h2> <pre><code>$t = $t-&gt;text_unlike(&#39;div.foo[x=y]&#39; =&gt; qr/Hello/); $t = $t-&gt;text_unlike(&#39;html head title&#39; =&gt; qr/Hello/, &#39;different title&#39;);</code></pre> <p>Opposite of <a href="#text_like">&quot;text_like&quot;</a>.</p> <h2 id="websocket_ok"><a class="permalink" href="#websocket_ok">#</a><a href="#toc">websocket_ok</a></h2> <pre><code>$t = $t-&gt;websocket_ok(&#39;http://example.com/echo&#39;); $t = $t-&gt;websocket_ok(&#39;/echo&#39;); $t = $t-&gt;websocket_ok(&#39;/echo&#39; =&gt; {DNT =&gt; 1} =&gt; [&#39;v1.proto&#39;]);</code></pre> <p>Open a WebSocket connection with transparent handshake, takes the same arguments as <a href="http://docs.mojolicious.org/Mojo/UserAgent#websocket">&quot;websocket&quot; in Mojo::UserAgent</a>, except for the callback.</p> <pre><code># WebSocket with permessage-deflate compression $t-&gt;websocket_ok(&#39;/&#39; =&gt; {&#39;Sec-WebSocket-Extensions&#39; =&gt; &#39;permessage-deflate&#39;}) -&gt;send_ok(&#39;y&#39; x 50000) -&gt;message_ok -&gt;message_is(&#39;z&#39; x 50000) -&gt;finish_ok;</code></pre> <h1 id="SEE-ALSO"><a class="permalink" href="#SEE-ALSO">#</a><a href="#toc">SEE ALSO</a></h1> <p><a href="http://docs.mojolicious.org/Mojolicious">Mojolicious</a>, <a href="http://docs.mojolicious.org/Mojolicious/Guides">Mojolicious::Guides</a>, <a href="https://mojolicious.org">https://mojolicious.org</a>.</p> </div> </main> </div> </div> <footer> <div class="container-fluid p-3 mojo-footer"> <div class="row"> <div class="col-sm align-self-center text-center mojo-free"> <b>Free</b> and <b>Open Source</b>. </div> <div class="col-sm align-self-center text-center mojo-copy"> <i class="far fa-copyright"></i> 2008-2023 Sebastian Riedel and the <a href="https://docs.mojolicious.org/Mojolicious#AUTHORS">Mojolicious contributors</a>. </div> <div class="col-sm align-self-center text-center mojo-social"> <a alt="GitHub" href="https://github.com/mojolicious/mojo"><i class="fab fa-github-alt"></i></a> <a alt="Mastodon" rel="me" href="https://fosstodon.org/@mojolicious"><i class="fab fa-mastodon"></i></a> <a alt="LinkedIn" href="https://www.linkedin.com/groups/8963713/"><i class="fab fa-linkedin"></i></a> </div> </div> </div> </footer> <script> const links = document.querySelectorAll('.mojo-sidebar ul li a[href^="#"]'); const linkById = Object.fromEntries(Array.from(links).map(e => [e.getAttribute('href').substr(1), e])); const sections = Array.from(links).map(e => document.getElementById(e.getAttribute('href').substr(1))).reverse(); let lastSectionId; let mojoOnScroll = () => { const pos = (document.documentElement.scrollTop || document.body.scrollTop) - 63; const section = sections.find(e => e.offsetTop <= pos); if (!section) return; if (section.id == lastSectionId) return; lastSectionId = section.id; links.forEach(e => e.classList.remove('font-weight-bold')); linkById[section.id].classList.add('font-weight-bold'); }; window.onscroll = mojoOnScroll; mojoOnScroll(); </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10