diff --git a/codeception.dist.yml b/codeception.dist.yml index 2b6e96a12..300f80631 100644 --- a/codeception.dist.yml +++ b/codeception.dist.yml @@ -23,3 +23,4 @@ extensions: - "lucatume\\WPBrowser\\Command\\RunOriginal" - "lucatume\\WPBrowser\\Command\\RunAll" - "lucatume\\WPBrowser\\Command\\GenerateWPUnit" + - "lucatume\\WPBrowser\\Command\\ChromedriverUpdate" diff --git a/composer.json b/composer.json index 66c9ba16e..2a4029410 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ "ext-fileinfo": "*", "ext-json": "*", "ext-curl": "*", + "ext-zip": "*", "composer-runtime-api": "^2.2", "codeception/codeception": "^5.0", "codeception/module-asserts": "^2.0 || ^3.0", diff --git a/config/containers/php/Dockerfile b/config/containers/php/Dockerfile index e244727a1..e1adc0662 100644 --- a/config/containers/php/Dockerfile +++ b/config/containers/php/Dockerfile @@ -46,3 +46,11 @@ RUN chmod a+x /usr/local/bin/xdebug-on && chmod a+x /usr/local/bin/xdebug-off # Ensure the gropup and user exist. RUN getent group ${USER_GID} || groupadd -g ${USER_GID} ${USER_NAME} RUN getent passwd ${USER_UID} || useradd -u ${USER_UID} -g ${USER_GID} -m -s /bin/bash ${USER_NAME} + +# Create a Chrome mock where expected. +RUN if [ "${TARGET}" = "codeception" ]; then \ + mkdir -p /usr/bin && \ + echo '#!/bin/bash' > /usr/bin/google-chrome && \ + echo 'echo 'Google Chrome 116.0.5845.96'' >> /usr/bin/google-chrome && \ + chmod a+x /usr/bin/google-chrome; \ + fi diff --git a/src/Command/ChromedriverUpdate.php b/src/Command/ChromedriverUpdate.php new file mode 100644 index 000000000..06b328cf9 --- /dev/null +++ b/src/Command/ChromedriverUpdate.php @@ -0,0 +1,73 @@ +setDescription('Updates the Chromedriver binary.') + ->addArgument( + 'version', + InputArgument::OPTIONAL, + 'The version of Chrome to install chromedriver for.', + '' + )->addOption( + 'platform', + '', + InputOption::VALUE_REQUIRED, + 'The platform to install Chromedriver for.', + '' + )->addOption( + 'binary', + '', + InputOption::VALUE_REQUIRED, + 'The path to the Chrome binary to download Chromedriver for.', + false + ); + } + + /** + * @throws JsonException + */ + public function execute(InputInterface $input, OutputInterface $output): int + { + $platform = $input->getOption('platform') ?: null; + + if ($platform && !is_string($platform)) { + throw new InvalidArgumentException('The platform option must be a string.'); + } + + $version = $input->getArgument('version') ?: null; + + if ($version && !is_string($version)) { + throw new InvalidArgumentException('The version argument must be a string.'); + } + + $binary = $input->getOption('binary') ?: null; + + if ($binary && !is_string($binary)) { + throw new InvalidArgumentException('The binary option must be a string.'); + } + + $chromedriverInstaller = new ChromedriverInstaller($version, $platform, $binary, $output); + $chromedriverInstaller->install(); + + return 0; + } +} diff --git a/src/Project/ContentProject.php b/src/Project/ContentProject.php index f5c80ade3..b87c84925 100644 --- a/src/Project/ContentProject.php +++ b/src/Project/ContentProject.php @@ -4,6 +4,7 @@ use Closure; use Codeception\InitTemplate; +use lucatume\WPBrowser\Command\ChromedriverUpdate; use lucatume\WPBrowser\Command\DevInfo; use lucatume\WPBrowser\Command\DevRestart; use lucatume\WPBrowser\Command\DevStart; @@ -11,6 +12,7 @@ use lucatume\WPBrowser\Exceptions\RuntimeException; use lucatume\WPBrowser\Extension\BuiltInServerController; use lucatume\WPBrowser\Extension\ChromeDriverController; +use lucatume\WPBrowser\Utils\ChromedriverInstaller; use lucatume\WPBrowser\Utils\Filesystem as FS; use lucatume\WPBrowser\Utils\Random; use lucatume\WPBrowser\WordPress\Database\SQLiteDatabase; @@ -20,8 +22,6 @@ abstract class ContentProject extends InitTemplate implements ProjectInterface { - use SetupTemplateTrait; - protected TestEnvironment $testEnvironment; abstract protected function getProjectType(): string; @@ -123,7 +123,9 @@ public function setup(): void } $this->sayInfo('Created database dump in tests/Support/Data/dump.sql.'); - $this->addChromedriverDevDependency(); + $this->sayInfo('Installing Chromedriver ...'); + $chromedriverPath = (new ChromedriverInstaller())->install(); + $this->sayInfo("Chromedriver installed in $chromedriverPath"); $chromedriverPort = Random::openLocalhostPort(); $this->testEnvironment->testTablePrefix = 'test_'; $this->testEnvironment->wpTablePrefix = 'wp_'; @@ -157,6 +159,7 @@ public function setup(): void $this->testEnvironment->customCommands[] = DevStop::class; $this->testEnvironment->customCommands[] = DevInfo::class; $this->testEnvironment->customCommands[] = DevRestart::class; + $this->testEnvironment->customCommands[] = ChromedriverUpdate::class; $this->testEnvironment->wpRootDir = FS::relativePath($this->workDir, $wpRootDir); $this->testEnvironment->dbUrl = 'sqlite://%codecept_root_dir%/tests/_wordpress/data/db.sqlite'; diff --git a/src/Project/SetupTemplateTrait.php b/src/Project/SetupTemplateTrait.php deleted file mode 100644 index a8ddee4fc..000000000 --- a/src/Project/SetupTemplateTrait.php +++ /dev/null @@ -1,30 +0,0 @@ -sayInfo('Adding Chromedriver binary as a development dependency ...'); - $composer = new Composer($this->workDir . '/composer.json'); - $composer->requireDev(['webdriver-binary/binary-chromedriver' => '*']); - $composer->allowPluginsFromPackage('webdriver-binary/binary-chromedriver'); - $composer->update('webdriver-binary/binary-chromedriver'); - } -} diff --git a/src/Project/SiteProject.php b/src/Project/SiteProject.php index 29929da41..2cca7985d 100644 --- a/src/Project/SiteProject.php +++ b/src/Project/SiteProject.php @@ -3,6 +3,7 @@ namespace lucatume\WPBrowser\Project; use Codeception\InitTemplate; +use lucatume\WPBrowser\Command\ChromedriverUpdate; use lucatume\WPBrowser\Command\DevInfo; use lucatume\WPBrowser\Command\DevRestart; use lucatume\WPBrowser\Command\DevStart; @@ -10,6 +11,7 @@ use lucatume\WPBrowser\Exceptions\RuntimeException; use lucatume\WPBrowser\Extension\BuiltInServerController; use lucatume\WPBrowser\Extension\ChromeDriverController; +use lucatume\WPBrowser\Utils\ChromedriverInstaller; use lucatume\WPBrowser\Utils\Filesystem as FS; use lucatume\WPBrowser\Utils\Random; use lucatume\WPBrowser\WordPress\Database\SQLiteDatabase; @@ -22,8 +24,6 @@ class SiteProject extends InitTemplate implements ProjectInterface { - use SetupTemplateTrait; - private Installation $installation; private TestEnvironment $testEnvironment; @@ -117,7 +117,9 @@ public function setup(): void } $this->sayInfo('Created database dump in tests/Support/Data/dump.sql.'); - $this->addChromedriverDevDependency(); + $this->sayInfo('Installing Chromedriver ...'); + $chromedriverPath = (new ChromedriverInstaller())->install(); + $this->sayInfo("Chromedriver installed in $chromedriverPath"); $chromedriverPort = Random::openLocalhostPort(); $this->testEnvironment->testTablePrefix = 'test_'; $this->testEnvironment->wpTablePrefix = 'wp_'; @@ -152,6 +154,7 @@ public function setup(): void $this->testEnvironment->customCommands[] = DevStop::class; $this->testEnvironment->customCommands[] = DevInfo::class; $this->testEnvironment->customCommands[] = DevRestart::class; + $this->testEnvironment->customCommands[] = ChromedriverUpdate::class; $this->testEnvironment->wpRootDir = '.'; $this->testEnvironment->dbUrl = 'sqlite://%codecept_root_dir%/tests/Support/Data/db.sqlite'; diff --git a/src/Utils/ChromedriverInstaller.php b/src/Utils/ChromedriverInstaller.php new file mode 100644 index 000000000..ec3e07170 --- /dev/null +++ b/src/Utils/ChromedriverInstaller.php @@ -0,0 +1,323 @@ +output = $output ?? new NullOutput(); + + $platform = $platform ?? $this->detectPlatform(); + $this->platform = $this->checkPlatform($platform); + + $this->output->writeln("Platform: $platform"); + + $binary = $binary ?? $this->detectBinary(); + $this->binary = $this->checkBinary($binary); + + $this->output->writeln("Binary: $binary"); + + $version = $version ?? $this->detectVersion(); + $this->version = $this->checkVersion($version); + + $this->output->writeln("Version: $version"); + } + + /** + * @throws JsonException + */ + public function install(string $dir = null): string + { + if ($dir === null) { + global $_composer_bin_dir; + $dir = $_composer_bin_dir; + $composerEnvBinDir = getenv('COMPOSER_BIN_DIR'); + if ($composerEnvBinDir && is_string($composerEnvBinDir) && is_dir($composerEnvBinDir)) { + $dir = $composerEnvBinDir; + } + } + + if (!is_dir($dir)) { + throw new InvalidArgumentException( + "The directory $dir does not exist.", + self::ERR_DESTINATION_NOT_DIR + ); + } + + $this->output->writeln("Fetching Chromedriver version URL ..."); + + $downloadUrl = $this->fetchChromedriverVersionUrl(); + $zipFilePathname = rtrim(sys_get_temp_dir(), '\\/') . '/' . basename($downloadUrl); + + if (is_file($zipFilePathname) && !unlink($zipFilePathname)) { + throw new RuntimeException( + "Could not remove existing zip file $zipFilePathname", + self::ERR_REMOVE_EXISTING_ZIP_FILE + ); + } + + $zipFilePathname = Download::fileFromUrl($downloadUrl, $zipFilePathname); + $this->output->writeln('Downloaded Chromedriver to ' . $zipFilePathname); + + $executableFileName = $dir . '/' . $this->getExecutableFileName(); + + if (is_file($executableFileName) && !unlink($executableFileName)) { + throw new RuntimeException( + "Could not remove existing executable file $executableFileName", + self::ERR_REMOVE_EXISTING_BINARY + ); + } + + $extractedPath = Zip::extractTo($zipFilePathname, sys_get_temp_dir()); + + if (!rename( + "$extractedPath/chromedriver-$this->platform/" . $this->getExecutableFileName(), + $executableFileName + )) { + throw new RuntimeException( + "Could not move Chromedriver to $executableFileName", + self::ERR_MOVE_BINARY + ); + } + + if (chmod($executableFileName, 0755) === false) { + throw new RuntimeException( + "Could not make Chromedriver executable", + self::ERR_BINARY_CHMOD + ); + } + + $this->output->writeln("Installed Chromedriver to $executableFileName"); + + return $executableFileName; + } + + /** + * @throws RuntimeException + */ + private function detectVersion(): string + { + $chromeVersion = exec($this->binary . ' --version'); + if (!($chromeVersion && is_string($chromeVersion))) { + throw new RuntimeException( + "Could not detect Chrome version from $this->binary", + self::ERR_VERSION_NOT_STRING + ); + } + + return $chromeVersion; + } + + /** + * @throws RuntimeException + */ + private function detectPlatform(): string + { + // Return one of `linux64`, `mac-arm64`,`mac-x64`, `win32`, `win64`. + $system = php_uname('s'); + $arch = php_uname('m'); + + if ($system === 'Darwin') { + if ($arch === 'arm64') { + return 'mac-arm64'; + } + + return 'mac-x64'; + } + + if ($system === 'Linux') { + return 'linux64'; + } + + if ($system === 'Windows NT') { + if ($arch === 'x86_64') { + return 'win64'; + } + + return 'win32'; + } + + throw new RuntimeException('Failed to detect platform.', self::ERR_DETECT_PLATFORM); + } + + /** + * @return 'linux64'|'mac-x64'|'mac-arm64'|'win32'|'win64' + * + * @throws RuntimeException + */ + private function checkPlatform(mixed $platform): string + { + if (!(is_string($platform) && in_array($platform, [ + 'linux64', + 'mac-arm64', + 'mac-x64', + 'win32', + 'win64' + ]))) { + throw new RuntimeException( + 'Invalid platform, supported platforms are: linux64, mac-arm64, mac-x64, win32, win64.', + self::ERR_UNSUPPORTED_PLATFORM + ); + } + + /** @var 'linux64'|'mac-x64'|'mac-arm64'|'win32'|'win64' $platform */ + return $platform; + } + + /** + * @throws RuntimeException + */ + private function detectBinary(): string + { + return match ($this->platform) { + 'linux64' => '/usr/bin/google-chrome', + 'mac-x64', 'mac-arm64' => '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome', + 'win32', 'win64' => 'C:\\\\Program Files (x86)\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe' + }; + } + + private function checkBinary(mixed $binary): string + { + // Replace escaped spaces with spaces to check the binary. + if (!(is_string($binary) && is_executable(str_replace('\ ', ' ', $binary)))) { + throw new RuntimeException( + "Invalid Chrome binary: not executable or not existing.", + self::ERR_INVALID_BINARY + ); + } + + return $binary; + } + + private function checkVersion(mixed $version): string + { + $matches = []; + if (!(is_string($version) && preg_match('/^.*?(?\d+\.\d+\.\d+\.\d+)$/', $version, $matches))) { + throw new RuntimeException( + "Invalid Chrome version: must be in the form X.Y.Z.W.", + self::ERR_INVALID_VERSION_FORMAT + ); + } + + return $matches['version']; + } + + /** + * @throws JsonException + */ + private function fetchChromedriverVersionUrl(): string + { + $knownGoodVersionsWithDownloads = file_get_contents( + 'https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json' + ); + + if ($knownGoodVersionsWithDownloads === false) { + throw new RuntimeException( + 'Failed to fetch known good Chrome and Chromedriver versions with downloads.', + self::ERR_FETCH_KNOWN_GOOD_VERSIONS_WITH_DOWNLOADS + ); + } + + $decoded = json_decode($knownGoodVersionsWithDownloads, true, 512, JSON_THROW_ON_ERROR); + + if (!( + is_array($decoded) + && isset($decoded['versions']) + && is_array($decoded['versions']) + )) { + throw new RuntimeException( + 'Failed to decode known good Chrome and Chromedriver versions with downloads.', + self::ERR_DECODE_KNOWN_GOOD_VERSIONS_WITH_DOWNLOADS + ); + } + + foreach ($decoded['versions'] as $versionData) { + if (!( + is_array($versionData) + && isset($versionData['version'], $versionData['downloads']) + && $versionData['version'] === $this->version + && is_array($versionData['downloads']) + && isset($versionData['downloads']['chromedriver']) + && is_array($versionData['downloads']['chromedriver']) + )) { + continue; + } + + foreach ($versionData['downloads']['chromedriver'] as $chromedriverDownload) { + if (!( + is_array($chromedriverDownload) + && isset($chromedriverDownload['platform'], $chromedriverDownload['url']) + && $chromedriverDownload['platform'] === $this->platform + && is_string($chromedriverDownload['url']) + ) + ) { + continue; + } + + return $chromedriverDownload['url']; + } + + break; + } + + throw new RuntimeException( + 'Failed to find a download URL for Chromedriver version ' . $this->version, + self::ERR_DOWNLOAD_URL_NOT_FOUND + ); + } + + private function getExecutableFileName(): string + { + return match ($this->platform) { + 'linux64', 'mac-x64', 'mac-arm64' => 'chromedriver', + 'win32', 'win64' => 'chromedriver.exe' + }; + } + + public function getVersion(): string + { + return $this->version; + } + + public function getBinary(): string + { + return $this->binary; + } + + public function getPlatform(): string + { + return $this->platform; + } +} diff --git a/tests/_data/bins/chrome-mock b/tests/_data/bins/chrome-mock new file mode 100755 index 000000000..7c7d413c9 --- /dev/null +++ b/tests/_data/bins/chrome-mock @@ -0,0 +1,4 @@ +#! /usr/bin/env sh + +echo 'Google Chrome 116.0.5845.96' +exit 0 diff --git a/tests/_data/bins/chrome-version-not-string b/tests/_data/bins/chrome-version-not-string new file mode 100755 index 000000000..10af03b01 --- /dev/null +++ b/tests/_data/bins/chrome-version-not-string @@ -0,0 +1,3 @@ +#! /usr/bin/env sh + +exit 0 diff --git a/tests/_data/bins/chrome-version-wrong-format b/tests/_data/bins/chrome-version-wrong-format new file mode 100755 index 000000000..2d5741aa7 --- /dev/null +++ b/tests/_data/bins/chrome-version-wrong-format @@ -0,0 +1,4 @@ +#! /usr/bin/env sh + +echo 'Google Chrome 116.lorem.5845.96' +exit 0 diff --git a/tests/_support/_generated/UnitTesterActions.php b/tests/_support/_generated/UnitTesterActions.php index 031a3919f..79ffd76da 100644 --- a/tests/_support/_generated/UnitTesterActions.php +++ b/tests/_support/_generated/UnitTesterActions.php @@ -1,4 +1,4 @@ - [ 'plugin.php' => " $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); @@ -83,7 +87,7 @@ public function should_scaffold_for_plugin_with_plugin_php_file(): void 'wpbrowser', '--path=' . $projectDir . '/plugin_89' ]; - $process = new Process($command); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/plugin_89/vendor/bin']); $process->setInput( "yes\n" // Yes, use recommended setup. @@ -95,14 +99,12 @@ public function should_scaffold_for_plugin_with_plugin_php_file(): void FS::rrmdir($projectDir . '/plugin_89/tests/Support/_generated'); $this->assertFileExists($projectDir . '/plugin_89/vendor/bin/chromedriver'); - $this->assertFileExists($projectDir . '/plugin_89/composer.lock'); $this->assertFileExists($projectDir . '/plugin_89/tests/_wordpress/wp-config.php'); $this->assertFileExists($projectDir . '/plugin_89/tests/Support/Data/dump.sql'); // Remove generated or downloaded files that are not needed for the snapshot. FS::rrmdir($projectDir . '/plugin_89/tests/_wordpress'); FS::rrmdir($projectDir . '/plugin_89/vendor'); - unlink($projectDir . '/plugin_89/composer.lock'); unlink($projectDir . '/plugin_89/tests/Support/Data/dump.sql'); unlink($projectDir . '/plugin_89/composer'); @@ -130,7 +132,11 @@ public function should_scaffold_for_plugin_with_non_plugin_php_file(): void $projectDir = FS::tmpDir('setup_', [ 'plugin_89' => [ 'main-file.php' => " $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); @@ -143,7 +149,7 @@ public function should_scaffold_for_plugin_with_non_plugin_php_file(): void 'wpbrowser', '--path=' . $projectDir . '/plugin_89' ]; - $process = new Process($command, null); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/plugin_89/vendor/bin']); $process->setInput( "yes\n" // Yes, use recommended setup. @@ -155,7 +161,6 @@ public function should_scaffold_for_plugin_with_non_plugin_php_file(): void FS::rrmdir($projectDir . '/plugin_89/tests/Support/_generated'); $this->assertFileExists($projectDir . '/plugin_89/vendor/bin/chromedriver'); - $this->assertFileExists($projectDir . '/plugin_89/composer.lock'); $this->assertFileExists($projectDir . '/plugin_89/tests/_wordpress/wp-config.php'); $this->assertFileExists($projectDir . '/plugin_89/tests/Support/Data/dump.sql'); @@ -163,7 +168,6 @@ public function should_scaffold_for_plugin_with_non_plugin_php_file(): void FS::rrmdir($projectDir . '/plugin_89/tests/_wordpress'); FS::rrmdir($projectDir . '/plugin_89/vendor'); FS::rrmdir($projectDir . '/plugin_89/var'); - unlink($projectDir . '/plugin_89/composer.lock'); unlink($projectDir . '/plugin_89/tests/Support/Data/dump.sql'); unlink($projectDir . '/plugin_89/composer'); @@ -191,7 +195,11 @@ public function should_scaffold_for_plugin_with_plugin_php_file_custom(): void $projectDir = FS::tmpDir('setup_', [ 'plugin_89' => [ 'plugin.php' => " $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); @@ -202,7 +210,7 @@ public function should_scaffold_for_plugin_with_plugin_php_file_custom(): void 'wpbrowser', '--path=' . $projectDir . '/plugin_89' ]; - $process = new Process($command); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/plugin_89/vendor/bin']); $process->setInput( "no\n" // No, do not use recommended setup. @@ -237,7 +245,11 @@ public function should_scaffold_for_plugin_with_non_plugin_php_file_custom(): vo $projectDir = FS::tmpDir('setup_', [ 'plugin_89' => [ 'main.php' => " $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); @@ -248,7 +260,7 @@ public function should_scaffold_for_plugin_with_non_plugin_php_file_custom(): vo 'wpbrowser', '--path=' . $projectDir . '/plugin_89' ]; - $process = new Process($command); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/plugin_89/vendor/bin']); $process->setInput( "no\n" // No, do not use recommended setup. @@ -283,7 +295,11 @@ public function should_scaffold_for_theme_correctly(): void $projectDir = FS::tmpDir('setup_', [ 'theme_23' => [ 'style.css' => "/*\nTheme Name: Theme 23\n*/", - 'composer.json' => $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); @@ -296,7 +312,7 @@ public function should_scaffold_for_theme_correctly(): void 'wpbrowser', '--path=' . $projectDir . '/theme_23' ]; - $process = new Process($command); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/theme_23/vendor/bin']); $process->setInput( "yes\n" // Yes, use recommended setup. @@ -308,14 +324,12 @@ public function should_scaffold_for_theme_correctly(): void FS::rrmdir($projectDir . '/theme_23/tests/Support/_generated'); $this->assertFileExists($projectDir . '/theme_23/vendor/bin/chromedriver'); - $this->assertFileExists($projectDir . '/theme_23/composer.lock'); $this->assertFileExists($projectDir . '/theme_23/tests/_wordpress/wp-config.php'); $this->assertFileExists($projectDir . '/theme_23/tests/Support/Data/dump.sql'); // Remove generated or downloaded files that are not needed for the snapshot. FS::rrmdir($projectDir . '/theme_23/tests/_wordpress'); FS::rrmdir($projectDir . '/theme_23/vendor'); - unlink($projectDir . '/theme_23/composer.lock'); unlink($projectDir . '/theme_23/tests/Support/Data/dump.sql'); unlink($projectDir . '/theme_23/composer'); @@ -348,7 +362,11 @@ public function should_scaffold_for_child_theme_correctly(): void Template: twentytwenty */ EOT, - 'composer.json' => $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); @@ -361,7 +379,7 @@ public function should_scaffold_for_child_theme_correctly(): void 'wpbrowser', '--path=' . $projectDir . '/theme_23' ]; - $process = new Process($command); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/theme_23/vendor/bin']); $process->setInput( "yes\n" // Yes, use recommended setup. @@ -373,14 +391,12 @@ public function should_scaffold_for_child_theme_correctly(): void FS::rrmdir($projectDir . '/theme_23/tests/Support/_generated'); $this->assertFileExists($projectDir . '/theme_23/vendor/bin/chromedriver'); - $this->assertFileExists($projectDir . '/theme_23/composer.lock'); $this->assertFileExists($projectDir . '/theme_23/tests/_wordpress/wp-config.php'); $this->assertFileExists($projectDir . '/theme_23/tests/Support/Data/dump.sql'); // Remove generated or downloaded files that are not needed for the snapshot. FS::rrmdir($projectDir . '/theme_23/tests/_wordpress'); FS::rrmdir($projectDir . '/theme_23/vendor'); - unlink($projectDir . '/theme_23/composer.lock'); unlink($projectDir . '/theme_23/tests/Support/Data/dump.sql'); unlink($projectDir . '/theme_23/composer'); @@ -412,7 +428,11 @@ public function should_scaffold_for_theme_custom_correctly(): void Theme Name: Theme 23 */ EOT, - 'composer.json' => $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); @@ -425,7 +445,7 @@ public function should_scaffold_for_theme_custom_correctly(): void 'wpbrowser', '--path=' . $projectDir . '/theme_23' ]; - $process = new Process($command); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/theme_23/vendor/bin']); $process->setInput( "no\n" // No, do not use recommended setup. @@ -459,7 +479,11 @@ public function should_scaffold_for_single_site_correctly(): void $projectDir = FS::tmpDir('setup_', [ 'site' => [ - 'composer.json' => $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); $dbName = Random::dbName(); @@ -486,7 +510,7 @@ public function should_scaffold_for_single_site_correctly(): void 'wpbrowser', '--path=' . $projectDir . '/site' ]; - $process = new Process($command); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/site/vendor/bin']); $process->setInput( "yes\n" // Yes, use recommended setup. @@ -534,7 +558,11 @@ public function should_scaffold_for_multi_site_correctly(): void $projectDir = FS::tmpDir('setup_', [ 'site' => [ - 'composer.json' => $composerFileCode + 'composer.json' => $composerFileCode, + 'vendor' => [ + 'bin' => [ + ] + ], ] ]); $dbName = Random::dbName(); @@ -561,7 +589,7 @@ public function should_scaffold_for_multi_site_correctly(): void 'wpbrowser', '--path=' . $projectDir . '/site' ]; - $process = new Process($command); + $process = new Process($command, null, ['COMPOSER_BIN_DIR' => $projectDir . '/site/vendor/bin']); $process->setInput( "yes\n" // Yes, use recommended setup. @@ -632,8 +660,11 @@ public function should_scaffold_correctly_on_site_with_non_default_structure(): $process->mustRun(); + // Remove some hashed files. + FS::rrmdir($projectDir . '/tests/Support/_generated'); + // Random ports will change: visit the data to replace the random ports with a placeholder. - $this->assertMatchesDirectorySnapshot($projectDir. '/tests', + $this->assertMatchesDirectorySnapshot($projectDir . '/tests', fn() => $this->replaceRandomPorts(...func_get_args())); } } diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_correctly_on_site_with_non_default_structure__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_correctly_on_site_with_non_default_structure__0.snapshot index 4419b2bb0..1c0a7c29f 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_correctly_on_site_with_non_default_structure__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_correctly_on_site_with_non_default_structure__0.snapshot @@ -198,9874 +198,6 @@ class IntegrationTester extends \Codeception\Actor <<< /Support/IntegrationTester.php <<< ->>> /Support/_generated/EndToEndTesterActions.php >>> -loginAsAdmin(); - * $I->amOnAdminPage('/'); - * $I->see('Dashboard'); - * ``` - * - * @param int $timeout The max time, in seconds, to try to login. - * @param int $maxAttempts The max number of attempts to try to login. - * - * - * @throws ModuleException If all the attempts of obtaining the cookie fail. - * @see \lucatume\WPBrowser\Module\WPWebDriver::loginAsAdmin() - */ - public function loginAsAdmin(int $timeout = 10, int $maxAttempts = 5): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('loginAsAdmin', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Login as the specified user. - * - * The method will **not** follow redirection, after the login, to any page. - * Depending on the driven browser the login might be "too fast" and the server might have not - * replied with valid cookies yet; in that case the method will re-attempt the login to obtain - * the cookies. - * - * @example - * ```php - * $I->loginAs('user', 'password'); - * $I->amOnAdminPage('/'); - * $I->see('Dashboard'); - * ``` - * - * @param string $username The user login name. - * @param string $password The user password in plain text. - * @param int $timeout The max time, in seconds, to try to login. - * @param int $maxAttempts The max number of attempts to try to login. - * - * @throws ModuleException If all the attempts of obtaining the cookie fail. - * - * @see \lucatume\WPBrowser\Module\WPWebDriver::loginAs() - */ - public function loginAs(string $username, string $password, int $timeout = 10, int $maxAttempts = 5): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('loginAs', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Returns all the cookies whose name matches a regex pattern. - * - * @example - * ```php - * $I->loginAs('customer','password'); - * $I->amOnPage('/shop'); - * $cartCookies = $I->grabCookiesWithPattern("#^shop_cart\\.*#"); - * ``` - * - * @param string $cookiePattern The regular expression pattern to use for the matching. - * - * @return array|null An array of cookies matching the pattern. - * @see \lucatume\WPBrowser\Module\WPWebDriver::grabCookiesWithPattern() - */ - public function grabCookiesWithPattern(string $cookiePattern): ?array { - return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookiesWithPattern', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Waits for any jQuery triggered AJAX request to be resolved. - * - * @example - * ```php - * $I->amOnPage('/triggering-ajax-requests'); - * $I->waitForJqueryAjax(); - * $I->see('From AJAX'); - * ``` - * - * @param int $time The max time to wait for AJAX requests to complete. - * @see \lucatume\WPBrowser\Module\WPWebDriver::waitForJqueryAjax() - */ - public function waitForJqueryAjax(int $time = 10): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('waitForJqueryAjax', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Grabs the current page full URL including the query vars. - * - * @example - * ```php - * $today = date('Y-m-d'); - * $I->amOnPage('/concerts?date=' . $today); - * $I->assertRegExp('#\\/concerts$#', $I->grabFullUrl()); - * ``` - * - * @return string The full page URL. - * @throws ModuleException - * @see \lucatume\WPBrowser\Module\WPWebDriver::grabFullUrl() - */ - public function grabFullUrl(): string { - return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFullUrl', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * In the plugin administration screen deactivate a plugin clicking the "Deactivate" link. - * - * The method will **not** handle authentication and navigation to the plugins administration page. - * - * @example - * ```php - * // Deactivate one plugin. - * $I->loginAsAdmin(); - * $I->amOnPluginsPage(); - * $I->deactivatePlugin('hello-dolly'); - * // Deactivate a list of plugins. - * $I->loginAsAdmin(); - * $I->amOnPluginsPage(); - * $I->deactivatePlugin(['hello-dolly', 'my-plugin']); - * ``` - * - * @param string|array $pluginSlug The plugin slug, like "hello-dolly", or a list of plugin slugs. - * - * - * @throws JsonException If there's an issue encoding the debug message. - * @see \lucatume\WPBrowser\Module\WPWebDriver::deactivatePlugin() - */ - public function deactivatePlugin(array|string $pluginSlug): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('deactivatePlugin', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * In the plugin administration screen activates one or more plugins clicking the "Activate" link. - * - * The method will **not** handle authentication and navigation to the plugins administration page. - * - * @example - * ```php - * // Activate a plugin. - * $I->loginAsAdmin(); - * $I->amOnPluginsPage(); - * $I->activatePlugin('hello-dolly'); - * // Activate a list of plugins. - * $I->loginAsAdmin(); - * $I->amOnPluginsPage(); - * $I->activatePlugin(['hello-dolly','another-plugin']); - * ``` - * - * @param string|array $pluginSlug The plugin slug, like "hello-dolly" or a list of plugin slugs. - * - * - * @throws JsonException If there's an issue encoding the debug message. - * @see \lucatume\WPBrowser\Module\WPWebDriver::activatePlugin() - */ - public function activatePlugin(array|string $pluginSlug): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('activatePlugin', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Print out latest Selenium Logs in debug mode - * @see \Codeception\Module\WebDriver::debugWebDriverLogs() - */ - public function debugWebDriverLogs(?\Codeception\TestInterface $test = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('debugWebDriverLogs', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Changes the subdomain for the 'url' configuration parameter. - * Does not open a page; use `amOnPage` for that. - * - * ``` php - * amOnSubdomain('user'); - * $I->amOnPage('/'); - * // moves to https://user.mysite.com/ - * ``` - * - * @see \Codeception\Module\WebDriver::amOnSubdomain() - */ - public function amOnSubdomain(string $subdomain): void { - $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnSubdomain', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Takes a screenshot of the current window and saves it to `tests/_output/debug`. - * - * ``` php - * amOnPage('/user/edit'); - * $I->makeScreenshot('edit_page'); - * // saved to: tests/_output/debug/edit_page.png - * $I->makeScreenshot(); - * // saved to: tests/_output/debug/2017-05-26_14-24-11_4b3403665fea6.png - * ``` - * @see \Codeception\Module\WebDriver::makeScreenshot() - */ - public function makeScreenshot(?string $name = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('makeScreenshot', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Takes a screenshot of an element of the current window and saves it to `tests/_output/debug`. - * - * ``` php - * amOnPage('/user/edit'); - * $I->makeElementScreenshot('#dialog', 'edit_page'); - * // saved to: tests/_output/debug/edit_page.png - * $I->makeElementScreenshot('#dialog'); - * // saved to: tests/_output/debug/2017-05-26_14-24-11_4b3403665fea6.png - * ``` - * - * @param WebDriverBy|array $selector - * @see \Codeception\Module\WebDriver::makeElementScreenshot() - */ - public function makeElementScreenshot($selector, ?string $name = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('makeElementScreenshot', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Use this method within an [interactive pause](https://codeception.com/docs/02-GettingStarted#Interactive-Pause) to save the HTML source code of the current page. - * - * ```php - * makeHtmlSnapshot('edit_page'); - * // saved to: tests/_output/debug/edit_page.html - * $I->makeHtmlSnapshot(); - * // saved to: tests/_output/debug/2017-05-26_14-24-11_4b3403665fea6.html - * ``` - * @see \Codeception\Module\WebDriver::makeHtmlSnapshot() - */ - public function makeHtmlSnapshot(?string $name = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('makeHtmlSnapshot', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Resize the current window. - * - * ``` php - * resizeWindow(800, 600); - * - * ``` - * @see \Codeception\Module\WebDriver::resizeWindow() - */ - public function resizeWindow(int $width, int $height): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('resizeWindow', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that a cookie with the given name is set. - * You can set additional cookie params like `domain`, `path` as array passed in last argument. - * - * ``` php - * seeCookie('PHPSESSID'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::seeCookie() - */ - public function seeCookie($cookie, array $params = [], bool $showDebug = true): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCookie', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that a cookie with the given name is set. - * You can set additional cookie params like `domain`, `path` as array passed in last argument. - * - * ``` php - * seeCookie('PHPSESSID'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::seeCookie() - */ - public function canSeeCookie($cookie, array $params = [], bool $showDebug = true): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCookie', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that there isn't a cookie with the given name. - * You can set additional cookie params like `domain`, `path` as array passed in last argument. - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::dontSeeCookie() - */ - public function dontSeeCookie($cookie, array $params = [], bool $showDebug = true): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeCookie', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that there isn't a cookie with the given name. - * You can set additional cookie params like `domain`, `path` as array passed in last argument. - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::dontSeeCookie() - */ - public function cantSeeCookie($cookie, array $params = [], bool $showDebug = true): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCookie', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Sets a cookie with the given name and value. - * You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. - * - * ``` php - * setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::setCookie() - */ - public function setCookie($name, $value, array $params = [], $showDebug = true): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('setCookie', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Unsets cookie with the given name. - * You can set additional cookie params like `domain`, `path` in array passed as last argument. - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::resetCookie() - */ - public function resetCookie($cookie, array $params = [], bool $showDebug = true): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('resetCookie', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Grabs a cookie value. - * You can set additional cookie params like `domain`, `path` in array passed as last argument. - * If the cookie is set by an ajax request (XMLHttpRequest), there might be some delay caused by the browser, so try `$I->wait(0.1)`. - * @see \Codeception\Module\WebDriver::grabCookie() - */ - public function grabCookie($cookie, array $params = []): mixed { - return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookie', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Grabs current page source code. - * - * @throws ModuleException if no page was opened. - * @return string Current page source code. - * @see \Codeception\Module\WebDriver::grabPageSource() - */ - public function grabPageSource(): string { - return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPageSource', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Open web page at the given absolute URL and sets its hostname as the base host. - * - * ``` php - * amOnUrl('https://codeception.com'); - * $I->amOnPage('/quickstart'); // moves to https://codeception.com/quickstart - * ``` - * @see \Codeception\Module\WebDriver::amOnUrl() - */ - public function amOnUrl($url): void { - $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnUrl', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Opens the page for the given relative URI. - * - * ``` php - * amOnPage('/'); - * // opens /register page - * $I->amOnPage('/register'); - * ``` - * @see \Codeception\Module\WebDriver::amOnPage() - */ - public function amOnPage($page): void { - $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnPage', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the current page contains the given string (case insensitive). - * - * You can specify a specific HTML element (via CSS or XPath) as the second - * parameter to only search within that element. - * - * ``` php - * see('Logout'); // I can suppose user is logged in - * $I->see('Sign Up', 'h1'); // I can suppose it's a signup page - * $I->see('Sign Up', '//body/h1'); // with XPath - * $I->see('Sign Up', ['css' => 'body h1']); // with strict CSS locator - * ``` - * - * Note that the search is done after stripping all HTML tags from the body, - * so `$I->see('strong')` will return true for strings like: - * - * - `

I am Stronger than thou

` - * - `` - * - * But will *not* be true for strings like: - * - * - `Home` - * - `
Home` - * - `` - * - * For checking the raw source code, use `seeInSource()`. - * - * @param array|string $selector optional - * @see \Codeception\Module\WebDriver::see() - */ - public function see($text, $selector = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('see', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the current page contains the given string (case insensitive). - * - * You can specify a specific HTML element (via CSS or XPath) as the second - * parameter to only search within that element. - * - * ``` php - * see('Logout'); // I can suppose user is logged in - * $I->see('Sign Up', 'h1'); // I can suppose it's a signup page - * $I->see('Sign Up', '//body/h1'); // with XPath - * $I->see('Sign Up', ['css' => 'body h1']); // with strict CSS locator - * ``` - * - * Note that the search is done after stripping all HTML tags from the body, - * so `$I->see('strong')` will return true for strings like: - * - * - `

I am Stronger than thou

` - * - `` - * - * But will *not* be true for strings like: - * - * - `Home` - * - `
Home` - * - `` - * - * For checking the raw source code, use `seeInSource()`. - * - * @param array|string $selector optional - * @see \Codeception\Module\WebDriver::see() - */ - public function canSee($text, $selector = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('see', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the current page doesn't contain the text specified (case insensitive). - * Give a locator as the second parameter to match a specific region. - * - * ```php - * dontSee('Login'); // I can suppose user is already logged in - * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page - * $I->dontSee('Sign Up','//body/h1'); // with XPath - * $I->dontSee('Sign Up', ['css' => 'body h1']); // with strict CSS locator - * ``` - * - * Note that the search is done after stripping all HTML tags from the body, - * so `$I->dontSee('strong')` will fail on strings like: - * - * - `

I am Stronger than thou

` - * - `` - * - * But will ignore strings like: - * - * - `Home` - * - `
Home` - * - `` - * - * For checking the raw source code, use `seeInSource()`. - * - * @param array|string $selector optional - * @see \Codeception\Module\WebDriver::dontSee() - */ - public function dontSee($text, $selector = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSee', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the current page doesn't contain the text specified (case insensitive). - * Give a locator as the second parameter to match a specific region. - * - * ```php - * dontSee('Login'); // I can suppose user is already logged in - * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page - * $I->dontSee('Sign Up','//body/h1'); // with XPath - * $I->dontSee('Sign Up', ['css' => 'body h1']); // with strict CSS locator - * ``` - * - * Note that the search is done after stripping all HTML tags from the body, - * so `$I->dontSee('strong')` will fail on strings like: - * - * - `

I am Stronger than thou

` - * - `` - * - * But will ignore strings like: - * - * - `Home` - * - `
Home` - * - `` - * - * For checking the raw source code, use `seeInSource()`. - * - * @param array|string $selector optional - * @see \Codeception\Module\WebDriver::dontSee() - */ - public function cantSee($text, $selector = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSee', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the current page contains the given string in its - * raw source code. - * - * ``` php - * seeInSource('

Green eggs & ham

'); - * ``` - * @see \Codeception\Module\WebDriver::seeInSource() - */ - public function seeInSource($raw): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInSource', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the current page contains the given string in its - * raw source code. - * - * ``` php - * seeInSource('

Green eggs & ham

'); - * ``` - * @see \Codeception\Module\WebDriver::seeInSource() - */ - public function canSeeInSource($raw): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInSource', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the current page contains the given string in its - * raw source code. - * - * ```php - * dontSeeInSource('

Green eggs & ham

'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeInSource() - */ - public function dontSeeInSource($raw): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInSource', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the current page contains the given string in its - * raw source code. - * - * ```php - * dontSeeInSource('

Green eggs & ham

'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeInSource() - */ - public function cantSeeInSource($raw): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInSource', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the page source contains the given string. - * - * ```php - * seeInPageSource('getScenario()->runStep(new \Codeception\Step\Assertion('seeInPageSource', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the page source contains the given string. - * - * ```php - * seeInPageSource('getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInPageSource', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the page source doesn't contain the given string. - * @see \Codeception\Module\WebDriver::dontSeeInPageSource() - */ - public function dontSeeInPageSource(string $text): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInPageSource', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the page source doesn't contain the given string. - * @see \Codeception\Module\WebDriver::dontSeeInPageSource() - */ - public function cantSeeInPageSource(string $text): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInPageSource', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Perform a click on a link or a button, given by a locator. - * If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. - * For buttons, the "value" attribute, "name" attribute, and inner text are searched. - * For links, the link text is searched. - * For images, the "alt" attribute and inner text of any parent links are searched. - * - * The second parameter is a context (CSS or XPath locator) to narrow the search. - * - * Note that if the locator matches a button of type `submit`, the form will be submitted. - * - * ``` php - * click('Logout'); - * // button of form - * $I->click('Submit'); - * // CSS button - * $I->click('#form input[type=submit]'); - * // XPath - * $I->click('//form/*[@type="submit"]'); - * // link in context - * $I->click('Logout', '#nav'); - * // using strict locator - * $I->click(['link' => 'Login']); - * ``` - * @param string|array $link - * @see \Codeception\Module\WebDriver::click() - */ - public function click($link, $context = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('click', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that there's a link with the specified text. - * Give a full URL as the second parameter to match links with that exact URL. - * - * ``` php - * seeLink('Logout'); // matches Logout - * $I->seeLink('Logout','/logout'); // matches Logout - * ``` - * @see \Codeception\Module\WebDriver::seeLink() - */ - public function seeLink(string $text, ?string $url = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeLink', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that there's a link with the specified text. - * Give a full URL as the second parameter to match links with that exact URL. - * - * ``` php - * seeLink('Logout'); // matches Logout - * $I->seeLink('Logout','/logout'); // matches Logout - * ``` - * @see \Codeception\Module\WebDriver::seeLink() - */ - public function canSeeLink(string $text, ?string $url = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeLink', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the page doesn't contain a link with the given string. - * If the second parameter is given, only links with a matching "href" attribute will be checked. - * - * ``` php - * dontSeeLink('Logout'); // I suppose user is not logged in - * $I->dontSeeLink('Checkout now', '/store/cart.php'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeLink() - */ - public function dontSeeLink(string $text, string $url = ""): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeLink', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the page doesn't contain a link with the given string. - * If the second parameter is given, only links with a matching "href" attribute will be checked. - * - * ``` php - * dontSeeLink('Logout'); // I suppose user is not logged in - * $I->dontSeeLink('Checkout now', '/store/cart.php'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeLink() - */ - public function cantSeeLink(string $text, string $url = ""): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeLink', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that current URI contains the given string. - * - * ``` php - * seeInCurrentUrl('home'); - * // to match: /users/1 - * $I->seeInCurrentUrl('/users/'); - * ``` - * @see \Codeception\Module\WebDriver::seeInCurrentUrl() - */ - public function seeInCurrentUrl(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInCurrentUrl', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that current URI contains the given string. - * - * ``` php - * seeInCurrentUrl('home'); - * // to match: /users/1 - * $I->seeInCurrentUrl('/users/'); - * ``` - * @see \Codeception\Module\WebDriver::seeInCurrentUrl() - */ - public function canSeeInCurrentUrl(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInCurrentUrl', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the current URL is equal to the given string. - * Unlike `seeInCurrentUrl`, this only matches the full URL. - * - * ``` php - * seeCurrentUrlEquals('/'); - * ``` - * @see \Codeception\Module\WebDriver::seeCurrentUrlEquals() - */ - public function seeCurrentUrlEquals(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentUrlEquals', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the current URL is equal to the given string. - * Unlike `seeInCurrentUrl`, this only matches the full URL. - * - * ``` php - * seeCurrentUrlEquals('/'); - * ``` - * @see \Codeception\Module\WebDriver::seeCurrentUrlEquals() - */ - public function canSeeCurrentUrlEquals(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlEquals', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the current URL matches the given regular expression. - * - * ``` php - * seeCurrentUrlMatches('~^/users/(\d+)~'); - * ``` - * @see \Codeception\Module\WebDriver::seeCurrentUrlMatches() - */ - public function seeCurrentUrlMatches(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentUrlMatches', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the current URL matches the given regular expression. - * - * ``` php - * seeCurrentUrlMatches('~^/users/(\d+)~'); - * ``` - * @see \Codeception\Module\WebDriver::seeCurrentUrlMatches() - */ - public function canSeeCurrentUrlMatches(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlMatches', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the current URI doesn't contain the given string. - * - * ``` php - * dontSeeInCurrentUrl('/users/'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeInCurrentUrl() - */ - public function dontSeeInCurrentUrl(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInCurrentUrl', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the current URI doesn't contain the given string. - * - * ``` php - * dontSeeInCurrentUrl('/users/'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeInCurrentUrl() - */ - public function cantSeeInCurrentUrl(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInCurrentUrl', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the current URL doesn't equal the given string. - * Unlike `dontSeeInCurrentUrl`, this only matches the full URL. - * - * ``` php - * dontSeeCurrentUrlEquals('/'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeCurrentUrlEquals() - */ - public function dontSeeCurrentUrlEquals(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeCurrentUrlEquals', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the current URL doesn't equal the given string. - * Unlike `dontSeeInCurrentUrl`, this only matches the full URL. - * - * ``` php - * dontSeeCurrentUrlEquals('/'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeCurrentUrlEquals() - */ - public function cantSeeCurrentUrlEquals(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlEquals', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that current url doesn't match the given regular expression. - * - * ``` php - * dontSeeCurrentUrlMatches('~^/users/(\d+)~'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeCurrentUrlMatches() - */ - public function dontSeeCurrentUrlMatches(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeCurrentUrlMatches', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that current url doesn't match the given regular expression. - * - * ``` php - * dontSeeCurrentUrlMatches('~^/users/(\d+)~'); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeCurrentUrlMatches() - */ - public function cantSeeCurrentUrlMatches(string $uri): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlMatches', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Executes the given regular expression against the current URI and returns the first capturing group. - * If no parameters are provided, the full URI is returned. - * - * ``` php - * grabFromCurrentUrl('~^/user/(\d+)/~'); - * $uri = $I->grabFromCurrentUrl(); - * ``` - * @see \Codeception\Module\WebDriver::grabFromCurrentUrl() - */ - public function grabFromCurrentUrl($uri = NULL): mixed { - return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFromCurrentUrl', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the specified checkbox is checked. - * - * ``` php - * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms - * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. - * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); - * ``` - * @see \Codeception\Module\WebDriver::seeCheckboxIsChecked() - */ - public function seeCheckboxIsChecked($checkbox): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCheckboxIsChecked', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the specified checkbox is checked. - * - * ``` php - * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms - * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. - * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); - * ``` - * @see \Codeception\Module\WebDriver::seeCheckboxIsChecked() - */ - public function canSeeCheckboxIsChecked($checkbox): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCheckboxIsChecked', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Check that the specified checkbox is unchecked. - * - * ``` php - * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms - * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. - * ``` - * @see \Codeception\Module\WebDriver::dontSeeCheckboxIsChecked() - */ - public function dontSeeCheckboxIsChecked($checkbox): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeCheckboxIsChecked', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Check that the specified checkbox is unchecked. - * - * ``` php - * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms - * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. - * ``` - * @see \Codeception\Module\WebDriver::dontSeeCheckboxIsChecked() - */ - public function cantSeeCheckboxIsChecked($checkbox): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCheckboxIsChecked', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. - * Fields are matched by label text, the "name" attribute, CSS, or XPath. - * - * ``` php - * seeInField('Body','Type your comment here'); - * $I->seeInField('form textarea[name=body]','Type your comment here'); - * $I->seeInField('form input[type=hidden]','hidden_value'); - * $I->seeInField('#searchform input','Search'); - * $I->seeInField('//form/*[@name=search]','Search'); - * $I->seeInField(['name' => 'search'], 'Search'); - * ``` - * - * @param string|array $field - * @see \Codeception\Module\WebDriver::seeInField() - */ - public function seeInField($field, $value): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInField', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the given input field or textarea *equals* (i.e. not just contains) the given value. - * Fields are matched by label text, the "name" attribute, CSS, or XPath. - * - * ``` php - * seeInField('Body','Type your comment here'); - * $I->seeInField('form textarea[name=body]','Type your comment here'); - * $I->seeInField('form input[type=hidden]','hidden_value'); - * $I->seeInField('#searchform input','Search'); - * $I->seeInField('//form/*[@name=search]','Search'); - * $I->seeInField(['name' => 'search'], 'Search'); - * ``` - * - * @param string|array $field - * @see \Codeception\Module\WebDriver::seeInField() - */ - public function canSeeInField($field, $value): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInField', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that an input field or textarea doesn't contain the given value. - * For fuzzy locators, the field is matched by label text, CSS and XPath. - * - * ``` php - * dontSeeInField('Body','Type your comment here'); - * $I->dontSeeInField('form textarea[name=body]','Type your comment here'); - * $I->dontSeeInField('form input[type=hidden]','hidden_value'); - * $I->dontSeeInField('#searchform input','Search'); - * $I->dontSeeInField('//form/*[@name=search]','Search'); - * $I->dontSeeInField(['name' => 'search'], 'Search'); - * ``` - * @param string|array $field - * @see \Codeception\Module\WebDriver::dontSeeInField() - */ - public function dontSeeInField($field, $value): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInField', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that an input field or textarea doesn't contain the given value. - * For fuzzy locators, the field is matched by label text, CSS and XPath. - * - * ``` php - * dontSeeInField('Body','Type your comment here'); - * $I->dontSeeInField('form textarea[name=body]','Type your comment here'); - * $I->dontSeeInField('form input[type=hidden]','hidden_value'); - * $I->dontSeeInField('#searchform input','Search'); - * $I->dontSeeInField('//form/*[@name=search]','Search'); - * $I->dontSeeInField(['name' => 'search'], 'Search'); - * ``` - * @param string|array $field - * @see \Codeception\Module\WebDriver::dontSeeInField() - */ - public function cantSeeInField($field, $value): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInField', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks if the array of form parameters (name => value) are set on the form matched with the - * passed selector. - * - * ``` php - * seeInFormFields('form[name=myform]', [ - * 'input1' => 'value', - * 'input2' => 'other value', - * ]); - * ``` - * - * For multi-select elements, or to check values of multiple elements with the same name, an - * array may be passed: - * - * ``` php - * seeInFormFields('.form-class', [ - * 'multiselect' => [ - * 'value1', - * 'value2', - * ], - * 'checkbox[]' => [ - * 'a checked value', - * 'another checked value', - * ], - * ]); - * ``` - * - * Additionally, checkbox values can be checked with a boolean. - * - * ``` php - * seeInFormFields('#form-id', [ - * 'checkbox1' => true, // passes if checked - * 'checkbox2' => false, // passes if unchecked - * ]); - * ``` - * - * Pair this with submitForm for quick testing magic. - * - * ``` php - * 'value', - * 'field2' => 'another value', - * 'checkbox1' => true, - * // ... - * ]; - * $I->submitForm('//form[@id=my-form]', string $form, 'submitButton'); - * // $I->amOnPage('/path/to/form-page') may be needed - * $I->seeInFormFields('//form[@id=my-form]', string $form); - * ``` - * @see \Codeception\Module\WebDriver::seeInFormFields() - */ - public function seeInFormFields($formSelector, array $params): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInFormFields', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks if the array of form parameters (name => value) are set on the form matched with the - * passed selector. - * - * ``` php - * seeInFormFields('form[name=myform]', [ - * 'input1' => 'value', - * 'input2' => 'other value', - * ]); - * ``` - * - * For multi-select elements, or to check values of multiple elements with the same name, an - * array may be passed: - * - * ``` php - * seeInFormFields('.form-class', [ - * 'multiselect' => [ - * 'value1', - * 'value2', - * ], - * 'checkbox[]' => [ - * 'a checked value', - * 'another checked value', - * ], - * ]); - * ``` - * - * Additionally, checkbox values can be checked with a boolean. - * - * ``` php - * seeInFormFields('#form-id', [ - * 'checkbox1' => true, // passes if checked - * 'checkbox2' => false, // passes if unchecked - * ]); - * ``` - * - * Pair this with submitForm for quick testing magic. - * - * ``` php - * 'value', - * 'field2' => 'another value', - * 'checkbox1' => true, - * // ... - * ]; - * $I->submitForm('//form[@id=my-form]', string $form, 'submitButton'); - * // $I->amOnPage('/path/to/form-page') may be needed - * $I->seeInFormFields('//form[@id=my-form]', string $form); - * ``` - * @see \Codeception\Module\WebDriver::seeInFormFields() - */ - public function canSeeInFormFields($formSelector, array $params): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInFormFields', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks if the array of form parameters (name => value) are not set on the form matched with - * the passed selector. - * - * ``` php - * dontSeeInFormFields('form[name=myform]', [ - * 'input1' => 'non-existent value', - * 'input2' => 'other non-existent value', - * ]); - * ``` - * - * To check that an element hasn't been assigned any one of many values, an array can be passed - * as the value: - * - * ``` php - * dontSeeInFormFields('.form-class', [ - * 'fieldName' => [ - * 'This value shouldn\'t be set', - * 'And this value shouldn\'t be set', - * ], - * ]); - * ``` - * - * Additionally, checkbox values can be checked with a boolean. - * - * ``` php - * dontSeeInFormFields('#form-id', [ - * 'checkbox1' => true, // fails if checked - * 'checkbox2' => false, // fails if unchecked - * ]); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeInFormFields() - */ - public function dontSeeInFormFields($formSelector, array $params): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInFormFields', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks if the array of form parameters (name => value) are not set on the form matched with - * the passed selector. - * - * ``` php - * dontSeeInFormFields('form[name=myform]', [ - * 'input1' => 'non-existent value', - * 'input2' => 'other non-existent value', - * ]); - * ``` - * - * To check that an element hasn't been assigned any one of many values, an array can be passed - * as the value: - * - * ``` php - * dontSeeInFormFields('.form-class', [ - * 'fieldName' => [ - * 'This value shouldn\'t be set', - * 'And this value shouldn\'t be set', - * ], - * ]); - * ``` - * - * Additionally, checkbox values can be checked with a boolean. - * - * ``` php - * dontSeeInFormFields('#form-id', [ - * 'checkbox1' => true, // fails if checked - * 'checkbox2' => false, // fails if unchecked - * ]); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeInFormFields() - */ - public function cantSeeInFormFields($formSelector, array $params): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInFormFields', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Selects an option in a select tag or in radio button group. - * - * ``` php - * selectOption('form select[name=account]', 'Premium'); - * $I->selectOption('form input[name=payment]', 'Monthly'); - * $I->selectOption('//form/select[@name=account]', 'Monthly'); - * ``` - * - * Provide an array for the second argument to select multiple options: - * - * ``` php - * selectOption('Which OS do you use?', array('Windows','Linux')); - * ``` - * - * Or provide an associative array for the second argument to specifically define which selection method should be used: - * - * ``` php - * selectOption('Which OS do you use?', array('text' => 'Windows')); // Only search by text 'Windows' - * $I->selectOption('Which OS do you use?', array('value' => 'windows')); // Only search by value 'windows' - * ``` - * @see \Codeception\Module\WebDriver::selectOption() - */ - public function selectOption($select, $option): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('selectOption', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Unselect an option in the given select box. - * - * @param string|array|WebDriverBy $select - * @param string|array|WebDriverBy $option - * @see \Codeception\Module\WebDriver::unselectOption() - */ - public function unselectOption($select, $option): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('unselectOption', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Ticks a checkbox. For radio buttons, use the `selectOption` method instead. - * - * ``` php - * checkOption('#agree'); - * ``` - * @see \Codeception\Module\WebDriver::checkOption() - */ - public function checkOption($option): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('checkOption', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Unticks a checkbox. - * - * ``` php - * uncheckOption('#notify'); - * ``` - * @see \Codeception\Module\WebDriver::uncheckOption() - */ - public function uncheckOption($option): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('uncheckOption', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Fills a text field or textarea with the given string. - * - * ``` php - * fillField("//input[@type='text']", "Hello World!"); - * $I->fillField(['name' => 'email'], 'jon@example.com'); - * ``` - * @see \Codeception\Module\WebDriver::fillField() - */ - public function fillField($field, $value): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('fillField', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Clears given field which isn't empty. - * - * ``` php - * clearField('#username'); - * ``` - * - * @param string|array|WebDriverBy $field - * @see \Codeception\Module\WebDriver::clearField() - */ - public function clearField($field): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('clearField', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Type in characters on active element. - * With a second parameter you can specify delay between key presses. - * - * ```php - * click('#input'); - * - * // type text in active element - * $I->type('Hello world'); - * - * // type text with a 1sec delay between chars - * $I->type('Hello World', 1); - * ``` - * - * This might be useful when you an input reacts to typing and you need to slow it down to emulate human behavior. - * For instance, this is how Credit Card fields can be filled in. - * - * @param int $delay [sec] - * @see \Codeception\Module\WebDriver::type() - */ - public function type(string $text, int $delay = 0): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('type', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Attaches a file relative to the Codeception `_data` directory to the given file upload field. - * - * ``` php - * attachFile('input[@type="file"]', 'prices.xls'); - * ``` - * @see \Codeception\Module\WebDriver::attachFile() - */ - public function attachFile($field, string $filename): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('attachFile', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Finds and returns the text contents of the given element. - * If a fuzzy locator is used, the element is found using CSS, XPath, - * and by matching the full page source by regular expression. - * - * ``` php - * grabTextFrom('h1'); - * $heading = $I->grabTextFrom('descendant-or-self::h1'); - * $value = $I->grabTextFrom('~getScenario()->runStep(new \Codeception\Step\Action('grabTextFrom', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Grabs the value of the given attribute value from the given element. - * Fails if element is not found. - * - * ``` php - * grabAttributeFrom('#tooltip', 'title'); - * ``` - * @see \Codeception\Module\WebDriver::grabAttributeFrom() - */ - public function grabAttributeFrom($cssOrXpath, $attribute): ?string { - return $this->getScenario()->runStep(new \Codeception\Step\Action('grabAttributeFrom', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Finds the value for the given form field. - * If a fuzzy locator is used, the field is found by field name, CSS, and XPath. - * - * ``` php - * grabValueFrom('Name'); - * $name = $I->grabValueFrom('input[name=username]'); - * $name = $I->grabValueFrom('descendant-or-self::form/descendant::input[@name = 'username']'); - * $name = $I->grabValueFrom(['name' => 'username']); - * ``` - * @see \Codeception\Module\WebDriver::grabValueFrom() - */ - public function grabValueFrom($field): ?string { - return $this->getScenario()->runStep(new \Codeception\Step\Action('grabValueFrom', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Grabs either the text content, or attribute values, of nodes - * matched by $cssOrXpath and returns them as an array. - * - * ```html - * First - * Second - * Third - * ``` - * - * ```php - * grabMultiple('a'); - * - * // would return ['#first', '#second', '#third'] - * $aLinks = $I->grabMultiple('a', 'href'); - * ``` - * - * @return string[] - * @see \Codeception\Module\WebDriver::grabMultiple() - */ - public function grabMultiple($cssOrXpath, $attribute = NULL): array { - return $this->getScenario()->runStep(new \Codeception\Step\Action('grabMultiple', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the given element exists on the page and is visible. - * You can also specify expected attributes of this element. - * Only works if `` tag is present. - * - * ``` php - * seeElement('.error'); - * $I->seeElement('//form/input[1]'); - * $I->seeElement('input', ['name' => 'login']); - * $I->seeElement('input', ['value' => '123456']); - * - * // strict locator in first arg, attributes in second - * $I->seeElement(['css' => 'form input'], ['name' => 'login']); - * ``` - * @see \Codeception\Module\WebDriver::seeElement() - */ - public function seeElement($selector, array $attributes = []): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeElement', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the given element exists on the page and is visible. - * You can also specify expected attributes of this element. - * Only works if `` tag is present. - * - * ``` php - * seeElement('.error'); - * $I->seeElement('//form/input[1]'); - * $I->seeElement('input', ['name' => 'login']); - * $I->seeElement('input', ['value' => '123456']); - * - * // strict locator in first arg, attributes in second - * $I->seeElement(['css' => 'form input'], ['name' => 'login']); - * ``` - * @see \Codeception\Module\WebDriver::seeElement() - */ - public function canSeeElement($selector, array $attributes = []): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeElement', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the given element is invisible or not present on the page. - * You can also specify expected attributes of this element. - * - * ``` php - * dontSeeElement('.error'); - * $I->dontSeeElement('//form/input[1]'); - * $I->dontSeeElement('input', ['name' => 'login']); - * $I->dontSeeElement('input', ['value' => '123456']); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeElement() - */ - public function dontSeeElement($selector, array $attributes = []): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeElement', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the given element is invisible or not present on the page. - * You can also specify expected attributes of this element. - * - * ``` php - * dontSeeElement('.error'); - * $I->dontSeeElement('//form/input[1]'); - * $I->dontSeeElement('input', ['name' => 'login']); - * $I->dontSeeElement('input', ['value' => '123456']); - * ``` - * @see \Codeception\Module\WebDriver::dontSeeElement() - */ - public function cantSeeElement($selector, array $attributes = []): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeElement', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the given element exists on the page, even it is invisible. - * - * ``` php - * seeElementInDOM('//form/input[type=hidden]'); - * ``` - * - * @param string|array|WebDriverBy $selector - * @see \Codeception\Module\WebDriver::seeElementInDOM() - */ - public function seeElementInDOM($selector, array $attributes = []): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeElementInDOM', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the given element exists on the page, even it is invisible. - * - * ``` php - * seeElementInDOM('//form/input[type=hidden]'); - * ``` - * - * @param string|array|WebDriverBy $selector - * @see \Codeception\Module\WebDriver::seeElementInDOM() - */ - public function canSeeElementInDOM($selector, array $attributes = []): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeElementInDOM', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Opposite of `seeElementInDOM`. - * - * @param string|array|WebDriverBy $selector - * @see \Codeception\Module\WebDriver::dontSeeElementInDOM() - */ - public function dontSeeElementInDOM($selector, array $attributes = []): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeElementInDOM', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Opposite of `seeElementInDOM`. - * - * @param string|array|WebDriverBy $selector - * @see \Codeception\Module\WebDriver::dontSeeElementInDOM() - */ - public function cantSeeElementInDOM($selector, array $attributes = []): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeElementInDOM', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that there are a certain number of elements matched by the given locator on the page. - * - * ``` php - * seeNumberOfElements('tr', 10); - * $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements - * ``` - * - * @param int|int[] $expected - * @see \Codeception\Module\WebDriver::seeNumberOfElements() - */ - public function seeNumberOfElements($selector, $expected): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberOfElements', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that there are a certain number of elements matched by the given locator on the page. - * - * ``` php - * seeNumberOfElements('tr', 10); - * $I->seeNumberOfElements('tr', [0,10]); // between 0 and 10 elements - * ``` - * - * @param int|int[] $expected - * @see \Codeception\Module\WebDriver::seeNumberOfElements() - */ - public function canSeeNumberOfElements($selector, $expected): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberOfElements', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * @param string|array|WebDriverBy $selector - * @param int|array $expected - * @throws ModuleException - * @see \Codeception\Module\WebDriver::seeNumberOfElementsInDOM() - */ - public function seeNumberOfElementsInDOM($selector, $expected) { - return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberOfElementsInDOM', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * @param string|array|WebDriverBy $selector - * @param int|array $expected - * @throws ModuleException - * @see \Codeception\Module\WebDriver::seeNumberOfElementsInDOM() - */ - public function canSeeNumberOfElementsInDOM($selector, $expected) { - return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberOfElementsInDOM', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the given option is selected. - * - * ``` php - * seeOptionIsSelected('#form input[name=payment]', 'Visa'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::seeOptionIsSelected() - */ - public function seeOptionIsSelected($selector, $optionText): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionIsSelected', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the given option is selected. - * - * ``` php - * seeOptionIsSelected('#form input[name=payment]', 'Visa'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::seeOptionIsSelected() - */ - public function canSeeOptionIsSelected($selector, $optionText): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionIsSelected', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the given option is not selected. - * - * ``` php - * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::dontSeeOptionIsSelected() - */ - public function dontSeeOptionIsSelected($selector, $optionText): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeOptionIsSelected', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the given option is not selected. - * - * ``` php - * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::dontSeeOptionIsSelected() - */ - public function cantSeeOptionIsSelected($selector, $optionText): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionIsSelected', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the page title contains the given string. - * - * ``` php - * seeInTitle('Blog - Post #1'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::seeInTitle() - */ - public function seeInTitle($title) { - return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInTitle', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the page title contains the given string. - * - * ``` php - * seeInTitle('Blog - Post #1'); - * ``` - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::seeInTitle() - */ - public function canSeeInTitle($title) { - return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInTitle', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the page title does not contain the given string. - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::dontSeeInTitle() - */ - public function dontSeeInTitle($title) { - return $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInTitle', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the page title does not contain the given string. - * - * @return mixed|void - * @see \Codeception\Module\WebDriver::dontSeeInTitle() - */ - public function cantSeeInTitle($title) { - return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInTitle', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Accepts the active JavaScript native popup window, as created by `window.alert`|`window.confirm`|`window.prompt`. - * Don't confuse popups with modal windows, - * as created by [various libraries](https://jster.net/category/windows-modals-popups). - * @see \Codeception\Module\WebDriver::acceptPopup() - */ - public function acceptPopup(): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('acceptPopup', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Dismisses the active JavaScript popup, as created by `window.alert`, `window.confirm`, or `window.prompt`. - * @see \Codeception\Module\WebDriver::cancelPopup() - */ - public function cancelPopup(): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('cancelPopup', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the active JavaScript popup, - * as created by `window.alert`|`window.confirm`|`window.prompt`, contains the given string. - * - * @throws ModuleException - * @see \Codeception\Module\WebDriver::seeInPopup() - */ - public function seeInPopup(string $text): void { - $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInPopup', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the active JavaScript popup, - * as created by `window.alert`|`window.confirm`|`window.prompt`, contains the given string. - * - * @throws ModuleException - * @see \Codeception\Module\WebDriver::seeInPopup() - */ - public function canSeeInPopup(string $text): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInPopup', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that the active JavaScript popup, - * as created by `window.alert`|`window.confirm`|`window.prompt`, does NOT contain the given string. - * - * @throws ModuleException - * @see \Codeception\Module\WebDriver::dontSeeInPopup() - */ - public function dontSeeInPopup(string $text): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInPopup', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * [!] Conditional Assertion: Test won't be stopped on fail - * Checks that the active JavaScript popup, - * as created by `window.alert`|`window.confirm`|`window.prompt`, does NOT contain the given string. - * - * @throws ModuleException - * @see \Codeception\Module\WebDriver::dontSeeInPopup() - */ - public function cantSeeInPopup(string $text): void { - $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInPopup', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Enters text into a native JavaScript prompt popup, as created by `window.prompt`. - * - * @throws ModuleException - * @see \Codeception\Module\WebDriver::typeInPopup() - */ - public function typeInPopup(string $keys): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('typeInPopup', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Reloads the current page. - * @see \Codeception\Module\WebDriver::reloadPage() - */ - public function reloadPage(): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('reloadPage', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Moves back in history. - * @see \Codeception\Module\WebDriver::moveBack() - */ - public function moveBack(): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('moveBack', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Moves forward in history. - * @see \Codeception\Module\WebDriver::moveForward() - */ - public function moveForward(): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('moveForward', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Submits the given form on the page, optionally with the given form - * values. Give the form fields values as an array. Note that hidden fields - * can't be accessed. - * - * Skipped fields will be filled by their values from the page. - * You don't need to click the 'Submit' button afterwards. - * This command itself triggers the request to form's action. - * - * You can optionally specify what button's value to include - * in the request with the last parameter as an alternative to - * explicitly setting its value in the second parameter, as - * button values are not otherwise included in the request. - * - * Examples: - * - * ``` php - * submitForm('#login', [ - * 'login' => 'davert', - * 'password' => '123456' - * ]); - * // or - * $I->submitForm('#login', [ - * 'login' => 'davert', - * 'password' => '123456' - * ], 'submitButtonName'); - * - * ``` - * - * For example, given this sample "Sign Up" form: - * - * ``` html - *
- * Login: - *
- * Password: - *
- * Do you agree to our terms? - *
- * Select pricing plan: - * - * - *
- * ``` - * - * You could write the following to submit it: - * - * ``` php - * submitForm( - * '#userForm', - * [ - * 'user[login]' => 'Davert', - * 'user[password]' => '123456', - * 'user[agree]' => true - * ], - * 'submitButton' - * ); - * ``` - * Note that "2" will be the submitted value for the "plan" field, as it is - * the selected option. - * - * Also note that this differs from PhpBrowser, in that - * ```'user' => [ 'login' => 'Davert' ]``` is not supported at the moment. - * Named array keys *must* be included in the name as above. - * - * Pair this with seeInFormFields for quick testing magic. - * - * ``` php - * 'value', - * 'field2' => 'another value', - * 'checkbox1' => true, - * // ... - * ]; - * $I->submitForm('//form[@id=my-form]', $form, 'submitButton'); - * // $I->amOnPage('/path/to/form-page') may be needed - * $I->seeInFormFields('//form[@id=my-form]', $form); - * ``` - * - * Parameter values must be set to arrays for multiple input fields - * of the same name, or multi-select combo boxes. For checkboxes, - * either the string value can be used, or boolean values which will - * be replaced by the checkbox's value in the DOM. - * - * ``` php - * submitForm('#my-form', [ - * 'field1' => 'value', - * 'checkbox' => [ - * 'value of first checkbox', - * 'value of second checkbox', - * ], - * 'otherCheckboxes' => [ - * true, - * false, - * false, - * ], - * 'multiselect' => [ - * 'first option value', - * 'second option value', - * ] - * ]); - * ``` - * - * Mixing string and boolean values for a checkbox's value is not supported - * and may produce unexpected results. - * - * Field names ending in "[]" must be passed without the trailing square - * bracket characters, and must contain an array for its value. This allows - * submitting multiple values with the same name, consider: - * - * ```php - * $I->submitForm('#my-form', [ - * 'field[]' => 'value', - * 'field[]' => 'another value', // 'field[]' is already a defined key - * ]); - * ``` - * - * The solution is to pass an array value: - * - * ```php - * // this way both values are submitted - * $I->submitForm('#my-form', [ - * 'field' => [ - * 'value', - * 'another value', - * ] - * ]); - * ``` - * - * The `$button` parameter can be either a string, an array or an instance - * of Facebook\WebDriver\WebDriverBy. When it is a string, the - * button will be found by its "name" attribute. If $button is an - * array then it will be treated as a strict selector and a WebDriverBy - * will be used verbatim. - * - * For example, given the following HTML: - * - * ``` html - * - * ``` - * - * `$button` could be any one of the following: - * - 'submitButton' - * - ['name' => 'submitButton'] - * - WebDriverBy::name('submitButton') - * - * @param string|array|WebDriverBy $selector - * @param string|array|WebDriverBy|null $button - * @see \Codeception\Module\WebDriver::submitForm() - */ - public function submitForm($selector, array $params, $button = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('submitForm', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Waits up to $timeout seconds for the given element to change. - * Element "change" is determined by a callback function which is called repeatedly - * until the return value evaluates to true. - * - * ``` php - * waitForElementChange('#menu', function(WebDriverElement $el) { - * return $el->isDisplayed(); - * }, 100); - * ``` - * - * @param string|array|WebDriverBy $element - * @throws ElementNotFound - * @see \Codeception\Module\WebDriver::waitForElementChange() - */ - public function waitForElementChange($element, \Closure $callback, int $timeout = 30): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElementChange', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Waits up to $timeout seconds for an element to appear on the page. - * If the element doesn't appear, a timeout exception is thrown. - * - * ``` php - * waitForElement('#agree_button', 30); // secs - * $I->click('#agree_button'); - * ``` - * - * @param string|array|WebDriverBy $element - * @param int $timeout seconds - * @throws Exception - * @see \Codeception\Module\WebDriver::waitForElement() - */ - public function waitForElement($element, int $timeout = 10): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElement', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Waits up to $timeout seconds for the given element to be visible on the page. - * If element doesn't appear, a timeout exception is thrown. - * - * ``` php - * waitForElementVisible('#agree_button', 30); // secs - * $I->click('#agree_button'); - * ``` - * - * @param string|array|WebDriverBy $element - * @param int $timeout seconds - * @throws Exception - * @see \Codeception\Module\WebDriver::waitForElementVisible() - */ - public function waitForElementVisible($element, int $timeout = 10): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElementVisible', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Waits up to $timeout seconds for the given element to become invisible. - * If element stays visible, a timeout exception is thrown. - * - * ``` php - * waitForElementNotVisible('#agree_button', 30); // secs - * ``` - * - * @param string|array|WebDriverBy $element - * @param int $timeout seconds - * @throws Exception - * @see \Codeception\Module\WebDriver::waitForElementNotVisible() - */ - public function waitForElementNotVisible($element, int $timeout = 10): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElementNotVisible', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Waits up to $timeout seconds for the given element to be clickable. - * If element doesn't become clickable, a timeout exception is thrown. - * - * ``` php - * waitForElementClickable('#agree_button', 30); // secs - * $I->click('#agree_button'); - * ``` - * - * @param string|array|WebDriverBy $element - * @param int $timeout seconds - * @throws Exception - * @see \Codeception\Module\WebDriver::waitForElementClickable() - */ - public function waitForElementClickable($element, int $timeout = 10): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElementClickable', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Waits up to $timeout seconds for the given string to appear on the page. - * - * Can also be passed a selector to search in, be as specific as possible when using selectors. - * waitForText() will only watch the first instance of the matching selector / text provided. - * If the given text doesn't appear, a timeout exception is thrown. - * - * ``` php - * waitForText('foo', 30); // secs - * $I->waitForText('foo', 30, '.title'); // secs - * ``` - * - * @param int $timeout seconds - * @param null|string|array|WebDriverBy $selector - * @throws Exception - * @see \Codeception\Module\WebDriver::waitForText() - */ - public function waitForText(string $text, int $timeout = 10, $selector = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('waitForText', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Wait for $timeout seconds. - * - * @param int|float $timeout secs - * @throws TestRuntimeException - * @see \Codeception\Module\WebDriver::wait() - */ - public function wait($timeout): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('wait', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Low-level API method. - * If Codeception commands are not enough, this allows you to use Selenium WebDriver methods directly: - * - * ``` php - * $I->executeInSelenium(function(\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) { - * $webdriver->get('https://google.com'); - * }); - * ``` - * - * This runs in the context of the - * [RemoteWebDriver class](https://github.com/php-webdriver/php-webdriver/blob/master/lib/remote/RemoteWebDriver.php). - * Try not to use this command on a regular basis. - * If Codeception lacks a feature you need, please implement it and submit a patch. - * - * @param Closure $function - * @return mixed - * @see \Codeception\Module\WebDriver::executeInSelenium() - */ - public function executeInSelenium(\Closure $function) { - return $this->getScenario()->runStep(new \Codeception\Step\Action('executeInSelenium', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Switch to another window identified by name. - * - * The window can only be identified by name. If the $name parameter is blank, the parent window will be used. - * - * Example: - * ``` html - * - * ``` - * - * ``` php - * click("Open window"); - * # switch to another window - * $I->switchToWindow("another_window"); - * # switch to parent window - * $I->switchToWindow(); - * ``` - * - * If the window has no name, match it by switching to next active tab using `switchToNextTab` method. - * - * Or use native Selenium functions to get access to all opened windows: - * - * ``` php - * executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) { - * $handles=$webdriver->getWindowHandles(); - * $last_window = end($handles); - * $webdriver->switchTo()->window($last_window); - * }); - * ``` - * @see \Codeception\Module\WebDriver::switchToWindow() - */ - public function switchToWindow(?string $name = NULL): void { - $this->getScenario()->runStep(new \Codeception\Step\Action('switchToWindow', func_get_args())); - } - - - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Switch to another iframe on the page. - * - * Example: - * ``` html - *