Trog-Bundle.t 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #!/usr/bin/env perl
  2. use 5.040;
  3. use re '/aasx';
  4. use warnings FATAL => 'all';
  5. use Test::More;
  6. use Test::MockModule qw{strict};
  7. use Cwd();
  8. use File::Path();
  9. use File::Temp();
  10. use Path::Tiny();
  11. use FindBin::libs;
  12. # Every path in tCMS is relative to the instance root, so this stands in one.
  13. my $root = File::Temp::tempdir( 'tcms-bundle-XXXXXX', TMPDIR => 1, CLEANUP => 0 );
  14. my $oldcwd = Cwd::getcwd();
  15. chdir($root) or die "could not chdir to the sandbox: $!";
  16. END {
  17. chdir($oldcwd) if $oldcwd;
  18. File::Path::remove_tree($root) if $root && -d $root;
  19. }
  20. require_ok('Trog::Bundle') or BAIL_OUT("Can't find SUT");
  21. my $stock = Path::Tiny->new('www/scripts');
  22. my $theme = Path::Tiny->new('www/themes/spec/scripts');
  23. $_->mkpath foreach ( $stock, $theme );
  24. $stock->child('one.js')->spew_raw("function one () {\n return 1;\n}\n");
  25. $stock->child('two.js')->spew_raw("// two\nvar two = 2;\n");
  26. $stock->child('vendor.min.js')->spew_raw("var vendor = 'kept as it is'; // a trailing comment");
  27. $stock->child('themed.js')->spew_raw("var themed = 'stock';\n");
  28. $theme->child('themed.js')->spew_raw("var themed = 'theme';\n");
  29. my $themedir = '';
  30. my $mock = Test::MockModule->new('Trog::Themes');
  31. $mock->redefine( 'get_dir', sub { $themedir } );
  32. my @warned;
  33. local $SIG{__WARN__} = sub { push @warned, $_[0] };
  34. subtest 'the scripts, in the order named' => sub {
  35. my $bundle = Trog::Bundle::scripts(qw{two.js vendor.min.js one.js two.js});
  36. is( $bundle->{body}, "var two=2;\n;\nvar vendor = 'kept as it is'; // a trailing comment\n;\nfunction one(){return 1;}", 'minified, except the one that already is, and a name given twice is used once' );
  37. like( $bundle->{version}, qr/\A[[:xdigit:]]{16}\z/, 'the version is a digest' );
  38. is( $bundle->{href}, "/bundle/$bundle->{version}/two+vendor.min+one.js", 'and the href carries it, and the names' );
  39. };
  40. subtest 'a name that is not a script' => sub {
  41. @warned = ();
  42. my $bundle = Trog::Bundle::scripts( qw{one.js nothere.js ../one.js .hidden.js sub/one.js one.css}, 'one.js+two' );
  43. is( $bundle->{href}, "/bundle/$bundle->{version}/one.js", 'is left out' );
  44. is( scalar(@warned), 6, 'with a warning for each' ) or diag( explain( \@warned ) );
  45. like( $warned[0], qr/no[ ]script[ ]nothere[.]js/, 'that names it' );
  46. @warned = ();
  47. is( Trog::Bundle::scripts(qw{nothere.js}), undef, 'and a list of nothing else is no bundle' );
  48. is( Trog::Bundle::scripts(), undef, 'nor is an empty one' );
  49. };
  50. subtest "the theme's copy" => sub {
  51. is( Trog::Bundle::scripts(qw{themed.js})->{body}, "var themed='stock';", 'is not used without the theme' );
  52. $themedir = 'www/themes/spec';
  53. is( Trog::Bundle::scripts(qw{themed.js})->{body}, "var themed='theme';", 'and is used in place of the stock one with it' );
  54. is( Trog::Bundle::scripts(qw{one.js})->{body}, 'function one(){return 1;}', 'while a script the theme lacks is the stock one' );
  55. $themedir = '';
  56. };
  57. subtest 'a script that changes' => sub {
  58. my $before = Trog::Bundle::scripts(qw{one.js});
  59. is( Trog::Bundle::scripts(qw{one.js}), $before, 'the bundle is built once' );
  60. $stock->child('one.js')->spew_raw("function one () {\n return 'one';\n}\n");
  61. utime( time + 10, time + 10, $stock->child('one.js') ) or die "could not touch one.js: $!";
  62. my $after = Trog::Bundle::scripts(qw{one.js});
  63. is( $after->{body}, "function one(){return'one';}", 'and built again when a file in it changes' );
  64. isnt( $after->{href}, $before->{href}, 'at a new href' );
  65. };
  66. subtest 'many lists' => sub {
  67. $stock->child("s$_.js")->spew_raw("var s$_;") for 1 .. 20;
  68. @warned = ();
  69. my %bundle = map { $_ => Trog::Bundle::scripts( 'one.js', "s$_.js" ) } 1 .. 20;
  70. my %body = map { $_ => $bundle{$_}{body} } keys %bundle;
  71. is( scalar(@warned), 0, 'twenty lists' );
  72. isnt( Trog::Bundle::scripts(qw{one.js s1.js}), $bundle{1}, 'are more than the cache keeps, so it was emptied' );
  73. is( Trog::Bundle::scripts( 'one.js', "s$_.js" )->{body}, $body{$_}, "list $_ still has its body after the cache is emptied" ) for 1, 20;
  74. };
  75. done_testing();