logo
Ask your Symfony questions! Pay money and get answers fast! (more info)

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.

$25
Can not signin in my functional tests

I've tried every variation I can think on all of the tutorials I've read, and I still can not get this to work.

I'm using Symfony 1.4.

I thought this bit from Sandbox Web Solutions would work for me, but perhaps it is for an older version of Symfony.

Here is what I have right now:

include(dirname(__FILE__).'/../../bootstrap/functional.php');

$username = 'xxx';
$password = 'xxx';

$browser = new sfGuardTestFunctional(new sfBrowser());

$browser->
get('/restaurant_award/index')->
signin($username, $password)->
get('/restaurant_award/index')->
with('response')->begin()->
isStatusCode(200)->
end()
;

$browser->
get('/restaurant_award/index')->

with('request')->begin()->
isParameter('module', 'restaurant_award')->
isParameter('action', 'index')->
end()->

with('response')->begin()->
checkElement('body', '!/This is a temporary page/')->
end()

;


I do not get an outright failure, but I do get a warning, which I do not want:

  PHP sent a "warning" error at /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/test/sfTestFunctionalBase.class.php line 433 (call_user_func_array(): First argument is expected to be a valid callback, 'sfBrowser::isRedirected' was given) 


I did put this in my lib folder:

<?php

class sfGuardTestFunctional extends sfTestFunctional {

public function signin($username, $password) {
return $this->
info(sprintf('Signin user using username "%s" and password "%s"', $username, $password))->
post('/sfGuardAuth/signin', array('signin' => array('username' => $username, 'password' => $password,)))->
isRedirected()
;
}
}



Any thoughts on what causes this warning?


[UPDATE]

I'm trying this code:


$browser = new sfTestFunctional(new sfBrowser());

$browser->setAuth($username, $password)->

get('/restaurant_award/some_action')->

isForwardedTo('sfGuardAuth', 'signin')->

// it redirects back to the original uri
isRedirected(true)->

// we have to follow the redirect, otherwise we do not get
// the correct response
followRedirect()->

// did we recieved the correct response?
with('request')->begin()->
isParameter('module', 'restaurant_award')->
isParameter('action', 'index')->
end()->

responseContains('foobar');


Now I get:

Fatal error: Call to a member function getModuleName() on a non-object in /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/test/sfTestFunctional.class.php on line 62


I assume there is some mismatch between the code I'm borrowing and the actual version of Symfony I have installed: 1.4.

Can anyone point to an example of login code that works with 1.4? I can not imagine this is difficult. I assume developers do this every day?


[[UPDATE]]


Please read what I posted below in the comments.

I almost wonder if I'm the sfBrowser is getting the wrong page, perhaps a 404, or the wrong sigin page. Is there a way I can see the raw HTML that is coming back to sfBrowser?

I should note that the whole application is locked down. I know there was a bug regarding that in 2009, but I assume it is long fixed.



[UPDATE]

Okay, I tried this:

  $browser->get('/signin')->        
with('response')->debug();


and got this:


./symfony test:functional tastingnotes RestaurantAwardsActions
# get /signin


Response debug


# WARNING
# An error occurred when processing this request.
# The real response content has been replaced with the exception message to ease debugging.
HTTP/1.X 404
Content-Type: text/html; charset=utf-8

exception 'sfError404Exception' with message 'Action "signin/index" does not exist.' in /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/controller/sfController.class.php:196

Stack trace:

#0 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/controller/sfFrontWebController.class.php(48): sfController->forward('signin', 'index')

#1 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/util/sfBrowser.class.php(43): sfFrontWebController->dispatch()

#2 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/util/sfBrowserBase.class.php(323): sfBrowser->doCall()

#3 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/test/sfTestFunctionalBase.class.php(246): sfBrowserBase->call('/signin', 'get', Array, true)

#4 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/test/sfTestFunctionalBase.class.php(184): sfTestFunctionalBase->call('/signin', 'get', Array, true)

#5 /home/lkrubner/dev/tastingnotes/test/functional/tastingnotes/RestaurantAwardsActionsTest.php(12): sfTestFunctionalBase->get('/signin')

#6 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/task/test/sfTestFunctionalTask.class.php(89): include('/home/lkrubner/...')

#7 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/task/sfBaseTask.class.php(68): sfTestFunctionalTask->execute(Array, Array)

#8 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/task/sfTask.class.php(97): sfBaseTask->doRun(Object(sfCommandManager), NULL)

#9 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/command/sfSymfonyCommandApplication.class.php(76): sfTask->runFromCLI(Object(sfCommandManager), NULL)

#10 /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/command/cli.php(20): sfSymfonyCommandApplication->run()

#11 /home/lkrubner/dev/tastingnotes/symfony(14): include('/home/lkrubner/...')

#12 {main}

# Looks like everything went fine.



So, '/signin' seems to get a 404 error, even though I can go to in my browser without a problem.



[UPDATE]

Apparently I was dealing with the same bug described here:

http://sandbox-ws.com/2009/01/functional-testing-a-secured-module/

Sam wrote:

I have noticed some strange behaviour. If you enable security globally and tries to access a non existing module/action via browser you get displayed a 404 page correctly, but if you try that as a functional test you will be redirected to the login page. Does this occur with sfGuard too? I wanted to test the security of some module to ensure that the correct actions are permitted and others not. But this incorrect rendering of the scenario is somehow not very helpful


That bug existed in 2009. I'm surprised it was not fixed yet.

This question has been answered.

Lawrence Krubner | 03/16/11 at 1:03pm Edit

Previous versions of this question: 03/16/11 at 5:02pm | 03/16/11 at 5:05pm | 03/21/11 at 12:01pm | 03/21/11 at 1:13pm | 03/21/11 at 1:15pm | 03/21/11 at 1:25pm | 03/21/11 at 1:29pm | 03/21/11 at 1:38pm | 03/21/11 at 1:42pm

The experts have suggested, on average, a prize of $10 for this question.

(17) Responses

See a threaded view of answers?

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

  • avatar
    Last edited:
    03/21/11
    1:43pm
    Francesco Tassi says:

    use followRedirect() instead of isRedirected()

  • avatar
    Last edited:
    03/21/11
    1:43pm
    Jakub Zalas says:

    Here is an example copied from one of my projects:


    $browser->get('/signin')->
    click('.signin_login', array('signin' => array('username' => 'user', 'password' => '$ecret')))->
    with('form')->hasErrors(false)->
    with('user')->begin()->
    isAuthenticated(true)->
    hasCredential(array('frontend.user'))->
    end()->
    followRedirect()->
    with('request')->begin()->
    isParameter('module', 'article')->
    isParameter('action', 'index')->
    end()->
    with('response')->begin()->
    isStatusCode(200)->
    end()
    ;


    You can debug many testsers (form, response, etc) with debug() method:


    $browser->get('/signin')->
    click('.signin_login', array('signin' => array('username' => 'user', 'password' => '$ecret')))->
    with('form')->debug()
    ;


    Previous versions of this answer: 03/16/11 at 5:12pm

  • avatar
    Last edited:
    03/16/11
    3:46pm
    Lawrence Krubner says:

    I get "The request was not redirected. "

    See the attached screenshot.

    attachment image expert uploaded image

  • avatar
    Last edited:
    03/16/11
    4:00pm
    Francesco Tassi says:

    maybe the request was not redirected :D
    The for might have some errors, try using form validator to check it out.
    This is a better implementation of signin method:

    https://gist.github.com/873204

    Could add a debug()-> before line 9 to check form errors. (notice that a test will always fail with a debug() in it)

  • avatar
    Last edited:
    03/16/11
    4:10pm
    Francesco Tassi says:

    Maybe you are missing csrf token, try to get() signin page and then click() submit button instead of sending your post data with post() method.

    Using click() you submit real form with hidden data (as csrf token).

  • avatar
    Last edited:
    03/16/11
    4:35pm
    Lawrence Krubner says:

    Went to git. Now using this code:


    class sfGuardTestFunctional extends sfTestFunctional {

    public function signin($username, $password) {

    return $this->
    info(sprintf('Signin user using username "%s" and password "%s"', $username, $password))->
    post('/sfGuardAuth/signin', array('signin' => array('username' => $username, 'password' => $password,)))->
    with('form')->begin()->
    hasErrors(0)->
    end()->
    isRedirected()
    ;
    }
    }





    lkrubner@webdev:~/dev/tastingnotes$ ./symfony test:functional tastingnotes RestaurantAwardsActions
    # get /restaurant_award/index
    > Signin user using username "xxx" and password "xxx"
    # post /sfGuardAuth/signin
    not ok 1 - the submitted form has 0 errors.
    # Failed test (./lib/vendor/symfony/lib/test/sfTesterForm.class.php at line 91)
    # got: 1
    # expected: 0

    PHP sent a "warning" error at /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/test/sfTestFunctionalBase.class.php line 433 (call_user_func_array(): First argument is expected to be a valid callback, 'sfBrowser::isRedirected' was given)


    1..1
    # Looks like you failed 1 tests of 1.

  • avatar
    Last edited:
    03/16/11
    4:44pm
    Lawrence Krubner says:

    I guess I'm confused about this. I thought this was standard with Symfony? I've never worked with 1.4 before, but I thought Symfony made it easy to test pages, even those that are secured?

    My user account has super admin privileges. The page requires a special "restaurant_reader" credential, but I assume super admin overrides all that. Anyway to test?

  • avatar
    Last edited:
    03/16/11
    4:44pm
    Francesco Tassi says:

    sorry, to much copy/paste.
    isRedirected() is not a valid method, you have to use followRedirect().

    I've fixed here:

    https://gist.github.com/873204/5bcdb84dd86f6944fd6473d9415388ea76608505

    However using click() instead of post() would be a better solutions but to write a correct test i need your to now your login action url and your form markup (to check how to identift submit button), something like this:

    https://gist.github.com/873204/2f6a2b8afe3d58d08546d7fffc86e376cbc8dad5

    Be sure to replace:

    /sfGuardAuth/signin on line 7 with your signin url
    first signin in line 8 with something thatk match your submit button (value or id)

  • avatar
    Last edited:
    03/16/11
    5:18pm
    Francesco Tassi says:

    here are two example:

    https://gist.github.com/873338/2aca69671586a160e62c98172abaa7e9c1287a09

    you have to replace your*** string with real value (the depends on your code), but it should work.

    To authenticate with functional test you have to:

    - get signin page
    - click submit button sending correct username and password
    - followRedirect

  • avatar
    Last edited:
    03/21/11
    11:57am
    Lawrence Krubner says:

    I appreciate the sample code, but it does not seem to work. I get the error:

    Could not find the element "Signin" (position 1) in the current DOM.  


    I've tried using both the id and the value of the submit button. For instance, here is the HTML of "/signin" on my project:

    <form action="/index.php/login" method="post">
    <table>
    <tbody>

    <tr>
    <th><label for="signin_username">Username or E-Mail</label></th>
    <td><input type="text" name="signin[username]" id="signin_username" /></td>
    </tr>
    <tr>
    <th><label for="signin_password">Password</label></th>
    <td><input type="password" name="signin[password]" id="signin_password" /></td>
    </tr>
    <tr>
    <th><label for="signin_remember">Remember</label></th>

    <td><input type="checkbox" name="signin[remember]" id="signin_remember" /><input type="hidden" name="signin[_csrf_token]" value="309e12fe0b5eb89a9280de310aba0073" id="signin__csrf_token" /></td>
    </tr>
    </tbody>
    <tfoot>
    <tr>
    <td colspan="2">
    <input id="signin_login" type="submit" value="Signin" />
    </td>
    </tr>
    </tfoot>
    </table>
    </form>


    I've tried both this:


      $browser->get('/signin')->
    click('Signin', array('signin' => array('username' => $username, 'password' => $password)))->
    with('form')->hasErrors(false)->
    with('user')->begin()->
    isAuthenticated(true)->
    hasCredential(array('tastingnotes.user'))->
    end()->
    followRedirect()->
    with('request')->begin()->
    isParameter('module', 'restaurant_award')->
    isParameter('action', 'index')->
    end()->
    with('response')->begin()->
    isStatusCode(200)->
    end()
    ;



    and I've tried this:


      $browser->get('/signin')->
    click('signin_login', array('signin' => array('username' => $username, 'password' => $password)))->
    with('form')->hasErrors(false)->
    with('user')->begin()->
    isAuthenticated(true)->
    hasCredential(array('tastingnotes.user'))->
    end()->
    followRedirect()->
    with('request')->begin()->
    isParameter('module', 'restaurant_award')->
    isParameter('action', 'index')->
    end()->
    with('response')->begin()->
    isStatusCode(200)->
    end()
    ;



    I also tried putting a period before the id, as in your example.

    In all cases I get this error:

      Could not find the element "Signin" (position 1) in the current DOM.

  • avatar
    Last edited:
    03/21/11
    12:40pm
    Lawrence Krubner says:

    My bad, partly. The text "Signin" was not unique. I should have given a position. But instead I changed it to unique text:

    Log in now

    But now I still get:

    Could not find the element "Log in now" (position 1) in the current DOM.

  • avatar
    Last edited:
    03/21/11
    12:46pm
    Lawrence Krubner says:

    Changed my code to just:

      $browser->get('/signin')->
    click('Log in now', array('signin' => array('username' => $username, 'password' => $password)))->
    with('form')->debug();


    but debug() gets me nothing since the code basically dies on the click(). All I get is:

    ./symfony test:functional tastingnotes RestaurantAwardsActions
    # get /signin


    Could not find the element "Log in now" (position 1) in the current DOM.


    # Looks like everything went fine.

  • avatar
    Last edited:
    03/21/11
    12:50pm
    Jakub Zalas says:

    Lawrance, '.signin_login' is a css class name of the button:


    <input class="signin_login" type="submit" value="<?php echo __('Log in') ?>

  • avatar
    Last edited:
    03/21/11
    12:51pm
    Jakub Zalas says:

    The dot in front of 'singin_login' is important.

  • avatar
    Last edited:
    03/21/11
    12:54pm
    Jakub Zalas says:

    Also, followRedirect() is a method on browser but isRedirected() is a response tester method.

    It's:

    $browser->followRedirect();


    but:
    $browser->with('response')->isRedirected();

  • avatar
    Last edited:
    03/21/11
    1:09pm
    Lawrence Krubner says:

    I'll try your suggestions.

    I did try:

    $browser->get('/signin')->debug();


    but it only got me:


    ./symfony test:functional tastingnotes RestaurantAwardsActions
    # get /signin


    PHP sent a "warning" error at /home/lkrubner/dev/tastingnotes/lib/vendor/symfony/lib/test/sfTestFunctionalBase.class.php line 433 (call_user_func_array(): First argument is expected to be a valid callback, 'sfBrowser::debug' was given)


    # Looks like everything went fine.

  • avatar
    Last edited:
    03/21/11
    1:13pm
    Lawrence Krubner says:

    Okay, right now I'm using this code:

      $browser->get('/signin')->        
    click('.signin_login', array('signin' => array('username' => $username, 'password' => $password)))->
    with('form')->debug();


    I get this error:

    ./symfony test:functional tastingnotes RestaurantAwardsActions
    # get /signin

    Could not find the element ".signin_login" (position 1) in the current DOM.

    # Looks like everything went fine.


    When I point my browser at '/signin' and look at the source code, this is the HTML I see:


    <form action="/index.php/login" method="post">
    <table>
    <tbody>

    <tr>
    <th><label for="signin_username">Username or E-Mail</label></th>
    <td><input type="text" name="signin[username]" id="signin_username" /></td>
    </tr>
    <tr>
    <th><label for="signin_password">Password</label></th>
    <td><input type="password" name="signin[password]" id="signin_password" /></td>
    </tr>
    <tr>
    <th><label for="signin_remember">Remember</label></th>

    <td><input type="checkbox" name="signin[remember]" id="signin_remember" /><input type="hidden" name="signin[_csrf_token]" value="309e12fe0b5eb89a9280de310aba0073" id="signin__csrf_token" /></td>
    </tr>
    </tbody>
    <tfoot>
    <tr>
    <td colspan="2">
    <input class="signin_login" type="submit" value="Signin" />


    </td>
    </tr>

    </tfoot>
    </table>
    </form>



    Any thoughts why this doesn't work?

This question has expired.





Current status of this question: Completed



Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.