aboutsummaryrefslogtreecommitdiffstats
path: root/t/app
diff options
context:
space:
mode:
Diffstat (limited to 't/app')
-rw-r--r--t/app/01app.t10
-rw-r--r--t/app/02pod.t10
-rw-r--r--t/app/03podcoverage.t14
-rw-r--r--t/app/controller/about.t26
-rw-r--r--t/app/controller/auth.t217
-rw-r--r--t/app/controller/my.t19
-rw-r--r--t/app/controller/page_not_found.t20
-rw-r--r--t/app/controller/report_import.t158
-rw-r--r--t/app/controller/report_new.t465
-rw-r--r--t/app/controller/sample.jpgbin0 -> 22588 bytes
-rw-r--r--t/app/helpers/send_email.t44
-rw-r--r--t/app/helpers/send_email_sample.txt29
-rw-r--r--t/app/load_general_config.t13
-rw-r--r--t/app/model/db.t8
-rw-r--r--t/app/model/token.t96
-rw-r--r--t/app/view/email.t8
-rw-r--r--t/app/view/web.t8
17 files changed, 1145 insertions, 0 deletions
diff --git a/t/app/01app.t b/t/app/01app.t
new file mode 100644
index 000000000..02ffcd217
--- /dev/null
+++ b/t/app/01app.t
@@ -0,0 +1,10 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More;
+
+use Catalyst::Test 'FixMyStreet::App';
+
+ok( request('/')->is_success, 'Request should succeed' );
+
+done_testing();
diff --git a/t/app/02pod.t b/t/app/02pod.t
new file mode 100644
index 000000000..ababc2eaa
--- /dev/null
+++ b/t/app/02pod.t
@@ -0,0 +1,10 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More;
+
+plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
+eval "use Test::Pod 1.14";
+plan skip_all => 'Test::Pod 1.14 required' if $@;
+
+all_pod_files_ok();
diff --git a/t/app/03podcoverage.t b/t/app/03podcoverage.t
new file mode 100644
index 000000000..6ddc5c6b6
--- /dev/null
+++ b/t/app/03podcoverage.t
@@ -0,0 +1,14 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More;
+
+plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
+
+eval "use Test::Pod::Coverage 1.04";
+plan skip_all => 'Test::Pod::Coverage 1.04 required' if $@;
+
+eval "use Pod::Coverage 0.20";
+plan skip_all => 'Pod::Coverage 0.20 required' if $@;
+
+all_pod_coverage_ok();
diff --git a/t/app/controller/about.t b/t/app/controller/about.t
new file mode 100644
index 000000000..aeca47d86
--- /dev/null
+++ b/t/app/controller/about.t
@@ -0,0 +1,26 @@
+use strict;
+use warnings;
+
+use Test::More;
+use Test::WWW::Mechanize::Catalyst 'FixMyStreet::App';
+
+ok( my $mech = Test::WWW::Mechanize::Catalyst->new, 'Created mech object' );
+
+# check that we can get the page
+$mech->get_ok('/about');
+$mech->content_contains('About Us :: FixMyStreet.com');
+$mech->content_contains('html lang="en-gb"');
+
+# check that geting the page as EHA produces a different page
+ok $mech->host("reportemptyhomes.co.uk"), 'change host to reportemptyhomes';
+$mech->get_ok('/about');
+$mech->content_contains('About us :: Report Empty Homes');
+$mech->content_contains('html lang="en-gb"');
+
+# check that geting the page as EHA in welsh produces a different page
+ok $mech->host("cy.reportemptyhomes.co.uk"), 'host to cy.reportemptyhomes';
+$mech->get_ok('/about');
+$mech->content_contains('Amdanom ni :: Adrodd am Eiddo Gwag');
+$mech->content_contains('html lang="cy"');
+
+done_testing();
diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t
new file mode 100644
index 000000000..6e1e8d58d
--- /dev/null
+++ b/t/app/controller/auth.t
@@ -0,0 +1,217 @@
+use strict;
+use warnings;
+
+use Test::More tests => 97;
+
+use FixMyStreet::TestMech;
+my $mech = FixMyStreet::TestMech->new;
+
+my $test_email = 'test@example.com';
+my $test_password = 'foobar';
+
+END {
+ ok( FixMyStreet::App->model('DB::User')->find( { email => $_ } )->delete,
+ "delete test user '$_'" )
+ for ($test_email);
+}
+
+$mech->get_ok('/auth');
+
+# check that we can't reach a page that is only available to authenticated users
+$mech->not_logged_in_ok;
+
+# check that submitting form with no / bad email creates an error.
+$mech->get_ok('/auth');
+
+for my $test (
+ [ '' => 'enter an email address' ],
+ [ 'not an email' => 'check your email address is correct' ],
+ [ 'bob@foo' => 'check your email address is correct' ],
+ [ 'bob@foonaoedudnueu.co.uk' => 'check your email address is correct' ],
+ )
+{
+ my ( $email, $error_message ) = @$test;
+ pass "--- testing bad email '$email' gives error '$error_message'";
+ $mech->get_ok('/auth');
+ $mech->content_lacks($error_message);
+ $mech->submit_form_ok(
+ {
+ form_name => 'general_auth',
+ fields => { email => $email, },
+ button => 'email_login',
+ },
+ "try to create an account with email '$email'"
+ );
+ is $mech->uri->path, '/auth', "still on auth page";
+ $mech->content_contains($error_message);
+}
+
+# create a new account
+$mech->clear_emails_ok;
+$mech->get_ok('/auth');
+$mech->submit_form_ok(
+ {
+ form_name => 'general_auth',
+ fields => { email => $test_email, },
+ button => 'email_login',
+ },
+ "create an account for '$test_email'"
+);
+is $mech->uri->path, '/auth/token', "redirected to welcome page";
+
+# check that we are not logged in yet
+$mech->not_logged_in_ok;
+
+# check that we got one email
+{
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ $mech->clear_emails_ok;
+ is $email->header('Subject'), "Your FixMyStreet.com account details",
+ "subject is correct";
+ is $email->header('To'), $test_email, "to is correct";
+
+ # extract the link
+ my ($link) = $email->body =~ m{(http://\S+)};
+ ok $link, "Found a link in email '$link'";
+
+ # check that the user does not exist
+ sub get_user {
+ FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ }
+ ok !get_user(), "no user exists";
+
+ # visit the confirm link (with bad token) and check user no confirmed
+ $mech->get_ok( $link . 'XXX' );
+ ok !get_user(), "no user exists";
+ $mech->not_logged_in_ok;
+
+ # visit the confirm link and check user is confirmed
+ $mech->get_ok($link);
+ ok get_user(), "user created";
+ is $mech->uri->path, '/my', "redirected to the 'my' section of site";
+ $mech->logged_in_ok;
+
+ # logout and try to use the token again
+ $mech->log_out_ok;
+ $mech->get_ok($link);
+ is $mech->uri, $link, "not logged in";
+ $mech->content_contains( 'Link too old or already used',
+ 'token now invalid' );
+ $mech->not_logged_in_ok;
+}
+
+# get a login email and change password
+{
+ $mech->clear_emails_ok;
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ {
+ form_name => 'general_auth',
+ fields => { email => "$test_email", },
+ button => 'email_login',
+ },
+ "email_login with '$test_email'"
+ );
+ is $mech->uri->path, '/auth/token', "redirected to token page";
+
+ # rest is as before so no need to test
+
+ # follow link and change password - check not prompted for old password
+ $mech->not_logged_in_ok;
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ $mech->clear_emails_ok;
+ my ($link) = $email->body =~ m{(http://\S+)};
+ $mech->get_ok($link);
+
+ $mech->follow_link_ok( { url => '/auth/change_password' } );
+
+ ok my $form = $mech->form_name('change_password'),
+ "found change password form";
+ is_deeply [ sort grep { $_ } map { $_->name } $form->inputs ], #
+ [ 'confirm', 'new_password' ],
+ "check we got expected fields (ie not old_password)";
+
+ # check the various ways the form can be wrong
+ for my $test (
+ { new => '', conf => '', err => 'enter a password', },
+ { new => 'secret', conf => '', err => 'do not match', },
+ { new => '', conf => 'secret', err => 'do not match', },
+ { new => 'secret', conf => 'not_secret', err => 'do not match', },
+ )
+ {
+ $mech->get_ok('/auth/change_password');
+ $mech->content_lacks( $test->{err}, "did not find expected error" );
+ $mech->submit_form_ok(
+ {
+ form_name => 'change_password',
+ fields =>
+ { new_password => $test->{new}, confirm => $test->{conf}, },
+ },
+ "change_password with '$test->{new}' and '$test->{conf}'"
+ );
+ $mech->content_contains( $test->{err}, "found expected error" );
+ }
+
+ my $user =
+ FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ ok $user, "got a user";
+ ok !$user->password, "user has no password";
+
+ $mech->get_ok('/auth/change_password');
+ $mech->submit_form_ok(
+ {
+ form_name => 'change_password',
+ fields =>
+ { new_password => $test_password, confirm => $test_password, },
+ },
+ "change_password with '$test_password' and '$test_password'"
+ );
+ is $mech->uri->path, '/auth/change_password',
+ "still on change password page";
+ $mech->content_contains( 'password has been changed',
+ "found password changed" );
+
+ $user->discard_changes();
+ ok $user->password, "user now has a password";
+}
+
+# login using valid details
+$mech->get_ok('/auth');
+$mech->submit_form_ok(
+ {
+ form_name => 'general_auth',
+ fields => {
+ email => $test_email,
+ password => $test_password,
+ },
+ button => 'login',
+ },
+ "login with '$test_email' & '$test_password"
+);
+is $mech->uri->path, '/my', "redirected to correct page";
+
+# logout
+$mech->log_out_ok;
+
+# try to login with bad details
+$mech->get_ok('/auth');
+$mech->submit_form_ok(
+ {
+ form_name => 'general_auth',
+ fields => {
+ email => $test_email,
+ password => 'not the password',
+ },
+ button => 'login',
+ },
+ "login with '$test_email' & '$test_password"
+);
+is $mech->uri->path, '/auth', "redirected to correct page";
+$mech->content_contains( 'Email or password wrong', 'found error message' );
+
+# more test:
+# TODO: test that email are always lowercased
+
diff --git a/t/app/controller/my.t b/t/app/controller/my.t
new file mode 100644
index 000000000..1ed6806a4
--- /dev/null
+++ b/t/app/controller/my.t
@@ -0,0 +1,19 @@
+use strict;
+use warnings;
+
+use Test::More tests => 11;
+
+use FixMyStreet::TestMech;
+my $mech = FixMyStreet::TestMech->new;
+
+$mech->get_ok('/my');
+is $mech->uri->path, '/auth', "got sent to the login page";
+
+# login
+my $user = $mech->log_in_ok( 'test@example.com' );
+$mech->get_ok('/my');
+is $mech->uri->path, '/my', "stayed on '/my/' page";
+
+# cleanup
+$mech->delete_user( $user );
+
diff --git a/t/app/controller/page_not_found.t b/t/app/controller/page_not_found.t
new file mode 100644
index 000000000..9c8d7e5a6
--- /dev/null
+++ b/t/app/controller/page_not_found.t
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Test::WWW::Mechanize::Catalyst 'FixMyStreet::App';
+
+my $mech = Test::WWW::Mechanize::Catalyst->new;
+
+# homepage ok
+$mech->get_ok('/');
+
+# get 404 page
+my $path_to_404 = '/bad/path/page_not_found';
+my $res = $mech->get($path_to_404);
+ok !$res->is_success(), "want a bad response";
+is $res->code, 404, "got 404";
+$mech->content_contains($path_to_404);
diff --git a/t/app/controller/report_import.t b/t/app/controller/report_import.t
new file mode 100644
index 000000000..5c16324d3
--- /dev/null
+++ b/t/app/controller/report_import.t
@@ -0,0 +1,158 @@
+use strict;
+use warnings;
+use Test::More;
+
+use FixMyStreet::TestMech;
+use Web::Scraper;
+use Path::Class;
+
+my $mech = FixMyStreet::TestMech->new;
+$mech->get_ok('/import');
+
+my $sample_file = file(__FILE__)->parent->file("sample.jpg")->stringify;
+ok -e $sample_file, "sample file $sample_file exists";
+
+# submit an empty report to import - check we get all errors
+subtest "Test creating bad partial entries" => sub {
+
+ foreach my $test (
+ {
+ fields => { email => 'bob', },
+ errors => [
+ 'You must supply a service',
+ 'Please enter a subject',
+ 'Please enter your name',
+ 'Please enter a valid email',
+ 'Either a location or a photo must be provided.',
+ ],
+ },
+ {
+ fields => { email => 'bob@example.com' },
+ errors => [
+ 'You must supply a service',
+ 'Please enter a subject',
+ 'Please enter your name',
+ 'Either a location or a photo must be provided.',
+ ],
+ },
+ {
+ fields => { lat => 1, lon => 1, },
+ errors => [
+ 'You must supply a service',
+ 'Please enter a subject',
+ 'Please enter your name',
+ 'Please enter your email',
+'We had a problem with the supplied co-ordinates - outside the UK?',
+ ],
+ },
+ {
+ fields => { photo => $sample_file, },
+ errors => [
+ 'You must supply a service',
+ 'Please enter a subject',
+ 'Please enter your name',
+ 'Please enter your email',
+ ],
+ },
+ )
+ {
+ $mech->get_ok('/import');
+
+ $mech->submit_form_ok( #
+ { with_fields => $test->{fields} },
+ "fill in form"
+ );
+
+ is_deeply( $mech->import_errors, $test->{errors}, "expected errors" );
+ }
+
+};
+
+# submit an empty report to import - check we get all errors
+subtest "Submit a correct entry" => sub {
+
+ $mech->get_ok('/import');
+
+ $mech->submit_form_ok( #
+ {
+ with_fields => {
+ service => 'test-script',
+ name => 'Test User',
+ email => 'test@example.com',
+ subject => 'Test report',
+ detail => 'This is a test report',
+ photo => $sample_file,
+ }
+ },
+ "fill in form"
+ );
+
+ is_deeply( $mech->import_errors, [], "got no errors" );
+ is $mech->content, 'SUCCESS', "Got success response";
+
+ # check that we have received the email
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ $mech->clear_emails_ok;
+
+ my ($token_url) = $email->body =~ m{(http://\S+)};
+ ok $token_url, "Found a token url $token_url";
+
+ # go to the token url
+ $mech->get_ok($token_url);
+
+ # check that we are not shown anything as we don't have a location yet
+ is_deeply $mech->visible_form_values, { pc => '' },
+ "check only pc field is shown";
+
+ $mech->submit_form_ok( #
+ { with_fields => { pc => 'SW1A 1AA' } },
+ "fill in postcode"
+ );
+
+ # check that we are not shown anything as we don't have a location yet
+ is_deeply $mech->visible_form_values,
+ {
+ name => 'Test User',
+ email => 'test@example.com',
+ title => 'Test report',
+ detail => 'This is a test report',
+ photo => '',
+ phone => '',
+ may_show_name => '1',
+ },
+ "check imported fields are shown";
+
+ TODO: {
+ local $TODO = "'/report/123' urls not srved by catalyst yet";
+
+ # change the details
+ $mech->submit_form_ok( #
+ {
+ with_fields => {
+ name => 'New Test User',
+ email => 'test@example.com',
+ title => 'New Test report',
+ detail => 'This is a test report',
+ phone => '01234 567 890',
+ may_show_name => '1',
+ }
+ },
+ "Update details and save"
+ );
+ }
+
+ # check that report has been created
+ my $user =
+ FixMyStreet::App->model('DB::User')
+ ->find( { email => 'test@example.com' } );
+ ok $user, "Found a user";
+
+ my $report = $user->problems->first;
+ is $report->state, 'confirmed', 'is confirmed';
+ is $report->title, 'New Test report', 'title is correct';
+
+ $mech->delete_user($user);
+};
+
+done_testing();
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
new file mode 100644
index 000000000..dca86db77
--- /dev/null
+++ b/t/app/controller/report_new.t
@@ -0,0 +1,465 @@
+use strict;
+use warnings;
+use Test::More;
+
+use FixMyStreet::TestMech;
+use Web::Scraper;
+
+my $mech = FixMyStreet::TestMech->new;
+$mech->get_ok('/report/new');
+
+# test various locations on inital search box
+foreach my $test (
+ {
+ pc => '', #
+ errors => [],
+ pc_alternatives => [],
+ },
+ {
+ pc => 'xxxxxxxxxxxxxxxxxxxxxxxxxxx',
+ errors => ['Sorry, we could not find that location.'],
+ pc_alternatives => [],
+ },
+ {
+ pc => 'glenthorpe',
+ errors => [],
+ pc_alternatives => [ # TODO - should filter out these non-UK addresses
+ 'Glenthorpe Crescent, Leeds LS9 7, UK',
+ 'Glenthorpe Rd, Merton, Greater London SM4 4, UK',
+ 'Glenthorpe Ln, Katy, TX 77494, USA',
+ 'Glenthorpe Dr, Walnut, CA 91789, USA',
+ 'Glenthorpe Ave, Leeds LS9 7, UK',
+ 'Glenthorpe Ct, Katy, TX 77494, USA',
+ ],
+ },
+ {
+ pc => 'Glenthorpe Ct, Katy, TX 77494, USA',
+ errors =>
+ ['We had a problem with the supplied co-ordinates - outside the UK?'],
+ pc_alternatives => [],
+ },
+ )
+{
+ subtest "test bad pc value '$test->{pc}'" => sub {
+ $mech->get_ok('/report/new');
+ $mech->submit_form_ok( { with_fields => { pc => $test->{pc} } },
+ "bad location" );
+ is_deeply $mech->form_errors, $test->{errors},
+ "expected errors for pc '$test->{pc}'";
+ is_deeply $mech->pc_alternatives, $test->{pc_alternatives},
+ "expected alternatives for pc '$test->{pc}'";
+ };
+}
+
+# check that exact queries result in the correct lat,lng
+foreach my $test (
+ {
+ pc => 'SW1A 1AA',
+ latitude => '51.5010096115539',
+ longitude => '-0.141587067110009',
+ },
+ {
+ pc => 'Manchester',
+ latitude => '53.4807125',
+ longitude => '-2.2343765',
+ },
+ {
+ pc => 'Glenthorpe Rd, Merton, Greater London SM4 4, UK',
+ latitude => '51.3937997',
+ longitude => '-0.2209596',
+ },
+ )
+{
+ subtest "check lat/lng for '$test->{pc}'" => sub {
+ $mech->get_ok('/report/new');
+ $mech->submit_form_ok( { with_fields => { pc => $test->{pc} } },
+ "good location" );
+ is_deeply $mech->form_errors, [], "no errors for pc '$test->{pc}'";
+ is_deeply $mech->extract_location, $test,
+ "got expected location for pc '$test->{pc}'";
+ };
+}
+
+# test that the various bit of form get filled in and errors correctly
+# generated.
+foreach my $test (
+ {
+ msg => 'all fields empty',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo => '',
+ name => '',
+ may_show_name => '1',
+ email => '',
+ phone => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please enter your name',
+ 'Please enter your email',
+ ],
+ },
+ {
+ msg => 'may_show_name defaults to true',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo => '',
+ name => '',
+ may_show_name => undef,
+ email => '',
+ phone => '',
+ },
+ changes => { may_show_name => '1' },
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please enter your name',
+ 'Please enter your email',
+ ],
+ },
+ {
+ msg => 'may_show_name unchanged if name is present (stays false)',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo => '',
+ name => 'Bob Jones',
+ may_show_name => undef,
+ email => '',
+ phone => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please enter your email',
+ ],
+ },
+ {
+ msg => 'may_show_name unchanged if name is present (stays true)',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo => '',
+ name => 'Bob Jones',
+ may_show_name => '1',
+ email => '',
+ phone => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please enter your email',
+ ],
+ },
+ {
+ msg => 'title and details tidied up',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'DOG SHIT ON WALLS',
+ detail => 'on this portakabin - more of a portaloo HEH!!',
+ photo => '',
+ name => 'Bob Jones',
+ may_show_name => '1',
+ email => '',
+ phone => '',
+ },
+ changes => {
+ title => 'Dog poo on walls',
+ detail =>
+ 'On this [portable cabin] - more of a [portable loo] HEH!!',
+ },
+ errors => [ 'Please enter your email', ],
+ },
+ {
+ msg => 'name too short',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'Test title',
+ detail => 'Test detail',
+ photo => '',
+ name => 'DUDE',
+ may_show_name => '1',
+ email => '',
+ phone => '',
+ },
+ changes => {},
+ errors => [
+'Please enter your full name, councils need this information - if you do not wish your name to be shown on the site, untick the box',
+ 'Please enter your email',
+ ],
+ },
+ {
+ msg => 'name is anonymous',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'Test title',
+ detail => 'Test detail',
+ photo => '',
+ name => 'anonymous',
+ may_show_name => '1',
+ email => '',
+ phone => '',
+ },
+ changes => {},
+ errors => [
+'Please enter your full name, councils need this information - if you do not wish your name to be shown on the site, untick the box',
+ 'Please enter your email',
+ ],
+ },
+ {
+ msg => 'email invalid',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'Test title',
+ detail => 'Test detail',
+ photo => '',
+ name => 'Joe Smith',
+ may_show_name => '1',
+ email => 'not an email',
+ phone => '',
+ },
+ changes => { email => 'notanemail', },
+ errors => [ 'Please enter a valid email', ],
+ },
+ {
+ msg => 'cleanup title and detail',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => " Test title ",
+ detail => " first line \n\n second\nline\n\n ",
+ photo => '',
+ name => '',
+ may_show_name => '1',
+ email => '',
+ phone => '',
+ },
+ changes => {
+ title => 'Test title',
+ detail => "First line\n\nSecond line",
+ },
+ errors => [ 'Please enter your name', 'Please enter your email', ],
+ },
+ {
+ msg => 'clean up name and email',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo => '',
+ name => ' Bob Jones ',
+ may_show_name => '1',
+ email => ' BOB @ExAmplE.COM ',
+ phone => '',
+ },
+ changes => {
+ name => 'Bob Jones',
+ email => 'bob@example.com',
+ },
+ errors => [ 'Please enter a subject', 'Please enter some details', ],
+ },
+ )
+{
+ subtest "check form errors where $test->{msg}" => sub {
+ $mech->get_ok('/report/new');
+
+ # submit initial pc form
+ $mech->submit_form_ok( { with_fields => { pc => $test->{pc} } },
+ "submit location" );
+ is_deeply $mech->form_errors, [], "no errors for pc '$test->{pc}'";
+
+ # submit the main form
+ $mech->submit_form_ok( { with_fields => $test->{fields} },
+ "submit form" );
+
+ # check that we got the errors expected
+ is_deeply $mech->form_errors, $test->{errors}, "check errors";
+
+ # check that fields have changed as expected
+ my $new_values = {
+ %{ $test->{fields} }, # values added to form
+ %{ $test->{changes} }, # changes we expect
+ };
+ is_deeply $mech->visible_form_values, $new_values,
+ "values correctly changed";
+ };
+}
+
+subtest "test report creation for a user who does not have an account" => sub {
+ $mech->log_out_ok;
+ $mech->clear_emails_ok;
+
+ # check that the user does not exist
+ my $test_email = 'test-1@example.com';
+ ok !FixMyStreet::App->model('DB::User')->find( { email => $test_email } ),
+ "test user does not exist";
+
+ # submit initial pc form
+ $mech->get_ok('/report/new');
+ $mech->submit_form_ok( { with_fields => { pc => 'SW1A 1AA', } },
+ "submit location" );
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ photo => '',
+ name => 'Joe Bloggs',
+ may_show_name => '1',
+ email => 'test-1@example.com',
+ phone => '07903 123 456',
+ }
+ },
+ "submit good details"
+ );
+
+ # check that we got the errors expected
+ is_deeply $mech->form_errors, [], "check there were no errors";
+
+ # check that the user has been created
+ my $user =
+ FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ ok $user, "created new user";
+
+ # find the report
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+
+ # check that the report is not available yet.
+ is $report->state, 'unconfirmed', "report not confirmed";
+ is $mech->get( '/report/' . $report->id )->code, 404, "report not found";
+
+ # receive token
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $email->body, qr/confirm the problem/i, "confirm the problem";
+
+ my ($url) = $email->body =~ m{(http://\S+)};
+ ok $url, "extracted confirm url '$url'";
+
+ # confirm token
+ $mech->get_ok($url);
+ $report->discard_changes;
+ is $report->state, 'confirmed', "Report is now confirmed";
+ is $report->state, 'confirmed', "report is now confirmed";
+
+ TODO: {
+ local $TODO = "'/report/<<id>>' not handled by catalyst yet";
+ $mech->get_ok( '/report/' . $report->id );
+ }
+
+ # user is created and logged in
+ $mech->logged_in_ok;
+
+ # cleanup
+ $mech->delete_user($user);
+};
+
+#### test report creation for a user who has account but is not logged in
+# come to site
+# fill in report
+# receive token
+# confirm token
+# report is confirmed
+
+#### test report creation for user with account and logged in
+subtest "test report creation for a user who is logged in" => sub {
+
+ # check that the user does not exist
+ my $test_email = 'test-2@example.com';
+
+ $mech->clear_emails_ok;
+ my $user = $mech->log_in_ok($test_email);
+
+ # setup the user.
+ ok $user->update(
+ {
+ name => 'Test User',
+ phone => '01234 567 890',
+ }
+ ),
+ "set users details";
+
+ # submit initial pc form
+ $mech->get_ok('/report/new');
+ $mech->submit_form_ok( { with_fields => { pc => 'SW1A 1AA', } },
+ "submit location" );
+
+ # check that the fields are correctly prefilled
+ is_deeply(
+ $mech->visible_form_values,
+ {
+ title => '',
+ detail => '',
+ may_show_name => '1',
+ email => $test_email,
+ name => 'Test User',
+ phone => '01234 567 890',
+ photo => '',
+ },
+ "user's details prefilled"
+ );
+
+ TODO: {
+ local $TODO =
+"'/report/<<id>>' not handled by catalyst yet - form creation redirects to there on success if logged in";
+ eval {
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ photo => '',
+ name => 'Joe Bloggs',
+ may_show_name => '1',
+ phone => '07903 123 456',
+ }
+ },
+ "submit good details"
+ );
+ };
+ }
+
+ # find the report
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+
+ # check that we got redirected to /report/
+ is $mech->uri->path, "/report/" . $report->id, "redirected to report page";
+
+ # check that no emails have been sent
+ $mech->email_count_is(0);
+
+ # check report is confirmed and available
+ is $report->state, 'confirmed', "report is now confirmed";
+ TODO: {
+ local $TODO = "'/report/<<id>>' not handled by catalyst yet";
+ $mech->get_ok( '/report/' . $report->id );
+ }
+
+ # user is still logged in
+ $mech->logged_in_ok;
+
+ # cleanup
+ $mech->delete_user($user);
+};
+
+#### test uploading an image
+
+#### test completing a partial report (eq flickr upload)
+
+#### possibly manual testing
+# create report without using map
+# create report by clicking on may with javascript off
+# create report with images off
+
+done_testing();
diff --git a/t/app/controller/sample.jpg b/t/app/controller/sample.jpg
new file mode 100644
index 000000000..23198cb83
--- /dev/null
+++ b/t/app/controller/sample.jpg
Binary files differ
diff --git a/t/app/helpers/send_email.t b/t/app/helpers/send_email.t
new file mode 100644
index 000000000..adf2c56c1
--- /dev/null
+++ b/t/app/helpers/send_email.t
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use utf8;
+
+BEGIN {
+ use FixMyStreet;
+ FixMyStreet->test_mode(1);
+}
+
+use Test::More tests => 5;
+
+use Email::Send::Test;
+use Path::Class;
+
+use_ok 'FixMyStreet::App';
+my $c = FixMyStreet::App->new;
+
+# fake up the request a little
+$c->req->uri( URI->new('http://localhost/') );
+$c->req->base( $c->req->uri );
+
+# set some values in the stash
+$c->stash->{foo} = 'bar';
+
+# clear the email queue
+Email::Send::Test->clear;
+
+# send the test email
+ok $c->send_email( 'test.txt', { to => 'test@recipient.com' } ),
+ "sent an email";
+
+# check it got templated and sent correctly
+my @emails = Email::Send::Test->emails;
+is scalar(@emails), 1, "caught one email";
+
+# Get the email, check it has a date and then strip it out
+my $email_as_string = $emails[0]->as_string;
+ok $email_as_string =~ s{\s+Date:\s+\S.*?$}{}xms, "Found and stripped out date";
+
+is $email_as_string,
+ file(__FILE__)->dir->file('send_email_sample.txt')->slurp,
+ "email is as expected";
diff --git a/t/app/helpers/send_email_sample.txt b/t/app/helpers/send_email_sample.txt
new file mode 100644
index 000000000..c6bdac74f
--- /dev/null
+++ b/t/app/helpers/send_email_sample.txt
@@ -0,0 +1,29 @@
+MIME-Version: 1.0
+Subject: test email =?utf-8?Q?=E2=98=BA?=
+Content-Type: text/plain; charset="utf-8"
+To: test@recipient.com
+Content-Transfer-Encoding: quoted-printable
+From: evdb@ecclestoad.co.uk
+
+ Hello,
+
+ This is a test email where foo: bar.
+
+ utf8: =E6=88=91=E4=BB=AC=E5=BA=94=E8=AF=A5=E8=83=BD=E5=A4=9F=E6=97=A0=
+=E7=BC=9D=E5=A4=84=E7=90=86UTF8=E7=BC=96=E7=A0=81
+
+ indented_text
+
+ long line: Lorem ipsum dolor sit amet, consectetur adipisicing
+ elit, sed do eiusmod tempor incididunt ut labore et dolore
+ magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo
+ consequat. Duis aute irure dolor in reprehenderit in voluptate
+ velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
+ sint occaecat cupidatat non proident, sunt in culpa qui officia
+ deserunt mollit anim id est laborum.
+
+ Yours,
+ FixMyStreet.
+
+
diff --git a/t/app/load_general_config.t b/t/app/load_general_config.t
new file mode 100644
index 000000000..3855c2565
--- /dev/null
+++ b/t/app/load_general_config.t
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use_ok 'FixMyStreet::App';
+
+# GAZE_URL chosen as it is unlikely to change
+is FixMyStreet::App->config->{GAZE_URL}, #
+ 'http://gaze.mysociety.org/gaze', #
+ "check that known config param is loaded";
diff --git a/t/app/model/db.t b/t/app/model/db.t
new file mode 100644
index 000000000..bebd68f0b
--- /dev/null
+++ b/t/app/model/db.t
@@ -0,0 +1,8 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+use_ok 'FixMyStreet::App::Model::DB';
+
+done_testing();
diff --git a/t/app/model/token.t b/t/app/model/token.t
new file mode 100644
index 000000000..12945975e
--- /dev/null
+++ b/t/app/model/token.t
@@ -0,0 +1,96 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 45;
+
+use FixMyStreet;
+use FixMyStreet::App;
+use mySociety::AuthToken;
+use mySociety::DBHandle 'dbh';
+
+# set things up so that code using mySociety::DBHandle is happy
+FixMyStreet->configure_mysociety_dbhandle();
+
+# NOTE - remember that you need to explicitly dbh()->commit after making
+# database changes with the mySociety::* modules.
+
+# create a token using DBIC and check we can read it using AuthToken, and vice
+# versa
+
+my %tests = (
+ nested_hash => { foo => 'bar', and => [ 'baz', 'bundy' ] },
+ array => [ 'foo', 'bar' ],
+ scalar => 123,
+);
+
+my $token_rs = FixMyStreet::App->model('DB::Token');
+
+# create using DBIC
+foreach my $test_data_name ( sort keys %tests ) {
+ my $test_data = $tests{$test_data_name};
+
+ pass "--- testing DBIC create using '$test_data_name'";
+
+ my $dbic_token =
+ $token_rs->create( { scope => 'testing', data => $test_data } );
+ my $token = $dbic_token->token;
+ ok $token, "stored token '$token'";
+
+ is_deeply $dbic_token->data, $test_data, "data stored correctly using DBIC";
+
+ # read back using DBIC
+ is_deeply $token_rs->find( { token => $token, scope => 'testing' } )->data,
+ $test_data,
+ "data read back correctly with DBIC";
+
+ # read back using mySociety::AuthToken
+ is_deeply mySociety::AuthToken::retrieve( 'testing', $token ),
+ $test_data, "data read back correctly with m::AT";
+
+ # delete token
+ ok $dbic_token->delete, "delete token";
+
+ is $token_rs->find( { token => $token, scope => 'testing' } ),
+ undef,
+ "token gone for DBIC";
+
+ # read back using mySociety::AuthToken
+ is mySociety::AuthToken::retrieve( 'testing', $token ),
+ undef, "token gone with m::AT";
+
+}
+
+# create using m::AT
+foreach my $test_data_name ( sort keys %tests ) {
+ my $test_data = $tests{$test_data_name};
+
+ pass "--- testing m::AT create using '$test_data_name'";
+
+ my $token = mySociety::AuthToken::store( 'testing', $test_data );
+ dbh->commit();
+ ok $token, "stored token '$token'";
+
+ # read back using DBIC
+ is_deeply $token_rs->find( { token => $token, scope => 'testing' } )->data,
+ $test_data,
+ "data read back correctly with DBIC";
+
+ # read back using mySociety::AuthToken
+ is_deeply mySociety::AuthToken::retrieve( 'testing', $token ),
+ $test_data, "data read back correctly with m::AT";
+
+ # delete token
+ ok mySociety::AuthToken::destroy( 'testing', $token ), "destroy token";
+ dbh->commit();
+
+ is $token_rs->find( { token => $token, scope => 'testing' } ),
+ undef,
+ "token gone for DBIC";
+
+ # read back using mySociety::AuthToken
+ is mySociety::AuthToken::retrieve( 'testing', $token ),
+ undef, "token gone with m::AT";
+
+}
diff --git a/t/app/view/email.t b/t/app/view/email.t
new file mode 100644
index 000000000..4d7bbe8ff
--- /dev/null
+++ b/t/app/view/email.t
@@ -0,0 +1,8 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+BEGIN { use_ok 'FixMyStreet::App::View::Email' }
+
+done_testing();
diff --git a/t/app/view/web.t b/t/app/view/web.t
new file mode 100644
index 000000000..0f49b986b
--- /dev/null
+++ b/t/app/view/web.t
@@ -0,0 +1,8 @@
+use strict;
+use warnings;
+use Test::More;
+use Test::More;
+
+BEGIN { use_ok 'FixMyStreet::App::View::Web' }
+
+done_testing();