GU10 follow up – price checking

This is really a follow up to http://blog.v-s-f.co.uk/2011/12/the-real-cost-of-gu10s/.  I’ve been monitoring the prices of the new 4W LED GU10s on CPC for a few weeks now.  When CPC adds a product to their website, they add the base product code, E.g. LP04169 and then there are up to 99 further product code permutation possible.  E.g. LP04169[01-99].  For the past three weeks I’ve been checking all the codes manually (typing in the product code into the search and visually identifying the cheapest product code.

So today (yes… I know it’s Christmas day, but I couldn’t sleep…) I decided to automate the process.  I started off by writing a program using Mule 3.2, but Mule doesn’t follow the redirects and load the Javascript correctly.  So my next choice was Selenium, but I don’t like the fiddly UI for firefox.  I created the bare basics for a Selenium test and then found I could export the test to Java!  I last used Java Selenium 2 years ago and it wasn’t all that easy, but they’ve vastly improved it since then and added Maven support.  I then proceeded to re-write the code it automatically generated and added in what I really wanted to achieve – price checking.

Below is the code required to check a product on CPC for the lowest price available:

(I’ve used TestNG rather than Junit as it was the test framework already imported for the previous utilities class, but it could be substituted for Junit.)

/**
 * <p>Copyright 2011 Victoria Scales</p>
 * <p>This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</p>
 * <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.</p>
 * <p>You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.</p>
 */
package uk.co.vsf.utilities;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

/**
 * Simple class for checking the price of a CPC product to find the cheapest code.
 * 
 * @author Victoria
 * @date 2011-12-25
 * @version 0.1
 */
public class CPCPriceCheckerSelenium
{
    // set the driver to the firefox driver by default
    private WebDriver driver = new FirefoxDriver();
    // set the url to the website you wish to check
    private String baseUrl = "http://cpc.farnell.com/";

    @BeforeMethod
    public void setUp() throws Exception
    {
        // this configures a timeout if a selection is not successful after X seconds.
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    }

    @Test
    public void productPriceCheck() throws Exception
    {
        Map<String, Double> pricesFound = new HashMap<String, Double>();
        final int pagesPossible = 100;
        for (int i = 0 ; i < pagesPossible ; i++)
        {
            try
            {
                String product = "LP04169" + pageExtension(i);
                driver.get(baseUrl + product);

                // select the price off the page (if possible)
                // if the text is not found, NoSuchElementException is thrown.
                String price = driver.findElement(By.cssSelector("span.taxedvalue")).getText();
                price = price.replace("(£", "");
                price = price.replace(")", "");

                double priceAsMonetary = Double.parseDouble(price);

                pricesFound.put(product, priceAsMonetary);
            }
            catch (NoSuchElementException e)
            {

            }

            // wait for 10 seconds so as not to spam the website and get blocked...
            Thread.sleep(10000);
        }

        List<String> productCodes = new ArrayList<String>();
        productCodes.addAll(pricesFound.keySet());
        Collections.sort(productCodes);

        for (String instance : productCodes)
        {
            System.out.println(instance + " " + pricesFound.get(instance));
        }

        // cheapest price

        List<Double> pricesOrdered = new ArrayList<Double>();
        pricesOrdered.addAll(pricesFound.values());
        Collections.sort(pricesOrdered);

        System.out.println();
        System.out.println("Cheapest price: £" + pricesOrdered.get(0));
        System.out.println("Most expensive price: £" + pricesOrdered.get(pricesOrdered.size() - 1));
    }

    private String pageExtension(int i)
    {
        if (i == 0)
        {
            return "";
        }
        else if (i > 9)
        {
            return "" + i;
        }

        return "0" + i;
    }

    @AfterMethod
    public void tearDown() throws Exception
    {
        driver.quit();
    }
}

To use Selenium with Maven add the following to your pom:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>2.15.0</version>
</dependency>