27

I'm totally new with CodeCeption.

I want to do an action/assertion depending on another assertion result, like this:

if ($I->see('message')){

    $I->click('button_close');

}

Is something like that possible? I tried, but doesn't work. Probably the assertion result doesn't apply to IF, but is there any alternative?

Thanks in advance!

IMPORTANT UPDATE:

Finally Codeception now has the function performOn!! http://codeception.com/docs/modules/WebDriver#performOn

Borjovsky
  • 758
  • 2
  • 10
  • 24

8 Answers8

22

I had this same issue. Although it's not ideal, you can do this:

try {
    $I->see('message');
    // Continue to do this if it's present
    // ...
} catch (Exception $e) {
    // Do this if it's not present.
    // ...
}
DAB
  • 1,303
  • 14
  • 23
  • Great!! This solution is better than mine! Much more flexible, and looks better. I didn't know that try/catch could work. Thank you very much! – Borjovsky Dec 18 '15 at 11:44
  • np! One thing to note - it won't show the test as failed, but if you do have a failure after that it may add an additional error line that can be confusing. But if the rest of the tests pass it won't complain. – DAB Dec 18 '15 at 16:48
  • Thanks DAB! I guess I'll be able to deal with such situations with the catch. – Borjovsky Dec 18 '15 at 23:41
  • This didn't do anything for me, my tests still fail if the element isn't present. Anyone have any follow ups? – Pix81 Dec 31 '20 at 21:10
  • This right here has just saved the last of the thinning hair on my head from being pulled out, Catching the exception it seems is the only way to run a specific conditional like this = for instance I have a page that only displays a form once a button is pressed, trying to $I->see means I can tell the test to press the button (it is not always enabled) Thank you! – JimmyBorofan Aug 09 '22 at 10:20
10

In tests/_support/AcceptanceHelper.php add additional method

function seePageHasElement($element)
{
    try {
        $this->getModule('WebDriver')->_findElements($element);
    } catch (\PHPUnit_Framework_AssertionFailedError $f) {
        return false;
    }
    return true;
}

Then to test in your acceptance test use:

if ($I->seePageHasElement("input[name=address]")) {
    $I->fillField("input[name=address]", "IM");
}
Community
  • 1
  • 1
Matija
  • 17,604
  • 2
  • 48
  • 43
4

You can use a workaround like this or similar combinations:

$tmp = $I->grabTextFrom('SELECTOR');
if ($tmp == 'your text') {

$I->click('button_close');

}
Wonderas
  • 111
  • 1
  • 5
  • That idea is fine, but there is a problem: If the 'SELECTOR' is not present (no 'message' in my example), the assertion fails and the test suite stops. So, one assertion **must** depend on another assertion. But thank you anyway! – Borjovsky Nov 12 '14 at 17:24
3

ULTIMATE SOLUTION!

Finally Codeception now has the function performOn, wich does exactly what I asked for!!

[Version 2.2.9]

http://codeception.com/docs/modules/WebDriver#performOn

Answering my example:

$I->performOn('.message', ['click' => '#button_close'], 30);

Waits up to 30 seconds to see the element with class='message', then click the element with id='button_close'.

Borjovsky
  • 758
  • 2
  • 10
  • 24
2

Codeception now has tryTo..., e.g, tryToSee() trytoClick(), etc., so there's no need for a Try/Catch block. I find it more readable than performOn().

You need to enable it with this in acceptance.suite.yml or codeception.yml:

# enable conditional $I actions like $I->tryToSee()
step_decorators:
    - \Codeception\Step\TryTo
    - \Codeception\Step\ConditionalAssertion`

You can click on something that may or may not be there with:

$I->tryToClick('#save_button`);

If there's no button, the code goes on with no error message. This could also be used to click on the node to expand a section of a tree before examining it, but only if that section is closed (there should always be a class that's only there when it's closed).

Another way to go is in an if statement. The tryTo... methods all return true on success and false on failure, so you can do this, which some might consider clearer than the above (no error will be thrown):

if ($I->tryToSee('some_locator')) {
    $I->click('some_locator');
}

This form is also useful if there is a sequence of actions you want to perform based on a condition, the else is optional.

if ($I->tryToSee('some_locator')) {
    $I->fillField('username', 'myname');
    $I->fillfield('password', 'mypassword);
    $I->click('Submit');
} else {
   /* Do something else */
}
Bob Ray
  • 1,105
  • 10
  • 20
0

Release for my project comes on weeken

/**
 * https://stackoverflow.com/questions/26183792/use-codeception-assertion-in-conditional-if-statement
 * @param $element
 * @return bool
 * @throws \Codeception\Exception\ModuleException
 */
public function seePageHasElement($element)
{
    $findElement = $this->getModule('WebDriver')->_findElements($element);
    return count($findElement) > 0;
}
0

The reason why the assertion doesn't work with conditional statements is that Codeception first executes the assertion inside the IF brackets, and in case it is not true - it fails the test right away. My way of overcoming this is using the SOFT assertions TryTo which will be ignored by Codeception if fails: https://codeception.com/docs/08-Customization#Step-Decorators

if ($I->tryToSee('message')){

    $I->click('button_close');

}```
EvgenyPok
  • 9
  • 1
-1

100% working solution !! Thanx me later ;)

In tests/_support/AcceptanceHelper.php add additional method

public function seePageHasElement($element)
{
    try {
        $this->getModule('WebDriver')->_findElements($element);
    } catch (\PHPUnit_Framework_AssertionFailedError $f) {
        return false;
    }
    return true;
}

Then to test in your acceptance test use:

if ($I->seePageHasElement($element)) {
    $I->fillField($element);
}

The 'seeElement' function of WebDriver doesnot work on this case so needs little modified function as i have used one '_findElements' .Please donot forget to build your actors after any changes done.

iamuser2
  • 1,041
  • 1
  • 7
  • 4
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/low-quality-posts/16363692) – Naktibalda Jun 08 '17 at 14:20
  • What do you mean with "This does not work"? Do you get an error? Please be specific. – Naktibalda Jun 08 '17 at 14:23
  • @Naktibalda i mean by "This does not work"? is that the solution doesnot work for me as i had the same case. I figured out the right solution that worked for me & i have posted it so that needy can be benefited. – iamuser2 Jun 09 '17 at 06:11
  • A problem with your solution is that `_findElements` doesn't throw PHPUnit_Framework_AssertionFailedError exception when the element does not exist, it returns an empty array. – Naktibalda Jun 09 '17 at 09:12
  • @Naktibalda ur right !! That part isnot handled.I provide the solution to fulfill the need of using 'IF' statement to compare something and do the required task if its true. And i didnot find any working solution for using "IF" condition in my codeception code. – iamuser2 Jun 09 '17 at 11:54
  • That's Matija's solution. – Borjovsky Jan 13 '18 at 23:21