
prerna.test.Playwrighter2 Maven / Gradle / Ivy
The newest version!
package prerna.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Download;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Locator.FilterOptions;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Page.GetByRoleOptions;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.PlaywrightException;
import com.microsoft.playwright.options.AriaRole;
public class Playwrighter2 {
Playwright playwright = Playwright.create();
public static final String css_id = "pw_id";
List inputList = new ArrayList();
Map inputLinks = new Hashtable();
Map locators = new HashMap();
Map variables = new HashMap();
String outputDir = "c:/temp/playwright";
String session = null;
String baseUrl = null;
int sleep = 400;
boolean tracePage = false;
boolean traceScreenshot = false;
Page cur_page = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
// read the file
// for every action do the appropriate action
String fileName = "c:/users/pkapaleeswaran/workspacegit/playwright/playwright.json";
fileName = "c:/users/pkapaleeswaran/workspacegit/playwright/timesheet.json";
fileName = "c:/users/pkapaleeswaran/workspacegit/playwright/downloader.json";
fileName = "c:/users/pkapaleeswaran/workspacegit/playwright/timesheet_time_approval.json";
Playwrighter2 pw = new Playwrighter2();
pw.initPlaywright();
pw.tracePage = true;
pw.traceScreenshot = true;
pw.processFile(fileName);
}
public void initPlaywright()
{
//LaunchOptions lp = new LaunchOptions();
//lp.setChannel(BrowserChannel.CHROME);
//lp.setHeadless(false);
BrowserType firefox = playwright.chromium();
//BrowserType firefox = playwright.webkit();
Browser browser = firefox.launch();
BrowserContext ctx = browser.newContext();
//page = ctx.newPage();
cur_page = ctx.newPage();
session = java.util.UUID.randomUUID() +"";
// default sleep value to 200
this.sleep = 200;
}
public void processFile(String fileName)
{
try {
String jsonData = FileUtils.readFileToString(new File(fileName), Charset.defaultCharset());
JSONObject root = new JSONObject(jsonData);
JSONArray actions = root.getJSONArray("actions");
System.err.println(actions);
boolean go = true;
for(int actionIndex = 0;actionIndex < actions.length() && go;actionIndex++)
{
String actionId = actions.getString(actionIndex);
JSONObject action = root.getJSONObject(actionId);
String actionName = action.getString("action");
String actor = action.getString("actor");
go = processAction(action, actionId);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private boolean processAction(JSONObject action, String actionId)
{
String actionName = action.getString("action");
boolean go = true;
String actor = action.getString("actor");
boolean critical = action.has("critical") && action.getString("critical").equalsIgnoreCase("True");
System.err.println("Processing ::: " + actionId);
if(actor.equalsIgnoreCase("system"))
{
try {
if(actionName.equalsIgnoreCase("navigate"))
{
navigate(action);
handleSleep(action);
trace(actionId, actionName);
}
if(actionName.equalsIgnoreCase("getByPlaceHolder"))
{
getByPlaceHolder(action, actionId);
handleSleep(action);
trace(actionId, actionName);
}
if(actionName.equalsIgnoreCase("locator"))
{
locator(action, actionId);
handleSleep(action);
trace(actionId, actionName);
}
if(actionName.equalsIgnoreCase("getByRole"))
{
getByRole(action, actionId);
handleSleep(action);
trace(actionId, actionName);
}
if(actionName.equalsIgnoreCase("getByLabel"))
{
getByLabel(action, actionId);
handleSleep(action);
trace(actionId, actionName);
}
if(actionName.equalsIgnoreCase("getByText"))
{
getByText(action, actionId);
handleSleep(action);
trace(actionId, actionName);
}
if(actionName.equalsIgnoreCase("filter"))
{
doFilter(action, actionId);
handleSleep(action);
trace(actionId, actionName);
}
if(actionName.equalsIgnoreCase("download"))
{
downloadFile(action, actionId);
handleSleep(action);
trace(actionId, actionName);
}
// other cases follow}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
if(!critical)
System.err.println("Failed " + actionId);
else
{
go = false;
}
}
}
else if(actor.equalsIgnoreCase("user"))
{
getUserInput(action, actionId);
handleSleep(action);
trace(actionId, actionName);
}
else if(actor.equalsIgnoreCase("pause"))
{
go = pause(action, actionId);
}
else if(actor.equalsIgnoreCase("trace"))
{
// this is where trace should go..
}
if(action.has("debug") && action.getString("debug").equalsIgnoreCase("true") && locators.containsKey(actionId))
System.err.println(locators.get(actionId).innerHTML());
return go;
}
public void navigate(JSONObject payload)
{
String website = payload.getString("website");
this.baseUrl = website;
cur_page.navigate(website);
handleSleep(payload);
}
public void getByPlaceHolder(JSONObject payload, String actionName)
{
JSONArray params = payload.getJSONArray("params");
String placeholder = params.get(0).toString();
String parent_action = null;
Locator loc = null;
if(payload.has("parent_action"))
{
parent_action = payload.getString("parent_action");
loc = locators.get(parent_action).getByPlaceholder(placeholder);
}
else
{
loc = cur_page.getByPlaceholder(placeholder);
}
locators.put(actionName, loc);
if(payload.has("event"))
{
String event = payload.getString("event");
// another event loop goes here
if(event.equalsIgnoreCase("click"))
loc.click();
if(event.equalsIgnoreCase("fill"))
{
String fillValue = payload.getString("fill_value");
loc.fill(fillValue);
}
}
}
public void locator(JSONObject payload, String actionName)
{
JSONArray params = payload.getJSONArray("params");
String placeholder = params.get(0).toString();
String parent_action = null;
Locator loc = null;
List allLoc = null;
if(payload.has("parent_action"))
{
parent_action = payload.getString("parent_action");
allLoc = locators.get(parent_action).locator(placeholder).all();
}
else
{
allLoc = cur_page.locator(placeholder).all();
}
loc = resolveLocator(allLoc, payload);
locators.put(actionName, loc);
if(payload.has("event"))
{
String event = payload.getString("event");
// another event loop goes here
if(event.equalsIgnoreCase("click"))
loc.click();
}
}
public void getByRole(JSONObject payload, String actionName)
{
JSONArray params = payload.getJSONArray("params");
String placeholder = params.get(0).toString();
String parent_action = null;
Locator loc = null;
List allLoc = null;
GetByRoleOptions options = createByRoleOptions(payload);
// need to trap exceptions
if(payload.has("parent_action"))
{
parent_action = payload.getString("parent_action");
if(placeholder.equalsIgnoreCase("AriaRole.LIST"))
allLoc = locators.get(parent_action).getByRole(AriaRole.LIST).all();
else if(placeholder.equalsIgnoreCase("AriaRole.BUTTON"))
allLoc = locators.get(parent_action).getByRole(AriaRole.BUTTON).all();
else if(placeholder.equalsIgnoreCase("AriaRole.LINK"))
allLoc = locators.get(parent_action).getByRole(AriaRole.LINK).all();
}
else
{
if(placeholder.equalsIgnoreCase("AriaRole.LIST"))
allLoc = cur_page.getByRole(AriaRole.LIST, options).all();
else if(placeholder.equalsIgnoreCase("AriaRole.BUTTON"))
allLoc = cur_page.getByRole(AriaRole.BUTTON, options).all();
else if(placeholder.equalsIgnoreCase("AriaRole.LINK"))
allLoc = cur_page.getByRole(AriaRole.LINK, options).all();
else if(placeholder.equalsIgnoreCase("AriaRole.ROW"))
allLoc = cur_page.getByRole(AriaRole.ROW, options).all();
}
loc = resolveLocator(allLoc, payload);
locators.put(actionName, loc);
final Locator newLoc = loc;
if(payload.has("event") && loc != null)
{
String event = payload.getString("event");
// another event loop goes here
if(event.equalsIgnoreCase("click"))
{
if(!payload.has("new_page"))
{
loc.click();
}
else
{
// get the new page
cur_page = cur_page.waitForPopup(() -> {
newLoc.click();
});
}
}
}
}
public void getByLabel(JSONObject payload, String actionName)
{
JSONArray params = payload.getJSONArray("params");
String placeholder = params.get(0).toString();
placeholder = evalPlaceholder(placeholder);
String parent_action = null;
Locator loc = null;
int sleep = 400;
if(payload.has("sleep_after"))
sleep = payload.getInt("sleep_after");
if(payload.has("parent_action"))
{
parent_action = payload.getString("parent_action");
loc = locators.get(parent_action).getByLabel(placeholder);
}
else
{
loc = cur_page.getByLabel(placeholder);
}
locators.put(actionName, loc);
if(payload.has("event"))
{
String event = payload.getString("event");
// another event loop goes here
if(event.equalsIgnoreCase("click"))
loc.click();
if(event.equalsIgnoreCase("fill"))
{
String type = payload.has("fill_type")?payload.getString("fill_type"):"string";
if(type.equalsIgnoreCase("string"))
{
String value = payload.getString("fill_value");
loc.fill(value);
}
else if(type.equalsIgnoreCase("int"))
{
int value = payload.getInt("fill_value");
loc.fill(value + "");
}
}
}
}
public void getByText(JSONObject payload, String actionName)
{
JSONArray params = payload.getJSONArray("params");
String placeholder = params.get(0).toString();
placeholder = evalPlaceholder(placeholder);
String parent_action = null;
Locator loc = null;
if(payload.has("parent_action"))
{
parent_action = payload.getString("parent_action");
loc = locators.get(parent_action).getByText(placeholder);
}
else
{
loc = cur_page.getByText(placeholder);
}
locators.put(actionName, loc);
if(payload.has("event"))
{
String event = payload.getString("event");
// another event loop goes here
if(event.equalsIgnoreCase("click"))
loc.click();
}
}
public boolean pause(JSONObject payload, String actionId)
{
boolean go = true;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String taskMessage = payload.getString("task_message");
String actionMessage = payload.getString("action");
System.err.println(taskMessage);
System.err.println(actionMessage);
String data = br.readLine();
go = data.toLowerCase().startsWith("y");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return go;
}
public void getUserInput(JSONObject payload, String actionId)
{
// get the user input and play it on the page
// as you enter.. generate page from it
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Locator loc = null;
if(payload.has("parent_action"))
{
String parent_action = null;
parent_action = payload.getString("parent_action");
loc = locators.get(parent_action);
boolean search = payload.has("search") && payload.getString("search").equalsIgnoreCase("true");
String action = payload.getString("action");
String data = null;
boolean sync = payload.getString("synchronize").equalsIgnoreCase("true");
if(loc != null)
{
do
{
String message = "Enter value";
if(payload.has("message"))
message = payload.getString("message");
try {
System.err.println(message);
data = br.readLine();
if(data.startsWith("!") && search) // this is a search we found our value come out of it
break;
else if(action.equalsIgnoreCase("fill") && !data.equalsIgnoreCase("e"))
{
loc.clear();
loc.fill(data.replaceFirst("!", ""));
}
if(sync)
trace(actionId, "- User - " + data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}while(!data.startsWith("!"));
if(payload.has("output"))
{
String outputName = payload.getString("output");
variables.put(outputName, data.replace("!", ""));
}
}
}
}
public void doFilter(JSONObject payload, String actionName)
{
JSONArray params = payload.getJSONArray("params");
String placeholder = params.get(0).toString();
// create filter options
FilterOptions options = createFilterOptions(payload);
String parent_action = null;
Locator loc = null;
List allLoc = null;
if(payload.has("parent_action"))
{
parent_action = payload.getString("parent_action");
allLoc = locators.get(parent_action).filter(options).all();
}
loc = resolveLocator(allLoc, payload);
locators.put(actionName, loc);
if(payload.has("event"))
{
String event = payload.getString("event");
// another event loop goes here
if(event.equalsIgnoreCase("click"))
loc.click();
}
}
private void downloadFile(JSONObject payload, String actionName)
{
if(payload.has("parent_action"))
{
String parent_action = payload.getString("parent_action");
final Locator loc = locators.get(parent_action);
Download download = cur_page.waitForDownload(() -> {
loc.click();
});
Path outputPath = Paths.get(payload.getString("path"));
download.saveAs(outputPath);
}
}
// private methods
private GetByRoleOptions createByRoleOptions(JSONObject payload)
{
//page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Search")).click();
GetByRoleOptions options = new Page.GetByRoleOptions();
if(payload.has("options"))
{
JSONArray optionArray = payload.getJSONArray("options");
JSONArray optionValues = payload.getJSONArray("option_values");
for(int optionIndex = 0;optionIndex < optionArray.length();optionIndex++)
{
String optionName = optionArray.getString(optionIndex);
String optionValue = optionValues.getString(optionIndex);
if(optionName.equalsIgnoreCase("setName"))
options.setName(optionValue);
}
}
options.setExact(payload.has("options_exact") && payload.getString("options_exact").equalsIgnoreCase("True"));
return options;
}
private FilterOptions createFilterOptions(JSONObject payload)
{
//page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Search")).click();
FilterOptions options = new Locator.FilterOptions();
if(payload.has("options"))
{
JSONArray optionArray = payload.getJSONArray("options");
JSONArray optionValues = payload.getJSONArray("option_values");
for(int optionIndex = 0;optionIndex < optionArray.length();optionIndex++)
{
String optionName = optionArray.getString(optionIndex);
String optionValue = optionValues.getString(optionIndex);
if(optionName.equalsIgnoreCase("setHasText"))
options.setHasText(optionValue);
}
}
return options;
}
private Locator resolveLocator(List allLoc, JSONObject payload)
{
// need also a try all option i.e. it tries one after the other..
// we just dont know which one..
// if there is only one it is easy
Locator loc = null;
if(allLoc.size() == 1)
loc = allLoc.get(0);
else if(payload.has("field_name"))
{
// need to see if there is some condition
String field_name = payload.getString("field_name");
String comparator = payload.getString("field_comparator");
String field_type = "string" ; //others we will incorporate later
String field_value = payload.getString("field_value");
for(int locIndex = 0;locIndex < allLoc.size();locIndex++)
{
Locator thisLocator = allLoc.get(locIndex);
String thisFieldValue = thisLocator.getAttribute(field_name);
if(comparator.equalsIgnoreCase("=="))
{
if(thisFieldValue.contains(field_value))
{
loc = thisLocator;
break;
}
}
else if(comparator.equalsIgnoreCase("!="))
{
if(thisFieldValue.contains(field_value))
{
loc = thisLocator;
break;
}
}
}
}
else if(payload.has("ordinal"))
{
int ordinal = payload.getInt("ordinal");
loc = allLoc.get(ordinal);
}
else if(allLoc.size() > 0)
loc = allLoc.get(0);
// super navigation i.e. do we need the parent.. if so do that
if(payload.has("super_navigate") && loc != null)
{
int navLevels = payload.getInt("super_navigate");
for(int navIndex = 0;navIndex < navLevels;navIndex++)
loc = loc.locator("..");
}
return loc;
}
private String evalPlaceholder(String placeholder)
{
if(placeholder.startsWith("_") && variables.containsKey(placeholder))
return variables.get(placeholder);
return placeholder;
}
// does the prints of page etc.
private void trace(String actionId, String actionName)
{
boolean success = false;
int attempt = 3;
while(!success)
{
try {
Thread.sleep(sleep);
String outputName = this.session + actionId;
if(this.tracePage)
{
// output html
String htmlContent = cur_page.content();
htmlContent = convertRelativeToAbsoluteLinks(htmlContent, htmlContent);
FileUtils.write(new File(outputDir + "/" + outputName + ".html"), htmlContent, Charset.defaultCharset());
}
if(this.traceScreenshot)
{
cur_page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get(outputDir + "/" + outputName + ".png")));
}
success = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch(PlaywrightException ex)
{
String message = ex.getMessage();
if(message.contains("navigating") && attempt < 4)
attempt++;
else success = true;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public String convertRelativeToAbsoluteLinks(String baseUrl, String page)
{
// Base URL of the document (you might need to adjust this based on your actual use case)
// Parse the HTML document
Document doc;
try {
doc = Jsoup.parse(page);
// Find all links
Elements links = doc.select("[href]");
replacer(baseUrl, links, "href");
// replace all image sources / javascripts
links = doc.select("[src]");
replacer(baseUrl, links, "src");
// add events and ids to objects
// add to the buttons
links = doc.select("button");
makeObservable(links, "button", "onclick");
links = doc.select("a");
//makeObservable(links, "hyper", "onclick");
// put all the inputs
links = doc.select("input");
makeObservable(links, "input", "onchange");
// also capture all the links / elements
//printElements(links);
links = doc.select("button");
// Convert relative links to absolute
return doc.html();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Print the updated HTML document
//System.out.println(doc.html());
return null;
}
private void makeObservable(Elements links, String name, String event)
{
for(int linkIndex = 0;linkIndex < links.size();linkIndex++)
{
Element link = links.get(linkIndex);
link.attr(css_id, name+linkIndex);
link.attr(event, "alert(document.querySelector('[" + css_id + "=" + name + linkIndex + "]').value)");
link.removeAttr("disabled");
String id = link.attr(css_id);
inputLinks.put(id, link);
inputList.add(id);
// get the id and name also
if(link.hasAttr("id"))
inputLinks.put(link.attr("id"), link);
if(link.hasAttr("name"))
inputLinks.put(link.attr("name"), link);
}
}
private void replacer(String baseUrl, Elements links, String attr)
{
try {
for (Element link : links) {
String href = link.attr(attr);
//System.err.println("Old Link " + href);
if (href.startsWith("/") || href.startsWith("./") || href.startsWith("../") || !href.startsWith("http"))
{
URI baseUri = new URI(baseUrl);
URI linkUri = new URI(href);
URI absoluteUri = baseUri.resolve(linkUri);
link.attr(attr, absoluteUri.toString());
//System.err.println("New Link " + absoluteUri.toString());
}
}
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
}
private void handleSleep(JSONObject payload)
{
if(payload.has("sleep_after"))
{
int sleepTime = payload.getInt("sleep_after");
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//Las-Vegas-McCarran-LAS
//Washington, D.C., District of
//Los Angeles, California,
/*
* Save and submit - getByLabel("Save & Submit")
getByLabel("Open Comments section")
getByLabel("Expand or Collapse Reasons").first()
getByText("Additional Time Worked")
getByPlaceholder("Enter text")
page.getByLabel("Add", new Page.GetByLabelOptions().setExact(true)).click();
*/
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy