MageTest / BehatMage

Behat for Magento
MIT License
85 stars 31 forks source link

Renaming Step iAmOn ( it is already defined in MinkContext) #35

Open ctasca opened 10 years ago

ctasca commented 10 years ago

This exception is thrown when trying to use MinkContext in a subclass of MagentoContext.

In this scenario:

behat.yml

default:
    formatter:
        name: pretty
    context:
        class: MyMagentoContext
        parameters:
             base_url:   http://example.dev
    extensions:
        MageTest\MagentoExtension\Extension:
            base_url: "http://example.dev"
        Behat\MinkExtension\Extension:
            base_url: http://example.dev
            goutte:
                server_parameters:
                    HTTP_HOST: %behat.mink.base_url%
            sahi: ~
customer:
    context:
        class: CustomerUserContext
        parameters:
             base_url:   http://example.dev

admin:
    context:
        class: AdminUserContext
        parameters:
             base_url:   http://example.dev

module:
    context:
        class: ModuleContext
        parameters:
             base_url:   http://example.dev

WHERE MyMagentoContext is in composer autoload and have following constructor:

class MyMagentoContext extends MagentoContext
{
    private $output;

    public function __construct(array $parameters)
    {
        $this->useContext('mink', new MinkContext);
    }

and AdminUserContext is defined as follow

use Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\TableNode;
use MageTest\MagentoExtension\Context\MagentoContext;

class AdminUserContext extends MyMagentoContext
{
    /**
     * @Given /^I am on the dashboard after logging in with "([^"]*)" and "([^"]*)"$/
     */
    public function iAmOnTheDashboardAfterLoggingInWithAnd($username, $password)
    {
        $this->getSession()->visit($this->getMinkParameter('base_url') . '/admin');
        $this->getSession()->getPage()->fillField('username', $username);
        $this->getSession()->getPage()->fillField('login', $password);
        $this->getSession()->getPage()->pressButton('Login');
        $this->iCloseMessagePopUp();
    }

    /**
     * @Given /^I close message pop up$/
     */
    public function iCloseMessagePopUp()
    {
        $this->getSession()->wait(2000);
        $function = <<<JS
(function(){
    closeMessagePopup();
})()
JS;
        return $this->getSession()->getDriver()->evaluateScript($function);
    }
}

WHEN I run command

bin/behat features/admin --profile admin

I get

  [Behat\Behat\Exception\RedundantException]
  Step "/^(?:|I )am on "(?P<page>[^"]+)"$/" is already defined in AdminUserContext::iAmOn()

  AdminUserContext::iAmOn()
  Behat\MinkExtension\Context\MinkContext::visit()

To make it all working I need to remove iAmOn from MagentoContext class. Maybe it should be renamed?

Thanks

alistairstead commented 10 years ago

Ideally people would not use MinkContext. This context provides too low level language. The Magento context should include elements of MinkContext as relevant and also domain specific steps.

Using MinkContext encourages feature definitions and steps that focus on implementation such as clicking links.... filling in forms one field at a time. This is great to get started but can become problematic as implementations change.

We constantly debate weather we should make it compatible with MinkContext or duplicate the step definitions.

The symfony2 context is a good example.

ctasca commented 10 years ago

I have been using MinkContext mainly because I am using Mink with Sahi Driver, and works better when inheriting methods from MinkContext rather than RawMinkContext. There is so much JS on admin side of Magento I thought Sahi would be better.

I was just wondering if renaming it would help who has this type of setup and prefer using MinkContext, but will have a look at symfony2 one as you suggested.

Thanks

Rud5G commented 10 years ago

As a temporary workaround its possible in php5.4 to use MinkDictionary as a trait.

class MyMagentoContext extends MagentoContext
{
    use MinkDictionary { visit as private; }

    private $output;

    public function __construct(array $parameters)
    {
        //$this->useContext('mink', new MinkContext);
    }

I'll also have a look at the symfony2 context.

jasperdcbe commented 10 years ago

I have implemented the workaround as described by Rud5G. I really did not feel like rewriting everything from MinkContext as it really has some very useful default functions.