In this example you'll see how to use a session to store some information sent in by a user and how to retreive it in another request. You'll also see how to test it.

Directory Layout

.
├── bin
│   └── app.pl
├── lib
│   └── App.pm
└── t
    ├── 01-index.t
    └── 02-psgi.t

Code launching the app

examples/dancer/app5/bin/app.pl

#!/usr/bin/env perl
use Dancer;
use App;
dance;

The code of the application

examples/dancer/app5/lib/App.pm

package App;
use strict;
use warnings;
use Dancer ':syntax';

set session => 'Simple';

get '/' => sub {
    my $text = session('txt') // '';
    return qq{
    <h1>Session</h1>
    Currently saved: <b>$text</b><p>
    <form action="/save" method="POST">
    <input type="text" name="txt">
    <input type="submit" value="Send">
    </form>
    <p>
    <a href="/delete">delete text</a>
    };
};

post '/save' => sub {
    my $text = param('txt');
    session txt => $text;
    return qq{
        You sent: <b>$text</b><p>
        Check it on the <a href="/">home page</a>
    };

};

get '/delete' => sub {
    session txt => undef;
    return 'DONE <a href="/">home</a>';
};

true;

The test code

examples/dancer/app5/t/01-index.t

use Test::More tests => 7;
use strict;
use warnings;

# the order is important
use App;
use Dancer::Test;

my $text1 = 'Hello World!';
my $text2 = 'Some other text';

subtest index => sub {
    my $resp = dancer_response GET => '/';
    is $resp->status, 200;
    like $resp->content, qr{<h1>Session</h1>};
    like $resp->content, qr{<form};
    like $resp->content, qr{<b></b>};
};

subtest save => sub {
    my $resp = dancer_response POST => '/save', {
        params => {
            txt => $text1,
        }
    };
    is $resp->status, 200;
    like $resp->content, qr{You sent: <b>$text1</b>};
};

subtest index => sub {
    my $resp = dancer_response GET => '/';
    is $resp->status, 200;
    like $resp->content, qr{<h1>Session</h1>};
    like $resp->content, qr{<form};
    like $resp->content, qr{<b>$text1</b>};
};

subtest save => sub {
    my $resp = dancer_response POST => '/save', {
        params => {
            txt => $text2,
        }
    };
    is $resp->status, 200;
    like $resp->content, qr{You sent: <b>$text2</b>};
};

subtest index => sub {
    my $resp = dancer_response GET => '/';
    is $resp->status, 200;
    like $resp->content, qr{<h1>Session</h1>};
    like $resp->content, qr{<form};
    like $resp->content, qr{<b>$text2</b>};
};

subtest delete => sub {
    my $resp = dancer_response GET => '/delete';
    is $resp->status, 200;
    like $resp->content, qr{DONE};
};


subtest index => sub {
    my $resp = dancer_response GET => '/';
    is $resp->status, 200;
    like $resp->content, qr{<h1>Session</h1>};
    like $resp->content, qr{<form};
    like $resp->content, qr{<b></b>};
};


Testing with Test::WWW::Mechanize::PSGI

Test::WWW::Mechanize::PSGI is an excellent testing library that makes it easy to create more complex interactions and to represent more than one browsers at the same time. So you can observe that while one user ($mech1) sees the newly set text use two $mech2 does not.

examples/dancer/app5/t/02-psgi.t

use Test::More tests => 4;
use strict;
use warnings;

# the order is important
# load all the parts of the Application (including hooks)
# before loading the Test:: module.
use App;
use Test::WWW::Mechanize::PSGI;


my $text1 = 'Hello World!';
my $text2 = 'Some other text';


my $mech1 = Test::WWW::Mechanize::PSGI->new( app => Dancer::Handler->psgi_app );
my $mech2 = Test::WWW::Mechanize::PSGI->new( app => Dancer::Handler->psgi_app );

subtest index => sub {
    $mech1->get_ok( '/' );
    $mech1->content_like( qr{<h1>Session</h1>} );
    $mech1->content_like( qr{<b></b>} );
};

subtest save => sub {
    $mech1->post_ok('/save', {
            txt => $text1,
    });
    $mech1->content_like( qr{You sent: <b>$text1</b>} );
};


subtest index => sub {
    $mech1->get_ok( '/' );
    $mech1->content_like( qr{<h1>Session</h1>} );
    $mech1->content_like( qr{<b>$text1</b>} );
};


subtest index_another_browser => sub {
    $mech2->get_ok( '/' );
    $mech2->content_like( qr{<h1>Session</h1>} );
    $mech2->content_like( qr{<b></b>} );
};

Running the tests

Be in the root directory of your project. (The common parent directory of bin, lib, and t.) and type:

prove -l