Skip to content
brianium edited this page Nov 8, 2014 · 5 revisions

Scopes are a very powerful feature of Peridot. All tests and suites in Peridot have a Scope associated with them.

A scope's most basic use is a place to safely store state for a test without causing collisions with tests themselves. When a test or suite makes a reference to $this it is actually referring to the Scope of that test or suite.

Scope objects are passed from parent nodes to their children.

##Extending functionality with scopes Since $this refers to a Scope inside of a test or suite, it gives us the ability to add additional state and behavior to that Scope.

How can we do this? Peridot uses a concept of child scopes to mix specialized behavior into an existing scope. This is exactly how the HttpKernel plugin adds BrowserKit functionality to tests, and how the Prophecy plugin is able to automatically inject mocks into tests.

Consider the following custom scope:

class WebDriverScope extends Scope
{
    protected $driver;
    protected $emitter;

    public function __construct(RemoteWebDriver $driver, EventEmitterInterface $emitter)
    {
        $this->driver = $driver;
        $this->emitter = $emitter;
        $this->emitter->on('runner.end', function() {
            $this->driver->quit();
        });
    }
    public function getPage($url)
    {
        $this->driver->get($url);
    }

    public function findElementById($id)
    {
        return $this->driver->findElement(\WebDriverBy::id($id));
    }
}

We can leverage this new behavior by adding it as a child scope:

###Adding via a plugin: One possible way to mix this scope in is via the peridot.php file using events

//peridot.php
return function(EventEmitterInterface $emitter) {
    $driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome());
    $driverScope = new WebDriverScope($driver);

    //add this scope into every suite
    $emitter->on('suite.start', function($test) use ($driverScope) {
        $test->getScope()->peridotAddChildScope($driverScope);
    });
}

###Adding manually Another possible way to mix a child scope in is to do so manually on a test or suite:

describe('The home page', function() {
    $driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome());
    $driverScope = new WebDriverScope($driver);
    $this->peridotAddChildScope($scope);

    it('should have a greeting', function() {
        $this->getPage('http://localhost:4000'); //getPage is made available by child scope
        $greeting = $this->findElementById('greeting'); //so is findElementById
        assert($greeting->getText() === "Hello", "should be Hello");
    });
});

###How child scopes work If a request for a method or property is made in a test or suite, and it does not exist on the root scope of that test or suite, the root scope will search all of it's descendants for a match.

This method allows us to build a hierarchy of child scopes containing specialized behavior and state without using traditional inheritance. We can visualize such a hierarchy like this:

                           +-----------+                        
                           |    Test   |                                          
                           +-----+-----+                        
                                 |                              
                                 |                              
                           +-----+-----+                        
                           |   Scope   |                        
                           +-----------+                        
                           |           |                        
       +-------+--------+--+           +--+-----------------+
       | WebDriverScope |                 | MockObjectScope |               
       +-------+--------+                 +-----------------+
               |                                                   
               |                                                                                                      
   +-----------+-----------+                                       
   | SpecialWebDriverScope |                                                            
   +-----------------------+                                       

##Plugins that leverage scopes

Clone this wiki locally