yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.24k stars 6.91k forks source link

Can't get functional testing working properly (specifically ContactCept) #1604

Closed amnah closed 10 years ago

amnah commented 10 years ago

I'm unsure why this one doesn't work for me. What seems to happen is that everything works up until the last part. After submitting valid data, the page redirects to the home page instead of going back to the contact page. So I don't see Thank you for contacting us. We will respond to you as soon as possible., but I do see the Congratulations! You have successfully created your Yii-powered application.

I'm using xampp 1.8.3 on Windows. Fresh install of yii2-app-basic, ran codecept build + codecept run. (added --debug flag for following output)

Trying to ensure that contact works (ContactCept.php)       
Scenario:
* I am on page "D:\programs\xampp\htdocs\yii-app-basic\codecept.phar?r=site/contact"
  [Response] 200
  [Page] http://localhost/D:\programs\xampp\htdocs\yii-app-basic\codecept.phar?r=site/contact
* I see "Contact","h1"
* I am going to submit contact form with no data
* I submit form "#contact-form",
  [Uri] /yii-app-basic/r=site/contact
  [Method] post
  [Parameters] {"_csrf":"8d2ed98a75a6558ecdeca2dbc95c05b520d5a51c","ContactForm":{"name":"","email":"","subject":"","verifyCode":"","body":""}}
  [Response] 200
  [Page] http://localhost/yii-app-basic/r=site/contact
* I expect to see validations errors
* I see "Contact","h1"
* I see "Name cannot be blank"
* I see "Email cannot be blank"
* I see "Subject cannot be blank"
* I see "Body cannot be blank"
* I see "The verification code is incorrect"
* I am going to submit contact form with not correct email
* I submit form "#contact-form",{"ContactForm[name]":"tester","ContactForm[email]":"tester.email","ContactForm[subject]":"test subject","ContactForm[body]":"test content","ContactForm[verifyCode]":"testme"}
  [Uri] /yii-app-basic/r=site/contact
  [Method] post
  [Parameters] {"_csrf":"72eaa079b66b6596d9c4b07c9ee1fc21e3ab8387","ContactForm":{"name":"tester","email":"tester.email","subject":"test subject","verifyCode":"testme","body":"test content"}}
  [Response] 200
  [Page] http://localhost/yii-app-basic/r=site/contact
* I expect to see that email adress is wrong
* I don't see "Name cannot be blank",".help-inline"
* I see "Email is not a valid email address."
* I don't see "Subject cannot be blank",".help-inline"
* I don't see "Body cannot be blank",".help-inline"
* I don't see "The verification code is incorrect",".help-inline"
* I am going to submit contact form with correct data
* I submit form "#contact-form",{"ContactForm[name]":"tester","ContactForm[email]":"tester@example.com","ContactForm[subject]":"test subject","ContactForm[body]":"test content","ContactForm[verifyCode]":"testme"}
  [Uri] /yii-app-basic/r=site/contact
  [Method] post
  [Parameters] {"_csrf":"83343ead4ec60fa3fae63bef015ab06f3ff9a45b","ContactForm":{"name":"tester","email":"tester@example.com","subject":"test subject","verifyCode":"testme","body":"test content"}}
  [Response] 200
  [Page] http://localhost/yii-app-basic/r=site/contact
* I don't see element "#contact-form"
* I see "Congratulations"
* I see "You have successfully created your Yii-powered application"
* I see "Thank you for contacting us. We will respond to you as soon as possible."
 FAIL 
Ragazzo commented 10 years ago

hm, reason can be different for that, unfortunately i dont use xamp, but is app working for you not from test (this page)?

Ragazzo commented 10 years ago

Checked this one on my pc, works well: Windows 7 (64), php 5.4.20, php-builtin server, codeception 1.8.1. Also check if you have all dependencies installed (gd library for php or imagick for example, they are used for generating captcha)

amnah commented 10 years ago

Yes, it works fine in the browser.

I tried to do some debugging, and it seems like it doesn't like $this->refresh(). If I replace it with a $this->redirect(), then it works properly.

public function refresh($anchor = '')
{
    return Yii::$app->getResponse()->redirect(Yii::$app->getRequest()->getUrl() . $anchor);
}

where Yii::$app->getRequest()->getUrl() computes to /yii-app-basic/r=site/contact

For now I guess I'll just stick with $this->redirect()

Ragazzo commented 10 years ago

/yii-app-basic/r=site/contact

strange url, it should contain index.php and correct query string.

amnah commented 10 years ago

Yes, it seems that the ? is somehow being left off $_SERVER['REQUEST_URI'].

This doesn't work: /yii-app-basic/r=site/contact But this does: /yii-app-basic/?r=site/contact

Not exactly sure how the $_SERVER is populated in functional tests.

amnah commented 10 years ago

Looks like $_SERVER is populated on Codeception's side, in \Codeception\Util\Connector\Yii2.

Also, it seems that testing does not work if urlManager.enablePrettyUrl = true. Took me some time to figure this out; perhaps it should be added to the docs at some point?

Ragazzo commented 10 years ago

will check this one a little bit later.

Ragazzo commented 10 years ago

still cant reproduce, on ubuntu with php 5.5. Can you maybe upload your archive somewhere, with xampp and all related things? Its hard to guess what is wrong when cant reproduce this strange behavior.

Ragazzo commented 10 years ago

ok, reproduced. this is a bug. (functional/acceptance tests not working with prettyUrl)

amnah commented 10 years ago

Ok here's a zip file of a fresh install. The only error I get is in ContactCept in functional tests.

https://dl.dropboxusercontent.com/u/60589606/yii2-app-basic.zip

Exact steps taken:

1) Download archive at github 2) Extract to d:\programs\xampp\htdocs\yii2-app-basic 3) Modify tests/acceptance.suite.yml url: 'http://localhost/yii2-app-basic/web/index-test-acceptance.php' 4) Modify tests/functional.suite.yml entryScript: 'web/index-test-functional.php' url: 'http://localhost/yii2-app-basic/ 5) Download codecept.phar into folder 6) Navigate to folder in cygwin

$ cd /d/programs/xampp/htdocs/yii2-app-basic
$ composer update
$ php codecept.phar build
$ php codecept.phar run

7) Output:

$ php codecept.phar run
Codeception PHP Testing Framework v1.8.1
Powered by PHPUnit 3.7.28 by Sebastian Bergmann.

Acceptance Tests (4) --------------------------------------------
Trying to ensure that about works (AboutCept.php)           Ok
Trying to ensure that contact works (ContactCept.php)       Ok
Trying to ensure that home page works (HomeCept.php)        Ok
Trying to ensure that login works (LoginCept.php)           Ok
-----------------------------------------------------------------

Functional Tests (4) --------------------------------------------
Trying to ensure that about works (AboutCept.php)           Ok
Trying to ensure that contact works (ContactCept.php)       Fail
Trying to ensure that home page works (HomeCept.php)        Ok
Trying to ensure that login works (LoginCept.php)           Ok
-----------------------------------------------------------------

Unit Tests (0) ------------------------------
---------------------------------------------
1) Failed to ensure that contact works in ContactCept.php
Sorry, I couldn't see "Thank you for contacting us. We will respond to you as soon as possible.":
Failed asserting that
-->  /yii2-app-basic/r=site/contact<!DOCTYPE html>
<html lang="en-US">
<head>
        <meta charset="UTF-8"/>
        <title>My Yii Application</title>
        <meta name="csrf-var" content="_csrf">
<meta name="csrf-token" content="b6980fcee5b645b92c9a685ad150c7208d70f2c5">
<link href="D:\programs\xampp\htdocs\yii2-app-basic\web/D:\programs\xampp\htdocs</info>
[Content too long to display. See complete response in '_log' directory]
--> contains "thank you for contacting us. we will respond to you as soon as possible.".

Scenario Steps:
23. I see "Thank you for contacting us. We will respond to you as soon as possible."
22. I don't see element "#contact-form"
21. I submit form "#contact-form",{"ContactForm[name]":"tester","ContactForm[email]":"tester@example.com","ContactForm[subject]":"test subject","ContactForm[body]":"test content","ContactForm[verifyCode]":"testme"}
20. I am going to submit contact form with correct data
19. I don't see "The verification code is incorrect",".help-inline"
18. I don't see "Body cannot be blank",".help-inline"
17. I don't see "Subject cannot be blank",".help-inline"

Time: 4.47 seconds, Memory: 29.50Mb

There was 1 failure:

---------

FAILURES!
Tests: 8, Assertions: 46, Failures: 1.
Ragazzo commented 10 years ago

@amnah no need in archive anymore, i reproduced this bug. Thank you for discovering it.

@qiangxue we have some fw-core problem here. Description: When we are using createUrl() in page-object (BasePage for example use it) and we use codecept.phar we have wrong url generated, because of UrlManager::getBaseUrl that is pointing to Request::getBaseUrl method. So for example for functional test:

* I am on page "codecept.phar?r=site/about"
* I see "About","h1"

codecept.phar should not be there. Also when enabling prettyurl it fails to work correctly, i guess it because some internal url-parsing

* I am on page "codecept.phar/site/about"
* I see "About","h1"

failing and always redirects to the main boilerplate index page. Can you check this and maybe fix when you will have time? i will also look how maybe to fix this issue. So overall it is because of not correct detecting server script_name and script_filename.

Ragazzo commented 10 years ago

ok, by some investigations the problem is bigger than i thought, i will make some discussion with @DavertMik about it.

qiangxue commented 10 years ago

Yes, I met this problem before, and my initial conclusion was it's something within Symfony, but I didn't have time then to dig deeper. Basically it's related with $_SERVER setting.

Ragazzo commented 10 years ago

yep, i investigated and unfortunately this is an Yii2 bug, will right description here shortly.

Ragazzo commented 10 years ago

ok, we have 2 problems:

  1. wrong url generation as you can see by `"codecept.phar?r=site/about"and/yii-app-basic/?r=site/contact`` (because of UrlManager)
  2. pretty url format not working with tests. All this two problems are closely related with $_SERVER and `pathInfo, i will post here some debug info, but to be true i think that only @qiangxue will be able to fix this bugs so they will not affect fw behavior.
Ragazzo commented 10 years ago

ok, second problem is not a problem i think (number 2). I got it working by digging in sf-bk implementation: As you can see here (https://github.com/symfony/BrowserKit/blob/master/Client.php#L291) second param is $uri and not full url, this method is called in a lot of placec in Yii2 < Framework (for example https://github.com/Codeception/Codeception/blob/1.8/src/Codeception/Util/Framework.php#L61). So to make it work in `$I->amOnPage we need to specify uri, that means with index.php file. Full implementation:

in your functional.yaml
class_name: TestGuy
modules:
    enabled:
      - Filesystem
      - TestHelper
      - Yii2
    config:
        Yii2:
            entryScript: 'web/index-test-functional.php'
            url: 'http://localhost/web/index-test-functional.php'

example in AboutCept.php with not pretty urls:

$I = new TestGuy($scenario);
$I->wantTo('ensure that about works');
$I->amOnPage('web/index-test-functional.php?r=site/about');
#AboutPage::openBy($I);
$I->see('About', 'h1');

Executed and passed:

Trying to ensure that about works (AboutCept.php)       
Scenario:
* I am on page "web/index-test-functional.php/site/about"
* I see "About","h1"
 PASSED 

example in AboutCept.php with pretty urls:

$I = new TestGuy($scenario);
$I->wantTo('ensure that about works');
$I->amOnPage('web/index-test-functional.php/site/about');
#AboutPage::openBy($I);
$I->see('About', 'h1');
Functional Tests (1) ----------------------------------------
Trying to ensure that about works (AboutCept.php)       
Scenario:
* I am on page "web/index-test-functional.php/site/about"
* I see "About","h1"
 PASSED 

So @qiangxue what do you think about it? I think it was misunderstanding about url/uri, so i think that we need to accept this behavior (specifying index file too in route). Also because of entryScript is web/index-test-functional.php' and url is http://localhost/web/index-test-functional.php we need to specify route in url like web/index-test-functional.php to get it working by some Yii2 internal route parsing rules. Or use it like this http://localhost/index-test-functional.php and route is index-test-functional.php as you see i removed web. This is to done to get correct $_SERVER values here (https://github.com/Codeception/Codeception/blob/1.8/src/Codeception/Util/Connector/Yii2.php#L42) so route will be correctly parsed by Yii2 here (https://github.com/yiisoft/yii2/blob/master/framework/yii/web/Request.php#L456). Hope you will understand that))) its really can be hard because of all this rules/matches/etc :) So whats your thoughts overall?

Ragazzo commented 10 years ago

Problem marked as number 1 with creating url-rules is still a problem :) need to investigate it and fix, also its once again about $_SERVER params)

qiangxue commented 10 years ago

I don't think we should use something like 'web/index-test-functional.php/site/about' in the cept files. This is not DRY and will fail to work if URL rules are modified.

Using the old code, could you try to print out the content of $_SERVER? I remember there's something wrong with $_SERVER which makes yii\web\Request unable to parse the URI information correctly.

Ragazzo commented 10 years ago

Second problem (number 2) is about then we use Codeception in console mode, so we have $_SERVER['SCRIPT_FILENAME'] pointing to vendor/bin/codecept or to codecept.phar depends on how it was installed. So this affect all url creation as you can see by: UrlManager::createurl() calls UrlManager::getBaseUrl() that calls https://github.com/yiisoft/yii2/blob/master/framework/yii/web/UrlManager.php#L304 as you can see. So we can fix it by either setting UrlManager::_baseUrl to needed thing like index-functional-test.php or by fixing method: $request->getScriptUrl() (calls getScriptFile that should be fixed) : $request->getBaseUrl() calls getScriptFile that should be fixed. They use $_SERVER['SCRIPT_FILENAME'].

Ragazzo commented 10 years ago

Never thought it would be such a problem))) Once we fix it we will be ok)

Ragazzo commented 10 years ago

this is a dump of var_dump($_SERVER); exit(); putted here https://github.com/Codeception/Codeception/blob/1.8/src/Codeception/Util/Connector/Yii2.php#L62

array(9) {
  ["HTTP_HOST"]=>
  string(9) "localhost"
  ["HTTP_USER_AGENT"]=>
  string(19) "Symfony2 BrowserKit"
  ["HTTPS"]=>
  bool(false)
  ["REMOTE_ADDR"]=>
  string(9) "127.0.0.1"
  ["REQUEST_METHOD"]=>
  string(3) "GET"
  ["REQUEST_URI"]=>
  string(33) "/vendor/bin/codecept?r=site/about"
  ["SCRIPT_NAME"]=>
  string(1) "/"
  ["SCRIPT_FILENAME"]=>
  string(61) "/home/mark/basic_second_feature/web/index-test-functional.php"
  ["PHP_SELF"]=>
  string(61) "/home/mark/basic_second_feature/web/index-test-functional.php"
}

this is a dump of phpbuiltin-server with var_dump($_SERVER); exit(); putted in index action of site controller:

array(22) {
  ["DOCUMENT_ROOT"]=>
  string(35) "/home/mark/basic_second_feature/web"
  ["REMOTE_ADDR"]=>
  string(9) "127.0.0.1"
  ["REMOTE_PORT"]=>
  string(5) "54351"
  ["SERVER_SOFTWARE"]=>
  string(39) "PHP 5.5.3-1ubuntu2.1 Development Server"
  ["SERVER_PROTOCOL"]=>
  string(8) "HTTP/1.1"
  ["SERVER_NAME"]=>
  string(9) "127.0.0.1"
  ["SERVER_PORT"]=>
  string(4) "8000"
  ["REQUEST_URI"]=>
  string(1) "/"
  ["REQUEST_METHOD"]=>
  string(3) "GET"
  ["SCRIPT_NAME"]=>
  string(10) "/index.php"
  ["SCRIPT_FILENAME"]=>
  string(45) "/home/mark/basic_second_feature/web/index.php"
  ["PHP_SELF"]=>
  string(10) "/index.php"
  ["HTTP_USER_AGENT"]=>
  string(60) "Opera/9.80 (X11; Linux x86_64) Presto/2.12.388 Version/12.16"
  ["HTTP_HOST"]=>
  string(14) "localhost:8000"
  ["HTTP_ACCEPT"]=>
  string(129) "text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1"
  ["HTTP_ACCEPT_LANGUAGE"]=>
  string(11) "ru,en;q=0.9"
  ["HTTP_ACCEPT_ENCODING"]=>
  string(13) "gzip, deflate"
  ["HTTP_COOKIE"]=>
  string(166) "PHPSESSID=6fodlmm9luqtnbps681o1cp4b1; _csrf=06377a93836247f6f737bc1efc841cdef92e9e1a081d6abf0cdaa6e4d6719a0es%3A40%3A%2252252b4b04914f0be4f97fc58060b1d320f8a694%22%3B"
  ["HTTP_CACHE_CONTROL"]=>
  string(8) "no-cache"
  ["HTTP_CONNECTION"]=>
  string(10) "Keep-Alive"
  ["REQUEST_TIME_FLOAT"]=>
  float(1388079553.9067)
  ["REQUEST_TIME"]=>
  int(1388079553)
}
Ragazzo commented 10 years ago

So as i said first problem - url generation is caused by wrong `$_SERVER['SCRIPT_FILENAME']`` As i mentioned here https://github.com/yiisoft/yii2/issues/1604#issuecomment-31229390. Should be fix then url generation will be ok.

I don't think we should use something like 'web/index-test-functional.php/site/about' in the cept files. This is not DRY and will fail to work if URL rules are modified

we will not, it will be in page objects also the only thing for us that needed is to add before generated url index-test-functional.php because it is part of the uri that is needed so Yii2 will resolve request correctly. So here https://github.com/yiisoft/yii2/blob/master/extensions/yii/codeception/BasePage.php#L70 it will be like

 $I->amOnPage('index-functional-test.php' . $page->getUrl($params));

Or if we will have a better solution lets use it) But before we need to fix url-generation as i've described above.