-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Build workflow with tests, sonar workflow, snyk workflow, added new C…
…ONTRIBUTING. (#40) * Added build, snyk & sonarcloud workflow. * Added tests. * Added new CONTRIBUTING.md.
- Loading branch information
1 parent
c76e11b
commit 32dba78
Showing
13 changed files
with
4,782 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
name: .NET build | ||
|
||
on: [push] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
dotnet-version: [6.x, 7.x, 8.x] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Setup .NET | ||
uses: actions/setup-dotnet@v4 | ||
with: | ||
dotnet-version: ${{ matrix.dotnet-version }} | ||
- name: Restore dependencies | ||
run: dotnet restore | ||
- name: Build | ||
run: dotnet build --no-restore | ||
- name: Test | ||
run: dotnet test --no-build --verbosity normal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Snyk vulenrability scan | ||
|
||
on: [push] | ||
jobs: | ||
security: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@master | ||
- name: Setup .NET | ||
uses: actions/setup-dotnet@v3 | ||
with: | ||
dotnet-version: '6.x' | ||
- name: Restore dependencies | ||
run: dotnet restore | ||
- name: Run Snyk to check for vulnerabilities | ||
uses: snyk/actions/dotnet@master | ||
continue-on-error: true # To make sure that SARIF upload gets called | ||
env: | ||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} | ||
with: | ||
args: | ||
--all-projects | ||
--sarif-file-output=snyk.sarif | ||
--severity-threshold=high | ||
- name: Upload result to GitHub Code Scanning | ||
uses: github/codeql-action/upload-sarif@v3 | ||
with: | ||
sarif_file: snyk.sarif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: SonarCloud analysis | ||
|
||
on: [push] | ||
|
||
jobs: | ||
sonarcloud: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
- name: Setup .NET | ||
uses: actions/setup-dotnet@v4 | ||
with: | ||
dotnet-version: '6.x' | ||
- name: Restore dependencies | ||
run: dotnet restore | ||
- name: Build | ||
run: dotnet build --no-restore | ||
- name: Install SonarScanner for .NET | ||
run: dotnet tool install --global dotnet-sonarscanner | ||
- name: Run SonarCloud Scan | ||
env: | ||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | ||
run: | | ||
dotnet-sonarscanner begin /k:"infobip_infobip-api-csharp-client" /o:"infobip" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" | ||
dotnet build | ||
dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
using System.Net; | ||
using Infobip.Api.Client; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using WireMock.Matchers; | ||
using WireMock.RequestBuilders; | ||
using WireMock.ResponseBuilders; | ||
using WireMock.Server; | ||
using WireMock.Types; | ||
|
||
namespace ApiClient.Tests.Api; | ||
|
||
public class ApiTest | ||
{ | ||
protected const string API_KEY_PREFIX = "App"; | ||
protected const string API_KEY = "003026bbc133714df1834b8638bb496e-8f4b3d9a-e931-478d-a994-28a725159ab9"; | ||
protected const string API_KEY_HEADER_VALUE = API_KEY_PREFIX + " " + API_KEY; | ||
protected const string CONTENT_TYPE_HEADER_VALUE = "application/json; charset=utf-8"; | ||
protected const string USER_AGENT_HEADER_VALUE = "infobip-api-client-csharp/" + Configuration.Version; | ||
protected const string ACCEPT_HEADER_VALUE = "application/json"; | ||
protected const string SERVER_HEADER_VALUE = "SMS API"; | ||
protected const string SERVER_HEADER_VALUE_COMMA = "SMS,API"; | ||
protected const string X_REQUEST_ID_HEADER_VALUE = "1608758729810312842"; | ||
|
||
protected Configuration? configuration; | ||
|
||
protected WireMockServer? wireMockServer; | ||
|
||
[TestInitialize] | ||
public void StartMockServer() | ||
{ | ||
wireMockServer = WireMockServer.Start(); | ||
|
||
configuration = new Configuration | ||
{ | ||
ApiKey = API_KEY, | ||
BasePath = "http://localhost:" + wireMockServer.Ports[0] | ||
}; | ||
} | ||
|
||
[TestCleanup] | ||
public void TearDown() | ||
{ | ||
wireMockServer!.Stop(); | ||
} | ||
|
||
protected void SetUpGetRequest(string url, string expectedResponse, int statusCode) | ||
{ | ||
SetUpGetRequest(url, new Dictionary<string, string>(), expectedResponse, statusCode); | ||
} | ||
|
||
protected void SetUpPostRequest(string url, string givenRequest, string expectedResponse, int statusCode) | ||
{ | ||
SetUpPostRequest(url, new Dictionary<string, string>(), givenRequest, expectedResponse, statusCode); | ||
} | ||
|
||
protected void SetUpPutRequest(string url, string givenRequest, string expectedResponse, int statusCode) | ||
{ | ||
SetUpPutRequest(url, new Dictionary<string, string>(), givenRequest, expectedResponse, statusCode); | ||
} | ||
|
||
protected void SetUpDeleteRequest(string url, int statusCode) | ||
{ | ||
SetUpDeleteRequest(url, new Dictionary<string, string>(), statusCode); | ||
} | ||
|
||
protected void SetUpGetRequest(string url, Dictionary<string, string> givenParameters, string expectedResponse, | ||
int statusCode) | ||
{ | ||
wireMockServer!.Given(Request.Create().UsingGet().WithPath(url) | ||
.WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) | ||
.WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) | ||
.WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) | ||
.WithParam(EqualToParams(givenParameters)) | ||
) | ||
.RespondWith(Response.Create() | ||
.WithStatusCode(statusCode) | ||
.WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) | ||
.WithHeader("Server", SERVER_HEADER_VALUE) | ||
.WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) | ||
.WithBody(expectedResponse) | ||
); | ||
} | ||
|
||
protected void SetUpPostRequest(string url, Dictionary<string, string> givenParameters, string givenRequest, | ||
string expectedResponse, int statusCode) | ||
{ | ||
wireMockServer!.Given(Request.Create().UsingPost().WithPath(url) | ||
.WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) | ||
.WithHeader("Content-Type", new ExactMatcher(CONTENT_TYPE_HEADER_VALUE)) | ||
.WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) | ||
.WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) | ||
.WithParam(EqualToParams(givenParameters)) | ||
.WithBody(new JsonMatcher(givenRequest, true)) | ||
) | ||
.RespondWith(Response.Create() | ||
.WithStatusCode(statusCode) | ||
.WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) | ||
.WithHeader("Server", SERVER_HEADER_VALUE) | ||
.WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) | ||
.WithBody(expectedResponse) | ||
); | ||
} | ||
|
||
protected void SetUpPostRequestBinary(string url, Dictionary<string, string> givenParameters, byte[] givenRequest, | ||
string expectedResponse, int statusCode) | ||
{ | ||
wireMockServer!.Given(Request.Create().UsingPost().WithPath(url) | ||
.WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) | ||
.WithHeader("Content-Type", new ExactMatcher("application/octet-stream")) | ||
.WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) | ||
.WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) | ||
.WithParam(EqualToParams(givenParameters)) | ||
.WithBody(givenRequest) | ||
) | ||
.RespondWith(Response.Create() | ||
.WithStatusCode(statusCode) | ||
.WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) | ||
.WithHeader("Server", SERVER_HEADER_VALUE) | ||
.WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) | ||
.WithBody(expectedResponse) | ||
); | ||
} | ||
|
||
protected void SetUpNoRequestBodyNoResponseBodyPostRequest(string url, int statusCode) | ||
{ | ||
wireMockServer!.Given(Request.Create().UsingPost().WithPath(url) | ||
.WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) | ||
.WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) | ||
.WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) | ||
) | ||
.RespondWith(Response.Create() | ||
.WithStatusCode(statusCode) | ||
.WithHeader("Server", SERVER_HEADER_VALUE) | ||
.WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) | ||
); | ||
} | ||
|
||
protected void SetUpPutRequest(string url, Dictionary<string, string> givenParameters, string givenRequest, | ||
string expectedResponse, int statusCode) | ||
{ | ||
wireMockServer!.Given(Request.Create().UsingPut().WithPath(url) | ||
.WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) | ||
.WithHeader("Content-Type", new ExactMatcher(CONTENT_TYPE_HEADER_VALUE)) | ||
.WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) | ||
.WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) | ||
.WithParam(EqualToParams(givenParameters)) | ||
.WithBody(new JsonMatcher(givenRequest, true)) | ||
) | ||
.RespondWith(Response.Create() | ||
.WithStatusCode(statusCode) | ||
.WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) | ||
.WithHeader("Server", SERVER_HEADER_VALUE) | ||
.WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) | ||
.WithBody(expectedResponse) | ||
); | ||
} | ||
|
||
protected void SetUpDeleteRequest(string url, Dictionary<string, string> givenParameters, int statusCode) | ||
{ | ||
wireMockServer!.Given(Request.Create().UsingDelete().WithPath(url) | ||
.WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) | ||
.WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) | ||
.WithParam(EqualToParams(givenParameters)) | ||
) | ||
.RespondWith(Response.Create() | ||
.WithStatusCode(statusCode) | ||
.WithHeader("Server", SERVER_HEADER_VALUE) | ||
.WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) | ||
); | ||
} | ||
|
||
protected void SetUpDeleteRequestWithResponseBody(string url, Dictionary<string, string> givenParameters, | ||
string expectedResponse, int statusCode) | ||
{ | ||
wireMockServer!.Given(Request.Create().UsingDelete().WithPath(url) | ||
.WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) | ||
.WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) | ||
.WithParam(EqualToParams(givenParameters)) | ||
) | ||
.RespondWith(Response.Create() | ||
.WithStatusCode(statusCode) | ||
.WithHeader("Server", SERVER_HEADER_VALUE) | ||
.WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) | ||
.WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) | ||
.WithBody(expectedResponse) | ||
); | ||
} | ||
|
||
protected void SetUpMultipartFormRequest(string url, Multimap<string, string> givenParts, string expectedResponse, | ||
int statusCode = 200) | ||
{ | ||
var req = Request.Create().UsingPost().WithPath(url) | ||
.WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) | ||
.WithHeader("Content-Type", new WildcardMatcher("multipart/form-data; boundary=\"---------*", true)) | ||
.WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) | ||
.WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)); | ||
|
||
req.WithBody(body => | ||
{ | ||
var allKeysFound = givenParts.All(kvp => | ||
body.Contains($"name={kvp.Key}", StringComparison.InvariantCultureIgnoreCase)); | ||
var allValuesFound = givenParts.All(kvp => | ||
kvp.Value.All(value => body.Contains(value, StringComparison.InvariantCultureIgnoreCase))); | ||
return allValuesFound && allKeysFound; | ||
}); | ||
|
||
var resp = Response.Create() | ||
.WithStatusCode(statusCode) | ||
.WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) | ||
.WithHeader("Server", SERVER_HEADER_VALUE) | ||
.WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) | ||
.WithBody(expectedResponse); | ||
|
||
wireMockServer!.Given(req).RespondWith(resp); | ||
} | ||
|
||
private Func<IDictionary<string, WireMockList<string>>, bool>[] EqualToParams(Dictionary<string, string> parameters) | ||
{ | ||
var funcs = new List<Func<IDictionary<string, WireMockList<string>>, bool>>(); | ||
foreach (var param in parameters) | ||
funcs.Add(delegate(IDictionary<string, WireMockList<string>> inputParams) | ||
{ | ||
return inputParams[param.Key][0] == param.Value; | ||
}); | ||
if (funcs.Count == 0) funcs.Add(x => true); | ||
return funcs.ToArray(); | ||
} | ||
|
||
public static void AssertResponse<T>(T apiResponse, Action<T> assertion) | ||
{ | ||
assertion.Invoke(apiResponse); | ||
} | ||
|
||
public static void AssertResponseWithHttpInfo<T>(ApiResponse<T> apiResponse, Action<T> assertion) | ||
{ | ||
Assert.AreEqual(HttpStatusCode.OK, apiResponse.StatusCode); | ||
|
||
Assert.AreEqual(SERVER_HEADER_VALUE_COMMA, apiResponse.Headers["Server"][0]); | ||
Assert.AreEqual(X_REQUEST_ID_HEADER_VALUE, apiResponse.Headers["X-Request-ID"][0]); | ||
Assert.AreEqual(CONTENT_TYPE_HEADER_VALUE, apiResponse.Headers["Content-Type"][0]); | ||
|
||
assertion.Invoke(apiResponse.Data); | ||
} | ||
|
||
public static void AssertNoBodyResponseWithHttpInfo<T>(ApiResponse<T> apiResponse, | ||
HttpStatusCode expectedHttpStatusCode) | ||
{ | ||
Assert.AreEqual(expectedHttpStatusCode, apiResponse.StatusCode); | ||
|
||
Assert.AreEqual(SERVER_HEADER_VALUE_COMMA, apiResponse.Headers["Server"][0]); | ||
Assert.AreEqual(X_REQUEST_ID_HEADER_VALUE, apiResponse.Headers["X-Request-ID"][0]); | ||
} | ||
} |
Oops, something went wrong.