Skip to content

Commit

Permalink
Merge pull request #174 from Nexmo/bugfix/ConfigurationAbstractionDep…
Browse files Browse the repository at this point in the history
…dencyBug

Fixing Unit tests, fixing Application flow, fixing possible NRE
  • Loading branch information
slorello89 authored Nov 11, 2019
2 parents 4c651e2 + 06efc55 commit ea42f4a
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 79 deletions.
Empty file added .travis.yml
Empty file.
67 changes: 59 additions & 8 deletions Nexmo.Api.Test.Unit/ApplicationV2Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void ShouldCreateApplication()

SetExpect($"{ApiUrl}/v2/applications",
"{\"id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",\"name\":\"AppV2Test\",\"capabilities\":{},\"keys\":{\"public_key\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwxyBT5FqzibSYK0vB+Gr\\nP+YlyYqsx4lvAmotTwmObZEhTWNAdU0p9hrnNXWX1Gy5O0NDIue40SUhYhJT5r4x\\nugbpNA/1KJauB8VQjetKr9bu697yskz2+EuKa2D9e6N2EMY6PD1tJWmeMmddM1tW\\n2DAXuYo7/xsDWIIA6egCTzyShNvzlKo5081t41xVVsPjsWN887Xp1KYfE0IMGV2j\\n8Nwdtw/MQfP/7Qz7i9VXb7bgx0LEg84dWsnz8u3VZ3IQHlydzPX/2iw7e4pc+k27\\nOU1SkmPn/2JtfFFS2LJpcO/FmdSyNnyHezNPyzNRLVbE0sJJ1tEhxi9GZc1I+Oc4\\ndwIDAQAB\\n-----END PUBLIC KEY-----\\n\",\"private_key\":\"-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDHIFPkWrOJtJg\\nrS8H4as/5iXJiqzHiW8Cai1PCY5tkSFNY0B1TSn2Guc1dZfUbLk7Q0Mi57jRJSFi\\nElPmvjG6Buk0D/Uolq4HxVCN60qv1u7r3vKyTPb4S4prYP17o3YQxjo8PW0laZ4y\\nZ10zW1bYMBe5ijv/GwNYggDp6AJPPJKE2/OUqjnTzW3jXFVWw+OxY3zztenUph8T\\nQgwZXaPw3B23D8xB8//tDPuL1VdvtuDHQsSDzh1ayfPy7dVnchAeXJ3M9f/aLDt7\\nilz6Tbs5TVKSY+f/Ym18UVLYsmlw78WZ1LI2fId7M0/LM1EtVsTSwknW0SHGL0Zl\\nzUj45zh3AgMBAAECggEAFP06iJ7p9fkQKwKbwMXNQIes1fm7QjtDJr0vAvB8vXBe\\nPER/7n6EE+vApqwapBP5eJTGTU7PP382kFB3bScAaMo4iSIUVgRLqXNXtJoKGVDO\\nYq/DvQbxjzQVKnMEdyoBAqdIeYAu1IEAWdzBFnbDfhNCYh0q/MkLpZhVVSm2dzkq\\nl+xrEOTyuE48RQxTQqliUYXXlUd5+bjR+oREuYsjt8j9iiK1u6Gv2ztDPeyzupny\\ntCvSlykvAKn/K6xmeO4hapPKUZ7DRthg3I3uPx+mw48GvO28mzhsqXpbDcYI7q82\\nfZgZJ3JKBTRaNnEE8d5llblC5dksMttLgO2EewdXlQKBgQDscfdVVvLYDW3lsPKl\\nAhEmi3ZcWvzDMCGeGLjJEZPfMnc+7rKbCBADQzNMZI/bsWwMJdQCMy2xMaDXr4Ew\\n4TiBdQ7ogpRex9yuJ3miKs3eey6bvpNxV70lj/xvZoSu7oANSFOCMNFUvSWFTPC5\\nNiNGk35g6xklf3WAYLx4bVJcDQKBgQDTP2qL2zQbU/hmQPnq8x/wgGn8T6zQZXbt\\nojyNPTsnIbQhwQzlFM01SzNsF4hVMB8Zz6r+8XHuo3TsDdg6Orx1auIV5lXCWMj/\\n3MW/jy2JabXJyh7BViHFqQjBPHWDrX17TGGsLK/rfOqMRPPgBGTXfVhINaCo7EAh\\nSTPv2x2RkwKBgBQinGpzDhkiA6LUz8UHiQhcRgcVZIMGvUYmWs4cphgSxx7f2uvi\\n4uI0PdEamzmdQVNDgWtyikiVrlnPw1OzSkmT+2IHhLURlhRqniwWMxPoL47pysqT\\nKzNgsKGX/GKdQuBesWXb3Ge399MDO1i6aIShGNkODEUqNoppMoOa47GdAoGAWn3t\\n/F84YQSFgfgPlu/zHKlFvYm788GjQoSe/7ndHxQ2/8ac6X0RsuS18HXcNvHYQMxO\\n6cswDRQEQCJmH/uNQ5c3pj33OruhzskaBMcmsJiSAREOP6/P48ZXM7/cbz3gZPMB\\nXCoAahYmu1PGTI5VTGIrcTNX0UTy689Z6kOo1PUCgYEAjYPkvv4j286XbGHDQyt7\\ngPvbFUPwtYxwk0u/CuZ1scBkVRCMwc8Gic1hL0yB09nvp86cCjNyYcFqa8fTpjom\\n0C7wjZd6zHR4y23U/jVxhdny6lotpgpWKO7DVprjyHQ90yGu+EDq3jDCOjyhdmqP\\n766dkdpKIYoBJOTH9+3r8gc=\\n-----END PRIVATE KEY-----\\n\"}}",
$"api_key={ApiKey}&api_secret={ApiSecret}&");
"{\"name\":\"AppV2Test\"}");


var result = ApplicationV2.Create(appRequest);
Expand All @@ -34,8 +34,60 @@ public void ShouldCreateApplication()
[TestMethod]
public void ShouldGetListOfApplications()
{
SetExpect($"{ApiUrl}/v2/applications?page_size=10&page_index=0&api_key={ApiKey}&api_secret={ApiSecret}&",
"{\"count\":1,\"page_size\":10,\"page_index\":0,\"_embedded\":{\"applications\":[{\"id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",\"name\":\"AppV2Test\",\"capabilities\":{},\"keys\":{\"public_key\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwxyBT5FqzibSYK0vB+Gr\\nP+YlyYqsx4lvAmotTwmObZEhTWNAdU0p9hrnNXWX1Gy5O0NDIue40SUhYhJT5r4x\\nugbpNA/1KJauB8VQjetKr9bu697yskz2+EuKa2D9e6N2EMY6PD1tJWmeMmddM1tW\\n2DAXuYo7/xsDWIIA6egCTzyShNvzlKo5081t41xVVsPjsWN887Xp1KYfE0IMGV2j\\n8Nwdtw/MQfP/7Qz7i9VXb7bgx0LEg84dWsnz8u3VZ3IQHlydzPX/2iw7e4pc+k27\\nOU1SkmPn/2JtfFFS2LJpcO/FmdSyNnyHezNPyzNRLVbE0sJJ1tEhxi9GZc1I+Oc4\\ndwIDAQAB\\n-----END PUBLIC KEY-----\\n\"}");
var expected = "{" +
"\"page_size\": 10," +
"\"page\": 1," +
"\"total_items\": 6," +
"\"total_pages\": 1," +
"\"_embedded\": {" +
"\"applications\": [" +
"{" +
"\"id\": \"78d335fa323d01149c3dd6f0d48968cf\"," +
"\"name\": \"My Application\"," +
"\"capabilities\": {" +
"\"voice\": {" +
"\"webhooks\": {" +
"\"answer_url\": {" +
"\"address\": \"https://example.com/webhooks/answer\"," +
"\"http_method\": \"POST\"" +
"}," +
"\"fallback_answer_url\": {" +
"\"address\": \"https://fallback.example.com/webhooks/answer\"," +
"\"http_method\": \"POST\"" +
"}," +
"\"event_url\": {" +
"\"address\": \"https://example.com/webhooks/event\"," +
"\"http_method\": \"POST\"" +
"}" +
"}" +
"}," +
"\"messages\": {" +
"\"webhooks\": {" +
"\"inbound_url\": {" +
"\"address\": \"https://example.com/webhooks/inbound\"," +
"\"http_method\": \"POST\"" +
"}," +
"\"status_url\": {" +
"\"address\": \"https://example.com/webhooks/status\"," +
"\"http_method\": \"POST\"" +
"}" +
"}" +
"}," +
"\"rtc\": {" +
"\"webhooks\": {" +
"\"event_url\": {" +
"\"address\": \"https://example.com/webhooks/event\"," +
"\"http_method\": \"POST\"" +
"}" +
"}" +
"}," +
"\"vbc\": {}" +
"}" +
"}" +
"]" +
"}" +
"}";
SetExpect($"{ApiUrl}/v2/applications?page_size=10&page=0&", expected);

var results = ApplicationV2.List();

Expand All @@ -47,8 +99,7 @@ public void ShouldGetApplication()
{
var appId = "ffffffff-ffff-ffff-ffff-ffffffffffff";

SetExpect($"{ApiUrl}/v2/applications/{appId}?api_key={ApiKey}&api_secret={ApiSecret}&",
"{\"id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",\"name\":\"AppV2Test\",\"capabilities\":{},\"keys\":{\"public_key\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwxyBT5FqzibSYK0vB+Gr\\nP+YlyYqsx4lvAmotTwmObZEhTWNAdU0p9hrnNXWX1Gy5O0NDIue40SUhYhJT5r4x\\nugbpNA/1KJauB8VQjetKr9bu697yskz2+EuKa2D9e6N2EMY6PD1tJWmeMmddM1tW\\n2DAXuYo7/xsDWIIA6egCTzyShNvzlKo5081t41xVVsPjsWN887Xp1KYfE0IMGV2j\\n8Nwdtw/MQfP/7Qz7i9VXb7bgx0LEg84dWsnz8u3VZ3IQHlydzPX/2iw7e4pc+k27\\nOU1SkmPn/2JtfFFS2LJpcO/FmdSyNnyHezNPyzNRLVbE0sJJ1tEhxi9GZc1I+Oc4\\ndwIDAQAB\\n-----END PUBLIC KEY-----\\n\"}");
SetExpect($"{ApiUrl}/v2/applications/{appId}", "{ \"id\": \"ffffffff-ffff-ffff-ffff-ffffffffffff\", \"name\": \"My Application\", \"capabilities\": {\"voice\": {\"webhooks\": {\"answer_url\": {\"address\": \"https://example.com/webhooks/answer\",\"http_method\": \"POST\"},\"fallback_answer_url\": {\"address\": \"https://fallback.example.com/webhooks/answer\",\"http_method\": \"POST\"},\"event_url\": {\"address\": \"https://example.com/webhooks/event\",\"http_method\": \"POST\"}}},\"messages\": {\"webhooks\": {\"inbound_url\": {\"address\": \"https://example.com/webhooks/inbound\",\"http_method\": \"POST\"},\"status_url\": {\"address\": \"https://example.com/webhooks/status\",\"http_method\": \"POST\"}}},\"rtc\": {\"webhooks\": {\"event_url\": {\"address\": \"https://example.com/webhooks/event\",\"http_method\": \"POST\"}}},\"vbc\": {}}}");

var results = ApplicationV2.Get(appId);

Expand All @@ -66,8 +117,8 @@ public void ShouldUpdateApplication()
};

// TODO: don't want to introduce UrlEncode dependency, but URLs are hardcoded
SetExpect($"{ApiUrl}/v2/applications/{appId}?id={appId}&name={appRequest.Name}&api_key={ApiKey}&api_secret={ApiSecret}&",
"{\"id\":\"ffffffff-ffff-ffff-ffff-ffffffffffff\",\"name\":\"UpdatedAppTest\",\"capabilities\":{},\"keys\":{\"public_key\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwxyBT5FqzibSYK0vB+Gr\\nP+YlyYqsx4lvAmotTwmObZEhTWNAdU0p9hrnNXWX1Gy5O0NDIue40SUhYhJT5r4x\\nugbpNA/1KJauB8VQjetKr9bu697yskz2+EuKa2D9e6N2EMY6PD1tJWmeMmddM1tW\\n2DAXuYo7/xsDWIIA6egCTzyShNvzlKo5081t41xVVsPjsWN887Xp1KYfE0IMGV2j\\n8Nwdtw/MQfP/7Qz7i9VXb7bgx0LEg84dWsnz8u3VZ3IQHlydzPX/2iw7e4pc+k27\\nOU1SkmPn/2JtfFFS2LJpcO/FmdSyNnyHezNPyzNRLVbE0sJJ1tEhxi9GZc1I+Oc4\\ndwIDAQAB\\n-----END PUBLIC KEY-----\\n\"},\"_links\":{\"self\":{\"href\":\"/v1/applications/ffffffff-ffff-ffff-ffff-ffffffffffff\"}}}");
SetExpect($"{ApiUrl}/v2/applications/{appId}",
"{ \"id\": \"ffffffff-ffff-ffff-ffff-ffffffffffff\", \"name\": \"UpdatedAppTest\", \"capabilities\": {\"voice\": {\"webhooks\": {\"answer_url\": {\"address\": \"https://example.com/webhooks/answer\",\"http_method\": \"POST\"},\"fallback_answer_url\": {\"address\": \"https://fallback.example.com/webhooks/answer\",\"http_method\": \"POST\"},\"event_url\": {\"address\": \"https://example.com/webhooks/event\",\"http_method\": \"POST\"}}},\"messages\": {\"webhooks\": {\"inbound_url\": {\"address\": \"https://example.com/webhooks/inbound\",\"http_method\": \"POST\"},\"status_url\": {\"address\": \"https://example.com/webhooks/status\",\"http_method\": \"POST\"}}},\"rtc\": {\"webhooks\": {\"event_url\": {\"address\": \"https://example.com/webhooks/event\",\"http_method\": \"POST\"}}},\"vbc\": {}}}");

var result = ApplicationV2.Update(appRequest);

Expand All @@ -79,7 +130,7 @@ public void ShouldDeleteApplication()
{
var appId = "ffffffff-ffff-ffff-ffff-ffffffffffff";

SetExpect($"{ApiUrl}/v2/applications/{appId}?api_key={ApiKey}&api_secret={ApiSecret}&",
SetExpect($"{ApiUrl}/v2/applications/{appId}",
"");
SetExpectStatus(HttpStatusCode.NoContent);
var result = ApplicationV2.Delete(appId);
Expand Down
18 changes: 17 additions & 1 deletion Nexmo.Api.Test.Unit/JwtTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,23 @@ public class JwtTest
[TestMethod]
public void should_generate_jwt()
{
var tok = Jwt.CreateToken(Configuration.Instance.Settings["appSettings:Nexmo.Application.Id"], Configuration.Instance.Settings["appSettings:Nexmo.Application.Key"]);
var mockAppId = "ffffffff-ffff-ffff-ffff-ffffffffffff";
var mockRsaPrivateKey = @"-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCRgWt83vGoI2vx+BIu1R39nLDvGLEvC8R4drrIvsiJkAvIlVZt
PlbeoifYJGDQwtlAR3a8i+B3/AP5tZEoWw+z+VWLX50aRjzHyTn22ih8OeGDoiBw
N3ysCTfQ/x8sDER6uSn8ElxfB9AEZTcRA+4rCRbmj+YLV/Nm+qSNoOIM4wIDAQAB
AoGAC8IZnY2mmZ/DKVqSnZY7RjNTWP710odw6QsvLOm96t/pE9x9j3ZqLrOL5LuL
11Lnm3oq7jGfghKrf5JcmJZDPnhWoGgZvtqFizt1l6y1GY/xlooWhOzEuK9kIrBS
PDhOjnvmLrQIB88Rjgq0LkxjNYsCa5d1zslkB2SfM7sOF4ECQQDkEzk/J0KnAa14
+T00BD5apQsDMU7Tz3aPA1IbmqsKY6wOuHcxrFBMmw3crce6jjq32w36samIPSwG
ucf/JngtAkEAo1IjyJLlVlFA74lGTJTbZ5drrotoYm/YeAnbe6Rhj6pXDfz+lVdQ
5ta/B0TKa1UEgx7pHs39Tmpl2IdfC5ozTwJBANVvL/lrsjI7na1CAQZ2miuVm9Kn
CA+rbFW1U9dFTJ7yW4eDFPhFOvgVeklzzx9EDqsTsedS70XxiQvaO9EInRkCQFKn
TELCzNvNTU6sq24wW4VmpXF1TgObVPMTEgfV3iYF7/69Td4ojWH1xkGYd9Sv9xOg
vhv/5bUctaRKhjhp9pMCQE8BLxzAMlS81dobP3GrCRLdlN/y9R7pu2hyURFFXUw5
j0hq3fgBZz1QLpLxY3TfkM3oFDVhpGvskzjINLk6hxc=
-----END RSA PRIVATE KEY-----";
var tok = Jwt.CreateToken(mockAppId, mockRsaPrivateKey);
Assert.IsFalse(string.IsNullOrEmpty(tok));
}
}
Expand Down
2 changes: 1 addition & 1 deletion Nexmo.Api.Test.Unit/Nexmo.Api.Test.Unit.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net452;net46;net461;net462;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>net452;net46;net461;net462;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;net47;net471;net472;net48</TargetFrameworks>
<AssemblyName>Nexmo.Api.Test.Unit</AssemblyName>
<PackageId>Nexmo.Api.Test.Unit</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
Expand Down
2 changes: 1 addition & 1 deletion Nexmo.Api.Test.Unit/NumberTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class NumberTest : MockedWebTest
[TestMethod]
public void should_search_numbers()
{
SetExpect($"{RestUrl}/number/search/?country=US&api_key={ApiKey}&api_secret={ApiSecret}&",
SetExpect($"{RestUrl}/number/search/?country=US&has_application=False&api_key={ApiKey}&api_secret={ApiSecret}&",
"{\"count\":177,\"numbers\":[{\"country\":\"US\",\"msisdn\":\"15102694548\",\"type\":\"mobile-lvn\",\"features\":[\"SMS\",\"VOICE\"],\"cost\":\"0.67\"},{\"country\":\"US\",\"msisdn\":\"17088568490\",\"type\":\"mobile-lvn\",\"features\":[\"SMS\",\"VOICE\"],\"cost\":\"0.67\"},{\"country\":\"US\",\"msisdn\":\"17088568491\",\"type\":\"mobile-lvn\",\"features\":[\"SMS\",\"VOICE\"],\"cost\":\"0.67\"},{\"country\":\"US\",\"msisdn\":\"17088568492\",\"type\":\"mobile-lvn\",\"features\":[\"SMS\",\"VOICE\"],\"cost\":\"0.67\"},{\"country\":\"US\",\"msisdn\":\"17088568973\",\"type\":\"mobile-lvn\",\"features\":[\"SMS\",\"VOICE\"],\"cost\":\"0.67\"}]}");

var results = Number.Search(new Number.SearchRequest
Expand Down
46 changes: 9 additions & 37 deletions Nexmo.Api/ApplicationV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ public class Webhook
public string HttpMethod { get; set; }
}

public class AppListFilter
{
public int page_size { get; set; }
public int page { get; set; }
}

public class AppResponse
{
/// <summary>
Expand Down Expand Up @@ -202,43 +208,9 @@ public static AppResponse Get(string appId, Credentials credentials = null)
/// <returns></returns>
public static List<AppResponse> List(int pageSize = 10, int page = 0, Credentials credentials = null)
{
// This is a dirty hack for the GET requests on Application V2 to work
// until the fix on the API level is implemented.
#if (!NETSTANDARD1_6)
{
string url = ApiRequest.GetBaseUriFor(typeof(ApplicationV2), "/v2/applications").ToString();
string result;
var authBytes = Encoding.UTF8.GetBytes(credentials.ApiKey + ":" + credentials.ApiSecret);
using (WebClient client = new WebClient())
{
client.Headers[HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(authBytes);
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.QueryString.Add("page_size", pageSize.ToString());
client.QueryString.Add("page", page.ToString());

result = client.DownloadString(url);
}

var response = JsonConvert.DeserializeObject<AppListResponse>(result);
return response._embedded.Applications;
}

#endif

return null;

// Proper solution

//var searchFilter = new Dictionary<string, string>
//{
// { "page_size", pageSize.ToString()},
// { "page", page.ToString()}
//};

//var json = VersionedApiRequest.DoRequest("GET", ApiRequest.GetBaseUriFor(typeof(ApplicationV2), "/v2/applications"), searchFilter, credentials);

//var response = JsonConvert.DeserializeObject<AppListResponse>(json.JsonResponse);
//return response._embedded.Applications;
var filter = new AppListFilter() { page = page, page_size = pageSize };
var response = VersionedApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(ApplicationV2), "/v2/applications"), filter, VersionedApiRequest.AuthType.Basic, credentials);
return JsonConvert.DeserializeObject<AppListResponse>(response)._embedded.Applications;
}

public static List<AppResponse> List()
Expand Down
Loading

0 comments on commit ea42f4a

Please # to comment.