nl.hsac.fitnesse.fixture.util.selenium.PageSourceSaver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hsac-fitnesse-fixtures Show documentation
Show all versions of hsac-fitnesse-fixtures Show documentation
Fixtures to assist in testing via FitNesse
package nl.hsac.fitnesse.fixture.util.selenium;
import nl.hsac.fitnesse.fixture.Environment;
import nl.hsac.fitnesse.fixture.util.FileUtil;
import nl.hsac.fitnesse.fixture.util.selenium.by.ConstantBy;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Saves page source to disk.
*/
public class PageSourceSaver {
private static final Pattern BASE_TAG_EXPR = Pattern.compile(" ", Pattern.CASE_INSENSITIVE);
private static final String FAKE_SRC_ATTR = "data-fake_src";
private final String pageSourceBase;
private final Environment environment = Environment.getInstance();
private final SeleniumHelper helper;
/**
* Creates new.
* @param pageSourceBase directory where pages will be saved.
* @param helper helper to interact with Selenium.
*/
public PageSourceSaver(String pageSourceBase, SeleniumHelper helper) {
this.pageSourceBase = pageSourceBase;
this.helper = helper;
}
/**
* Saves current page's source, as new file.
* @param fileName filename to use for saved page.
* @return wiki Url, if file was created inside wiki's files dir, absolute filename otherwise.
*/
public String savePageSource(String fileName) {
List framesWithFakeSources = new ArrayList<>(2);
Map sourceReplacements = new HashMap<>();
List frames = getFrames();
for (WebElement frame : frames) {
String newLocation = saveFrameSource(frame);
if (newLocation != null) {
String fullUrlOfFrame = frame.getAttribute("src");
if (StringUtils.isEmpty(fullUrlOfFrame)) {
framesWithFakeSources.add(frame);
fullUrlOfFrame = "anonymousFrame" + frames.indexOf(frame);
addFakeSourceAttr(frame, fullUrlOfFrame);
}
addSourceReplacementsForFrame(sourceReplacements, newLocation, fullUrlOfFrame);
}
}
String source = getCurrentFrameSource(sourceReplacements);
if (!framesWithFakeSources.isEmpty()) {
// replace fake_src by src
source = source.replace(" " + FAKE_SRC_ATTR + "=", " src=");
removeFakeSourceAttr(framesWithFakeSources);
}
return saveSourceAsPageSource(fileName, source);
}
protected String saveFrameSource(WebElement frame) {
SeleniumHelper helper = getSeleniumHelper();
SearchContext currentContext = helper.getCurrentContext();
try {
helper.switchToFrame(frame);
try {
String fileName = helper.getResourceNameFromLocation();
return savePageSource(fileName);
} finally {
helper.switchToParentFrame();
if (currentContext != null) {
helper.setCurrentContext(currentContext);
}
}
} catch (Exception e) {
System.err.println("Error saving sources of nested (i)frame: " + frame);
e.printStackTrace();
return null;
}
}
protected String getCurrentFrameSource(Map sourceReplacements) {
String source = getCurrentPageSource();
if (sourceReplacements != null && !sourceReplacements.isEmpty()) {
source = replaceSourceOfFrames(sourceReplacements, source);
// base tag changes behavior of relative src refs, we comment it out SO:
// - relative links to nested iframes work
// - it it still visible in saved html
Matcher matcher = BASE_TAG_EXPR.matcher(source);
if (matcher.find()) {
source = matcher.replaceAll("");
}
}
return source;
}
protected String replaceSourceOfFrames(Map sourceReplacements, String html) {
for (Map.Entry entry : sourceReplacements.entrySet()) {
String originalLocation = entry.getKey();
String newLocation = entry.getValue();
html = html.replace("src=\"" + originalLocation + "\"", "src=\"" + newLocation + "\"");
}
return html;
}
protected void addSourceReplacementsForFrame(Map sourceReplacements, String savedLocation, String fullUrlOfFrame) {
String fullUrlOfParent = getLocation();
int lastSlash = fullUrlOfParent.lastIndexOf("/");
String baseUrl = fullUrlOfParent.substring(0, lastSlash + 1);
String relativeUrlOfFrame = fullUrlOfFrame.replace(baseUrl, "");
String relativePathToSaved = savedLocation.replace("files/pagesources/", "");
sourceReplacements.put(fullUrlOfFrame, relativePathToSaved);
sourceReplacements.put(relativeUrlOfFrame, relativePathToSaved);
String framePathAndQuery = getPathAndQuery(fullUrlOfFrame);
if (framePathAndQuery != null) {
sourceReplacements.put(framePathAndQuery, relativePathToSaved);
}
}
protected String getPathAndQuery(String urlString) {
String path = null;
try {
URL url = new URL(urlString);
path = url.getPath();
String query = url.getQuery();
if (query != null) {
path += "?" + query;
}
} catch (MalformedURLException e) {
// leave path null
}
return path;
}
protected String saveSourceAsPageSource(String fileName, String source) {
String pageSourceName = getPageSourceName(fileName);
String ext = getPageSourceExtension();
byte[] content = convertSourceToBytes(source);
String file = FileUtil.saveToFile(pageSourceName, ext, content);
String wikiUrl = getWikiUrl(file);
String result;
if (wikiUrl != null) {
result = wikiUrl;
} else {
result = file;
}
return result;
}
protected String getPageSourceExtension() {
return "html";
}
protected String getCurrentPageSource() {
return getSeleniumHelper().getHtml();
}
protected byte[] convertSourceToBytes(String source) {
try {
return source.getBytes("utf-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Unable to save source", e);
}
}
/**
* Converts a file path into a relative wiki path, if the path is insides the wiki's 'files' section.
* @param filePath path to file.
* @return relative URL pointing to the file (so a hyperlink to it can be created).
*/
protected String getWikiUrl(String filePath) {
return environment.getWikiUrl(filePath);
}
protected List getFrames() {
return getDriver().findElements(ConstantBy.frames());
}
protected String getLocation() {
return getDriver().getCurrentUrl();
}
protected void addFakeSourceAttr(WebElement frame, String s) {
executeJavascript("arguments[0].setAttribute(arguments[1], arguments[2]);", frame, FAKE_SRC_ATTR, s);
}
protected void removeFakeSourceAttr(List framesWithFakeSources) {
for (WebElement frame : framesWithFakeSources) {
executeJavascript("arguments[0].removeAttribute(arguments[1]);", frame, FAKE_SRC_ATTR);
}
}
protected void executeJavascript(String pattern, Object... params) {
try {
getSeleniumHelper().executeJavascript(pattern, params);
} catch (RuntimeException e) {
// ignore exception adding/removing attributes and carry on rest of code
}
}
protected WebDriver getDriver() {
return getSeleniumHelper().driver();
}
protected String getPageSourceName(String fileName) {
return pageSourceBase + fileName;
}
protected SeleniumHelper getSeleniumHelper() {
return helper;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy