Skip to content

Commit

Permalink
Click JS Update and Unit Test Upgrades (#1)
Browse files Browse the repository at this point in the history
# Features
* Add JS mode to Click
* Add scroll-into-view operation for every click expression
* Add Expression unit tests
* Update documentation and warning suppressions
* Add version option for cmd line mode
* Add default case to all switch statements (should be impossible to reach any exception with 'FATAL' tag)
* Remove unused code from For
* Add DriverFactory

# Bug Fixes
* Remove unused code from For
* Remove plural-required-field utility function from Expression
* Remove unused utility functions from Expression
* Fix Screenshot bug which added an extra '-' to the tag name
* Fix switch-case bug(s)
  • Loading branch information
juanresendiz813 committed Oct 20, 2021
1 parent ec51818 commit db8db79
Show file tree
Hide file tree
Showing 23 changed files with 458 additions and 325 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<url>https://github.com/spicule-kythera/magnesium-script</url>
<groupId>uk.co.spicule</groupId>
<artifactId>magnesium-script</artifactId>
<version>0.1.6</version>
<version>0.2.0</version>

<!-- License -->
<licenses>
Expand Down
85 changes: 85 additions & 0 deletions src/main/java/uk/co/spicule/magnesium_script/DriverFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package uk.co.spicule.magnesium_script;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import uk.co.spicule.magnesium_script.expressions.Expression;

import java.util.ArrayList;

public class DriverFactory {
public enum BrowserType {
FIREFOX,
CHROME,
EDGE;

public static BrowserType stringToEnum(String name) throws Expression.InvalidExpressionSyntax {
return BrowserType.valueOf(Expression.validateTypeClass(BrowserType.class, name));
}
}

// Instance things
ArrayList<String> options = new ArrayList<String>() {
{
add("--no-sandbox");
add("--disable-gpu");
add("--disable-extensions");
add("--ignore-certificate-errors");
add("--incognito");
add("--window-size=1920,1080");
add("--proxy-server='direct://");
add("--proxy-bypass-list=*");
add("--disable-background-networking");
add("--safebrowsing-disable-auto-update");
add("--disable-sync");
add("--metrics-recording-only");
add("--disable-default-apps");
add("--no-first-run");
add("--disable-setuid-sandbox");
add("--hide-scrollbars");
add("--no-zygote");
add("--disable-notifications");
add("--disable-logging");
add("--disable-permissions-api");
}
};

public DriverFactory(boolean headless) {
if(headless) {
options.add("--headless");
}
}

public ChromeOptions buildChromeOptions() {
ChromeOptions options = new ChromeOptions();
this.options.forEach(options::addArguments);
return options;
}

public FirefoxOptions buildFirefoxOptions() {
FirefoxOptions options = new FirefoxOptions();
this.options.forEach(options::addArguments);
return options;
}

public EdgeOptions buildEdgeOptions() {
return new EdgeOptions();
}

public WebDriver build(BrowserType type) {
switch(type) {
case CHROME:
return new ChromeDriver(buildChromeOptions());
case EDGE:
return new EdgeDriver(buildEdgeOptions());
case FIREFOX:
return new FirefoxDriver(buildFirefoxOptions());
default:
throw new RuntimeException("FATAL: Invalid browser-type: " + type);
}
}
}
63 changes: 18 additions & 45 deletions src/main/java/uk/co/spicule/magnesium_script/MagnesiumScript.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
import org.json.simple.parser.ParseException;
import org.openqa.selenium.InvalidArgumentException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.co.spicule.magnesium_script.DriverFactory.BrowserType;
import uk.co.spicule.magnesium_script.expressions.Break;
import uk.co.spicule.magnesium_script.expressions.Expression;

Expand All @@ -24,16 +21,6 @@
import java.util.Map;

public class MagnesiumScript {
enum BrowserType {
FIREFOX,
CHROME,
EDGE;

protected static BrowserType stringToEnum(String name) throws Expression.InvalidExpressionSyntax {
return BrowserType.valueOf(Expression.validateTypeClass(BrowserType.class, name));
}
}

// Static things
private static WebDriver driver = null;
public final static Logger LOG = LoggerFactory.getLogger(MagnesiumScript.class);
Expand All @@ -50,7 +37,7 @@ public MagnesiumScript(WebDriver driver) {
MagnesiumScript.driver = driver;
}

public static final String version() {
public static String version() {
return "MagnesiumScript v" + MAJOR + "." + MINOR + "." + PATCH;
}

Expand All @@ -59,12 +46,10 @@ public static final String version() {
* type, then proceeds parse the contents iff no lexical errors occur.
* @param filePath Path to the file to read
* @throws IOException Occurs when the filePath was not found or could not be opened
* @throws ParseException Occurs when the file specified fails to parse to its primitive type (e.g. JSON or YAML syntax error)
* @throws Parser.InvalidExpressionType Occurs when an unknown expression is detected
* @throws Expression.InvalidExpressionSyntax Occurs when a syntactic error is detected
*/
public Program interpret(Path filePath) throws IOException,
ParseException,
Parser.InvalidExpressionType,
Expression.InvalidExpressionSyntax,
Break.StopIterationException {
Expand Down Expand Up @@ -97,19 +82,9 @@ public Program interpret(Map<String, Object> script) throws Parser.InvalidExpres
return program.run();
}

/**
* The main method if running the JAR as an executable and not a library
* @param args arguments and options passed in from the command line
* @throws ArgumentParserException
* @throws IOException
* @throws Parser.InvalidExpressionType
* @throws ParseException
* @throws Expression.InvalidExpressionSyntax
*/
public static void main(String[] args) throws ArgumentParserException,
IOException,
Parser.InvalidExpressionType,
ParseException,
Expression.InvalidExpressionSyntax,
Break.StopIterationException {
parser.addArgument("-f", "--file")
Expand All @@ -128,37 +103,35 @@ public static void main(String[] args) throws ArgumentParserException,
.setDefault("firefox")
.choices(Arrays.asList("firefox", "chrome", "edge"))
.help("Specify the Selenium driver type to use. (Default: firefox)");
parser.addArgument("-v", "--version")
.dest("version")
.type(Boolean.class)
.setDefault(false)
.help("Print the interpreter version then exit");
WebDriver driver = null;

try {
// Get the Args
Namespace parsedArgs = parser.parseArgs(args);
BrowserType type = BrowserType.stringToEnum(parsedArgs.getString("driver"));
boolean isHeadless = parsedArgs.getBoolean("headless");

// Set the driver headless mode

// Set up the driver
switch (type) {
case FIREFOX:
driver = new FirefoxDriver();
break;
case CHROME:
driver = new ChromeDriver();
break;
case EDGE:
driver = new EdgeDriver();
break;
default:
throw new InvalidArgumentException("Internal error: unknown browser type `" + type + "`");
DriverFactory factory = new DriverFactory(parsedArgs.getBoolean("headless"));

// Build the driver
driver = factory.build(type);

// Process version command
if(parsedArgs.getBoolean("version")) {
LOG.info(MagnesiumScript.version());
System.exit(0);
}

// Set up the interpreter
MagnesiumScript interpreter = new MagnesiumScript(driver);

// Parse and run the script
Path filePath = FileSystems.getDefault().getPath(parsedArgs.getString("filePath"));
interpreter.interpret(filePath);
Program program = interpreter.interpret(filePath);
program.run();
} catch (HelpScreenException e) {
// Do nothing for help menu
} finally {
Expand Down
81 changes: 49 additions & 32 deletions src/main/java/uk/co/spicule/magnesium_script/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.List;
import java.util.Map;

@SuppressWarnings("unchecked")
public class Parser {
// Static things
public final static Logger LOG = LoggerFactory.getLogger(Parser.class);
Expand Down Expand Up @@ -50,38 +51,54 @@ public Program parse(WebDriver driver, List<Map<String, Object>> runBlock, Expre

LOG.debug(instructionName + " -> " + instructionBlock);

if (instructionName.equals("alert")) {
program.addInstruction(new Alert(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("break")) {
program.addInstruction(new Break(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("click")) {
program.addInstruction(new Click(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("do")) {
program.addInstruction(new DoWhile(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("dump-stack")) {
program.addInstruction(new DumpStack(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("for")) {
program.addInstruction(new For(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("get")) {
program.addInstruction(new Get(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("if")) {
program.addInstruction(new If(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("no-op")) {
program.addInstruction(new NoOp(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("select")) {
program.addInstruction(new Select(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("send-keys")) {
program.addInstruction(new SendKeys(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("screenshot")) {
program.addInstruction(new Screenshot(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("snapshot")) {
program.addInstruction(new Snapshot(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("try")) {
program.addInstruction(new Try(driver, parent).parse(instructionBlock));
} else if (instructionName.equals("wait")) {
program.addInstruction(new Wait(driver, parent).parse(instructionBlock));
} else {
throw new InvalidExpressionType(instructionName);
switch (instructionName) {
case "alert":
program.addInstruction(new Alert(driver, parent).parse(instructionBlock));
break;
case "break":
program.addInstruction(new Break(driver, parent).parse(instructionBlock));
break;
case "click":
program.addInstruction(new Click(driver, parent).parse(instructionBlock));
break;
case "do":
program.addInstruction(new DoWhile(driver, parent).parse(instructionBlock));
break;
case "dump-stack":
program.addInstruction(new DumpStack(driver, parent).parse(instructionBlock));
break;
case "for":
program.addInstruction(new For(driver, parent).parse(instructionBlock));
break;
case "get":
program.addInstruction(new Get(driver, parent).parse(instructionBlock));
break;
case "if":
program.addInstruction(new If(driver, parent).parse(instructionBlock));
break;
case "no-op":
program.addInstruction(new NoOp(driver, parent).parse(instructionBlock));
break;
case "select":
program.addInstruction(new Select(driver, parent).parse(instructionBlock));
break;
case "send-keys":
program.addInstruction(new SendKeys(driver, parent).parse(instructionBlock));
break;
case "screenshot":
program.addInstruction(new Screenshot(driver, parent).parse(instructionBlock));
break;
case "snapshot":
program.addInstruction(new Snapshot(driver, parent).parse(instructionBlock));
break;
case "try":
program.addInstruction(new Try(driver, parent).parse(instructionBlock));
break;
case "wait":
program.addInstruction(new Wait(driver, parent).parse(instructionBlock));
break;
default:
throw new InvalidExpressionType(instructionName);
}
}
return program;
Expand Down
13 changes: 4 additions & 9 deletions src/main/java/uk/co/spicule/magnesium_script/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import javax.annotation.Nullable;
import java.util.*;

@SuppressWarnings("unused")
public class Program {
// Static things
protected static Logger LOG = LoggerFactory.getLogger(Program.class);
Expand Down Expand Up @@ -54,15 +55,9 @@ public final Program run() throws Break.StopIterationException {
return this;
}

protected boolean addInstruction(Expression instruction) {
try{
instruction.setParent(parent);
program.add(instruction);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
protected void addInstruction(Expression instruction) {
instruction.setParent(parent);
program.add(instruction);
}

public String toString() {
Expand Down

0 comments on commit db8db79

Please sign in to comment.