Firefox-Marionette

 view release on metacpan or  search on metacpan

t/01-marionette.t  view on Meta::CPAN

#! /usr/bin/perl

use strict;
use warnings;
use Digest::SHA();
use MIME::Base64();
use Test::More;
use Cwd();
use Encode();
use Firefox::Marionette();
use Waterfox::Marionette();
use Compress::Zlib();
use IO::Socket::IP();
use Config;
use HTTP::Daemon();
use HTTP::Status();
use HTTP::Response();
use IO::Socket::SSL();
use File::HomeDir();
BEGIN: {
    if ( $^O eq 'MSWin32' ) {
        require Win32::Process;
    }
}

my $segv_detected;
my $at_least_one_success;
my $terminated;
my $class;
my $arch_32bit_re = qr/^(?:x86|arm(?:hf|el)?)$/smxi;
my $quoted_home_directory = quotemeta File::HomeDir->my_home();
my $is_covering = !!(eval 'Devel::Cover::get_coverage()');

my $oldfh = select STDOUT; $| = 1; select $oldfh;
$oldfh = select STDERR; $| = 1; select $oldfh;

if (defined $ENV{WATERFOX}) {
	$class = 'Waterfox::Marionette';
	$class->import(qw(:all));
} else {
	$class = 'Firefox::Marionette';
	$class->import(qw(:all));
}
diag("Starting test at " . localtime);
my $alarm;
if (defined $ENV{FIREFOX_ALARM}) {
	if ($ENV{FIREFOX_ALARM} =~ /^(\d{1,6})\s*$/smx) {
		($alarm) = ($1);
		diag("Setting the ALARM value to $alarm");
		alarm $alarm;
	} else {
		die "Invalid value of FIREFOX_ALARM ($ENV{FIREFOX_ALARM})";
	}
}
foreach my $name (qw(FIREFOX_HOST FIREFOX_USER)) {
	if (exists $ENV{$name}) {
		if (defined $ENV{$name}) {
			$ENV{$name} =~ s/\s*$//smx;
		} else {
			die "This is just not possible:$name";
		}
	}
}

my $test_time_limit = 90;
my $page_content = 'page-content';
my $form_control = 'form-control';
my $css_form_control = 'input.form-control';
my $footer_links = 'footer-links';
my $xpath_for_read_text_and_size = '//a[@class="keyboard-shortcuts"]';
my $freeipapi_uri = 'data:application/json,{"ipVersion":6,"ipAddress":"2001:8001:4ab3:d800:7215:c1fe:fc85:1329","latitude":-37.5,"longitude":144.5,"countryName":"Australia","countryCode":"AU","timeZone":"+11:00","zipCode":"3000","cityName":"Melbourne...
my $geocode_maps_uri = 'data:application/json,[{"place_id":18637666,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"node","osm_id":6173167285,"boundingbox":["-37.6","-37.4","144.4","144.5"],"lat":"-37.5...
my $positionstack_uri = 'data:application/json,{"data":[{"latitude":-37.5,"longitude":144.5,"type":"address","name":"101 Collins Street","number":"101","postal_code":"3000","street":"Collins Street","confidence":1,"region":"Victoria","region_code":"V...
my $ipgeolocation_uri = 'data:application/json,{"ip":"2001:8001:4ab3:d800:7215:c1fe:fc85:1329","continent_code":"OC","continent_name":"Oceania","country_code2":"AU","country_code3":"AUS","country_name":"Australia","country_name_official":"Commonwealt...
my $ipstack_uri = 'data:application/json,{"ip": "2001:8003:4a03:d800:7285:c2ff:fe85:1528", "type": "ipv6", "continent_code": "OC", "continent_name": "Oceania", "country_code": "AU", "country_name": "Australia", "region_code": "VIC", "region_name": "V...
my $dummy1_uri = 'data:application/json,{"latitude":40.7,"longitude":-73.9,"time_zone":{"current_time":"2024-01-09 04:36:29.524-0500"}}'; # dummy data for testing (roughly new york)
my $dummy2_uri = 'data:application/json,{"latitude":40.7,"longitude":-73.9,"time_zone":{"current_time":"1234abc"}}'; # dummy data for testing bad data
my $most_common_useragent = q[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36];

t/01-marionette.t  view on Meta::CPAN

				diag("Xvfb rpm version is " . `rpm -qf /usr/bin/Xvfb`);
			}
		}
	}
}
if ($^O eq 'linux') {
	diag("grep -r Mem /proc/meminfo");
	diag(`grep -r Mem /proc/meminfo`);
	diag("ulimit -a | grep -i mem");
	diag(`ulimit -a | grep -i mem`);
} elsif ($^O =~ /bsd/i) {
	diag("sysctl hw | egrep 'hw.(phys|user|real)'");
	diag(`sysctl hw | egrep 'hw.(phys|user|real)'`);
	diag("ulimit -a | grep -i mem");
	diag(`ulimit -a | grep -i mem`);
}
my $count = 0;
foreach my $name (Firefox::Marionette::Profile->names()) {
	my $profile = Firefox::Marionette::Profile->existing($name);
	$count += 1;
}
foreach my $name (Waterfox::Marionette::Profile->names()) {
	my $profile = Waterfox::Marionette::Profile->existing($name);
	$count += 1;
}
ok(1, "Read $count existing profiles");
diag("This firefox installation has $count existing profiles");
if (Firefox::Marionette::Profile->default_name()) {
	ok(1, "Found default profile");
} else {
	ok(1, "No default profile");
}
if (Waterfox::Marionette::Profile->default_name()) {
	ok(1, "Found default waterfox profile");
} else {
	ok(1, "No default waterfox profile");
}
my $profile;
eval {
	if ($ENV{WATERFOX}) {
		$profile = Waterfox::Marionette::Profile->existing();
	} else {
		$profile = Firefox::Marionette::Profile->existing();
	}
};
ok(1, "Read existing profile if any");
my $firefox;
eval {
	$firefox = $class->new(binary => '/firefox/is/not/here');
};
chomp $@;
ok((($@) and (not($firefox))), "$class->new() threw an exception when launched with an incorrect path to a binary:$@");
eval {
	$firefox = $class->new(binary => $^X);
};
chomp $@;
ok((($@) and (not($firefox))), "$class->new() threw an exception when launched with a path to a non firefox binary:$@");
my $tls_tests_ok;
if ($ENV{RELEASE_TESTING}) {
	if ( 
		!IO::Socket::SSL->new(
		PeerAddr => 'missing.example.org:443',
		SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(),
			) ) {
		if ( IO::Socket::SSL->new(
		PeerAddr => 'metacpan.org:443',
		SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER(),
			) ) {
			diag("TLS/Network seem okay");
			$tls_tests_ok = 1;
		} else {
			diag("TLS/Network are NOT okay:Failed to connect to metacpan.org:$IO::Socket::SSL::SSL_ERROR");
		}
	} else {
		diag("TLS/Network are NOT okay:Successfully connected to missing.example.org");
	}
}
my $skip_message;
my $profiles_work = 1;
SKIP: {
	if ($ENV{FIREFOX_BINARY}) {
		skip("No profile testing when the FIREFOX_BINARY override is used", 6);
	}
	if (($ENV{WATERFOX}) || ($ENV{WATERFOX_VIA_FIREFOX})) {
		skip("No profile testing when any WATERFOX override is used", 6);
	}
	if ($ENV{FIREFOX_DEVELOPER}) {
		skip("No profile testing when the FIREFOX_DEVELOPER override is used", 6);
	}
	if ($ENV{FIREFOX_NIGHTLY}) {
		skip("No profile testing when the FIREFOX_NIGHTLY override is used", 6);
	}
	if (!$ENV{RELEASE_TESTING}) {
		skip("No profile testing except for RELEASE_TESTING", 6);
	}
	my @names = Firefox::Marionette::Profile->names();
	foreach my $name (@names) {
		next unless ($name eq 'throw');
		$profiles_work = 0;
		($skip_message, $firefox) = start_firefox(0, debug => 1, profile_name => $name );
		if (!$skip_message) {
			$at_least_one_success = 1;
		}
		if ($skip_message) {
			skip($skip_message, 6);
		}
		ok($firefox, "Firefox loaded with the $name profile");
		if ($major_version < 52) {
		} elsif (($^O eq 'openbsd') && (Cwd::cwd() !~ /^($quoted_home_directory\/Downloads|\/tmp)/)) {
		} else {
			my $install_path = Cwd::abs_path('t/addons/test.xpi');
			diag("Original install path is $install_path");
			if ($^O eq 'MSWin32') {
				$install_path =~ s/\//\\/smxg;
			}
			diag("Installing extension from $install_path");
			my $temporary = 1;
			my $install_id = $firefox->install($install_path, $temporary);
			ok($install_id, "Successfully installed an extension:$install_id");
			ok($firefox->uninstall($install_id), "Successfully uninstalled an extension");
		}
		ok($firefox->go('http://example.com'), "firefox with the $name profile loaded example.com");
		ok($firefox->quit() == 0, "firefox with the $name profile quit successfully");
		my $profile;
		if ($ENV{WATERFOX}) {
			$profile = Waterfox::Marionette::Profile->existing($name);
		} else {
			$profile = Firefox::Marionette::Profile->existing($name);
		}
		$profile->set_value('security.webauth.webauthn_enable_softtoken', 'true', 0);
		($skip_message, $firefox) = start_firefox(0, profile => $profile );
		if (defined $ENV{FIREFOX_DEBUG}) {

t/01-marionette.t  view on Meta::CPAN

		ok($result == &$name(), "Firefox::Marionette::Bookmark::$name() == $name() after Firefox::Marionette::Bookmark->import(:all)");
		use strict;
	}
	foreach my $name (qw(MENU ROOT TOOLBAR TAGS UNFILED)) {
		my $result = eval "return Firefox::Marionette::Bookmark::$name();";
		no strict;
		ok($result eq &$name(), "Firefox::Marionette::Bookmark::$name() eq $name() after Firefox::Marionette::Bookmark->import(:all)");
		use strict;
	}
	my $new_max_url_length = 4321;
	my $original_max_url_length = $firefox->get_pref('browser.history.maxStateObjectSize');
	ok($original_max_url_length =~ /^\d+$/smx, "Retrieved browser.history.maxStateObjectSize as a number '$original_max_url_length'");
	ok(ref $firefox->set_pref('browser.history.maxStateObjectSize', $new_max_url_length) eq $class, "\$firefox->set_pref correctly returns itself for chaining and set 'browser.history.maxStateObjectSize' to '$new_max_url_length'");
	my $max_url_length = $firefox->get_pref('browser.history.maxStateObjectSize');
	ok($max_url_length == $new_max_url_length, "Retrieved browser.history.maxStateObjectSize which was equal to the previous setting of '$new_max_url_length'");
	ok(ref $firefox->set_pref('browser.history.maxStateObjectSize', $original_max_url_length) eq $class, "\$firefox->set_pref correctly returns itself for chaining and set 'browser.history.maxStateObjectSize' to the original '$original_max_url_length'")...
	$max_url_length = $firefox->get_pref('browser.history.maxStateObjectSize');
	ok($max_url_length == $original_max_url_length, "Retrieved browser.history.maxStateObjectSize as a number '$max_url_length' which was equal to the original setting of '$original_max_url_length'");
	my $original_use_system_colours = $firefox->get_pref('browser.display.use_system_colors');
	ok($original_use_system_colours =~ /^[01]$/smx, "Retrieved browser.display.use_system_colors as a boolean '$original_use_system_colours', and set it as true");
	ok(ref $firefox->set_pref('browser.display.use_system_colors', \1) eq $class, "\$firefox->set_pref correctly returns itself for chaining and set 'browser.display.use_system_colors' to 'true'");;
	my $use_system_colours = $firefox->get_pref('browser.display.use_system_colors');
	ok($use_system_colours, "Retrieved browser.display.use_system_colors as true '$use_system_colours'");
	ok(ref $firefox->set_pref('browser.display.use_system_colors', \0) eq $class, "\$firefox->set_pref correctly returns itself for chaining and set 'browser.display.use_system_colors' to 'false'");;
	$use_system_colours = $firefox->get_pref('browser.display.use_system_colors');
	ok(!$use_system_colours, "Retrieved browser.display.use_system_colors as false '$use_system_colours'");
	ok(ref $firefox->clear_pref('browser.display.use_system_colors', \0) eq $class, "\$firefox->clear_pref correctly returns itself for chaining and cleared 'browser.display.use_system_colors'");
	$use_system_colours = $firefox->get_pref('browser.display.use_system_colors');
	ok($use_system_colours == $original_use_system_colours, "Retrieved original browser.display.use_system_colors as a boolean '$use_system_colours'");
	ok(!defined $firefox->get_pref('browser.no_such_key'), "Returned undef when querying for a non-existant key of 'browser.no_such_key'");
	my $new_value = "Can't be real:$$";
	ok(ref $firefox->set_pref('browser.no_such_key', $new_value) eq $class, "\$firefox->set_pref correctly returns itself for chaining and set 'browser.no_such_key' to '$new_value'");
	ok($firefox->get_pref('browser.no_such_key') eq $new_value, "Returned browser.no_such_key as a string '$new_value'");
	my $new_active_colour = '#FFFFFF';
	my $original_active_colour = $firefox->get_pref('browser.active_color');
	ok($original_active_colour =~ /^[#][[:xdigit:]]{6}$/smx, "Retrieved browser.active_color as a string '$original_active_colour'");
	my $active_colour = $firefox->get_pref('browser.active_color');
	ok($active_colour eq $original_active_colour, "Retrieved browser.active_color as a string '$active_colour' which was equal to the original setting of '$original_active_colour'");
	ok(ref $firefox->set_pref('browser.active_color', $new_active_colour) eq $class, "\$firefox->set_pref correctly returns itself for chaining and set 'browser.active_color' to '$new_active_colour'");;
	$active_colour = $firefox->get_pref('browser.active_color');
	ok($active_colour eq $new_active_colour, "Retrieved browser.active_color as a string '$active_colour' which was equal to the new setting of '$new_active_colour'");
	ok(ref $firefox->clear_pref('browser.active_color') eq $class, "\$firefox->clear_pref correctly returns itself for chaining and cleared 'browser.active_color'");;
	$active_colour = $firefox->get_pref('browser.active_color');
	ok($active_colour eq $original_active_colour, "Retrieved browser.active_color as a string '$active_colour' which was equal to the original string of '$original_active_colour'");
	my $capabilities = $firefox->capabilities();
	ok((ref $capabilities) eq 'Firefox::Marionette::Capabilities', "\$firefox->capabilities() returns a Firefox::Marionette::Capabilities object");
	if (out_of_time()) {
		skip("Running out of time.  Trying to shutdown tests as fast as possible", 2);
	}
	if (!$ENV{RELEASE_TESTING}) {
		skip("Skipping network tests", 2);
	}
	if (grep /^accept_insecure_certs$/, $capabilities->enumerate()) {
		ok(!$capabilities->accept_insecure_certs(), "\$capabilities->accept_insecure_certs() is false");
		if (($ENV{FIREFOX_HOST}) && ($ENV{FIREFOX_HOST} ne 'localhost')) {
			diag("insecure cert test is not supported for remote hosts");
		} elsif (($ENV{FIREFOX_HOST}) && ($ENV{FIREFOX_HOST} eq 'localhost') && ($ENV{FIREFOX_PORT})) {
			diag("insecure cert test is not supported for remote hosts");
		} elsif ((exists $Config::Config{'d_fork'}) && (defined $Config::Config{'d_fork'}) && ($Config::Config{'d_fork'} eq 'define')) {
			my $ip_address = '127.0.0.1';
			my $daemon = IO::Socket::SSL->new(
				LocalAddr => $ip_address,
				LocalPort => 0,
				Listen => 20,
				SSL_cert_file => $ca_cert_handle->filename(),
				SSL_key_file => $ca_private_key_handle->filename(),
			);
			my $url = "https://$ip_address:" . $daemon->sockport();
			if (my $pid = fork) {
				wait_for_server_on($daemon, $url, $pid);
				eval { $firefox->go(URI->new($url)) };
				my $exception = "$@";
				chomp $exception;
				ok(ref $@ eq 'Firefox::Marionette::Exception::InsecureCertificate', $url . " threw an exception:$exception");
				while(kill 0, $pid) {
					kill $signals_by_name{TERM}, $pid;
					sleep 1;
					waitpid $pid, POSIX::WNOHANG();
				}
			} elsif (defined $pid) {
				eval {
					local $SIG{ALRM} = sub { die "alarm during insecure cert test\n" };
					alarm 40;
					$0 = "[Test insecure cert test for " . getppid . "]";
					diag("Accepting connections on $url for $0");
					foreach ((1 .. 3)) {
						my $connection = $daemon->accept();
					}
					exit 0;
				};
				chomp $@;
				diag("insecure cert test server failed:$@");
				exit 1;
			} else {
				diag("insecure cert test fork failed:$@");
			}
		} else {
			diag("No forking available for $^O");
		}
	} else {
		diag("\$capabilities->accept_insecure_certs is not supported for " . $capabilities->browser_version());
	}
	if (out_of_time()) {
		skip("Running out of time.  Trying to shutdown tests as fast as possible", 2);
	}
	my $profile_directory = $firefox->profile_directory();
	ok($profile_directory, "\$firefox->profile_directory() returns $profile_directory");
	my $possible_logins_path = File::Spec->catfile($profile_directory, 'logins.json');
	ok(!-e $possible_logins_path, "There is no logins.json file yet");
	eval { $firefox->fill_login() };
	ok(ref $@ eq 'Firefox::Marionette::Exception', "Unable to fill in form when no form is present:$@");
	my $cant_load_github;
	my $result;
	eval {
		$result = $firefox->go('https://github.com/login');
	};
	if ($@) {
		$cant_load_github = 1;
		diag("\$firefox->go('https://github.com/login') threw an exception:$@");
	} else {
		ok($result, "\$firefox loads https://github.com/login");



( run in 2.628 seconds using v1.01-cache-2.11-cpan-ad19def0cd9 )