All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ats.executor.drivers.engines.SapDriverEngine Maven / Gradle / Ivy

The newest version!
package com.ats.executor.drivers.engines;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.openqa.selenium.ElementNotInteractableException;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebElement;

import com.ats.data.Dimension;
import com.ats.data.Point;
import com.ats.data.Rectangle;
import com.ats.driver.ApplicationProperties;
import com.ats.element.AtsBaseElement;
import com.ats.element.AtsSapElement;
import com.ats.element.FoundElement;
import com.ats.element.RemoteRootElement;
import com.ats.element.SapDialogBox;
import com.ats.element.test.TestElement;
import com.ats.executor.ActionStatus;
import com.ats.executor.ActionTestScript;
import com.ats.executor.SendKeyData;
import com.ats.executor.TestBound;
import com.ats.executor.channels.Channel;
import com.ats.executor.drivers.IDriverInfo;
import com.ats.executor.drivers.desktop.DesktopWindow;
import com.ats.executor.drivers.desktop.SystemDriver;
import com.ats.generator.ATS;
import com.ats.generator.objects.MouseDirection;
import com.ats.generator.variables.CalculatedProperty;
import com.ats.generator.variables.CalculatedValue;
import com.ats.script.actions.ActionApi;
import com.ats.script.actions.ActionSelect;
import com.ats.tools.Utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.CharStreams;
import com.google.gson.JsonSyntaxException;

import okhttp3.OkHttpClient;
import okhttp3.OkHttpClient.Builder;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class SapDriverEngine extends DriverEngine implements IDriverEngine {

	public static final String START_TIMEOUT_OPTION = "--start-timeout";

	private static final Pattern SAP_URL_PATTERN = Pattern.compile("(.*):(.*)@(.*)", Pattern.CASE_INSENSITIVE);

	private final byte[] SAP_ICON = Base64.getDecoder().decode("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");

	private final static String SESSION = "session";
	private final static String SHUTDOWN = "shutdown";
	private final static String START = "start";
	private final static String STOP = "stop";
	private final static String SCROLL = "scroll";
	private final static String ELEMENTS = "elements";
	private final static String ELEMENT = "element";
	private final static String PRESS = "press";
	private final static String DBL_CLICK = "dbclick";
	private final static String DIALOG_BOX = "dialogBox";
	private final static String TEXT = "text";
	private final static String TREE = "tree";
	private final static String OPTIONS = "options";
	private final static String SELECT = "select";
	private final static String PARENTS = "parents";
	private final static String WINDOW = "window";
	private final static String SWITCH = "switch";
	private final static String CLOSE = "close";
	private final static String SCRIPT = "script";
	private final static String GOTO_URL = "gotoUrl";
	private final static String FOCUS = "focus";

	public final static String SAP_NETWORKOPTION = "NetworkOption";
	public final static String SAP_ENDPOINT = "Endpoint";
	public final static String SAP_MAJOR_VERSION = "MajorVersion";
	public final static String SAP_NETWORKOPTION_FAST = "fast";
	public final static String SAP_NETWORKOPTION_SLOW = "slow";

	public final static String SAP_CONNECTION_ID = "connectionId";

	private String sapUser;
	private String sapPassword;
	private String sapClient = "001";
	private String sapLang = "EN";

	private String applicationName;

	private OkHttpClient httpClient;
	private String userAgent;
	private String sapDriverUrl;

	private String connectionId;

	private List elementMapLocation;

	private FoundElement currentElement;

	private final ObjectMapper jsonMapper = new ObjectMapper();

	final private RemoteRootElement root = new RemoteRootElement();

	private String networkOption = "";

	private static final int ACTION_WAIT = 150; //maybe one day it will be needed to add this value in atsProperties file

	public SapDriverEngine(
			Channel channel,
			ActionStatus status,
			String application,
			IDriverInfo driverInfo,
			SystemDriver systemDriver,
			ApplicationProperties props,
			boolean enableLearning) {

		super(channel, driverInfo, systemDriver, props, ACTION_WAIT, 0, enableLearning);

		final String channelName = channel.getName();

		if(props.getUri() != null) {
			application = props.getUri();
		}else {
			application = application.replaceFirst("^sap:\\/\\/", "");
		}

		if(channelName.isBlank()) {
			status.setError(ActionStatus.CHANNEL_START_ERROR, "channel name cannot be empty");
			return;
		}

		sapDriverUrl = getDriverInfo().getDriverServerUri().resolve("/").toString();

		String auth = channel.getAuthenticationValue();
		if(props.getAuthentication() != null) {
			auth = props.getAuthentication();
		}

		if(auth != null && !auth.isBlank()){
			final String authenticationDecoded = new String(Base64.getDecoder().decode(auth), StandardCharsets.UTF_8);
			final String[] authenticationData = authenticationDecoded.split(":");

			if(authenticationData.length > 1) {
				sapUser = authenticationData[0];

				final CalculatedValue passValue = new CalculatedValue(channel.getTestScript(), authenticationData[1]);
				passValue.uncrypt(channel.getTestScript());
				sapPassword = passValue.getCalculated();

				String[] appUrl = application.split(":");
				if(appUrl.length > 1) {
					application = appUrl[0];
					sapClient = appUrl[1];
					if(appUrl.length > 2) {
						sapLang = appUrl[2];
					}
				}else {
					appUrl = application.split("/");
					if(appUrl.length > 1) {
						application = appUrl[0];
						sapClient = appUrl[1];
						if(appUrl.length > 2) {
							sapLang = appUrl[2];
						}
					}else {
						status.setError(ActionStatus.CHANNEL_START_ERROR, "missing client ID");
						return;
					}
				}

			}else {
				status.setError(ActionStatus.CHANNEL_START_ERROR, "no user and password defined");
				return;
			}

		}else {
			final Matcher mv = SAP_URL_PATTERN.matcher(application);
			if (mv.find()) {
				sapUser = mv.group(1);
				checkPassword(new CalculatedValue(channel.getTestScript(), mv.group(2)), 0);
				application = mv.group(3);
			}else {
				channel.getArguments().forEach(c -> checkArgs(c));
			}
		}

		applicationName = application;
		applicationPath = applicationName;

		this.httpClient = new Builder().cache(null).connectTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).readTimeout(80, TimeUnit.SECONDS).build();
		this.userAgent = "AtsSapDriver/" + ATS.getAtsVersion() + "," + System.getProperty("user.name") + ",";

		// -------------------------------------------------------------------------------------------------
		// try to connect to sap driver
		// -------------------------------------------------------------------------------------------------

		ImmutableMap connexionMap;
		if(sapUser != null && sapPassword != null) {
			connexionMap = ImmutableMap.of("connection", applicationName, "user", sapUser, "password", sapPassword, "client", sapClient, "lang", sapLang, "channel", channelName);
		}else {
			connexionMap = ImmutableMap.of("connection", applicationName, "channel", channelName);
		}

		int maxTry = 0;
		JsonNode response = executeRequest(connexionMap, SESSION, START);

		while(response == null && maxTry < 30) {
			maxTry++;
			channel.sleep(500);
			response = executeRequest(connexionMap, SESSION, START);
		}

		String sapGuiVersion = "";
		String warning = "";

		if (response == null) {
			status.setError(ActionStatus.CHANNEL_START_ERROR, "unable to connect to sap driver");
			return;
		}else {

			final JsonNode error = response.findValue("error");
			if(error != null) {
				status.setError(ActionStatus.CHANNEL_START_ERROR, error.findValue("Message").asText());
				return;
			}

			final JsonNode network =  response.findValue(SAP_NETWORKOPTION);
			if (network != null) {
				setNetworkOption(network.asText().toLowerCase());
				if(SAP_NETWORKOPTION_SLOW.equals(getNetworkOption())) {
					warning = "Slow network connection detected !";
				}
			}

			final JsonNode version =  response.findValue(SAP_MAJOR_VERSION);
			if (version != null) {
				sapGuiVersion = version.asText();
			}
		}

		// -------------------------------------------------------------------------------------------------
		// try to connect to get main sap window
		// -------------------------------------------------------------------------------------------------

		final JsonNode window = response.findValue("window");
		if(window != null) {
			connectionId = response.findValue("ConnexionId").asText();

			getSystemDriver().setEngine(new SystemDriverEngine(channel, enableLearning));
			final int pId = window.get("ProcessId").asInt(0);

			channel.setApplicationData(
					Channel.SAP,
					getSystemDriver().getOsName() + " (" + getSystemDriver().getOsVersion() +")",
					"SAP Gui",
					sapGuiVersion,
					getSystemDriver().getDriverVersion(),
					pId,
					window.get("Handle").asInt(0),
					SAP_ICON,
					warning,
					sapDriverUrl);

			channel.getDimension().update(
					window.get("ScreenX").asDouble(0.0),
					window.get("ScreenY").asDouble(0.0),
					window.get("Width").asDouble(0.0),
					window.get("Height").asDouble(0.0));

			final List windows = getSystemDriver().getWindowsByPid(pId);
			for(DesktopWindow win : windows) {
				final String s = win.getAttribute("Title");
				if(s != null && s.toLowerCase().contains("sap logon")) {
					getSystemDriver().ostracon(status, win.getHandle());
					// break;
				}
				if(s != null && s.toLowerCase().contains("sap easy access")) {
					getSystemDriver().getEngine().window = win;
				}
			}
		}else {
			status.setError(ActionStatus.CHANNEL_START_ERROR, "unable to find main SAP window");
		}
	}

	private void checkArgs(CalculatedValue cv) {

		final String v = cv.getCalculated();

		if(v.startsWith("user=")) {
			sapUser = v.substring(5);
		}else if(v.startsWith("pass=")) {
			checkPassword(cv, 5);
		}else if(v.startsWith("password=")) {
			checkPassword(cv, 9);
		}else if(v.startsWith("client=")) {
			sapClient = v.substring(7);
		}
	}

	private void checkPassword(CalculatedValue cv, int start) {
		cv.setCalculated(cv.getCalculated().substring(start));
		cv.uncrypt(channel.getTestScript());
		sapPassword = cv.getCalculated();
	}

	//----------------------------------------------------------------------------------------------
	// Request to driver
	//----------------------------------------------------------------------------------------------

	private JsonNode executeRequest(ImmutableMap map, String ... reqUrl) {

		final String url = sapDriverUrl + Stream.of(reqUrl).map(Object::toString).collect(Collectors.joining("/"));

		final Request.Builder requestBuilder = new Request.Builder();
		requestBuilder.url(url);

		final Request request = requestBuilder
				.addHeader("User-Agent", userAgent)
				.addHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF8")
				.post(RequestBody.Companion.create(jsonMapper.valueToTree(map).toString(), Utils.JSON_MEDIA))
				.build();

		try {

			final Response response = httpClient.newCall(request).execute();
			final String responseData = CharStreams.toString(new InputStreamReader(response.body().byteStream(), Charsets.UTF_8));
			response.close();

			return jsonMapper.readTree(responseData);

		} catch (JsonSyntaxException | IOException e) {
			return null;
		}
	}

	//----------------------------------------------------------------------------------------------
	// functions
	//----------------------------------------------------------------------------------------------

	private void loadElementsByTag(String parentId, String tagName, List list, int line, String controlType) {
		Map m;
		m = new HashMap<>(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "tag", tagName, "line", String.valueOf(line), "controlType", controlType));

		if(parentId != null) {
			m.put("parent", parentId);
		}

		final JsonNode response = executeRequest(ImmutableMap.copyOf(m), ELEMENTS);
		if (response != null) {
			JsonNode elements = response.findValue("elements");
			if(elements != null) {
				for (final JsonNode element : elements) {
					list.add(new AtsSapElement(jsonMapper, element));
				}
			}
		}
	}

	//----------------------------------------------------------------------------------------------
	//----------------------------------------------------------------------------------------------

	@Override
	public WebElement getRootElement(Channel cnl) {
		return root;
	}

	@Override
	public void close() {
		if(connectionId != null) {
			executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId), SESSION, STOP);
		}
	}

	@Override
	public void quit() {
		executeRequest(ImmutableMap.of(), SHUTDOWN);
	}

	@Override
	public boolean switchWindow(ActionStatus status, int index, int tries, boolean refresh) {
		JsonNode resp = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "index", index), WINDOW, SWITCH);
		int maxTry = 1 + tries;
		while(resp.findValue("error") != null && maxTry > 0) {
			channel.sleep(1000);
			resp = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "index", index), WINDOW, SWITCH);
			maxTry--;
		}

		if (resp != null) {
			JsonNode window = resp.findValue("window");
			if(window != null) {
				channel.getDimension().update(
						window.get("ScreenX").asDouble(0.0),
						window.get("ScreenY").asDouble(0.0),
						window.get("Width").asDouble(0.0),
						window.get("Height").asDouble(0.0));

				channel.setWinHandle(window.get("Handle").asInt());
				channel.toFront();

				status.setPassed(true);
			}else {
				JsonNode error = resp.findValue("error");
				if(error != null) {
					status.setError(ActionStatus.WINDOW_NOT_FOUND, error.get("Message").asText());
				}
			}
		}

		return false;
	}

	@Override
	public void closeWindow(ActionStatus status) {
		final JsonNode response = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId), WINDOW, CLOSE);
		if (response != null) {
			JsonNode window = response.findValue("window");
			if(window != null) {
				channel.getDimension().update(
						window.get("ScreenX").asDouble(0.0),
						window.get("ScreenY").asDouble(0.0),
						window.get("Width").asDouble(0.0),
						window.get("Height").asDouble(0.0));

				channel.setWinHandle(window.get("Handle").asInt());
				channel.toFront();

			}else {
				JsonNode error = response.findValue("error");
				if(error != null) {
					status.setError(ActionStatus.WINDOW_NOT_FOUND, error.get("Message").asText());
				}
			}
		}
	}

	@Override
	public Object executeScript(ActionStatus status, String script, Object... params) {
		return null;
	}

	@Override
	public Object executeJavaScript(ActionStatus status, String script, TestElement element) {
		return executeScript(status, element.getWebElementId(), script);
	}

	@Override
	public Object executeJavaScript(ActionStatus status, String script, boolean returnValue) {
        try {
            if(returnValue) {
                final Object result = executeScript(status, "", script);
                status.setMessage(result.toString());
                return result;
            }else {
                executeScript(status, "", script);
            }
            status.setPassed(true);
        }catch(StaleElementReferenceException e0) {
            throw e0;
        }catch(Exception e1) {
            status.setException(ActionStatus.JAVASCRIPT_ERROR, e1);
        }
        return null;
	}

	private String executeScript(ActionStatus status, String elementId, String script) {
		final JsonNode response = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", elementId, "script",	script), ELEMENT, SCRIPT);
		if (response != null) {
			final JsonNode jsonError = response.findValue("error");
			if(jsonError != null) {
				status.setError(jsonError.get("Code").asInt(0), jsonError.get("Message").asText());
				return "";
			}else {
				JsonNode result = response.findValue("result");
				if(result != null && !result.isNull()) {
					return result.asText();
				}
			}
		}

		return "";
	}

	@Override
	public void goToUrl(ActionStatus status, String url) {
		final JsonNode response = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "url",	url), GOTO_URL);
		if (response != null) {
			final JsonNode jsonError = response.findValue("error");
			if(jsonError != null) {
				status.setError(jsonError.get("Code").asInt(0), jsonError.get("Message").asText());
			}
		}
	}

	@Override
	public List findElements(boolean sysComp, TestElement testObject, String tagName, String[] attributes, String[] attributesValues, Predicate searchPredicate, WebElement startElement) {

		final List list = new ArrayList<>();
		final TestElement parent = testObject.getParent();
		int line = 0;

		String parentId = null;
		if (parent != null) {
			parentId = parent.getWebElementId();
		}

		if (attributes.length == 0 && testObject.getIndex() != 0) {
			//In the case of a line research without arguments
			line = testObject.getIndex();
		}

		String controlType = (sysComp) ? "WIN" : "SAP";

		loadElementsByTag(parentId, tagName, list, line, controlType);

		return list.parallelStream().filter(searchPredicate).map(FoundElement::new).collect(Collectors.toCollection(ArrayList::new));
	}

	@Override
	public Rectangle getBoundRect(TestElement testElement) {
		return null;
	}

	@Override
	public void waitAfterAction(ActionStatus status) {
		actionWait();
	}

	@Override
	public void updateDimensions() {
		final JsonNode response = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId), WINDOW);
		if (response != null) {
			JsonNode window = response.findValue("window");
			if(window != null && !window.isNull()) {
				channel.getDimension().update(
						window.get("ScreenX").asDouble(0.0),
						window.get("ScreenY").asDouble(0.0),
						window.get("Width").asDouble(0.0),
						window.get("Height").asDouble(0.0));
			}
		}
	}

	@Override
	public FoundElement getElementFromPoint(Boolean syscomp, Double x, Double y) {
		final double xPos = x;
		final double yPos = y;

		if (elementMapLocation != null && elementMapLocation.size() > 0) {
			final Optional fe = elementMapLocation.stream().filter(e -> e.isActive() && e.getRectangle().contains(xPos, yPos)).findFirst();
			if(fe.isPresent()) {
				return fe.get();
			}
		}
		return null;
	}

	@Override
	public FoundElement getElementFromRect(Boolean syscomp, Double x, Double y, Double w, Double h) {
		return null;
	}

	@Override
	public String getAttribute(ActionStatus status, FoundElement element, String attributeName, int maxTry) {
		final CalculatedProperty[] properties = getAttributes(element, true);
		for (CalculatedProperty prop : properties) {
			if(prop.getName().equals(attributeName)) {
				return prop.getValue().getCalculated();
			}
		}
		return null;
	}
	@Override
	public CalculatedProperty[] getAttributes(FoundElement element, boolean reload) {
		JsonNode response;
		response = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", element.getId()), ELEMENT);
		if (response != null) {
			JsonNode jsonElement = response.findValue("element");
			if(jsonElement != null) {
				final AtsSapElement elem = new AtsSapElement(jsonMapper, jsonElement);
				return elem.getAttributes();
			}
		}
		return new CalculatedProperty[0];
	}
	
	@Override
	public CalculatedProperty[] getHtmlAttributes(FoundElement element) {
		return getAttributes(element, true);
	}

	@Override
	public List loadSelectOptions(TestElement element) {
		final ArrayList result = new ArrayList<>();

		JsonNode response = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", element.getWebElementId()), ELEMENT, OPTIONS);
		if (response != null) {
			final JsonNode jsonOptions = response.findValue("options");
			jsonOptions.fields().forEachRemaining(f -> result.add(new String[] {f.getKey(), f.getValue().asText()}));
		}

		return result;
	}

	@Override
	public List findSelectOptions(TestBound dimension, TestElement element) {
		return null;
	}

	@Override
	public void selectOptionsItem(ActionStatus status, TestElement testElement, CalculatedProperty selectProperty, boolean keepSelect) {

		final String searchedValue = selectProperty.getValue().getCalculated();

		final List items = loadSelectOptions(testElement);
		String key;

		if(ActionSelect.SELECT_INDEX.equals(selectProperty.getName())){

			final int index = Utils.string2Int(searchedValue);
			if(items.size() > index) {
				key = items.get(index)[0];
			}else {
				status.setError(ActionStatus.OBJECT_NOT_INTERACTABLE, "index not found, max length options : " + items.size());
				return;
			}
		}else {

			Optional foundOption;

			int idx = 1;
			if(ActionSelect.SELECT_VALUE.equals(selectProperty.getName())){
				idx = 0;
			}
			final int dataIndex = idx;

			if(selectProperty.isRegexp()) {
				foundOption = items.stream().filter(e -> e[dataIndex].matches(searchedValue)).findFirst();
			}else {
				foundOption = items.stream().filter(e -> e[dataIndex].equals(searchedValue)).findFirst();
			}

			if(foundOption.isPresent()) {
				key = foundOption.get()[0];
			}else {
				status.setError(ActionStatus.OBJECT_NOT_INTERACTABLE, "option not found : " + searchedValue);
				return;
			}
		}

		checkResultError(
				executeRequest(
						ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", testElement.getWebElementId(), "key",	key), ELEMENT, SELECT),
				status);
	}

	@Override
	public void loadParents(FoundElement hoverElement) {
		JsonNode response = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", hoverElement.getId()), ELEMENT, PARENTS);
		if (response != null) {

			final double channelX = channel.getDimension().getX();
			final double channelY = channel.getDimension().getY();

			final JsonNode jsonParent = response.findValue("parent");
			if(jsonParent != null && !jsonParent.isNull()) {
				hoverElement.setParent(new FoundElement(channelX, channelY, jsonParent, jsonParent.get("Parent")));
			}
		}
	}

	private void checkResultError(JsonNode node, ActionStatus status) {
		if (node != null) {
			final JsonNode jsonError = node.findValue("error");
			if(jsonError != null) {
				status.setError(jsonError.get("Code").asInt(0), jsonError.get("Message").asText());
			}
		}
	}

	@Override
	public void sendTextData(ActionStatus status, TestElement element, ArrayList textActionList, int waitChar, ActionTestScript topScript) {
		boolean precIsSpecialKey = false;

		for(SendKeyData kd : textActionList) {
			if (kd.getData().length() > 0 || kd.getSpecialKey() != null) {
				String keySequence = kd.getSequenceMobile();
				String elementStr = (precIsSpecialKey ? "root" : element.getWebElementId());
				if (kd.getData() != null && kd.getData() != "" && kd.getDownKey() != null) {
					keySequence = "$KEY-" + kd.getDownKey().name() + "-" + kd.getData();
				}
				if (kd.getSpecialKeyString() == null || !keySequence.startsWith("$KEY-")) {

					checkResultError(
							executeRequest(
									ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "element", elementStr, "text", keySequence),
									TEXT),
							status);

					if (status.getCode() == ActionStatus.OBJECT_NOT_INTERACTABLE) { // Not interactable
						throw new ElementNotInteractableException(status.getMessage());
					}
				} else {
					if (elementStr != "root") {
						checkResultError(
								executeRequest(
										ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "element", elementStr, "text", keySequence),
										FOCUS),
								status);
					}
				}

				if (kd.getSpecialKey() != null && kd.getDownKey() == null &&   getSystemDriver() != null && getSystemDriver().getEngine() != null) {
					ArrayList specialKeyArray = new ArrayList<>();
					specialKeyArray.add(kd);
					getSystemDriver().getEngine().sendTextData(status, element, specialKeyArray, waitChar, topScript);
					precIsSpecialKey = true;

					waitAfterAction(status);

				} else {
					precIsSpecialKey = false;
				}
			}
		}
	}

	@Override
	public void mouseClick(ActionStatus status, FoundElement element, MouseDirection position, int offsetX,	int offsetY) {
		String tag =element.getTag();
		if (tag.equalsIgnoreCase("toolbarmenu") || tag.equalsIgnoreCase("menu")) {
			//click to extend the menu
			int x = (int)Math.round(element.getScreenX() + (element.getWidth()/2));
			int y = (int)Math.round(element.getScreenY() + (element.getHeight()/2));
			getSystemDriver().mouseMove(x,y);
			getSystemDriver().mouseClick();
		} else {
			checkResultError(
					executeRequest(
							ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", element.getId()),
							ELEMENT, PRESS),
					status);

			if (status.getCode() == ActionStatus.OBJECT_NOT_INTERACTABLE) { // Not interractable
				throw new ElementNotInteractableException(status.getMessage());
			}
		}
	}

	@Override
	public void mouseMoveToElement(ActionStatus status, FoundElement foundElement, MouseDirection position,	boolean desktopDragDrop, int offsetX, int offsetY) {
		currentElement = foundElement;
	}

	@Override
	public void mouseMoveToElement(FoundElement foundElement) {

		currentElement = foundElement;
		ActionStatus status = new ActionStatus(this.channel, "", 0);

		checkResultError(
				executeRequest(
						ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", foundElement.getId()),
						ELEMENT, FOCUS),
				status);

		if(status.getCode() == ActionStatus.OBJECT_NOT_INTERACTABLE) { // Not interractable
			throw new ElementNotInteractableException(status.getMessage());
		}
	}

	@Override
	public void doubleClick() {
		if(currentElement != null) {
			ActionStatus status = new ActionStatus(this.channel, "", 0);
			checkResultError(
					executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", currentElement.getId()), ELEMENT, DBL_CLICK),
					status
					);

			if(status.getCode() == ActionStatus.OBJECT_NOT_INTERACTABLE) { // Not interractable
				throw new ElementNotInteractableException(status.getMessage());
			}
		}
	}

	@Override
	public void setWindowToFront() {
		channel.toFront();
	}

	@Override
	public void refreshElementMapLocation() {
		new Thread(new LoadMapElement(channel, connectionId, this)).start();
	}

	private static class LoadMapElement	implements Runnable {
		final TestBound channelDimension;
		final String connectionId;
		final SapDriverEngine driver;

		public LoadMapElement(Channel channel, String connectionId,SapDriverEngine driver) {
			this.channelDimension = channel.getDimension();
			this.connectionId = connectionId;
			this.driver = driver;
		}

		@Override
		public void run() {
			final JsonNode response = driver.executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId), ELEMENTS, TREE);
			if (response != null) {
				final JsonNode elements = response.findValue("elements");
				if(elements != null) {

					final ArrayList list = new ArrayList<>();
					final double channelX = channelDimension.getX();
					final double channelY = channelDimension.getY();

					elements.elements().forEachRemaining(node -> list.add(new FoundElement(channelX, channelY, node)));

					driver.setElementMapLocation(list);
				}
			}
		}
	}


	public void setElementMapLocation(ArrayList value) {
		elementMapLocation = value;
	}

	@Override
	public String getTextData(FoundElement e) {//TODO implement text data
		return getAttribute(null, e, "Text", 5);
	}

	@Override
	public String getSelectedText(TestElement e) {
		return ""; //NOT implemented
	}

	//--------------------------------------------------------------------------------------------------------------------
	//--------------------------------------------------------------------------------------------------------------------

	@Override
	public void setSysProperty(String propertyName, String propertyValue) {}

	@Override
	public void scroll(int delta) {}

	@Override
	public void scroll(FoundElement element) {}

	@Override
	public void scroll(FoundElement element, int delta) {
		if (currentElement != null) {
			ActionStatus status = new ActionStatus(this.channel, "", 0);
			checkResultError(
					executeRequest(
							ImmutableMap.of(
									SAP_CONNECTION_ID,
									connectionId,
									"id",
									currentElement.getId(),
									"value",
									delta),
							SCROLL),
					status);
		}
	}

	@Override
	public void clearText(ActionStatus status, TestElement testElement, MouseDirection md) {}

	@Override
	public void rightClick() {

		int x = (int) (currentElement.getScreenX() + (Math.round(currentElement.getWidth())  / 2 ));
		int y = (int) (currentElement.getScreenY() + (Math.round(currentElement.getHeight())  / 2 ));

		getSystemDriver().mouseMove(x, y);
		getSystemDriver().mouseRightClick();
	}

	@Override
	public void middleClick(ActionStatus status, MouseDirection position, TestElement element) {}

	@Override
	public void buttonClick(ActionStatus status, String id) {}

	@Override
	public void tap(int count, FoundElement element) {}

	@Override
	public void press(int duration, ArrayList paths, FoundElement element) {}

	@Override
	public void drag(ActionStatus status, FoundElement element, MouseDirection position, int offsetX, int offsetY, boolean offset) {}

	@Override
	public void drop(FoundElement element, MouseDirection md, boolean desktopDragDrop) {}
	
	@Override
	public void swipe(ActionStatus status, FoundElement element, MouseDirection position, MouseDirection direction) {}

	@Override
	public void keyDown(Keys key) {}

	@Override
	public void keyUp(Keys key) {}

	@Override
	public void moveByOffset(int hDirection, int vDirection) {}

	@Override
	public SapDialogBox switchToAlert() {

		final JsonNode response = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId), ELEMENT, DIALOG_BOX);
		try {
			final String id = response.findValue("Id").asText();
			final String title = ""; //response.findValue("Title").asText();
			final String text = response.findValue("Text").asText();
			final String type = response.findValue("Tag").asText();
			return new SapDialogBox(this, id, title, text, type);
		}catch(Exception e) {
			throw new NoAlertPresentException();
		}
	}

	public void dialogBoxExecute(ActionStatus status, String id, String action) {
		JsonNode result = executeRequest(ImmutableMap.of(SAP_CONNECTION_ID, connectionId, "id", id, "execute", action), ELEMENT, DIALOG_BOX);
		final String response = result.findValue("result").asText();
		if ("ko".equalsIgnoreCase(response))
		{
			status.setMessage("Error:  " + result.findValue("error").asText());
			status.setPassed(false);
		}
	}

	@Override
	public boolean switchToDefaultContent(boolean dialog) {
		return false;
	}

	@Override
	public void switchToFrameId(String id) {
	}

	@Override
	public String getSource() {
		return null;
	}

	@Override
	public void api(ActionStatus status, ActionApi api) {
	}

	@Override
	public void windowState(ActionStatus status, Channel channel, String state) {
	}

	@Override
	public String getTitle() {
		return null;
	}

	@Override
	public int getNumWindows() {
		return 0;
	}

	@Override
	public String getUrl() {
		return null;
	}

	@Override
	protected void setPosition(Point pt) {
	}

	@Override
	protected void setSize(Dimension dim) {
	}

	@Override
	public String getCookies() {
		return "";
	}

	@Override
	public String getHeaders(ActionStatus status) {
		return "";
	}

	public String getNetworkOption() {
		return networkOption;
	}

	public void setNetworkOption(String value) {
		this.networkOption = value;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy