package api;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import models.FieldUrl;
import models.Target;
import org.junit.Before;
import org.junit.Test;
import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.*;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeCreator;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import play.Configuration;
import play.Logger;
import play.Play;
import play.libs.Json;
import play.libs.F.Callback;
import play.libs.F.Promise;
import play.libs.ws.WS;
import play.libs.ws.WSResponse;
import play.test.*;
import uk.bl.Const;
import uk.bl.Const.ScopeType;
import uk.bl.exception.ActException;
import uk.bl.scope.Scope;
import static play.test.Helpers.*;
public class APIIntegrationTests {
private static long timeout_ms = 60*1000; // in milliseconds
@Before
public void initialize() {
}
@Test
public void testInServer() {
final String defaultUser = "wa-sysadm@bl.uk";
final String defaultPw = "sysAdmin";
running(testServer(3333, fakeApplication()), new Runnable() {
@Override
public void run() {
String act_url = "http://localhost:3333/act";
Logger.info("STEP Getting the homepage...");
String act_user = defaultUser;
String act_pw = defaultPw;
Logger.info("Logging into "+act_url);
Logger.info("Logging in as "+act_user+" "+act_pw);
JsonNode json = Json.newObject()
.put("email",act_user)
.put("password",act_pw)
.put("redirectToUrl", "");
Promise<WSResponse> login = WS
.url(act_url + "/login")
.setContentType("application/x-www-form-urlencoded")
.setFollowRedirects(false)
.post(json);
WSResponse r = login.get(timeout_ms);
assertThat( r.getStatus() ).isLessThan(400);
if( r.getStatus() >= 400 ) {
Logger.error("Login failed.");
} else {
Logger.info("Login succeeded.");
}
String cookie = r.getHeader("Set-Cookie");
Logger.info("STEP Clearing out Test Data...");
// Clear out any existing data:
for( Target t : Target.findAll() ) {
t.delete();
}
// Send up test data:
try {
Logger.info("STEP Sending Test Data...");
sendTestData(act_url,cookie);
Logger.info("STEP Running API Tests...");
runSomeAPITests(act_url,cookie);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
/*
* Method to populate a running system with some test data.
*/
private static Long populate(String host, String cookie, String title, String url, String scope, String start_date, int expected) {
String one = "{\"title\": \""+title+"\", \"field_urls\": [\""+url+"\"],\"field_scope\": \""+scope+"\",\"field_crawl_start_date\": \""+start_date+"\", \"selector\": 1, \"field_crawl_frequency\": \"MONTHLY\" }";
Promise<WSResponse> result = WS.url(host+"/api/targets").setHeader("Cookie", cookie).setHeader("Content-Type", "application/json").post(one);
WSResponse response = result.get(timeout_ms);
Logger.info("populate GOT "+response.getStatus()+" "+response.getStatusText());
assertThat(response.getStatus()).isEqualTo(expected);
if( response.getAllHeaders().containsKey(LOCATION)) {
String loc = response.getHeader(LOCATION);
Long id = Long.parseLong(loc.substring(loc.lastIndexOf('/')+1));
return id;
} else {
return null;
}
}
private static void sendTestData(String host, String cookie) throws JsonParseException, JsonMappingException, IOException {
populate(host, cookie, "anjackson.net news", "http://anjackson.net/news/","resource", "", 201 );
populate(host, cookie, "British Library", "http://www.bl.uk","root", "1425790800", 201 );
populate(host, cookie, "British Library News", "http://www.bl.uk/news/","plus1", "1425790800", 201 );
populate(host, cookie, "M&S", "http://marksandspencer.com/","subdomains", "1425790800", 201 );
populate(host, cookie, "Example", "http://example.com/","subdomains", "1425790800", 201 );
populate(host, cookie, "Example Subdomain", "http://subdomain.example.com/","subdomains", "1425790800", 201 );
}
private static void runSomeAPITests(String host, String cookie) throws JsonParseException, JsonMappingException, IOException {
// Push and entry in:
Logger.info("STEP API New Target...");
Long oid = populate(host, cookie, "anjackson.net", "http://anjackson.net/","root", "", 201 );
Logger.info("STEP Check target is not easily duplicated (without a slash)...");
Long noid = populate(host, cookie, "anjackson.net noslash", "http://anjackson.net","root", "", 409 );
// Get it back:
Logger.info("STEP API Get Target...");
Target target = getTargetByID( host, oid, cookie);
Long tid = target.id;
Logger.info("Checking "+target.toString());
assertThat(target.title).isEqualTo("anjackson.net");
assertThat(target.fieldUrls.get(0).url).isEqualTo("http://anjackson.net/");
assertThat(target.scope).isEqualTo(ScopeType.root.name());
assertThat(target.crawlStartDate).isNull();
// Now PUT to the same ID, changing some fields:
Logger.info("STEP API Update Target (1)...");
String update = "{\"id\": "+tid+", \"field_scope\": \"subdomains\", \"field_crawl_frequency\": \"MONTHLY\" }";
WSResponse response = WS.url(host+"/api/targets/"+oid).setHeader("Cookie", cookie).setHeader("Content-Type", "application/json").put(update).get(timeout_ms);
Logger.info(response.getStatus()+" "+response.getStatusText());
assertThat(response.getStatus()).isEqualTo(OK);
Logger.info("STEP API Get Target (1)...");
Target t2 = getTargetByID( host, oid, cookie);
Logger.info("Now "+t2.toString());
// And change scope back, but leave the frequency:
Logger.info("STEP API Update Target (2)...");
String update2 = "{\"id\": "+tid+", \"field_scope\": \"root\" }";
response = WS.url(host+"/api/targets/"+oid).setHeader("Cookie", cookie).setHeader("Content-Type", "application/json").put(update2).get(timeout_ms);
Logger.info(response.getStatus()+" "+response.getStatusText());
assertThat(response.getStatus()).isEqualTo(OK);
Target t3 = getTargetByID( host, oid, cookie);
Logger.info("Now "+t2.toString());
// Check the default value for the frequency field in the Target class did not override the original value in the merge.
assertThat(t3.crawlFrequency).isEqualTo(Const.CrawlFrequency.MONTHLY.name());
}
private static Target getTargetByID( String host, Long id, String cookie ) throws JsonParseException, JsonMappingException, IOException {
WSResponse response = WS.url(host+"/api/targets/"+id).setFollowRedirects(false).get().get(timeout_ms);
Logger.info(response.getStatus()+" "+response.getStatusText());
Logger.debug(response.getBody());
assertThat(response.getStatus()).isNotEqualTo(OK);
response = WS.url(host+"/api/targets/"+id).setHeader("Cookie", cookie).get().get(timeout_ms);
Logger.info(response.getStatus()+" "+response.getStatusText());
Logger.debug(response.getBody());
assertThat(response.getStatus()).isEqualTo(OK);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(Include.NON_DEFAULT);
return objectMapper.readValue(response.getBody(), Target.class);
}
/**
* To populate a specified system with test data.
*
* @param args
*/
public static void main( String args[] ) throws Exception {
//sendTestData("http://localhost:9000/act");
}
}