/*
* Copyright © 2013. Palomino Labs (http://palominolabs.com)
*
* 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 com.palominolabs.crm.sf.rest;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.palominolabs.crm.sf.core.Id;
import com.palominolabs.crm.sf.core.SObject;
import com.palominolabs.crm.sf.soap.PartnerSObjectImpl;
import com.palominolabs.crm.sf.testutil.ConnectionTestSfUserProps;
import com.palominolabs.testutil.ResourceUtil;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.palominolabs.crm.sf.rest.HttpApiClient.API_VERSION;
import static com.palominolabs.crm.sf.rest.TestConnections.MAPPER;
import static com.palominolabs.crm.sf.rest.TestConnections.getHttpApiClient;
import static com.palominolabs.testutil.JsonAssert.assertJsonStringEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@SuppressWarnings("StaticNonFinalField")
public class HttpApiClientTest {
static final String USER =
ConnectionTestSfUserProps.getPropVal("com.palominolabs.test.crm.sf.conn.org2MainUser.sfLogin");
static final String PASSWORD =
ConnectionTestSfUserProps.getPropVal("com.palominolabs.test.crm.sf.conn.org2MainUser.sfPassword");
private static HttpApiClient client = null;
@BeforeClass
public static void setUpClass() throws com.palominolabs.crm.sf.soap.ApiException, MalformedURLException {
client = getHttpApiClient(USER, PASSWORD);
}
@Test
public void testCreateWithNoFields() throws IOException {
SObject sObj = RestSObjectImpl.getNew("Contact");
try {
client.create(sObj);
fail();
} catch (ApiException e) {
assertEquals("https://na3.salesforce.com:443/services/data/v" + API_VERSION + "/sobjects/Contact/", e.getUrl());
assertEquals("Bad Request", e.getHttpReason());
assertJsonStringEquals(
"[{\"fields\":[\"LastName\"],\"message\":\"Required fields are missing: [LastName]\"," +
"\"errorCode\":\"REQUIRED_FIELD_MISSING\"}]",
e.getHttpResponseBody());
assertEquals(400, e.getHttpResponseCode());
List<ApiError> errors = e.getErrors();
assertEquals(1, errors.size());
ApiError apiError = errors.get(0);
assertEquals("REQUIRED_FIELD_MISSING", apiError.getErrorCode());
assertEquals("Required fields are missing: [LastName]", apiError.getMessage());
assertEquals(Arrays.asList("LastName"), apiError.getFields());
}
}
@Test
public void testCreateThenDelete() throws IOException {
String createStr = createTask();
ObjectNode actual = MAPPER.readValue(createStr, ObjectNode.class);
ObjectNode expected =
MAPPER.readValue(ResourceUtil.readResource("/apiResponses/create.json"), ObjectNode.class);
String id = actual.get("id").textValue();
// id changes every time
expected.put("id", id);
assertEquals(expected, actual);
client.delete("Task", new Id(id));
}
@Test
public void testDeleteBadId() throws IOException {
try {
client.delete("Lead", new Id("00Q7zzz000Kj4Jn"));
fail();
} catch (ApiException e) {
assertEquals("https://na3.salesforce.com:443/services/data/v" + API_VERSION + "/sobjects/Lead/00Q7zzz000Kj4Jn",
e.getUrl());
assertEquals("Not Found", e.getHttpReason());
assertJsonStringEquals(
"[{\"message\":\"Provided external ID field does not exist or is not accessible:" +
" 00Q7zzz000Kj4Jn\",\"errorCode\":\"NOT_FOUND\"}]",
e.getHttpResponseBody());
assertEquals(404, e.getHttpResponseCode());
List<ApiError> errors = e.getErrors();
assertEquals(1, errors.size());
ApiError apiError = errors.get(0);
assertEquals("NOT_FOUND", apiError.getErrorCode());
assertEquals("Provided external ID field does not exist or is not accessible: 00Q7zzz000Kj4Jn",
apiError.getMessage());
assertEquals(0, apiError.getFields().size());
}
}
@Test
public void testDescribeGlobalResponse() throws IOException {
String actualJsonStr = reformatJson(client.describeGlobal());
assertJsonStringEquals(ResourceUtil.readResource("/apiResponses/describeGlobal.json"),
actualJsonStr);
}
@Test
public void testDescribeSObject() throws IOException {
String actualJsonStr = reformatJson(client.describeSObject("Account"));
assertJsonStringEquals(ResourceUtil.readResource("/apiResponses/describeSObject.json"),
actualJsonStr);
}
@Test
public void testBasicSObjectInfo() throws IOException {
String actualJsonStr = reformatJson(client.basicSObjectInfo("Account"));
assertJsonStringEquals(ResourceUtil.readResource("/apiResponses/basicSObjectMetadata.json"),
actualJsonStr);
}
@Test
public void testQuery() throws IOException {
String actualJsonStr = reformatJson(
client.query("SELECT Id,Name,Description FROM Product2 WHERE Id = '01t50000001L5cT'"));
assertJsonStringEquals(ResourceUtil.readResource("/apiResponses/query.json"), actualJsonStr);
}
@Test
public void testQueryWithSubquery() throws IOException {
String actualJsonStr = reformatJson(
client.query(
"SELECT Id, Name, AnnualRevenue, (SELECT Id, FirstName, Email FROM Contacts), " +
" (Select Id, Subject from Tasks) FROM Account WHERE Id='0015000000WWD7b'"));
assertJsonStringEquals(ResourceUtil.readResource("/apiResponses/queryWithSubquery.json"), actualJsonStr);
}
@Test
public void testQueryWithRelationship() throws IOException {
String actualJsonStr = reformatJson(
client.query("SELECT Id, Name, Owner.Name, Owner.Id FROM Account WHERE Id='0015000000WWD7b'"));
assertJsonStringEquals(ResourceUtil.readResource("/apiResponses/queryWithSubObject.json"), actualJsonStr);
}
@Test
public void testQueryMoreBadQueryLocator() throws IOException {
try {
client.queryMore(new RestQueryLocator("/services/data/v21.0/query/wrong"));
fail();
} catch (ApiException e) {
assertEquals(
"https://na3.salesforce.com:443/services/data/v21.0/query/wrong",
e.getUrl());
assertEquals("Bad Request", e.getHttpReason());
assertJsonStringEquals(
"[{\"message\":\"invalid query locator\",\"errorCode\":\"INVALID_QUERY_LOCATOR\"}]",
e.getHttpResponseBody());
assertEquals(400, e.getHttpResponseCode());
List<ApiError> errors = e.getErrors();
assertEquals(1, errors.size());
ApiError error = errors.get(0);
assertEquals("INVALID_QUERY_LOCATOR", error.getErrorCode());
assertEquals("invalid query locator", error.getMessage());
assertEquals(0, error.getFields().size());
}
}
@Test
public void testSearch() throws IOException {
String actualJsonStr = reformatJson(
client.search("FIND {dickenson.com} returning contact(id, phone, firstname, lastname, email)"));
assertJsonStringEquals(ResourceUtil.readResource("/apiResponses/search.json"), actualJsonStr);
}
@Test
public void testRetrieve() throws IOException {
String actualJsonStr = reformatJson(client.retrieve("Contact", new Id("0035000000km1oh"),
Arrays.asList("FirstName", "LastName")));
assertJsonStringEquals(ResourceUtil.readResource("/apiResponses/retrieve.json"), actualJsonStr);
}
private static String createTask() throws IOException {
SObject sObj = PartnerSObjectImpl.getNew("Task");
sObj.setField("Priority", "High");
sObj.setField("Status", "In Progress");
return checkNotNull(client.create(sObj));
}
private static String reformatJson(@Nullable String input) throws IOException {
checkNotNull(input);
JsonFactory jsonFactory = new JsonFactory();
JsonParser parser = jsonFactory.createParser(input);
StringWriter writer = new StringWriter();
JsonGenerator generator = jsonFactory.createGenerator(writer);
generator.useDefaultPrettyPrinter();
while (parser.nextToken() != null) {
generator.copyCurrentEvent(parser);
}
generator.close();
return writer.toString();
}
}