Developer-Dashboard
view release on metacpan or search on metacpan
t/20-skill-web-routes.t view on Meta::CPAN
}
{
no warnings 'redefine';
my $loaded_route_id = '';
local *Developer::Dashboard::Web::App::_resolve_skill_route_spec = sub {
return {
skill_name => 'route-skill',
route_segments => [],
skill_layers => ['layer'],
};
};
local *Developer::Dashboard::Web::App::_skill_dispatcher = sub { bless {}, 'Local::SkillDispatcherProbe' };
local *Local::SkillDispatcherProbe::_load_skill_page = sub {
my ( $self, %args ) = @_;
$loaded_route_id = $args{route_id};
return Developer::Dashboard::PageDocument->new(
id => 'route-skill',
title => 'Skill Route Index',
meta => { source_kind => 'skill' },
);
};
my $empty_route_page = $app->_load_skill_named_page('route-skill');
is( $loaded_route_id, 'index', 'empty smart route specs load the skill index bookmark id' );
isa_ok( $empty_route_page, 'Developer::Dashboard::PageDocument', 'empty smart route specs still return a page document' );
is( $empty_route_page->{meta}{render_route}, '/app/route-skill', 'empty smart route specs keep the canonical smart-routed render alias' );
}
{
no warnings 'redefine';
my $loaded_route_id = '';
local *Developer::Dashboard::Web::App::_resolve_skill_route_spec = sub {
return {
skill_name => 'route-skill',
skill_layers => ['layer'],
};
};
local *Developer::Dashboard::Web::App::_skill_dispatcher = sub { bless {}, 'Local::SkillDispatcherProbeMissingSegments' };
local *Local::SkillDispatcherProbeMissingSegments::_load_skill_page = sub {
my ( $self, %args ) = @_;
$loaded_route_id = $args{route_id};
return Developer::Dashboard::PageDocument->new(
id => 'route-skill',
title => 'Skill Route Index',
meta => { source_kind => 'skill' },
);
};
my $missing_segments_page = $app->_load_skill_named_page('route-skill');
is( $loaded_route_id, 'index', 'missing smart route segments default to the skill index bookmark id' );
isa_ok( $missing_segments_page, 'Developer::Dashboard::PageDocument', 'missing smart route segments still return a page document' );
is( $missing_segments_page->{meta}{render_route}, '/app/route-skill', 'missing smart route segments keep the canonical smart-routed render alias' );
}
my $ajax_page = $app->handle(
path => '/app/route-skill/ajax-demo',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $ajax_page->[0], 200, 'skill ajax demo page route returns success' );
like( $ajax_page->[2], qr{set_chain_value\(endpoints,'bar','/v1/route-skill/bar'\)}, 'skill page binds saved ajax helper to the canonical custom skill route' );
my $skill_alias_ajax = $app->handle(
path => '/v1/route-skill/bar',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $skill_alias_ajax->[0], 200, 'custom skill ajax alias route returns success' );
is( $skill_alias_ajax->[1], 'application/json; charset=utf-8', 'custom skill ajax alias route applies its default json content type' );
is( _drain_stream_body( $skill_alias_ajax->[2] ), qq|{"route":"bar"}\n|, 'custom skill ajax alias route streams the skill handler output' );
my $raw_mime_ajax = $app->handle(
path => '/v1/route-skill/raw',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $raw_mime_ajax->[0], 200, 'custom skill ajax route with a raw mime type returns success' );
is( $raw_mime_ajax->[1], 'application/vnd.route+json', 'custom skill ajax route keeps an arbitrary configured mime type' );
is( _drain_stream_body( $raw_mime_ajax->[2] ), qq|{"route":"raw"}\n|, 'custom skill ajax route with a raw mime type streams the skill handler output' );
my $skill_ajax = $app->handle(
path => '/ajax/route-skill/bar',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $skill_ajax->[0], 200, 'legacy smart skill ajax route still returns success' );
is( _drain_stream_body( $skill_ajax->[2] ), qq|{"route":"bar"}\n|, 'legacy smart skill ajax route still streams the skill handler output' );
my $custom_js = $app->handle(
path => '/assets/route-skill.js',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $custom_js->[0], 200, 'custom skill js route returns success' );
is( $custom_js->[2], qq{console.log("route-skill js");\n}, 'custom skill js route serves the skill asset' );
my $skill_js = $app->handle(
path => '/js/route-skill/skill.js',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $skill_js->[0], 200, 'skill-local js route returns success' );
is( $skill_js->[2], qq{console.log("route-skill js");\n}, 'skill-local js route serves the skill asset' );
my $skill_css = $app->handle(
path => '/css/route-skill/skill.css',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $skill_css->[0], 200, 'skill-local css route returns success' );
is( $skill_css->[2], qq{body { color: #123456; }\n}, 'skill-local css route serves the skill asset' );
my $custom_css = $app->handle(
path => '/assets/route-skill.css',
method => 'GET',
t/20-skill-web-routes.t view on Meta::CPAN
is( $skill_other->[0], 200, 'skill-local others route returns success' );
is( $skill_other->[2], "route-skill info\n", 'skill-local others route serves the skill asset' );
my $custom_other = $app->handle(
path => '/downloads/route-skill.txt',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $custom_other->[0], 200, 'custom skill others route returns success' );
is( $custom_other->[1], 'text/plain; charset=utf-8', 'custom skill others route applies an explicit configured mime type' );
is( $custom_other->[2], "route-skill info\n", 'custom skill others route serves the skill asset' );
my $nested_index = $app->handle(
path => '/app/route-skill/def',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_index->[0], 200, 'nested skill index route returns success' );
like( $nested_index->[2], qr/Nested Skill Index/, 'nested skill index route renders the nested skill bookmark' );
like( $nested_index->[2], qr/Nested Skill Nav/, 'nested skill index route renders nav fragments contributed by the nested skill' );
like( $nested_index->[2], qr{href="/app/route-skill/def/edit" id="view-source-url"}, 'nested skill index render exposes the smart-routed edit link' );
my $nested_index_edit = $app->handle(
path => '/app/route-skill/def/edit',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_index_edit->[0], 200, 'nested skill index edit route returns success' );
like( $nested_index_edit->[2], qr{<form method="post" action="/app/route-skill/def/edit" id="instruction-form">}, 'nested skill index edit route posts back to the nested smart-routed edit alias' );
like( $nested_index_edit->[2], qr/Nested Skill Index/, 'nested skill index edit route loads the nested skill index bookmark source' );
my $nested_page = $app->handle(
path => '/app/route-skill/def/foo',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_page->[0], 200, 'nested skill page route returns success' );
like( $nested_page->[2], qr/Nested Skill Foo/, 'nested skill page route renders the nested skill bookmark' );
like( $nested_page->[2], qr/Nested Skill Nav/, 'nested skill page route renders nav fragments contributed by the nested skill' );
my $nested_custom_page = $app->handle(
path => '/apps/route-skill/child/foo',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_custom_page->[0], 200, 'nested custom skill app route returns success' );
like( $nested_custom_page->[2], qr/Nested Skill Foo/, 'nested custom skill app route renders the nested skill bookmark' );
my $nested_ajax_page = $app->handle(
path => '/app/route-skill/def/ajax-demo',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_ajax_page->[0], 200, 'nested skill ajax demo page route returns success' );
like( $nested_ajax_page->[2], qr{set_chain_value\(endpoints,'nested','/v1/route-skill/nested'\)}, 'nested skill page binds saved ajax helper to the nested canonical custom route' );
my $nested_alias_ajax = $app->handle(
path => '/v1/route-skill/nested',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_alias_ajax->[0], 200, 'nested custom ajax alias route returns success' );
is( $nested_alias_ajax->[1], 'text/html; charset=utf-8', 'nested custom ajax alias route applies its default html content type' );
is( _drain_stream_body( $nested_alias_ajax->[2] ), "<p>nested skill ajax route</p>\n", 'nested custom ajax alias route streams the nested skill handler output' );
my $nested_ajax = $app->handle(
path => '/ajax/route-skill/def/nested',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_ajax->[0], 200, 'legacy nested skill-local ajax route still returns success' );
is( _drain_stream_body( $nested_ajax->[2] ), "<p>nested skill ajax route</p>\n", 'legacy nested skill-local ajax route still streams the nested skill handler output' );
my $nested_custom_js = $app->handle(
path => '/assets/route-skill-nested.js',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_custom_js->[0], 200, 'nested custom skill js route returns success' );
is( $nested_custom_js->[2], qq{console.log("nested js");\n}, 'nested custom skill js route serves the nested skill asset' );
my $nested_js = $app->handle(
path => '/js/route-skill/def/ijk/lmn.js',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_js->[0], 200, 'nested skill-local js route returns success' );
is( $nested_js->[2], qq{console.log("nested js");\n}, 'nested skill-local js route serves the nested skill asset' );
my $nested_css = $app->handle(
path => '/css/route-skill/def/ijk/lmn.css',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_css->[0], 200, 'nested skill-local css route returns success' );
is( $nested_css->[2], qq{body { background: #abcdef; }\n}, 'nested skill-local css route serves the nested skill asset' );
my $nested_custom_css = $app->handle(
path => '/assets/route-skill-nested.css',
method => 'GET',
headers => { host => '127.0.0.1' },
remote_addr => '127.0.0.1',
);
is( $nested_custom_css->[0], 200, 'nested custom skill css route returns success' );
is( $nested_custom_css->[2], qq{body { background: #abcdef; }\n}, 'nested custom skill css route serves the nested skill asset' );
my $nested_other = $app->handle(
path => '/others/route-skill/def/ijk/lmn.txt',
method => 'GET',
headers => { host => '127.0.0.1' },
t/20-skill-web-routes.t view on Meta::CPAN
}
done_testing();
END {
chdir $original_cwd if defined $original_cwd && length $original_cwd;
}
sub _create_skill_repo {
my ( $name, %args ) = @_;
my $repo = File::Spec->catdir( $test_repos, $name );
make_path($repo);
my $cwd = getcwd();
chdir $repo or die "Unable to chdir to $repo: $!";
_run_or_die(qw(git init --quiet));
_run_or_die(qw(git config user.email test@example.com));
_run_or_die(qw(git config user.name Test));
make_path('cli');
make_path('config');
make_path('dashboards');
make_path( File::Spec->catdir( 'dashboards', 'ajax' ) );
make_path( File::Spec->catdir( 'dashboards', 'public', 'js' ) );
make_path( File::Spec->catdir( 'dashboards', 'public', 'css' ) );
make_path( File::Spec->catdir( 'dashboards', 'public', 'others' ) );
_write_file( File::Spec->catfile( 'cli', 'noop' ), "#!/usr/bin/env perl\nprint qq{noop\\n};\n", 0755 );
_write_file( File::Spec->catfile( 'config', 'config.json' ), qq|{"skill_name":"$name"}\n|, 0644 );
_write_file(
File::Spec->catfile( 'dashboards', 'index' ),
<<'BOOKMARK',
TITLE: Skill Route Index
:--------------------------------------------------------------------------------:
BOOKMARK: index
:--------------------------------------------------------------------------------:
HTML:
Skill Route Index
BOOKMARK
0644,
);
_write_file(
File::Spec->catfile( 'dashboards', 'foo' ),
<<'BOOKMARK',
TITLE: Skill Route Foo
:--------------------------------------------------------------------------------:
BOOKMARK: foo
:--------------------------------------------------------------------------------:
HTML:
Skill Route Foo
BOOKMARK
0644,
);
_write_file(
File::Spec->catfile( 'dashboards', 'ajax-demo' ),
<<'BOOKMARK',
TITLE: Skill Ajax Demo
:--------------------------------------------------------------------------------:
BOOKMARK: ajax-demo
:--------------------------------------------------------------------------------:
HTML:
<div id="ajax-demo">Ajax Demo</div>
<script>
var endpoints = {};
</script>
:--------------------------------------------------------------------------------:
CODE1: Ajax jvar => 'endpoints.bar', file => 'bar', type => 'json', code => q{
print qq|{"route":"bar"}\n|;
};
BOOKMARK
0644,
);
_write_file(
File::Spec->catfile( 'config', 'routes.json' ),
sprintf(
<<'JSON',
{
"/apps/%s/home" : "/app/index",
"/apps/%s/foo" : "/app/foo",
"/v1/%s/bar" : "/ajax/bar",
"/v1/%s/raw" : {
"to" : "/ajax/raw",
"type" : "application/vnd.route+json"
},
"/assets/%s.css" : "/css/skill.css",
"/assets/%s.js" : "/js/skill.js",
"/downloads/%s.txt" : {
"to" : "/others/info.txt",
"type" : "text/plain; charset=utf-8"
}
}
JSON
($name) x 7,
),
0644,
);
_write_file( File::Spec->catfile( 'dashboards', 'ajax', 'bar' ), qq{print qq|{"route":"bar"}\\n|;\n}, 0700 );
_write_file( File::Spec->catfile( 'dashboards', 'ajax', 'raw' ), qq{print qq|{"route":"raw"}\\n|;\n}, 0700 );
_write_file( File::Spec->catfile( 'dashboards', 'public', 'js', 'skill.js' ), qq{console.log("$name js");\n}, 0644 );
_write_file( File::Spec->catfile( 'dashboards', 'public', 'css', 'skill.css' ), qq{body { color: #123456; }\n}, 0644 );
_write_file( File::Spec->catfile( 'dashboards', 'public', 'others', 'info.txt' ), "$name info\n", 0644 );
make_path( File::Spec->catdir( 'skills', 'def', 'dashboards', 'ajax' ) );
make_path( File::Spec->catdir( 'skills', 'def', 'dashboards', 'nav' ) );
make_path( File::Spec->catdir( 'skills', 'def', 'dashboards', 'public', 'js', 'ijk' ) );
make_path( File::Spec->catdir( 'skills', 'def', 'dashboards', 'public', 'css', 'ijk' ) );
make_path( File::Spec->catdir( 'skills', 'def', 'dashboards', 'public', 'others', 'ijk' ) );
make_path( File::Spec->catdir( 'skills', 'def', 'config' ) );
_write_file(
File::Spec->catfile( 'skills', 'def', 'dashboards', 'index' ),
<<'BOOKMARK',
TITLE: Nested Skill Index
:--------------------------------------------------------------------------------:
BOOKMARK: index
:--------------------------------------------------------------------------------:
HTML:
Nested Skill Index
BOOKMARK
0644,
);
_write_file(
File::Spec->catfile( 'skills', 'def', 'dashboards', 'foo' ),
<<'BOOKMARK',
TITLE: Nested Skill Foo
:--------------------------------------------------------------------------------:
BOOKMARK: foo
:--------------------------------------------------------------------------------:
HTML:
Nested Skill Foo
BOOKMARK
0644,
);
_write_file(
File::Spec->catfile( 'skills', 'def', 'dashboards', 'ajax-demo' ),
<<'BOOKMARK',
TITLE: Nested Skill Ajax Demo
:--------------------------------------------------------------------------------:
BOOKMARK: ajax-demo
:--------------------------------------------------------------------------------:
HTML:
<div id="nested-ajax-demo">Nested Ajax Demo</div>
<script>
var endpoints = {};
</script>
:--------------------------------------------------------------------------------:
CODE1: Ajax jvar => 'endpoints.nested', file => 'nested', code => q{
print "<p>nested skill ajax route</p>\n";
};
BOOKMARK
0644,
);
_write_file(
File::Spec->catfile( 'skills', 'def', 'config', 'routes.json' ),
sprintf(
<<'JSON',
{
"/apps/%s/child/foo" : "/app/foo",
"/v1/%s/nested" : {
"to" : "/ajax/nested",
"type" : "html"
},
"/assets/%s-nested.css" : "/css/ijk/lmn.css",
"/assets/%s-nested.js" : "/js/ijk/lmn.js",
"/downloads/%s-nested.txt" : "/others/ijk/lmn.txt"
}
JSON
($name) x 5,
),
0644,
);
_write_file( File::Spec->catfile( 'skills', 'def', 'dashboards', 'ajax', 'nested' ), qq{print "<p>nested skill ajax route</p>\\n";\n}, 0700 );
_write_file( File::Spec->catfile( 'skills', 'def', 'dashboards', 'nav', 'index.tt' ), "<div>Nested Skill Nav</div>\n", 0644 );
_write_file( File::Spec->catfile( 'skills', 'def', 'dashboards', 'public', 'js', 'ijk', 'lmn.js' ), qq{console.log("nested js");\n}, 0644 );
_write_file( File::Spec->catfile( 'skills', 'def', 'dashboards', 'public', 'css', 'ijk', 'lmn.css' ), qq{body { background: #abcdef; }\n}, 0644 );
_write_file( File::Spec->catfile( 'skills', 'def', 'dashboards', 'public', 'others', 'ijk', 'lmn.txt' ), "nested other asset\n", 0644 );
make_path( File::Spec->catdir( 'dashboards', 'nav' ) );
_write_file(
File::Spec->catfile( 'dashboards', 'nav', 'skill.tt' ),
'<div>' . ( $args{nav_label} || 'Skill Route Nav' ) . "</div>\n",
0644,
);
_run_or_die(qw(git add .));
_run_or_die( 'git', 'commit', '-m', 'Initial route skill' );
chdir $cwd or die "Unable to chdir back to $cwd: $!";
return $repo;
}
sub _write_file {
my ( $path, $content, $mode ) = @_;
open my $fh, '>', $path or die "Unable to write $path: $!";
print {$fh} $content;
close $fh;
chmod $mode, $path or die "Unable to chmod $path: $!";
return 1;
}
sub _run_or_die {
my (@command) = @_;
system(@command) == 0 or die "Command failed: @command";
return 1;
}
sub _drain_stream_body {
my ($body) = @_;
return $body if ref($body) ne 'HASH' || ref( $body->{stream} ) ne 'CODE';
my $output = '';
( run in 0.961 second using v1.01-cache-2.11-cpan-524268b4103 )