package Test::Pear::LocalLoop; use Moo; use Test::More; use File::Temp; use Test::Mojo; use DateTime::Format::Strptime; use DBIx::Class::Fixtures; # Conditionally require Test::PostgreSQL sub BUILD { if ( $ENV{PEAR_TEST_PG} ) { require Test::PostgreSQL or die "you need Test::PostgreSQL to run PG testing"; Test::PostgreSQL->import; } } sub DEMOLISH { my ( $self, $in_global_destruction ) = @_; if ( $ENV{PEAR_TEST_PG} && !$in_global_destruction ) { $self->mojo->app->schema->storage->dbh->disconnect; $self->pg->stop; } } has pg => ( is => 'lazy', builder => sub { return Test::PostgreSQL->new(); }, ); has config => ( is => 'lazy', builder => sub { my $self = shift; my $file = File::Temp->new; my $dsn; if ( $ENV{PEAR_TEST_PG} ) { $dsn = $self->pg->dsn; } else { $dsn = "dbi:SQLite::memory:"; } print $file <<"END"; { dsn => "$dsn", user => undef, pass => undef, } END $file->seek( 0, SEEK_END ); return $file; }, ); has mojo => ( is => 'lazy', builder => sub { my $self = shift; $ENV{MOJO_CONFIG} = $self->config->filename; my $t = Test::Mojo->new('Pear::LocalLoop'); $t->app->schema->deploy; return $t; }, ); has etc_dir => ( is => 'lazy', builder => sub { die "etc dir not set" }, ); has _deployed => ( is => 'rwp', default => 0, ); sub framework { my $self = shift; my $no_populate = shift; my $t = $self->mojo; my $schema = $t->app->schema; unless ( $no_populate || $self->_deployed ) { $schema->resultset('Leaderboard')->populate([ [ qw/ name type / ], [ 'Daily Total', 'daily_total' ], [ 'Daily Count', 'daily_count' ], [ 'Weekly Total', 'weekly_total' ], [ 'Weekly Count', 'weekly_count' ], [ 'Monthly Total', 'monthly_total' ], [ 'Monthly Count', 'monthly_count' ], [ 'All Time Total', 'all_time_total' ], [ 'All Time Count', 'all_time_count' ], ]); } $self->_set__deployed(1); return $t; }; sub dump_error { return sub { my $self = shift; if ( my $error = $self->tx->res->dom->at('pre[id="error"]') ) { diag $error->text; } else { diag $self->tx->res->to_string; } }; } sub register_customer { my $self = shift; my $args = shift; my $json = { usertype => 'customer', %$args, }; $self->framework->post_ok('/api/register' => json => $json) ->status_is(200)->or($self->dump_error) ->json_is('/success', Mojo::JSON->true)->or($self->dump_error); } sub register_organisation { my ( $self, $args ) = @_; $args->{usertype} = 'organisation'; $self->framework->post_ok('/api/register' => json => $args) ->status_is(200)->or($self->dump_error) ->json_is('/success', Mojo::JSON->true)->or($self->dump_error); } sub login { my $self = shift; my $args = shift; $self->framework->post_ok('/api/login' => json => $args) ->status_is(200)->or($self->dump_error) ->json_is('/success', Mojo::JSON->true)->or($self->dump_error); return $self->framework->tx->res->json->{session_key}; } sub logout { my $self = shift; my $session_key = shift; $self->framework->post_ok('/api/logout' => json => { session_key => $session_key }) ->status_is(200) ->json_is('/success', Mojo::JSON->true) ->json_like('/message', qr/Logged Out/); } sub gen_upload { my ( $self, $args ) = @_; my $file = { content => '', filename => 'text.jpg', 'Content-Type' => 'image/jpeg', }; return { json => Mojo::JSON::encode_json($args), file => $file, }; } sub install_fixtures { my ( $self, $fixture_name ) = @_; my $fixtures = DBIx::Class::Fixtures->new({ config_dir => File::Spec->catdir( $self->etc_dir, 'fixtures', 'config'), }); my $t = $self->framework(1); my $schema = $t->app->schema; $fixtures->populate({ directory => File::Spec->catdir( $self->etc_dir, 'fixtures', 'data', $fixture_name ), no_deploy => 1, schema => $schema, }); # Reset table id sequences if ( $ENV{PEAR_TEST_PG} ) { $schema->storage->dbh_do( sub { my ( $storage, $dbh, $sets ) = @_; for my $table ( keys %$sets ) { my $seq = $sets->{$table}; $dbh->do( qq/ SELECT setval( '$seq', COALESCE( (SELECT MAX(id)+1 FROM $table), 1 ), false ); /); } }, { entities => 'entities_id_seq', organisations => 'organisations_id_seq', } ); } } 1;