Playwright.t 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. use Test2::V0;
  2. use Test2::Tools::Explain;
  3. use JSON::MaybeXS;
  4. use Test::MockModule qw{strict};
  5. use Test::MockFile;
  6. use Async;
  7. my ($qxret,$qxcode) = ('',255);
  8. use Test::Mock::Cmd qx => sub { $? = $qxcode; return $qxret };
  9. #De-Fang our BEGIN block so we can test safely
  10. no warnings qw{redefine once};
  11. $Playwright::SKIP_BEGIN = 1;
  12. use warnings;
  13. require Playwright;
  14. my $path2here = File::Basename::dirname(Cwd::abs_path($INC{'Playwright.pm'}));
  15. subtest "_check_and_build_spec" => sub {
  16. #Simulate file not existing
  17. my $json = Test::MockFile->file("$path2here/../api.json");
  18. like( dies { Playwright::_check_and_build_spec() }, qr/specification/i, "Nonexistant api.json throws");
  19. undef $json;
  20. $json = Test::MockFile->file("$path2here/../api.json", '{"a":"b"}');
  21. my ($path) = Playwright::_check_and_build_spec();
  22. is($Playwright::spec, { a => 'b'}, "Spec parsed correctly");
  23. is($path,$path2here, "Path to module built correctly");
  24. };
  25. subtest "_build_classes" => sub {
  26. local $Playwright::spec = {
  27. Fake => {
  28. members => {
  29. tickle => {
  30. args => {
  31. chase => { type => { name => 'boolean' }, order => 1 },
  32. tickleOptions => {
  33. order => 0,
  34. type => {
  35. name => 'Object',
  36. properties => {
  37. intense => { name => 'intense', type => { name => 'boolean' } },
  38. tickler => { name => 'tickler', type => { name => 'string' } },
  39. optional => { name => 'optional', type => { name => 'boolean' } }, # Optional, shouldn't show up in output
  40. },
  41. },
  42. },
  43. who => { type => { name => 'string' }, order => 2 },
  44. hug => { type => { name => 'boolean' }, order => 3 }, # Optional bool arg, make sure we dont choke
  45. },
  46. },
  47. }
  48. },
  49. };
  50. #Very light testing here, example.pl is really what tests this
  51. Playwright::_build_classes();
  52. ok(defined &Playwright::Fake::new, "Constructors set up correctly");
  53. ok(defined &Playwright::Fake::tickle, "Class methods set up correctly");
  54. };
  55. subtest "_check_node" => sub {
  56. my $decoder = JSON::MaybeXS->new();
  57. my $bin = Test::MockFile->file("$path2here/../bin/playwright.js");
  58. like( dies { Playwright::_check_node($path2here, $decoder) }, qr/server in/i, "Server not existing throws");
  59. undef $bin;
  60. $bin = Test::MockFile->file("$path2here/../bin/playwright.js",'');
  61. my $which = Test::MockModule->new('File::Which');
  62. $which->redefine('which', sub { shift eq 'node' ? '/bogus' : '/hokum' });
  63. my $node = Test::MockFile->file('/bogus', undef, { mode => 0777 } );
  64. my $npm = Test::MockFile->file('/hokum', undef, { mode => 0777 } );
  65. like( dies { Playwright::_check_node($path2here, $decoder) }, qr/node must exist/i, "node not existing throws");
  66. undef $node;
  67. $node = Test::MockFile->file('/bogus', '', { mode => 0777 } );
  68. like( dies { Playwright::_check_node($path2here, $decoder) }, qr/npm must exist/i, "npm not existing throws");
  69. undef $npm;
  70. $npm = Test::MockFile->file('/hokum', '', { mode => 0777 } );
  71. my $fakecapture = Test::MockModule->new('Capture::Tiny');
  72. $fakecapture->redefine('capture_stderr', sub { 'oh no' });
  73. $qxret = '';
  74. like( dies { Playwright::_check_node($path2here, $decoder) }, qr/could not list/i, "package.json not existing throws");
  75. $qxret = '{
  76. "name": "playwright-server-perl",
  77. "version": "1.0.0",
  78. "problems": [
  79. "missing: express@^4.17, required by playwright-server-perl@1.0.0",
  80. "missing: playwright@^1.5, required by playwright-server-perl@1.0.0",
  81. "missing: yargs@^16.1, required by playwright-server-perl@1.0.0",
  82. "missing: uuid@^8.3, required by playwright-server-perl@1.0.0"
  83. ],
  84. "dependencies": {
  85. "express": {
  86. "required": "^4.17",
  87. "missing": true
  88. },
  89. "playwright": {
  90. "required": "^1.5",
  91. "missing": true
  92. },
  93. "yargs": {
  94. "required": "^16.1",
  95. "missing": true
  96. },
  97. "uuid": {
  98. "required": "^8.3",
  99. "missing": true
  100. }
  101. }
  102. }';
  103. #XXX doesn't look like we can mock $? correctly
  104. #like( dies { Playwright::_check_node($path2here, $decoder) }, qr/installing node/i, "npm failure throws");
  105. $fakecapture->redefine('capture_stderr', sub { 'package-lock' });
  106. $qxcode = 0;
  107. ok( lives { Playwright::_check_node($path2here, $decoder) }, "Can run all the way thru") or note $@;
  108. };
  109. subtest "new" => sub {
  110. my $portmock = Test::MockModule->new('Net::EmptyPort');
  111. $portmock->redefine('empty_port', sub { 420 });
  112. my $lwpmock = Test::MockModule->new('LWP::UserAgent');
  113. $lwpmock->redefine('new', sub { 'LWP' });
  114. my $selfmock = Test::MockModule->new('Playwright');
  115. $selfmock->redefine('_start_server', sub { 666 });
  116. $selfmock->redefine('DESTROY', sub {});
  117. my $expected = bless({
  118. ua => 'whee',
  119. debug => 1,
  120. parent => $$,
  121. pid => 666,
  122. port => 420,
  123. }, 'Playwright');
  124. is(Playwright->new( ua => 'whee', debug => 1), $expected, "Constructor functions as expected");
  125. $expected = bless({
  126. ua => 'LWP',
  127. debug => undef,
  128. parent => $$,
  129. pid => 666,
  130. port => 420,
  131. }, 'Playwright');
  132. is(Playwright->new(), $expected, "Constructor defaults expected");
  133. };
  134. subtest "launch" => sub {
  135. my $basemock = Test::MockModule->new('Playwright::Base');
  136. $basemock->redefine('_coerce', sub {});
  137. my $utilmock = Test::MockModule->new('Playwright::Util');
  138. $utilmock->redefine('request', sub { 'eee' });
  139. my $selfmock = Test::MockModule->new('Playwright');
  140. $selfmock->redefine('DESTROY', sub {});
  141. my $obj = bless({}, 'Playwright');
  142. is($obj->launch( type => 'eee' ), 'eee' ,"launch passthru works");
  143. #XXX Don't feel like mocking the objectification right now
  144. };
  145. subtest "await" => sub {
  146. my $selfmock = Test::MockModule->new('Playwright');
  147. $selfmock->redefine('DESTROY', sub {});
  148. my $res = {};
  149. no warnings qw{redefine once};
  150. local *AsyncData::result = sub { $res };
  151. use warnings;
  152. my $promise = bless({},'AsyncData');
  153. my $obj = bless({ ua => 'eee', 'port' => 1 }, 'Playwright');
  154. no warnings qw{redefine once};
  155. local *Playwright::Bogus::new = sub { my ($class, %input) = @_; return bless({ spec => 'whee', ua => $input{handle}{ua}, port => $input{handle}{port}, type => $input{type}, guid => $input{id} }, 'Playwright::Bogus') };
  156. use warnings;
  157. is($obj->await($promise),{},"await passthru works");
  158. $res = { _guid => 'abc123', _type => 'Bogus' };
  159. my $expected = bless({ spec => 'whee', ua => 'eee', port => 1, guid => 'abc123', type => 'Bogus' }, 'Bogus');
  160. is($obj->await($promise),$expected,"await objectification works");
  161. };
  162. #XXX Omitting destructor and server startup testing for now
  163. done_testing();