protected String doCypherRestCall( String endpoint, String script, Status status, Pair<String, String>... params) { data.get(); String parameterString = createParameterString(params); String queryString = "{\"query\": \"" + createScript(script) + "\"," + parameterString + "},"; gen.get() .expectedStatus(status.getStatusCode()) .payload(queryString) .description(AsciidocHelper.createCypherSnippet(script)); return gen.get().post(endpoint).entity(); }
protected String doGremlinRestCall( String endpoint, String script, Status status, Pair<String, String>... params) { data.get(); String parameterString = createParameterString(params); String queryString = "{\"script\": \"" + createScript(script) + "\"," + parameterString + "},"; gen.get() .expectedStatus(status.getStatusCode()) .payload(queryString) .description(formatGroovy(createScript(script))); return gen.get().post(endpoint).entity(); }
/** Set property on node. */ @Documented @Test public void shouldReturn204WhenPropertyIsSet() throws Exception { gen.get() .payload(JsonHelper.createJsonFrom("bar")) .expectedStatus(204) .put(getPropertyUri("foo").toString()); }
protected void captureScreenshot(String string) { WebDriver webDriver = wl.getWebDriver(); if (webDriver instanceof TakesScreenshot) { try { File screenshotFile = ((TakesScreenshot) webDriver).getScreenshotAs(FILE); System.out.println(screenshotFile.getAbsolutePath()); File dir = new File("target/docs/webadmin/images"); dir.mkdirs(); String imageName = string + ".png"; copyFile(screenshotFile, new File(dir, imageName)); gen.get().addImageSnippet(string, imageName, gen.get().getTitle()); } catch (Exception e) { e.printStackTrace(); } } }
/** * When auth is disabled * * <p>When auth has been disabled in the configuration, requests can be sent without an * +Authorization+ header. */ @Test @Documented public void auth_disabled() throws IOException { // Given startServer(false); // Document gen.get().noGraph().expectedStatus(200).get(dataURL()); }
/** * Property values can not be nested. * * <p>Nesting properties is not supported. You could for example store the nested json as a string * instead. */ @Documented @Test public void shouldReturn400WhenSendinIncompatibleJsonProperty() throws Exception { gen.get() .payload("{\"foo\" : {\"bar\" : \"baz\"}}") .expectedStatus(400) .post(functionalTestHelper.nodeUri()); JaxRsResponse response = setNodePropertyOnServer("jim", new HashMap<String, Object>()); assertEquals(400, response.getStatus()); response.close(); }
/** Update node properties. */ @Documented @Test public void shouldReturn204WhenPropertiesAreUpdated() throws JsonParseException { Map<String, Object> map = new HashMap<String, Object>(); map.put("jim", "tobias"); gen.get() .payload(JsonHelper.createJsonFrom(map)) .expectedStatus(204) .put(propertiesUri.toString()); JaxRsResponse response = updateNodePropertiesOnServer(map); assertEquals(204, response.getStatus()); }
@Test @Graph( value = {"John friend Sara", "John friend Joe", "Sara friend Maria", "Joe friend Steve"}, autoIndexNodes = true) public void intro_examples() throws Exception { try (Transaction ignored = graphdb.beginTx()) { Writer fw = AsciiDocGenerator.getFW(DOCS_TARGET, gen.get().getTitle()); data.get(); fw.append("\nImagine an example graph like the following one:\n\n"); fw.append( AsciiDocGenerator.dumpToSeparateFileWithType( new File(DOCS_TARGET), "intro.graph", AsciidocHelper.createGraphVizWithNodeId("Example Graph", graphdb(), "cypher-intro"))); fw.append( "\nFor example, here is a query which finds a user called John and John's friends (though not " + "his direct friends) before returning both John and any friends-of-friends that are found."); fw.append("\n\n"); String query = "MATCH (john {name: 'John'})-[:friend]->()-[:friend]->(fof) RETURN john, fof "; fw.append( AsciiDocGenerator.dumpToSeparateFileWithType( new File(DOCS_TARGET), "intro.query", createCypherSnippet(query))); fw.append("\nResulting in:\n\n"); fw.append( AsciiDocGenerator.dumpToSeparateFileWithType( new File(DOCS_TARGET), "intro.result", createQueryResultSnippet(engine.execute(query).dumpToString()))); fw.append( "\nNext up we will add filtering to set more parts " + "in motion:\n\nWe take a list of user names " + "and find all nodes with names from this list, match their friends and return " + "only those followed users who have a +name+ property starting with +S+."); query = "MATCH (user)-[:friend]->(follower) WHERE " + "user.name IN ['Joe', 'John', 'Sara', 'Maria', 'Steve'] AND follower.name =~ 'S.*' " + "RETURN user, follower.name "; fw.append("\n\n"); fw.append( AsciiDocGenerator.dumpToSeparateFileWithType( new File(DOCS_TARGET), "intro.query", createCypherSnippet(query))); fw.append("\nResulting in:\n\n"); fw.append( AsciiDocGenerator.dumpToSeparateFileWithType( new File(DOCS_TARGET), "intro.result", createQueryResultSnippet(engine.execute(query).dumpToString()))); fw.close(); } }
/** Get all relationships. */ @Documented @Test public void shouldRespondWith200AndListOfRelationshipRepresentationsWhenGettingAllRelationshipsForANode() throws JsonParseException { String entity = gen.get() .expectedStatus(200) .get( functionalTestHelper.nodeUri() + "/" + nodeWithRelationships + "/relationships" + "/all") .entity(); verifyRelReps(3, entity); }
/** * Authenticate to access the server * * <p>Authenticate by sending a username and a password to Neo4j using HTTP Basic Auth. Requests * should include an +Authorization+ header, with a value of +Basic realm="Neo4j" <payload>+, * where "payload" is a base64 encoded string of "username:password". */ @Test @Documented public void successful_authentication() throws PropertyValueException, IOException { // Given startServerWithConfiguredUser(); // Document RESTDocsGenerator.ResponseEntity response = gen.get() .noGraph() .expectedStatus(200) .withHeader(HttpHeaders.AUTHORIZATION, challengeResponse("neo4j", "secret")) .get(userURL("neo4j")); // Then JsonNode data = JsonHelper.jsonNode(response.entity()); assertThat(data.get("username").asText(), equalTo("neo4j")); assertThat(data.get("password_change_required").asBoolean(), equalTo(false)); assertThat(data.get("password_change").asText(), equalTo(passwordURL("neo4j"))); }
/** * Missing authorization * * <p>If an +Authorization+ header is not supplied, the server will reply with an error. */ @Test @Documented public void missing_authorization() throws PropertyValueException, IOException { // Given startServerWithConfiguredUser(); // Document RESTDocsGenerator.ResponseEntity response = gen.get() .noGraph() .expectedStatus(401) .expectedHeader("WWW-Authenticate", "None") .get(dataURL()); // Then JsonNode data = JsonHelper.jsonNode(response.entity()); JsonNode firstError = data.get("errors").get(0); assertThat( firstError.get("code").asText(), equalTo("Neo.ClientError.Security.AuthorizationFailed")); assertThat(firstError.get("message").asText(), equalTo("No authorization header supplied.")); }
/** * Incorrect authentication * * <p>If an incorrect username or password is provided, the server replies with an error. */ @Test @Documented public void incorrect_authentication() throws PropertyValueException, IOException { // Given startServerWithConfiguredUser(); // Document RESTDocsGenerator.ResponseEntity response = gen.get() .noGraph() .expectedStatus(401) .withHeader(HttpHeaders.AUTHORIZATION, challengeResponse("neo4j", "incorrect")) .expectedHeader("WWW-Authenticate", "None") .post(dataURL()); // Then JsonNode data = JsonHelper.jsonNode(response.entity()); JsonNode firstError = data.get("errors").get(0); assertThat( firstError.get("code").asText(), equalTo("Neo.ClientError.Security.AuthorizationFailed")); assertThat(firstError.get("message").asText(), equalTo("Invalid username or password.")); }
/** * Required password changes * * <p>In some cases, like the very first time Neo4j is accessed, the user will be required to * choose a new password. The database will signal that a new password is required and deny * access. * * <p>See <<rest-api-security-user-status-and-password-changing>> for how to set a new password. */ @Test @Documented public void password_change_required() throws PropertyValueException, IOException { // Given startServer(true); // Document RESTDocsGenerator.ResponseEntity response = gen.get() .noGraph() .expectedStatus(403) .withHeader(HttpHeaders.AUTHORIZATION, challengeResponse("neo4j", "neo4j")) .get(dataURL()); // Then JsonNode data = JsonHelper.jsonNode(response.entity()); JsonNode firstError = data.get("errors").get(0); assertThat( firstError.get("code").asText(), equalTo("Neo.ClientError.Security.AuthorizationFailed")); assertThat( firstError.get("message").asText(), equalTo("User is required to change their password.")); assertThat(data.get("password_change").asText(), equalTo(passwordURL("neo4j"))); }
/** The service root is your starting point to discover the REST API. */ @Documented @Test @TestData.Title("Get service root") public void assert200OkFromGet() throws Exception { gen.get().expectedStatus(200).get(functionalTestHelper.dataUri()); }
@After public void doc() { gen.get().document("target/docs", "webadmin"); }
@Before public void cleanContent() { cleanDatabase(); gen.get().setGraph(graphdb()); }
public RESTDocsGenerator gen() { return gen.get(); }
@Before public void setUp() { gen.get().setSection("dev/rest-api"); }