Giter Club home page Giter Club logo

mojo-phantom's Introduction

NAME

Test::Mojo::Role::Phantom - Adds phantom_ok to Test::Mojo

SYNOPSIS

use Mojolicious::Lite;

use Test::More;
use Test::Mojo::WithRoles qw/Phantom/;

any '/' => 'index';

my $t = Test::Mojo::WithRoles->new;

$t->phantom_ok('/' => <<'JS');
  var text = page.evaluate(function(){
    return document.getElementById('name').innerHTML;
  });
  perl.is(text, 'Bender', 'name changed after loading');
JS

done_testing;

__DATA__

@@ index.html.ep

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <p id="name">Leela</p>
    <script>
      (function(){ document.getElementById('name').innerHTML = 'Bender' })();
    </script>
  </body>
</html>

DESCRIPTION

Test::Mojo::Role::Phantom is a Role::Tiny role which adds a phantom_ok method to Test::Mojo or a Test::Mojo instance. This method tests the javascript behavior of the app via an external PhantomJS process. You must install that program and it must be in your PATH in order to use this method.

The author recommends using Test::Mojo::WithRoles to manage the role application. The low level interaction is handled by a Mojo::Phantom instance, but for the most part that is transparent to the test method.

WARNING

The upstream phantom.js has been retired in favor of headless chrome. A Mojo::Chrome (and related Test::Mojo::Role::Chrome) is planned and is already in the works (perhaps it is released already who knows?!). While this module will continue to function, just know that it depends on a project that is defunct.

METHODS

phantom_ok

$t = $t->phantom_ok(@url_for, $js, \%opts)

The arguments are as follows

url specification

phantom_ok takes a url or arguments for "url_for" in Mojolicious::Controller, a required string of javascript and and optional hash reference of additional arguments.

javascript

The javascript string will be executed once the phantom object has loaded the page in question. At this point, it will have access to all the symbols of a typical phantom process as well as

page

The page object.

status

The page request status, should be success.

perl

A function which takes the name of a perl function and arguments for that function. The function name and the arguments are serialized as JSON and then executed on the perl side.

If the function dies (or is CORE::die), the test fails.

Since it would be prohibitively expensive to start up a new phantom process for each test in the string, the entire string is executed as a subtest. The test result will be success if the entire subtest is a success.

If there is a javascript error, the subtest will fail.

options

The method also takes a hashreference of additional options. They are as follows:

name

The name of the subtest

plan

The number of tests that are expected. While not required, this is more useful than most plans in Test::More since the transport of the commands is volatile. By specifying a plan in this way, if the process exits (status zero) early or never starts, the test will still fail rather than silently pass assuming there were no tests.

package

The package that is searched for Perl functions if the function name is not fully qualified.

bind

A hash reference of key-value pairs which then have shortcuts built in the phantom process. The pairs passed are merged into

{
  ok    => 'Test::More::ok',
  is    => 'Test::More::is',
  diag  => 'Test::More::diag',
  note  => 'Test::More::note',
  fail  => 'Test::More::fail',
}

In the phantom process you may then use the shortcut as

perl.ok(@args)

Which is handy if you are using a certain function often.

Note that if the value is falsey, the key name is use as the target.

setup

A pass-through option specifying javascript to be run after the page object is created but before the url is opened.

phantom

If you need even more control, you may pass in an instance of Mojo::Phantom and it will be used.

no_exit

Do not automatically call phantom.exit() after the provided JavaScript code. This is useful when testing asynchronous events.

note_console

Redirect console.log output to TAP as note events. This is usually helpful, but can be turned off if it becomes too verbose.

phantom_args

Specifies an array reference of command-line arguments passed directly to the PhantomJS process.

DESIGN GOALS

Not enough people test their client-side javascript. The primary goal is make testing js in you Mojolicious app that you actually DO IT. To accomplish this, I make the following goals:

  • Have the test script not depend on a running mojolicious server (i.e. start one, like Test::Mojo scripts can), whether that be from a js or perl file doesn't matter

  • Emit tap in a normal way in a manner that prove -l can collect tests

  • Not have to reimplement a large chunk of the test methods in either Test::More or Test::Mojo. Note: if some javascript library has functionality like Test::* (that emits tap and can be collected subject to the previous goals) then that would be sufficient.

This module is the result of those goals and my limited design ability. I encourage contribution, whether to this implementation or some other implementation which meets these goals!

NOTES

The phantom_ok test itself mimics a subtest. While this outer test behaves correctly, individual tests do not report the correct line and file, instead emitting from inside the IOLoop. It is hoped that future versions of Test::More will make correct reporting possible, but it is not yet.

SOURCE REPOSITORY

http://github.com/jberger/Test-Mojo-Phantom

AUTHOR

Joel Berger, <[email protected]>

COPYRIGHT AND LICENSE

Copyright (C) 2015 by Joel Berger

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

mojo-phantom's People

Contributors

eckankar avatar jberger avatar plicease avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

mojo-phantom's Issues

Cannot install Mojo::Phantom

On ubuntu mate 16.04, 64 bits, perl v5.24.0 (also tried v5.22.1), and Phantomjs v2.1.1, installed whith:

$> sudo apt-get install phantomjs

trying to install Mojo::Phantom:

$> cpanm Mojo::Phantom

fails, with following log:

cpanm (App::cpanminus) 1.7040 on perl 5.024000 built for x86_64-linux-thread-multi
Work directory is /home/daniel/.cpanm/work/1464480846.2369
You have make /usr/bin/make
You have /usr/bin/wget
You have /bin/tar: tar (GNU tar) 1.28
Copyright © 2014 Free Software Foundation, Inc.
License GPLv3+: GPL de GNU versión 3 o posterior http://gnu.org/licenses/gpl.html
Esto es software libre: usted es libre de cambiarlo y redistribuirlo.
No hay NINGUNA GARANTÍA, hasta donde permite la ley.

Escrito por John Gilmore y Jay Fenlason.
You have /usr/bin/unzip
Searching Mojo::Phantom () on cpanmetadb ...
--> Working on Mojo::Phantom
Fetching http://www.cpan.org/authors/id/J/JB/JBERGER/Mojo-Phantom-0.03.tar.gz
-> OK
Unpacking Mojo-Phantom-0.03.tar.gz
Entering Mojo-Phantom-0.03
Checking configure dependencies from META.json
Checking if you have IPC::Cmd 0 ... Yes (0.92)
Checking if you have Module::Build::Tiny 0.007 ... Yes (0.039)
Configuring Mojo-Phantom-0.03
Running Build.PL
Creating new 'Build' script for 'Mojo-Phantom' version '0.03'
-> OK
Checking dependencies from MYMETA.json ...
Checking if you have Mojolicious 6.0 ... Yes (6.62)
Checking if you have Test::Mojo::WithRoles 0 ... Yes (0.02)
Checking if you have Test::More 0 ... Yes (1.001014)
Checking if you have JavaScript::Value::Escape 0 ... Yes (0.07)
Checking if you have Role::Tiny 0 ... Yes (2.000003)
Building and testing Mojo-Phantom-0.03
cp lib/Test/Mojo/Role/Phantom.pm blib/lib/Test/Mojo/Role/Phantom.pm
cp lib/Mojo/Phantom.pm blib/lib/Mojo/Phantom.pm
cp lib/Mojo/Phantom/Process.pm blib/lib/Mojo/Phantom/Process.pm
t/basic.t ...... ok

#   Failed test 'don't get here'
#   at (eval 94) line 1.

Use of uninitialized value $error in scalar chomp at t/exception.t line 51.

#   Failed test 'got the right error'
#   at t/exception.t line 52.
#                   undef
#     doesn't match '(?^:PHANTOM ERROR.*dozNotExistz)'
# Looks like you failed 2 tests of 4.

# Failed test 'js side error'
# at t/exception.t line 53.
# Looks like you failed 1 test of 3.
t/exception.t ..
Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/3 subtests
# Failed to import cookie mojolicious
t/session.t .... ok
t/setup.t ...... ok
t/synopsis.t ... ok

Test Summary Report

t/exception.t (Wstat: 256 Tests: 3 Failed: 1)
Failed test: 2
Non-zero exit status: 1
Files=5, Tests=12, 7 wallclock secs ( 0.06 usr 0.01 sys + 5.57 cusr 0.68 csys = 6.32 CPU)
Result: FAIL
-> FAIL Installing Mojo::Phantom failed. See /home/daniel/.cpanm/work/1464480846.2369/build.log for details. Retry with --force to force install it.

Can't locate object method "delay" via package "Mojo::IOLoop"

The module probably does not work with Mojolicious 9.x anymore:

#   Failed test 'No tests run for subtest "all phantom tests successful"'
#   at t/arguments.t line 25.
Can't locate object method "delay" via package "Mojo::IOLoop" at /home/cpansand/.cpan/build/2021030710/Mojo-Phantom-0.11-0/blib/lib/Test/Mojo/Role/Phantom.pm line 58.
# Tests were run but no plan was declared and done_testing() was not seen.
# Looks like your test exited with 29 just after 1.
t/arguments.t .. 
Dubious, test returned 29 (wstat 7424, 0x1d00)
Failed 1/1 subtests 
    # No tests run!
... etc ...

Mojo::Util::spurt deprecated in favor of Mojo::File::spurt

In version 0.07, with Mojolicious v7.28, just running the code example shown in main page, you get:

# Subtest: all phantom tests successful Mojo::Util::spurt is DEPRECATED in favor of Mojo::File::spurt at /home/bam/.plenv/versions/5.24.1/lib/perl5/site_perl/5.24.1/Test/Mojo/Role/Phantom.pm line 47. ok 1 - name changed after loading 1..1 ok 1 - all phantom tests successful 1..1

I think the deprecated code is in line 162 of lib/Mojo/Phantom.pm:

Mojo::Util::spurt($js => "$tmp");

exception / syntax error can cause test to hang forever

Consider:

use Mojolicious::Lite;

any '/' => 'main';

use Test::More;
use Test::Mojo::WithRoles qw/Phantom/;

my $t = Test::Mojo::WithRoles->new;

my $js = <<'JS';
  throw 'foo';
JS

$t->phantom_ok('main', $js);

done_testing;

__DATA__

@@ main.html.ep

<!DOCTYPE html>
<html>
  <head></head>
  <body>
  </body>
</html>

Because the exception is thrown before the code gets to the phantom.exit() the test hangs. Worse there isn't a diagnostic. Wrapping my code in an eval helps:

my $js = <<'JS';
  try {
    throw 'foo';
  } catch (e) {
    perl.fail('javascript exception: ' + e);
  }
JS

This might be a sane default (?), but does not help for a syntax error which also exhibits the same hang with no diagnostic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.