Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
lemonldap-ng
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
244
Issues
244
List
Boards
Labels
Service Desk
Milestones
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
LemonLDAP NG
lemonldap-ng
Commits
73908208
Commit
73908208
authored
Sep 06, 2018
by
Xavier Guimard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add test framework doc
parent
150d762d
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
472 additions
and
0 deletions
+472
-0
lemonldap-ng-portal/t/README.md
lemonldap-ng-portal/t/README.md
+188
-0
lemonldap-ng-portal/t/test-lib.pm
lemonldap-ng-portal/t/test-lib.pm
+284
-0
No files found.
lemonldap-ng-portal/t/README.md
0 → 100644
View file @
73908208
# NAME
test-lib.pm - Test framework for LLNG portal
# SYNOPSIS
use Test::More;
use strict;
use IO::String;
require 't/test-lib.pm';
my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
#...
}
}
);
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),
length => 23
),
'Auth query'
);
count(1);
expectOK($res);
my $id = expectCookie($res);
clean_sessions();
done_testing( count() );
# DESCRIPTION
This test library permits to simulate browser navigation.
## Functions
In these functions,
`$res`
is the result of a
`LLNG::Manager::Test::_get()`
or
`LLNG::Manager::Test::_post()`
call _(see below)_.
#### count($inc)
Returns number of tests done. Increment test number if an argument is given
#### explain( $result, $expected\_result )
Used to display error if test fails:
ok( $res->[0] == 302, 'Get redirection' ) or
explain( $res->[0], 302 );
#### clean\_sessions()
Clean sessions created during tests
#### expectRedirection( $res, $location )
Verify that request result is a redirection to $location. $location can be:
-
a string: location must match exactly
-
a regexp: location must match this regexp. In this case, the list of
matching strings are returned. Example:
my( $uri, $query ) = expectRedirection( $res, qr#http://host(/[^\?]*)?(.*)$# );
#### expectAutoPost(@args)
Same behaviour as
`expectForm()`
but verify also that form method is post.
TODO: verify javascript
#### expectForm( $res, $hostRe, $uriRe, @requiredFields )
Verify form in HTML result and return ( $host, $uri, $query, $method ):
-
verify that a GET/POST form exists
-
if a $hostRe regexp is given, verify that form target matches and
populates $host. Skipped if $hostRe eq "#"
-
if a $uriRe regexp is given, verify that form target matches and
populates $uri
-
if @requiredFields exists, verify that each element is an input name
-
build form-url-encoded string looking at parameters/values and store it
in $query
#### expectAuthenticatedAs($user)
Verify that result has a
`Lm-Remote-User`
header and value is $user
#### expectOK($res)
Verify that returned code is 200
#### expectBadRequest($res)
Verify that returned code is 400. Note that it works only for Ajax request
(see below).
#### expectReject( $res, $code )
Verify that returned code is 401 and JSON result contains
`error:"$code"`
.
Note that it works only for Ajax request (see below).
#### expectCookie( $res, $cookieName )
Check if a
`Set-Cookie`
exists and set a cookie named $cookieName. Return
its value.
#### exceptCspFormOK( $res, $host )
Verify that
`Content-Security-Policy`
header allows to connect to $host.
#### getCookies($res)
Returns an hash ref with names => values of cookies set by server.
#### getHeader( $res, $hname )
Returns value of first header named $hname in $res response.
#### getRedirection($res)
Returns value of
`Location`
header.
#### getUser($res)
Returns value of
`Lm-Remote-User`
header.
## LLNG::Manager::Test Class
### Accessors
-
app: built application
-
class: class to test (default Lemonldap::NG::Portal::Main)
-
p: portal object
-
ini: initialization parameters ($defaultIni values + given parameters)
### Methods
#### logout($id)
Launch a
`/?logout=1`
request an test:
-
if response is 200
-
if cookie 'lemonldap' and 'lemonldappdata' have no value
-
if a GET request with previous cookie value _($i)_ is rejected
#### \_get( $path, %args )
Simulates a GET requests to $path. Accepted arguments:
-
accept: accepted content, default to Ajax request. Use 'text/html'
to test content _(to launch a
`expectForm()`
for example)_.
-
cookie: full cookie string
-
custom: additional headers (hash ref only)
-
ip: remote address. Default to 127.0.0.1
-
method: default to GET. Only GET/DELETE values are acceptable
(use
`_post()`
if you want to launch a POST/PUT request)
-
query: query string
-
referer
-
remote
\_
user: REMOTE
\_
USER header value
#### \_post( $path, $body, %args )
Same as
`_get`
except that a body is required. $body must be a file handle.
Example with IO::String:
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),
length => 23
),
'Auth query'
);
#### \_delete( $path, %args )
Call
`_get()`
with method set to DELETE.
#### \_put( $path, $body, %args )
Call
`_post()`
with method set to PUT
lemonldap-ng-portal/t/test-lib.pm
View file @
73908208
# Base library for portal tests
package
main
;
=pod
=encoding utf8
=head1 NAME
test-lib.pm - Test framework for LLNG portal
=head1 SYNOPSIS
use Test::More;
use strict;
use IO::String;
require 't/test-lib.pm';
my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
#...
}
}
);
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),
length => 23
),
'Auth query'
);
count(1);
expectOK($res);
my $id = expectCookie($res);
clean_sessions();
done_testing( count() );
=head1 DESCRIPTION
This test library permits to simulate browser navigation.
=head2 Functions
In these functions, C<$res> is the result of a C<LLNG::Manager::Test::_get()> or
C<LLNG::Manager::Test::_post()> call I<(see below)>.
=cut
use
strict
;
use
Data::
Dumper
;
use
LWP::
UserAgent
;
...
...
@@ -20,18 +72,39 @@ $Data::Dumper::Sortkeys = 1;
$
Data::Dumper::
Useperl
=
1
;
my
$ini
;
=head4 count($inc)
Returns number of tests done. Increment test number if an argument is given
=cut
sub
count
{
my
$c
=
shift
;
$count
+=
$c
if
(
$c
);
return
$count
;
}
=head4 explain( $result, $expected_result )
Used to display error if test fails:
ok( $res->[0] == 302, 'Get redirection' ) or
explain( $res->[0], 302 );
=cut
sub
main
::explain {
my
(
$get
,
$ref
)
=
@_
;
$get
=
Dumper
(
$get
)
if
(
ref
$get
);
diag
("
Expect
$ref
, get
$get
\n
");
}
=head4 clean_sessions()
Clean sessions created during tests
=cut
sub
clean_sessions
{
opendir
D
,
'
t/sessions
'
or
die
$!
;
foreach
(
grep
{
/^[^\.]/
}
readdir
(
D
)
)
{
...
...
@@ -60,6 +133,23 @@ sub getCache {
);
}
=head4 expectRedirection( $res, $location )
Verify that request result is a redirection to $location. $location can be:
=over
=item a string: location must match exactly
=item a regexp: location must match this regexp. In this case, the list of
matching strings are returned. Example:
my( $uri, $query ) = expectRedirection( $res, qr#http://host(/[^\?]*)?(.*)$# );
=back
=cut
sub
expectRedirection
{
my
(
$res
,
$location
)
=
@_
;
ok
(
$res
->
[
0
]
==
302
,
'
Get redirection
'
)
...
...
@@ -80,6 +170,14 @@ sub expectRedirection {
}
}
=head4 expectAutoPost(@args)
Same behaviour as C<expectForm()> but verify also that form method is post.
TODO: verify javascript
=cut
sub
expectAutoPost
{
my
@r
=
expectForm
(
@
_
);
my
$method
=
pop
@r
;
...
...
@@ -88,6 +186,29 @@ sub expectAutoPost {
return
@r
;
}
=head4 expectForm( $res, $hostRe, $uriRe, @requiredFields )
Verify form in HTML result and return ( $host, $uri, $query, $method ):
=over
=item verify that a GET/POST form exists
=item if a $hostRe regexp is given, verify that form target matches and
populates $host. Skipped if $hostRe eq "#"
=item if a $uriRe regexp is given, verify that form target matches and
populates $uri
=item if @requiredFields exists, verify that each element is an input name
=item build form-url-encoded string looking at parameters/values and store it
in $query
=back
=cut
sub
expectForm
{
my
(
$res
,
$hostRe
,
$uriRe
,
@requiredFields
)
=
@_
;
expectOK
(
$res
);
...
...
@@ -143,6 +264,12 @@ m@<form.+?action="(?:(?:http://([^/]+))?(/.*?)?|(#))".+method="(post|get)"@is,
}
}
=head4 expectAuthenticatedAs($user)
Verify that result has a C<Lm-Remote-User> header and value is $user
=cut
sub
expectAuthenticatedAs
{
my
(
$res
,
$user
)
=
@_
;
ok
(
getHeader
(
$res
,
'
Lm-Remote-User
'
)
eq
$user
,
...
...
@@ -151,18 +278,38 @@ sub expectAuthenticatedAs {
count
(
1
);
}
=head4 expectOK($res)
Verify that returned code is 200
=cut
sub
expectOK
{
my
(
$res
)
=
@_
;
ok
(
$res
->
[
0
]
==
200
,
'
HTTP code is 200
'
)
or
explain
(
$res
,
200
);
count
(
1
);
}
=head4 expectBadRequest($res)
Verify that returned code is 400. Note that it works only for Ajax request
(see below).
=cut
sub
expectBadRequest
{
my
(
$res
)
=
@_
;
ok
(
$res
->
[
0
]
==
400
,
'
HTTP code is 400
'
)
or
explain
(
$res
->
[
0
],
400
);
count
(
1
);
}
=head4 expectReject( $res, $code )
Verify that returned code is 401 and JSON result contains C<error:"$code">.
Note that it works only for Ajax request (see below).
=cut
sub
expectReject
{
my
(
$res
,
$code
)
=
@_
;
ok
(
$res
->
[
0
]
==
401
,
'
Response is 401
'
)
or
explain
(
$res
->
[
0
],
401
);
...
...
@@ -179,6 +326,13 @@ sub expectReject {
count
(
3
);
}
=head4 expectCookie( $res, $cookieName )
Check if a C<Set-Cookie> exists and set a cookie named $cookieName. Return
its value.
=cut
sub
expectCookie
{
my
(
$res
,
$cookieName
)
=
@_
;
$cookieName
||=
'
lemonldap
';
...
...
@@ -192,6 +346,12 @@ sub expectCookie {
return
$id
;
}
=head4 exceptCspFormOK( $res, $host )
Verify that C<Content-Security-Policy> header allows to connect to $host.
=cut
sub
exceptCspFormOK
{
my
(
$res
,
$host
)
=
@_
;
return
1
unless
(
$host
);
...
...
@@ -213,6 +373,12 @@ sub exceptCspFormOK {
count
(
1
);
}
=head4 getCookies($res)
Returns an hash ref with names => values of cookies set by server.
=cut
sub
getCookies
{
my
(
$resp
)
=
@_
;
my
@hdrs
=
@
{
$resp
->
[
1
]
};
...
...
@@ -228,6 +394,12 @@ sub getCookies {
return
$res
;
}
=head4 getHeader( $res, $hname )
Returns value of first header named $hname in $res response.
=cut
sub
getHeader
{
my
(
$resp
,
$hname
)
=
@_
;
my
@hdrs
=
@
{
$resp
->
[
1
]
};
...
...
@@ -241,16 +413,32 @@ sub getHeader {
return
undef
;
}
=head4 getRedirection($res)
Returns value of C<Location> header.
=cut
sub
getRedirection
{
my
(
$resp
)
=
@_
;
return
getHeader
(
$resp
,
'
Location
'
);
}
=head4 getUser($res)
Returns value of C<Lm-Remote-User> header.
=cut
sub
getUser
{
my
(
$resp
)
=
@_
;
return
getHeader
(
$resp
,
'
Lm-Remote-User
'
);
}
=head2 LLNG::Manager::Test Class
=cut
package
LLNG::Manager::
Test
;
use
strict
;
...
...
@@ -278,15 +466,35 @@ our $defaultIni = {
https
=>
0
,
};
=head3 Accessors
=over
=item app: built application
=cut
has
app
=>
(
is
=>
'
rw
',
isa
=>
'
CodeRef
',
);
=item class: class to test (default Lemonldap::NG::Portal::Main)
=cut
has
class
=>
(
is
=>
'
ro
',
default
=>
'
Lemonldap::NG::Portal::Main
'
);
=item p: portal object
=cut
has
p
=>
(
is
=>
'
rw
'
);
=item ini: initialization parameters ($defaultIni values + given parameters)
=cut
has
ini
=>
(
is
=>
'
rw
',
default
=>
sub
{
$defaultIni
;
},
...
...
@@ -317,6 +525,26 @@ has ini => (
}
);
=back
=head3 Methods
=head4 logout($id)
Launch a C</?logout=1> request an test:
=over
=item if response is 200
=item if cookie 'lemonldap' and 'lemonldappdata' have no value
=item if a GET request with previous cookie value I<($i)> is rejected
=back
=cut
sub
logout
{
my
(
$self
,
$id
)
=
@_
;
my
$res
;
...
...
@@ -346,6 +574,34 @@ sub logout {
}
=head4 _get( $path, %args )
Simulates a GET requests to $path. Accepted arguments:
=over
=item accept: accepted content, default to Ajax request. Use 'text/html'
to test content I<(to launch a C<expectForm()> for example)>.
=item cookie: full cookie string
=item custom: additional headers (hash ref only)
=item ip: remote address. Default to 127.0.0.1
=item method: default to GET. Only GET/DELETE values are acceptable
(use C<_post()> if you want to launch a POST/PUT request)
=item query: query string
=item referer
=item remote_user: REMOTE_USER header value
=back
=cut
sub
_get
{
my
(
$self
,
$path
,
%args
)
=
@_
;
my
$res
=
$self
->
app
->
(
...
...
@@ -381,6 +637,22 @@ sub _get {
return
$res
;
}
=head4 _post( $path, $body, %args )
Same as C<_get> except that a body is required. $body must be a file handle.
Example with IO::String:
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),
length => 23
),
'Auth query'
);
=cut
sub
_post
{
my
(
$self
,
$path
,
$body
,
%args
)
=
@_
;
die
"
$body
must be a IO::Handle
"
...
...
@@ -421,12 +693,24 @@ sub _post {
return
$res
;
}
=head4 _delete( $path, %args )
Call C<_get()> with method set to DELETE.
=cut
sub
_delete
{
my
(
$self
,
$path
,
%args
)
=
@_
;
$args
{
method
}
=
'
DELETE
';
return
$self
->
_get
(
$path
,
%args
);
}
=head4 _put( $path, $body, %args )
Call C<_post()> with method set to PUT
=cut
sub
_put
{
my
(
$self
,
$path
,
$body
,
%args
)
=
@_
;
$args
{
method
}
=
'
PUT
';
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment