File Coverage

blib/lib/Test/JavaScript.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Test::JavaScript;
2              
3             =head1 NAME
4              
5             Test::JavaScript - JavaScript Testing Module
6              
7             =head1 SYNOPSIS
8              
9             use Test::JavaScript qw(no_plan);
10              
11             js_eval_ok("/path/to/MyFile.js");
12              
13             js_ok("var obj = new MyFile", "Create a MyFile object");
14              
15             js_ok("obj.someFunction = function () { return 'ok' }");
16              
17             js_is("obj.someFunction()", "ok");
18              
19             =head1 DESCRIPTION
20              
21             Test::JavaScript provides a method of unit testing javascript code from within
22             perl. This module uses the JavaScript::SpiderMonkey package to evaluate
23             JavaScript using the SpiderMonkey JavaScript engine.
24              
25             =cut
26              
27 6     6   64634 use strict 'vars';
  6         14  
  6         195  
28 6     6   34 use warnings;
  6         7  
  6         149  
29              
30 6     6   29 use Exporter;
  6         32  
  6         261  
31 6     6   48 use Carp qw(croak);
  6         9  
  6         2757  
32              
33 6     6   6407 use Test::Builder;
  6         97228  
  6         313  
34             our $Test = Test::Builder->new;
35              
36 6     6   14370 use JavaScript::SpiderMonkey;
  0            
  0            
37             our $js = JavaScript::SpiderMonkey->new();
38             $js->init();
39             END { $js->destroy };
40              
41             our $VERSION = 0.06;
42             our @ISA = qw(Exporter);
43             our @EXPORT = qw(js_ok js_eval_ok js_is js_isnt js_diag);
44              
45             sub no_ending { $Test->no_ending(@_) }
46             sub plan { $Test->plan(@_) }
47              
48             sub import {
49             my $self = shift;
50             my $caller = caller;
51              
52             for my $f (@EXPORT) {
53             *{$caller.'::'.$f} = \&$f;
54             }
55              
56             $Test->exported_to($caller);
57             $Test->plan(@_);
58             }
59              
60             sub try_eval {
61             my ($code, $name) = @_;
62             my $rc = $js->eval($code);
63             unless ($rc) {
64             my $ok = $Test->ok( !$@, $name );
65             $Test->diag(<
66             $@
67             DIAGNOSTIC
68             $@ = '';
69             }
70             }
71              
72             sub escape_args {
73             my $name = pop @_;
74             my @args = @_;
75             $args[0] = $name and $name = '' unless @args;
76             s/'/\\'/g foreach @args;
77             (my $escaped = $name) =~ s/'/\\'/g;
78             return (@args,$escaped,$name);
79             }
80              
81             =item B
82              
83             js_eval_ok($filename)
84              
85             This reads a file and evals it in JavaScript
86              
87             For example:
88              
89             js_eval_ok( "/path/to/some/file.js" );
90              
91             =cut
92              
93             sub js_eval_ok ($;@) {
94             my $filename = shift || croak "filename required";
95             croak "$filename doesn't exist" unless $filename;
96              
97             open my $fh, $filename or die "Couldn't read $filename: $!";
98             my @lines = <$fh>;
99             close $fh or die "Couldn't read $filename: $!";
100              
101             my $rc = $js->eval(join("\n", @lines));
102             my $ok = $Test->ok( !$@, "use $filename;" );
103              
104             unless( $rc ) {
105             $Test->diag(<
106             Tried to use '$filename'.
107             $@
108             DIAGNOSTIC
109             }
110             }
111              
112             =item B
113              
114             =item B
115              
116             js_is ( $this, $that, $test_name );
117             js_isnt( $this, $that, $test_name );
118              
119             This compares two values in JavaScript land. They can be literal strings
120             passed from perl or variables defined earlier.
121              
122             For example:
123              
124             js_ok("var i = 3"); // ok
125             js_is("i", 3, "i is 3"); // ok
126             js_is("3", 3, "3 is 3"); // ok
127             js_is("3", 2, "3 is 2"); // not ok
128              
129             js_ok("function three () { return 3 }"); // ok
130             js_is("three()", 3); // ok
131             js_is("three()", 4); // not ok
132              
133             js_isnt("3", 4, "3 is not 4"); // ok
134              
135             =cut
136              
137             $js->function_set("is", sub { $Test->is_eq(@_) });
138              
139             sub js_is {
140             my ($test,$actual,$ename,$name) = escape_args(@_);
141             my $code = <
142             is( $test, '$actual', '$ename'.replace(/\\'/,"'"));
143             EOT
144             try_eval($code, $name);
145             }
146              
147             $js->function_set("isnt", sub { $Test->isnt_eq(@_) });
148              
149             sub js_isnt {
150             my ($test,$actual,$ename,$name) = escape_args(@_);
151             my $code = <
152             isnt( $test, '$actual', '$ename'.replace(/\\'/,"'"));
153             EOT
154             try_eval($code, $name);
155             }
156              
157             =item B
158              
159             js_ok("var monkey = 3", $test_name);
160              
161             The expression passed as the first parameter is evaluated as either true or
162             false. The test fails if the expression explicitly returns false, or if a
163             syntax error occurs in JavaScript land
164              
165             For example:
166              
167             js_ok("var i = 3"); // ok
168             js_ok("true", "true is true"); // ok
169             js_ok("1 == 2", "1 is equal to 2"); // not ok
170             js_ok("false", "false is false"); // not ok
171             js_ok("var array = ['one','two',non_existing_var];") // not ok
172              
173             =cut
174              
175             $js->function_set("ok", sub { $Test->ok(@_) });
176             sub js_ok {
177             my ($test,$ename,$name) = escape_args(@_);
178             my $lines = join"\n", map { "code.push('$_');" } split("\n", $test);
179             my $code = <
180             var code = new Array;
181             $lines
182             var result = eval(code.join("\\n")) ? true : false;
183             ok( result, '$ename'.replace(/\\'/,"'"));
184             EOT
185              
186             try_eval($code, $name);
187             }
188              
189             =item B
190              
191             js_ok("var myval = 3; diag('the variable myval is ' + myval)");
192              
193             This subroutine simply logs the parameters passed as a comment
194              
195             =cut
196              
197             $js->function_set("diag", sub { $Test->diag(@_) });
198              
199             =head1 AUTHORS
200              
201             Kevin Jones, C<< >>
202              
203             =head1 COPYRIGHT
204              
205             Copyright 2006 Kevin Jones, All Rights Reserved.
206              
207             This program is free software; you can redistribute it and/or modify it
208             under the same terms as Perl itself.
209              
210             =cut
211              
212             return 1;