Laravel4 Tutorial – Episode 1 from Abu Ashraf Masnun on Vimeo.
While doing acceptance tests, we often run into scenarios where we need to click on elements which can’t be found or clicked on using simple expressions like – I follow “Login”. Let me give an example, on a page there is an anchor tag with specific id. The anchor tag has no text but an image inside it. In such cases, we are left no other choices than querying the dom. XPath could be a decent way to find the anchor tag here. Let’s assume that the anchor tag has the id – 14. So the xpath query should be – “//a[@id=’14’]”.
PS: We can use Firebug to test out XPath queries. There is a built in function – $x – on a firebug console, just pass xpath queries as string to this function and it will throw matching elements.
Here’s a step definition I wrote inside my FeaturedContext class. This method takes in a xpath query and clicks on the element:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/** * Click on the element with the provided xpath query * * @When /^I click on the element with xpath "([^"]*)"$/ */ public function iClickOnTheElementWithXPath($xpath) { $session = $this->getSession(); // get the mink session $element = $session->getPage()->find( 'xpath', $session->getSelectorsHandler()->selectorToXpath('xpath', $xpath) ); // runs the actual query and returns the element // errors must not pass silently if (null === $element) { throw new \InvalidArgumentException(sprintf('Could not evaluate XPath: "%s"', $xpath)); } // ok, let's click on it $element->click(); } |
And how do we use it inside a “feature” file?
1 |
Given I click on the element with xpath "//a[@id='14']" |
Using a jQuery like CSS Selector is pretty easy. Looks like Mink also allows CSS Selectors by default. Here’s the same method with CSS Selector:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** * Click on the element with the provided CSS Selector * * @When /^I click on the element with css selector "([^"]*)"$/ */ public function iClickOnTheElementWithCSSSelector($cssSelector) { $session = $this->getSession(); $element = $session->getPage()->find( 'xpath', $session->getSelectorsHandler()->selectorToXpath('css', $cssSelector) // just changed xpath to css ); if (null === $element) { throw new \InvalidArgumentException(sprintf('Could not evaluate CSS Selector: "%s"', $cssSelector)); } $element->click(); } |
And we use it in the feature file like:
1 |
Given I click on the element with css selector "a#14" |
The test should fail in case a matching element was not found. Let me know if you run into any issues or find even better or elegant ways to do this.
I usually use Apache and it’s PHP5 module for my day to day php development. However, here came a time, when I needed to work on a project that involved using nginx. Installing nginx was easy with homebrew:
1 |
brew install nginx |
However, the recommended way to use php with nginx is using php-fpm. Since I use the apache module most of the time and building php with fpm builds it “–without-apache”, I didn’t want to go for anything complex for just one project at hand. I knew I could use the native “php-cgi” module, so I just googled, found few tips and set it up.
This is my nginx configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; server { listen 8080; server_name localhost; location / { root /Users/masnun/Sites; index index.html index.htm index.php; } # pass the PHP scripts to FastCGI server listening on unix socket location ~ \.php$ { root /Users/masnun/Sites; fastcgi_pass unix:/tmp/php.socket; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } } |
Basically, all I did was change the root element to point to my current “~/Sites” directory which I use as the htdocs for apache. And I’m using unix sockets for better performance. Please read the nginx docs if you don’t understand any of the directives but I’m pretty confident that all of them are more or less self explanatory.
Now, we bind php-cgi to the socket mentioned in our nginx conf file. That’s quite straightforward:
1 |
php-cgi -b /tmp/php.socket |
Once we have updated the nginx configuration and started the php-cgi process, we should restart nginx:
1 2 |
nginx -s stop nginx |
This should restart nginx and all files with the “.php” extension will be parsed by php.
If you get “no input file specified”, check your nginx configuration and make sure that the paths are all correct. Specially this one:
1 |
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
Also check that if the root element is defined in appropriate scope for the block to have access to. If you still run along some issues, do a quick google or ask in stackoverflow. And feel free to experiment with different nginx features, specially url rewrites 🙂