Skip to content

Commit

Permalink
test basic node HTML responses using HTMLUnit
Browse files Browse the repository at this point in the history
  • Loading branch information
cbeer committed Nov 6, 2013
1 parent e79b15c commit e76f7a9
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 10 deletions.
24 changes: 24 additions & 0 deletions fcrepo-http-api/pom.xml
Expand Up @@ -129,6 +129,30 @@
<version>1.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<scope>test</scope>
<version>2.13</version>

<exclusions>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit-core-js</artifactId>
<scope>test</scope>
<version>2.13</version>
</dependency>
<!-- This dependency is for compile-time: it keeps this module independent
of any given choice of JAX-RS implementation. It must be _after_ the test
gear. Otherwise it will get loaded during test phase, but because this is
Expand Down
26 changes: 26 additions & 0 deletions fcrepo-http-api/src/main/java/org/fcrepo/http/api/FedoraNodes.java
Expand Up @@ -83,6 +83,7 @@
import javax.ws.rs.core.UriInfo;

import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.sun.jersey.multipart.FormDataParam;
import org.apache.commons.io.IOUtils;
import org.apache.jena.riot.Lang;
import org.fcrepo.http.commons.AbstractResource;
Expand Down Expand Up @@ -521,6 +522,31 @@ public Response createObject(@PathParam("path")
}
}

/**
* Create a new object from a multipart/form-data POST request
* @param pathList
* @param mixin
* @param slug
* @param uriInfo
* @param file
* @return
* @throws Exception
*/
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Timed
public Response createObjectFromFormPost(
@PathParam("path") final List<PathSegment> pathList,
@FormDataParam("mixin") final String mixin,
@FormDataParam("slug") final String slug,
@Context final UriInfo uriInfo,
@FormDataParam("file") final InputStream file
) throws Exception {

return createObject(pathList, mixin, null, null, slug, uriInfo, file);

}

/**
* Deletes an object.
*
Expand Down
16 changes: 9 additions & 7 deletions fcrepo-http-api/src/main/resources/views/common-node-actions.vsl
@@ -1,11 +1,11 @@

<form id="action_create">
<form id="action_create" method="POST" enctype="multipart/form-data">
<h3>Create New Node</h3>
<div class="form-group">
<label for="new_mixin" class="control-label">
Type
</label>
<select id="new_mixin" class="form-control">
<select id="new_mixin" name="mixin" class="form-control">
<option value="fedora:object">object</option>
<option value="fedora:datastream">datastream</option>
</select>
Expand All @@ -15,22 +15,23 @@
<label for="new_id" class="control-label">
Identifier
</label>
<input type="text" id="new_id" placeholder="(auto-generated identifier)" class="form-control"/>
<input type="text" id="new_id" name="slug" placeholder="(auto-generated identifier)" class="form-control"/>
</div>


<div id="datastream_payload_container" class="form-group">
<label for="datastream_payload" class="control-label">
File
</label>
<input type="file" id="datastream_payload"/>
<input type="file" name="file" id="datastream_payload"/>
</div>
<button type="submit" class="btn btn-primary">Add</button>
<hr />
</form>


<form id="action_sparql_update">
<form id="action_sparql_update" method="POST">
<input type="hidden" name="_method" value="PATCH" />
<h3>Update Properties</h3>
<div class="form-group">
<textarea rows="10" id="sparql_update_query" name="query" class="form-control">
Expand All @@ -45,7 +46,8 @@ WHERE { }
</form>


<form id="action_delete" action="javascript:deleteItem()">
<form id="action_delete" action="javascript:deleteItem()" method="POST">
<input type="hidden" name="_method" value="DELETE" />
<h3>Delete Object</h3>
<button type="submit" class="btn btn-danger">Delete</button>
<hr />
Expand Down Expand Up @@ -76,7 +78,7 @@ WHERE { }
#set ($serializations = $rdf.find($nodeany, $topic, $helpers.asNode($rdfLexicon.HAS_SERIALIZATION), $nodeany))

#if($serializations.hasNext())
<form id="action_import">
<form id="action_import" action="fcr:import" method="POST">
<h3>Import</h3>


Expand Down
4 changes: 2 additions & 2 deletions fcrepo-http-api/src/main/resources/views/node.vsl
Expand Up @@ -21,7 +21,7 @@
#parse("views/common-breadcrumb.vsl")
</div>

<div class="col-md-3 col-md-push-9 clearfix">
<div id="sidebar" class="col-md-3 col-md-push-9 clearfix">
<button id="toggle-actions" type="button" class="visible-xs visible-sm btn btn-danger" data-toggle="collapse" data-target=".actions">
<span>Toggle actions</span>
</button>
Expand All @@ -32,7 +32,7 @@
</div>
</div>

<div class="col-md-9 col-md-pull-3">
<div id="metadata" class="col-md-9 col-md-pull-3">

#parse("views/common-metadata.vsl")

Expand Down
@@ -0,0 +1,197 @@
/**
* Copyright 2013 DuraSpace, Inc.
*
* 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.
*/
package org.fcrepo.integration.http.api.html;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlFileInput;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
import com.gargoylesoftware.htmlunit.html.HtmlTextArea;
import org.fcrepo.integration.http.api.AbstractResourceIT;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import java.io.IOException;

import static java.util.UUID.randomUUID;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class FedoraHtmlResponsesIT extends AbstractResourceIT {

WebClient webClient;
WebClient javascriptlessWebClient;

@Before
public void setUp() {
webClient = getDefaultWebClient();

javascriptlessWebClient = getDefaultWebClient();
javascriptlessWebClient.getOptions().setJavaScriptEnabled(false);
}

@After
public void cleanUp() {
webClient.closeAllWindows();
javascriptlessWebClient.closeAllWindows();
}

@Test
public void testDescribeHtml() throws IOException {
final HtmlPage page = webClient.getPage(serverAddress);

checkForHeaderBranding(page);
checkForHeaderSearch(page);
}

@Test
public void testCreateNewNodeWithProvidedId() throws IOException, InterruptedException {

final String pid = randomUUID().toString();

final HtmlPage page = webClient.getPage(serverAddress);

final HtmlInput new_id = (HtmlInput)page.getElementById("new_id");
new_id.setValueAttribute(pid);
page.executeJavaScript("$('#action_create .btn-primary').click();");
webClient.waitForBackgroundJavaScript(1000);

final HtmlPage page1 = webClient.getPage(serverAddress + pid);
assertEquals(serverAddress + pid, page1.getTitleText());
}

@Test
public void testCreateNewNodeWithGeneratedId() throws IOException, InterruptedException {

final HtmlPage page = webClient.getPage(serverAddress);

page.executeJavaScript("$('#action_create .btn-primary').click();");
webClient.waitForBackgroundJavaScript(1000);

}

@Test
public void testCreateNewDatastream() throws IOException, InterruptedException {

final String pid = randomUUID().toString();

// can't do this with javascript, because HTMLUnit doesn't speak the HTML5 file api
final HtmlPage page = javascriptlessWebClient.getPage(serverAddress);
final HtmlForm form = (HtmlForm)page.getElementById("action_create");

final HtmlInput slug = form.getInputByName("slug");
slug.setValueAttribute(pid);

final HtmlSelect type = form.getSelectByName("mixin");
type.getOptionByValue("fedora:datastream").setSelected(true);

final HtmlFileInput fileInput = (HtmlFileInput)page.getElementById("datastream_payload");
fileInput.setData("abcdef".getBytes());
fileInput.setContentType("application/pdf");

final HtmlButton button = form.getFirstByXPath("button");
button.click();

final HtmlPage page1 = webClient.getPage(serverAddress + pid);
assertEquals(serverAddress + pid, page1.getTitleText());
}

@Test
public void testCreateNewObjectAndDeleteIt() throws IOException {
final boolean throwExceptionOnFailingStatusCode = webClient.getOptions().isThrowExceptionOnFailingStatusCode();
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);

final String pid = createNewObject();

final HtmlPage page1 = webClient.getPage(serverAddress + pid);
final HtmlForm action_delete = (HtmlForm) page1.getElementById("action_delete");
((HtmlButton)action_delete.getFirstByXPath("button")).click();
webClient.waitForBackgroundJavaScript(1000);


final HtmlPage page2 = webClient.getPage(serverAddress + pid);
assertEquals(404, page2.getWebResponse().getStatusCode());

webClient.getOptions().setThrowExceptionOnFailingStatusCode(throwExceptionOnFailingStatusCode);
}

@Test
@Ignore
public void testCreateNewObjectAndSetProperties() throws IOException {
final String pid = createNewObject();

final HtmlPage page = webClient.getPage(serverAddress + pid);
final HtmlForm form = (HtmlForm)page.getElementById("action_sparql_update");
final HtmlTextArea sparql_update_query = (HtmlTextArea)page.getElementById("sparql_update_query");
sparql_update_query.setText("INSERT { <> <info:some-predicate> 'asdf' } WHERE { }");

final HtmlButton button = form.getFirstByXPath("button");
button.click();

final HtmlPage page1 = webClient.getPage(serverAddress + pid);
assertTrue(page1.getElementById("metadata").asText().contains("some-predicate"));
}

private void checkForHeaderSearch(HtmlPage page) {
final HtmlForm form = page.getFirstByXPath("//form[@role='search']");
assertNotNull(form);
assertEquals(serverAddress + "fcr:search", form.getActionAttribute());
}

private void checkForHeaderBranding(final HtmlPage page) {
assertNotNull(page.getFirstByXPath("//nav[@role='navigation']/div[@class='navbar-header']/a[@class='navbar-brand']"));
}

private String createNewObject() throws IOException {

final String pid = randomUUID().toString();

final HtmlPage page = webClient.getPage(serverAddress);
final HtmlForm form = (HtmlForm)page.getElementById("action_create");

final HtmlInput slug = form.getInputByName("slug");
slug.setValueAttribute(pid);

final HtmlButton button = form.getFirstByXPath("button");
button.click();

webClient.waitForBackgroundJavaScript(1000);
return pid;
}


private WebClient getDefaultWebClient() {

WebClient webClient = new WebClient(BrowserVersion.FIREFOX_17);
webClient.addRequestHeader("Accept", "text/html");

webClient.waitForBackgroundJavaScript(1000);
webClient.waitForBackgroundJavaScriptStartingBefore(10000);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
return webClient;

}

}
6 changes: 5 additions & 1 deletion fcrepo-http-api/src/test/resources/web.xml
Expand Up @@ -27,7 +27,11 @@
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>com.sun.jersey.api.container.filter.PostReplaceFilter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
Expand Down

0 comments on commit e76f7a9

Please sign in to comment.