From 049b63845e47ad3dae482bb34b9291bb5c99134f Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 14 Nov 2019 15:02:16 +0100 Subject: [PATCH 1/7] Support HTML5 form attribute https://github.com/Codeception/Codeception/issues/5477 --- src/Codeception/Lib/InnerBrowser.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Codeception/Lib/InnerBrowser.php b/src/Codeception/Lib/InnerBrowser.php index 296c5b9..e1a6142 100644 --- a/src/Codeception/Lib/InnerBrowser.php +++ b/src/Codeception/Lib/InnerBrowser.php @@ -447,6 +447,18 @@ private function clickButton(\DOMNode $node) $formParams = [$buttonName => $buttonValue]; } + if (!empty($node->getAttribute('form'))) { + $formCrawler = $this->filterByCSS('#' . $node->getAttribute('form')); + if ($formCrawler->count() !== 1) { + throw new TestRuntimeException("Found form with id {$node->getAttribute('form')} {$formCrawler->count()} times, expected exactly 1"); + } + $this->proceedSubmitForm( + new Crawler($formCrawler->getNode(0), $this->getAbsoluteUrlFor($this->_getCurrentUri()), $this->getBaseUrl()), + $formParams + ); + return true; + } + while ($node->parentNode !== null) { $node = $node->parentNode; if (!isset($node->tagName)) { From 4e7e96894370f379b63f94814faa2cd995a49d99 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 14 Nov 2019 18:19:03 +0100 Subject: [PATCH 2/7] Update .travis.yml Set up code coverage --- .travis.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4e34745..fbb3836 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,25 @@ language: php - +stages: + - test + - php: - 5.6 - 7.0 - 7.1 - 7.2 - 7.3 - # faster builds on new travis setup not using sudo sudo: false install: - '[[ -z "$CI_USER_TOKEN" ]] || composer config github-oauth.github.com ${CI_USER_TOKEN};' - travis_retry composer self-update && composer --version - - travis_retry composer update --prefer-dist --no-interaction - + - travis_retry composer install --prefer-dist --no-interaction + - phpenv config-rm xdebug.ini + - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then pecl install -f pcov; fi + script: - php ./vendor/bin/codecept run + - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then php ./vendor/bin/codecept run --coverage-xml; fi +after_script: + - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then wget https://scrutinizer-ci.com/ocular.phar; php ocular.phar code-coverage:upload --format=php-clover tests/_output/coverage.xml -f pcov; fi From ae38852808c5be3cfabe771b09dbd0966f31765c Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 14 Nov 2019 18:22:56 +0100 Subject: [PATCH 3/7] Update codeception config to gather coverage info --- codeception.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/codeception.yml b/codeception.yml index 0048e8a..abe375d 100644 --- a/codeception.yml +++ b/codeception.yml @@ -5,3 +5,8 @@ paths: support: tests/_support envs: tests/_envs actor_suffix: Tester +coverage: + enabled: true + local: true + include: + - src/*.php From dacf49bc3034c53c933599ed2168280a8ccfacfb Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 14 Nov 2019 18:28:06 +0100 Subject: [PATCH 4/7] Fixed copy paste error --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fbb3836..8071c86 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,4 +22,4 @@ script: - php ./vendor/bin/codecept run - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then php ./vendor/bin/codecept run --coverage-xml; fi after_script: - - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then wget https://scrutinizer-ci.com/ocular.phar; php ocular.phar code-coverage:upload --format=php-clover tests/_output/coverage.xml -f pcov; fi + - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then wget https://scrutinizer-ci.com/ocular.phar; php ocular.phar code-coverage:upload --format=php-clover tests/_output/coverage.xml; fi From c5aa2c978ec6bace9a857d2ee522164543b5925e Mon Sep 17 00:00:00 2001 From: Sam Mousa Date: Fri, 15 Nov 2019 15:48:22 +0100 Subject: [PATCH 5/7] Added composer test command --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index 5e51595..071433b 100644 --- a/composer.json +++ b/composer.json @@ -34,5 +34,8 @@ }, "config": { "classmap-authoritative": true + }, + "scripts": { + "test": "codecept run --coverage-xml" } } From f56afe3644c16674f49ffa6c1830d62b82931251 Mon Sep 17 00:00:00 2001 From: Sam Mousa Date: Fri, 15 Nov 2019 15:55:31 +0100 Subject: [PATCH 6/7] Add scrutinizer config --- .scrutinizer.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .scrutinizer.yml diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000..8849d54 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,11 @@ +tools: + external_code_coverage: true +build: + nodes: + analysis: + tests: + override: + - php-scrutinizer-run +filter: + excluded_paths: + - "tests/_support/_generated" \ No newline at end of file From 83f26090997fb96fb8dba1fa87dedbc713957981 Mon Sep 17 00:00:00 2001 From: Sam Mousa Date: Fri, 15 Nov 2019 16:51:51 +0100 Subject: [PATCH 7/7] Refactored button clicking, added tests for full coverage --- src/Codeception/Lib/InnerBrowser.php | 62 ++++++++++--------- .../data/app/view/form/button-not-in-form.php | 5 ++ tests/unit/Codeception/Module/TestsForWeb.php | 36 +++++++++++ 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/src/Codeception/Lib/InnerBrowser.php b/src/Codeception/Lib/InnerBrowser.php index e1a6142..9a92995 100644 --- a/src/Codeception/Lib/InnerBrowser.php +++ b/src/Codeception/Lib/InnerBrowser.php @@ -439,41 +439,47 @@ protected function clickByLocator($link) */ private function clickButton(\DOMNode $node) { - $formParams = []; - $buttonName = (string)$node->getAttribute('name'); - $buttonValue = $node->getAttribute('value'); - - if ($buttonName !== '' && $buttonValue !== null) { - $formParams = [$buttonName => $buttonValue]; + /** + * First we check if the button is associated to a form. + * It is associated to a form when it has a nonempty form + */ + $formAttribute = $node->attributes->getNamedItem('form'); + if (isset($formAttribute)) { + $form = empty($formAttribute->nodeValue) ? null : $this->filterByCSS('#' . $formAttribute->nodeValue)->getNode(0); + } else { + // Check parents + $currentNode = $node; + $form = null; + while ($currentNode->parentNode !== null) { + $currentNode = $currentNode->parentNode; + if ($currentNode->nodeName === 'form') { + $form = $node; + break; + } + } } - if (!empty($node->getAttribute('form'))) { - $formCrawler = $this->filterByCSS('#' . $node->getAttribute('form')); - if ($formCrawler->count() !== 1) { - throw new TestRuntimeException("Found form with id {$node->getAttribute('form')} {$formCrawler->count()} times, expected exactly 1"); + if (isset($form)) { + $buttonName = $node->getAttribute('name'); + if ($buttonName !== '') { + $formParams = [$buttonName => $node->getAttribute('value')]; + } else { + $formParams = []; } $this->proceedSubmitForm( - new Crawler($formCrawler->getNode(0), $this->getAbsoluteUrlFor($this->_getCurrentUri()), $this->getBaseUrl()), + new Crawler($form, $this->getAbsoluteUrlFor($this->_getCurrentUri()), $this->getBaseUrl()), $formParams ); return true; - } - - while ($node->parentNode !== null) { - $node = $node->parentNode; - if (!isset($node->tagName)) { - // this is the top most node, it has no parent either - break; - } - if ($node->tagName === 'a') { - $this->openHrefFromDomNode($node); - return true; - } elseif ($node->tagName === 'form') { - $this->proceedSubmitForm( - new Crawler($node, $this->getAbsoluteUrlFor($this->_getCurrentUri()), $this->getBaseUrl()), - $formParams - ); - return true; + } else { + // Check if the button is inside an anchor. + $currentNode = $node; + while ($currentNode->parentNode !== null) { + $currentNode = $currentNode->parentNode; + if ($currentNode->nodeName === 'a') { + $this->openHrefFromDomNode($currentNode); + return true; + } } } throw new TestRuntimeException('Button is not inside a link or a form'); diff --git a/tests/data/app/view/form/button-not-in-form.php b/tests/data/app/view/form/button-not-in-form.php index 77ad75c..e6338f5 100644 --- a/tests/data/app/view/form/button-not-in-form.php +++ b/tests/data/app/view/form/button-not-in-form.php @@ -5,11 +5,16 @@
+ +
+ + +
\ No newline at end of file diff --git a/tests/unit/Codeception/Module/TestsForWeb.php b/tests/unit/Codeception/Module/TestsForWeb.php index 8ce984c..f173060 100644 --- a/tests/unit/Codeception/Module/TestsForWeb.php +++ b/tests/unit/Codeception/Module/TestsForWeb.php @@ -1648,6 +1648,42 @@ public function testClickHashButton() $this->module->seeCurrentUrlEquals('/form/anchor'); } + public function testClickButtonWithForm() + { + $this->module->amOnPage('/form/button-not-in-form'); + $this->module->click('Submit 2'); + $this->module->seeCurrentUrlEquals('/form/button'); + } + + public function testClickButtonWithEmptyForm() + { + $this->module->amOnPage('/form/button-not-in-form'); + $this->expectException(\Codeception\Exception\TestRuntimeException::class); + $this->module->click('Should not submit'); + $this->module->seeCurrentUrlEquals('/form/button-not-in-form'); + } + + public function testClickButtonNotInForm() + { + $this->module->amOnPage('/form/button-not-in-form'); + $this->expectException(\Codeception\Exception\TestRuntimeException::class); + $this->module->click('Outside submit'); + } + + public function testClickButtonWithFormInvalidIdInside() + { + $this->module->amOnPage('/form/button-not-in-form'); + $this->expectException(\Codeception\Exception\TestRuntimeException::class); + $this->module->click('Invalid form2'); + } + + public function testClickButtonWithFormInvalidIdOutside() + { + $this->module->amOnPage('/form/button-not-in-form'); + $this->expectException(\Codeception\Exception\TestRuntimeException::class); + $this->module->click('Invalid form'); + } + public function testSubmitHashForm() { $this->module->amOnPage('/form/anchor');