/*
* (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* <a href="mailto:grenard@nuxeo.com">Guillaume</a>
*/
package org.nuxeo.functionaltests;
import static org.nuxeo.functionaltests.AbstractTest.NUXEO_URL;
import static org.nuxeo.functionaltests.Constants.ADMINISTRATOR;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.internal.runners.statements.RunAfters;
import org.junit.rules.TestWatchman;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.nuxeo.client.api.Client;
import org.nuxeo.client.api.NuxeoClient;
import org.nuxeo.common.utils.URIUtils;
import org.openqa.selenium.remote.RemoteWebDriver;
import okhttp3.Response;
/**
* Watchman to log info about the test and create snapshot on failure.
*
* @since 5.8
*/
public class LogTestWatchman extends TestWatchman {
protected static final Log log = LogFactory.getLog(AbstractTest.class);
protected String lastScreenshot;
protected String lastPageSource;
protected String filePrefix;
protected RemoteWebDriver driver;
protected String serverURL;
public LogTestWatchman(final RemoteWebDriver driver, final String serverURL) {
this.driver = driver;
this.serverURL = serverURL;
}
public LogTestWatchman() {
}
@Override
@SuppressWarnings("unchecked")
public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
starting(method);
try {
if (base instanceof RunAfters) {
// Hack JUnit: in order to take screenshot at the right
// time we add through reflection an after
// function that will be executed before all other
// ones. See NXP-12742
Field fAtersField = RunAfters.class.getDeclaredField("fAfters");
fAtersField.setAccessible(true);
List<FrameworkMethod> afters = (List<FrameworkMethod>) fAtersField.get(base);
if (afters != null && !afters.isEmpty()) {
try {
// Improve this and instead of finding a
// special function, we could register
// functions specially annotated.
FrameworkMethod first = afters.get(0);
Method m = AbstractTest.class.getMethod("runBeforeAfters", (Class<?>[]) null);
FrameworkMethod f = new FrameworkMethod(m);
if (first != null && !first.equals(f)) {
afters.add(0, f);
}
} catch (NoSuchMethodException e) {
// Do nothing
}
}
}
base.evaluate();
succeeded(method);
} catch (Throwable t) {
failed(t, method);
throw t;
} finally {
finished(method);
}
}
};
}
@Override
public void failed(Throwable e, FrameworkMethod method) {
String className = getTestClassName(method);
String methodName = method.getName();
log.error(String.format("Test '%s#%s' failed", className, methodName), e);
if (lastScreenshot == null || lastPageSource == null) {
ScreenshotTaker taker = new ScreenshotTaker();
if (lastScreenshot == null) {
File temp = taker.takeScreenshot(driver, filePrefix);
lastScreenshot = temp != null ? temp.getAbsolutePath() : null;
}
if (lastPageSource == null) {
File temp = taker.dumpPageSource(driver, filePrefix);
lastPageSource = temp != null ? temp.getAbsolutePath() : null;
}
}
log.info(String.format("Created screenshot file named '%s'", lastScreenshot));
log.info(String.format("Created page source file named '%s'", lastPageSource));
super.failed(e, method);
}
@Override
public void finished(FrameworkMethod method) {
log.info(String.format("Finished test '%s#%s'", getTestClassName(method), method.getName()));
lastScreenshot = null;
lastPageSource = null;
super.finished(method);
}
public RemoteWebDriver getDriver() {
return driver;
}
public String getServerURL() {
return serverURL;
}
protected String getTestClassName(FrameworkMethod method) {
return method.getMethod().getDeclaringClass().getName();
}
protected void logOnServer(String message) {
if (driver != null) {
Client client = new NuxeoClient(NUXEO_URL, ADMINISTRATOR, ADMINISTRATOR);
Response response = client.get(NUXEO_URL + "/restAPI/systemLog");
if (response.isSuccessful()) {
driver.get(String.format("%s/restAPI/systemLog?token=dolog&level=WARN&message=----- WebDriver: %s",
serverURL, URIUtils.quoteURIPathComponent(message, true)));
return;
}
}
log.warn(String.format("Cannot log on server message: %s", message));
}
public void runBeforeAfters() {
if (driver != null) {
ScreenshotTaker taker = new ScreenshotTaker();
lastScreenshot = taker.takeScreenshot(driver, filePrefix).getAbsolutePath();
lastPageSource = taker.dumpPageSource(driver, filePrefix).getAbsolutePath();
}
}
public void setDriver(RemoteWebDriver driver) {
this.driver = driver;
}
public void setServerURL(String serverURL) {
this.serverURL = serverURL;
}
@Override
public void starting(FrameworkMethod method) {
String message = String.format("Starting test '%s#%s'", getTestClassName(method), method.getName());
log.info(message);
String className = getTestClassName(method);
String methodName = method.getName();
filePrefix = String.format("screenshot-lastpage-%s-%s", className, methodName);
logOnServer(message);
}
@Override
public void succeeded(FrameworkMethod method) {
if (lastPageSource != null) {
new File(lastPageSource).delete();
}
if (lastScreenshot != null) {
new File(lastScreenshot).delete();
}
}
}