File: pg_admin.t

package info (click to toggle)
libminion-perl 10.25%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,052 kB
  • sloc: javascript: 3,572; perl: 1,029; sql: 79; makefile: 10
file content (127 lines) | stat: -rw-r--r-- 6,351 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use Mojo::Base -strict;

BEGIN { $ENV{MOJO_REACTOR} = 'Mojo::Reactor::Poll' }

use Test::More;

plan skip_all => 'set TEST_ONLINE to enable this test' unless $ENV{TEST_ONLINE};

use Mojolicious::Lite;
use Test::Mojo;

# Isolate tests
require Mojo::Pg;
my $pg = Mojo::Pg->new($ENV{TEST_ONLINE});
$pg->db->query('DROP SCHEMA IF EXISTS minion_admin_test CASCADE');
$pg->db->query('CREATE SCHEMA minion_admin_test');
plugin Minion => {Pg => $ENV{TEST_ONLINE}};
app->minion->backend->pg->search_path(['minion_admin_test']);

app->minion->add_task(test => sub { });
my $finished = app->minion->enqueue('test');
app->minion->perform_jobs;
my $inactive = app->minion->enqueue('test');
get '/home' => 'test_home';

plugin 'Minion::Admin';

my $t = Test::Mojo->new;

subtest 'Dashboard' => sub {
  $t->get_ok('/minion')->status_is(200)->content_like(qr/Dashboard/)->element_exists('a[href=/]');
};

subtest 'Stats' => sub {
  $t->get_ok('/minion/stats')->status_is(200)->json_is('/active_jobs' => 0)->json_is('/active_locks' => 0)
    ->json_is('/active_workers'   => 0)->json_is('/delayed_jobs'  => 0)->json_is('/enqueued_jobs' => 2)
    ->json_is('/failed_jobs'      => 0)->json_is('/finished_jobs' => 1)->json_is('/inactive_jobs' => 1)
    ->json_is('/inactive_workers' => 0)->json_has('/uptime');
};

subtest 'Jobs' => sub {
  $t->get_ok('/minion/jobs?state=inactive')->status_is(200)->text_like('tbody td a' => qr/$inactive/)
    ->text_unlike('tbody td a' => qr/$finished/);
  $t->get_ok('/minion/jobs?state=finished')->status_is(200)->text_like('tbody td a' => qr/$finished/)
    ->text_unlike('tbody td a' => qr/$inactive/);
};

subtest 'Workers' => sub {
  $t->get_ok('/minion/workers')->status_is(200)->element_exists_not('tbody td a');
  my $worker = app->minion->worker->register;
  $t->get_ok('/minion/workers')->status_is(200)->element_exists('tbody td a')
    ->text_like('tbody td a' => qr/@{[$worker->id]}/);
  $worker->unregister;
  $t->get_ok('/minion/workers')->status_is(200)->element_exists_not('tbody td a');
};

subtest 'Locks' => sub {
  $t->app->minion->lock('foo', 3600);
  $t->app->minion->lock('bar', 3600);
  $t->ua->max_redirects(5);
  $t->get_ok('/minion/locks')->status_is(200)->text_like('tbody td a' => qr/bar/);
  $t->get_ok('/minion/locks?name=foo')->status_is(200)->text_like('tbody td a' => qr/foo/);
  $t->post_ok('/minion/locks?_method=DELETE&name=bar')->status_is(200)->text_like('tbody td a' => qr/foo/)
    ->text_like('.alert-success', qr/All selected named locks released/);
  is $t->tx->previous->res->code, 302, 'right status';
  like $t->tx->previous->res->headers->location, qr/locks/, 'right "Location" value';
  $t->post_ok('/minion/locks?_method=DELETE&name=foo')->status_is(200)->element_exists_not('tbody td a')
    ->text_like('.alert-success', qr/All selected named locks released/);
  is $t->tx->previous->res->code, 302, 'right status';
  like $t->tx->previous->res->headers->location, qr/locks/, 'right "Location" value';
};

subtest 'Manage jobs' => sub {
  is app->minion->job($finished)->info->{state}, 'finished', 'right state';
  $t->post_ok('/minion/jobs?_method=PATCH' => form => {id => $finished, do => 'retry'})
    ->text_like('.alert-success', qr/All selected jobs retried/);
  is $t->tx->previous->res->code, 302, 'right status';
  like $t->tx->previous->res->headers->location, qr/id=$finished/, 'right "Location" value';
  is app->minion->job($finished)->info->{state}, 'inactive', 'right state';
  $t->post_ok('/minion/jobs?_method=PATCH' => form => {id => $finished, do => 'stop'})
    ->text_like('.alert-info', qr/Trying to stop all selected jobs/);
  is $t->tx->previous->res->code, 302, 'right status';
  like $t->tx->previous->res->headers->location, qr/id=$finished/, 'right "Location" value';

  my $subscribers = $t->app->log->subscribers('message');
  my $level       = $t->app->log->level;
  $t->app->log->unsubscribe('message');
  my $log = '';
  my $cb  = $t->app->log->level('debug')->on(message => sub { $log .= pop });
  $t->post_ok('/minion/jobs?_method=PATCH' => form => {id => $finished, do => 'remove'})
    ->text_like('.alert-success', qr/All selected jobs removed/);
  $t->app->log->level($level)->unsubscribe(message => $cb);
  $t->app->log->on(message => $_) for @$subscribers;
  like $log, qr/Jobs removed by user ".+": $finished/, 'right log message';
  is $t->tx->previous->res->code, 302, 'right status';
  like $t->tx->previous->res->headers->location, qr/id=$finished/, 'right "Location" value';
  is app->minion->job($finished), undef, 'job has been removed';
};

subtest 'Bundled static files' => sub {
  $t->get_ok('/minion/bootstrap/bootstrap.js')->status_is(200)->content_type_is('application/javascript');
  $t->get_ok('/minion/bootstrap/bootstrap.css')->status_is(200)->content_type_is('text/css');
  $t->get_ok('/minion/d3/d3.js')->status_is(200)->content_type_is('application/javascript');
  $t->get_ok('/minion/epoch/epoch.js')->status_is(200)->content_type_is('application/javascript');
  $t->get_ok('/minion/epoch/epoch.css')->status_is(200)->content_type_is('text/css');
  $t->get_ok('/minion/fontawesome/fontawesome.css')->status_is(200)->content_type_is('text/css');
  $t->get_ok('/minion/fonts/forkawesome-webfont.eot')->status_is(200);
  $t->get_ok('/minion/fonts/forkawesome-webfont.svg')->status_is(200);
  $t->get_ok('/minion/fonts/forkawesome-webfont.ttf')->status_is(200);
  $t->get_ok('/minion/fonts/forkawesome-webfont.woff')->status_is(200);
  $t->get_ok('/minion/fonts/forkawesome-webfont.woff2')->status_is(200);
  $t->get_ok('/minion/moment/moment.js')->status_is(200)->content_type_is('application/javascript');
  $t->get_ok('/minion/app.js')->status_is(200)->content_type_is('application/javascript');
  $t->get_ok('/minion/app.css')->status_is(200)->content_type_is('text/css');
  $t->get_ok('/minion/logo-black-2x.png')->status_is(200)->content_type_is('image/png');
  $t->get_ok('/minion/logo-black.png')->status_is(200)->content_type_is('image/png');
};

subtest 'Different prefix and return route' => sub {
  plugin 'Minion::Admin' => {route => app->routes->any('/also_minion'), return_to => 'test_home'};
  $t->get_ok('/also_minion')->status_is(200)->content_like(qr/Dashboard/)->element_exists('a[href=/home]');
};

# Clean up once we are done
$pg->db->query('DROP SCHEMA minion_admin_test CASCADE');

done_testing();