com.arcbees.test.CurrentScenarioAspect.java Source code

Java tutorial

Introduction

Here is the source code for com.arcbees.test.CurrentScenarioAspect.java

Source

/*
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.arcbees.test;

import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;

import com.arcbees.test.annotation.ImplicitWait;
import com.google.inject.Inject;

import cucumber.runtime.StepDefinitionMatch;
import cucumber.runtime.model.CucumberScenario;
import gherkin.formatter.model.Step;

import static org.openqa.selenium.remote.CapabilityType.BROWSER_NAME;

@Aspect
public class CurrentScenarioAspect {
    private static final ThreadLocal<CucumberScenario> scenario = new ThreadLocal<CucumberScenario>();
    private static final ConcurrentMap<String, WebDriver> webDrivers = new ConcurrentHashMap<String, WebDriver>();
    private static final ConcurrentMap<Step, CucumberScenario> steps = new ConcurrentHashMap<Step, CucumberScenario>();
    private static final ReentrantLock lock = new ReentrantLock(true);

    @Inject(optional = true)
    @ImplicitWait
    private Long implicitWait = 0L;

    @Before("(call(public * cucumber.runtime.model.CucumberScenario.run(..))) "
            + "|| (call(public * cucumber.runtime.model.CucumberTagStatement.run(..)) "
            + "&& target(cucumber.runtime.model.CucumberScenario))")
    public void beforeRunningScenario(JoinPoint thisJoinPoint) throws InterruptedException {
        scenario.set((CucumberScenario) thisJoinPoint.getTarget());
        lock.lock();
        registerSteps(scenario.get());
    }

    @After("call(public * cucumber.runtime.model.CucumberScenario.run(..)) "
            + "|| (call(public * cucumber.runtime.model.CucumberTagStatement.run(..))"
            + "&& target(cucumber.runtime.model.CucumberScenario))")
    public void afterRunningScenario() {
        webDrivers.remove(getScenarioName());
        lock.unlock();
        scenario.set(null);
    }

    @Before("call(public * cucumber.runtime.StepDefinitionMatch.runStep(..)) && within(cucumber.runtime.Runtime)")
    public void beforeRunningStep(JoinPoint thisJoinPoint) {
        StepDefinitionMatch stepDefinitionMatch = (StepDefinitionMatch) thisJoinPoint.getTarget();
        Step step = (Step) getFieldValueInObject(stepDefinitionMatch, "step");
        setScenarioFromStep(step);
    }

    @After("call(public * cucumber.runtime.StepDefinitionMatch.runStep(..)) && within(cucumber.runtime.Runtime)")
    public void afterRunningStep(JoinPoint thisJoinPoint) {
        StepDefinitionMatch stepDefinitionMatch = (StepDefinitionMatch) thisJoinPoint.getTarget();
        Step step = (Step) getFieldValueInObject(stepDefinitionMatch, "step");
        steps.remove(step);
    }

    @Around("call(public * javax.inject.Provider.get(..)) && target(com.arcbees.test.WebDriverProvider)")
    public java.lang.Object aroundGetWebDriver(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        if (TestParameters.USE_SELENIUM_GRID) {
            return getGridWebDriver();
        } else {
            return getDefaultWebDriver();
        }
    }

    private void registerSteps(CucumberScenario scenario) {
        registerSteps(scenario, scenario.getSteps());
        if (scenario.getCucumberBackground() != null) {
            registerSteps(scenario, scenario.getCucumberBackground().getSteps());
        }
    }

    private void registerSteps(CucumberScenario scenario, List<Step> scenarioSteps) {
        for (Step step : scenarioSteps) {
            steps.put(step, scenario);
        }
    }

    private void setScenarioFromStep(Step step) {
        CucumberScenario stepScenario = steps.get(step);
        scenario.set(stepScenario);
    }

    private WebDriver getDefaultWebDriver() {
        WebDriver webDriver = webDrivers.get(getScenarioName());
        if (webDriver == null) {
            webDriver = new ChromeDriver();
            initWebDriver(webDriver);
        }
        return webDriver;
    }

    private WebDriver getGridWebDriver() throws MalformedURLException {
        WebDriver webDriver = webDrivers.get(getScenarioName());
        if (webDriver == null) {
            webDriver = createGridWebDriver();
            initWebDriver(webDriver);
        }
        return webDriver;
    }

    private void initWebDriver(WebDriver webDriver) {
        if (implicitWait > 0) {
            webDriver.manage().timeouts().implicitlyWait(implicitWait, TimeUnit.MILLISECONDS);
        }
        webDrivers.put(getScenarioName(), webDriver);
    }

    private WebDriver createGridWebDriver() throws MalformedURLException {
        URL hubUrl = new URL(TestParameters.SELENIUM_HUB_URL);
        DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
        desiredCapabilities.setCapability(BROWSER_NAME, TestParameters.BROWSER);
        return new RemoteWebDriver(hubUrl, desiredCapabilities);
    }

    private String getScenarioName() {
        return scenario.get().getVisualName();
    }

    private <T> Object getFieldValueInObject(T m, String field) {
        try {
            Field fieldInObject = getFieldInObject(m, field);
            fieldInObject.setAccessible(true);
            return fieldInObject.get(m);
        } catch (Exception e) {
            return null;
        }
    }

    private <T> Field getFieldInObject(T m, String field) throws NoSuchFieldException {
        return m.getClass().getDeclaredField(field);
    }
}