Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to have different base urls per suite #155

Open
wouterj opened this issue Jul 1, 2014 · 13 comments
Open

Allow to have different base urls per suite #155

wouterj opened this issue Jul 1, 2014 · 13 comments

Comments

@wouterj
Copy link
Contributor

@wouterj wouterj commented Jul 1, 2014

I've 2 suites in behat: frontend and backend. They both live on another subdomain. There should be a way to configure the base url per suite.

Does this already exists?

@Sorbing

This comment has been minimized.

Copy link

@Sorbing Sorbing commented Sep 4, 2014

I have the same situation( I do not know how to solve this problem.

@timiTao

This comment has been minimized.

Copy link

@timiTao timiTao commented Jan 9, 2015

you can always create separete profiles, and define others base_url

@jbouzekri

This comment has been minimized.

Copy link

@jbouzekri jbouzekri commented Feb 20, 2015

I tried created separate profile but I don't see a configuration to run all test suites with behat switching automatically profile according to the current suite it is executing.

This is my behat.yml. With this configuration, I would like to run all scenario with the tag club2 on club2.localhost and the other on club1.localhost. With this configuration, I can make the club2 suite work by runing the command : behat --suite=club2 --profile=club2. But I am looking for a way to run all suite in one command and automaticaly switching profile in the suite.

default:
    autoload:
        '': %paths.base%/features/bootstrap
    extensions:
        Behat\Symfony2Extension: ~
        SensioLabs\Behat\PageObjectExtension: ~
        Behat\MinkExtension:
            base_url: http://club1.localhost/
            selenium2: ~
    suites:
        default:
            contexts:
                - Context\FeatureContext
                - Context\SecurityContext
            filters:
                tags: ~@club2
        club2:
            contexts:
                - Context\FeatureContext
                - Context\SecurityContext
            filters:
                tags: @club2

club2:
    extensions:
        Behat\Symfony2Extension: ~
        SensioLabs\Behat\PageObjectExtension: ~
        Behat\MinkExtension:
            base_url: http://club2.localhost/
            selenium2: ~

I don't know if I went the right way, but I found a solution by creating a custom context which modify all context in the environment before each scenario.

<?php

namespace Context;

use Behat\Behat\Hook\Scope\BeforeScenarioScope;

/**
 * Description of MinkOverrideContext
 *
 * @author jobou
 */
class MinkOverrideContext extends Base\BaseMinkContext
{

    protected $baseUrl;

    public function __construct($base_url)
    {
        $this->baseUrl = $base_url;

    }

    /** @BeforeScenario */
    public function gatherContexts(BeforeScenarioScope $scope)
    {
        $environment = $scope->getEnvironment();

        foreach ($environment->getContexts() as $context) {
            if ($context instanceof \Behat\MinkExtension\Context\RawMinkContext) {
                $context->setMinkParameter('base_url', $this->baseUrl);
            }
        }
    }
}

And then loading it only for my club2 suite :

suites:
        club2:
            contexts:
                - Context\FeatureContext
                - Context\SecurityContext
                - Context\MinkOverrideContext:
                    base_url: http://club2.localhost/
            filters:
                tags: @club2

It seems to work but I would like to have your feedback on good and bad practice of what I am doing.

@amitaibu

This comment has been minimized.

Copy link

@amitaibu amitaibu commented Mar 3, 2015

Indeed, it seems only the base_url of default is taken into account, and the rest are ignored.

@amitaibu

This comment has been minimized.

Copy link

@amitaibu amitaibu commented Mar 3, 2015

That's the closest example that I found for v3, but even when I do the following it doesn't work:

class ApiContext extends MinkContext {

  public function __construct($base_url) {
    $this->setMinkParameter('base_url', $base_url);
  }
}
@jbouzekri

This comment has been minimized.

Copy link

@jbouzekri jbouzekri commented Mar 3, 2015

I think it only changes the base_url parameter for the current context instance. If you look at my example #155 (comment). I was able to make it works by changing the base_url parameter in all context involved in my test suites. However I don'y know if there is a better solution.

    /** @BeforeScenario */
    public function gatherContexts(BeforeScenarioScope $scope)
    {
        $environment = $scope->getEnvironment();

        foreach ($environment->getContexts() as $context) {
            if ($context instanceof \Behat\MinkExtension\Context\RawMinkContext) {
                $context->setMinkParameter('base_url', $this->baseUrl);
            }
        }
    }
@jacquesbh

This comment has been minimized.

Copy link

@jacquesbh jacquesbh commented Mar 8, 2015

I have the same problem.

I use a website with subdomains (two applications linked to each other), and I need to do that, by example:

Feature: 404
    In order to see 404 pages
    As a visitor
    I need to visit bad url

@www1
Scenario: 404 on www1
    Given I am on "blabla"
    Then the response status code should be 404

@www2
Scenario: 404 on www2
    Given I am on "blabla"
    Then the response status code should be 404

I think using tags is the best way to update the base_url for each scenario. But my problem is: how?

    /** @BeforeScenario */
    public function updateUrl(BeforeScenarioScope $scope)
    {
        // Here I need to access configuration
        // If the tag @www1: use www1->base_url in configuration
        // If the tag @www2: use www2->base_url in configuration
        // But… how set the new base url and how make it works :/
    }

I don't want to use profiles because I want to run all tests but on different URLs.

@kyleferguson

This comment has been minimized.

Copy link

@kyleferguson kyleferguson commented Aug 20, 2015

With MinkExtension you can call setMinkParameter to set the base url inside the definition of a step. For example, you could have a step:

Given I am on subdomain "foo"

With a definition like:

/**
 * @Given I am on subdomain :name
 */
public function iAmOnSubdomain($name)
{
    $url = 'http://'.$name.'.myapp.com';
    $this->setMinkParameter('base_url', $url);
}

You can also call getMinkParameter('base_url') to get the default and alter as needed.

@capkafitz

This comment has been minimized.

Copy link

@capkafitz capkafitz commented Oct 20, 2016

Combining the answers of jacquesbh and kyleferguson you could do something like this:

  1. Using tags to change the base_url
Feature: 404
    In order to see 404 pages
    As a visitor
    I need to visit bad url

@www1
Scenario: 404 on www1
    Given I am on "blabla"
    Then the response status code should be 404

@www2
Scenario: 404 on www2
    Given I am on "blabla"
    Then the response status code should be 404
  1. Using setMinkParameter to change the base_url
/** 
 * @BeforeScenario @www1
 */
public function updateUrlToWw1()
{
    $this->setMinkParameter('base_url', 'url to www1');
}

/** 
 * @BeforeScenario @www2
 */
public function updateUrlToWw2()
{
    $this->setMinkParameter('base_url', 'url to www2');
}

@jacquesbh

This comment has been minimized.

Copy link

@jacquesbh jacquesbh commented Oct 25, 2016

I like this solution!

It's a really good idea, very simple. As simple that we didn't see it!

@sumachaa

This comment has been minimized.

Copy link

@sumachaa sumachaa commented Dec 15, 2016

BeforeScenario & setMinkParameter is setting the value correctly,

but for the step

Given I am on the homepage
OR
Given I am on "xyz"

This resets the value of the base_url to the value defined in YML file

@BramDriesen

This comment has been minimized.

Copy link

@BramDriesen BramDriesen commented Feb 22, 2017

Sorry to bump this but for us the solution of jbouzekri actually did the trick. So some context, we set a base_url in our custom FeatureContext since we can't use the selenium2 base_url anymore if we want to switch around.

In our behat.yml we added a custom parameter which we save in our FeatureContext.

Behat.yml

default:
    suites:
        default:
            contexts:
                - FeatureContext:
                    parameters:
                        base_url: "https://pim.local.example.com"

The basic logic is that we set the base url for every scenario with the before scenario hook. If we want to change it we call an extra step Given I change the base url to frontend (We only need to switch between the first sub domain https://pim.example.com and https://example.com or another example https://pim.local.example.com and https://local.example.com

Featurecontext:

  /**
   * Parameters array.
   *
   * @var array
   */
  protected $parameters;

  /**
   * Environment array.
   *
   * @var array
   */
  protected $environment;

  /**
   * Initializes context.
   *
   * Every scenario gets its own context instance.
   * You can also pass arbitrary arguments to the
   * context constructor through behat.yml.
   *
   * @param array $parameters
   *   Parameters from the behat.yml.
   */
  public function __construct($parameters) {
    $this->parameters = $parameters;
  }

  /**
   * Set before each scenario the base URL, if needed override it.
   *
   * @see iChangeTheBaseUrlToFrontend
   *
   * @BeforeScenario
   */
  public function beforeScenario(BeforeScenarioScope $scope) {
    // Load and save the environment for each scenario.
    $this->environment = $scope->getEnvironment();
    // Set the base URL. Can be overridden check @see.
    $base_url = $this->parameters['base_url'];
    $this->setBaseUrl($base_url);
  }

  /**
   * Function to change the base URL to frontend, needed for all frontend tests.
   *
   * @Given I change the base url to frontend
   */
  public function iChangeTheBaseUrlToFrontend() {
    $base_url = $this->parameters['base_url'];
    $base_url = str_replace('https://pim.', '', $base_url);
    $url = 'https://' . $base_url;
    $this->setBaseUrl($url);
  }

  /**
   * Sets the base URL for all environments.
   *
   * @param string $url
   *   The url to set.
   *
   * @see: https://github.com/Behat/MinkExtension/issues/155#issuecomment-77041296
   */
  private function setBaseUrl($url) {
    foreach ($this->environment->getContexts() as $context) {
      if ($context instanceof \Behat\MinkExtension\Context\RawMinkContext) {
        $context->setMinkParameter('base_url', $url);
      }
    }
  }

I hope this can help some one else in the future since it was quite a challenge to find this out :)

@stof

This comment has been minimized.

Copy link
Member

@stof stof commented Jul 17, 2019

Well, this is the repo of the MinkExtension. So of course everything is about Mink. Anything else is out of the scope of this extension.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.