Skip to content

Shuhan Jin #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CompanyApi/Company.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ public Company(string name)
{
Id = Guid.NewGuid().ToString();
Name = name;
Employees = new List<Employee>();
}

public string Id { get; set; }

public string Name { get; set; }

public List<Employee> Employees { get; set; } = new List<Employee>();
}
}
78 changes: 77 additions & 1 deletion CompanyApi/Controllers/CompanyController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using System.Linq;

namespace CompanyApi.Controllers
{
Expand All @@ -22,8 +23,83 @@ public ActionResult<Company> Create(CreateCompanyRequest request)

[HttpDelete]
public void ClearData()
{
{
companies.Clear();
}

[HttpGet]
public ActionResult<List<Company>> GetAll([FromQuery] int? pageSize, int? pageIndex)
{
if (pageSize != null && pageIndex != null)
{
var startIndex = (pageIndex - 1) * pageSize;
var companiesPage = companies.Skip((int)startIndex).Take((int)pageSize).ToList();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well: nice to use Skip and Take

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WangKe:
Great using of the Linq syntax 👍

return Ok(companiesPage);
}

return companies;
}

[HttpGet("{id}")]
public ActionResult<Company> Get(string id)
{
var company = companies.Find(cp => cp.Id == id);

if (company != null)
{
return company;
}

return NotFound();
}

[HttpPut("{id}")]
public ActionResult<Company> Update(string id, [FromBody] Company updatedCompany)
{
var existingCompany = companies.Find(c => c.Id == id);
if (existingCompany == null)
{
return NotFound();
}

existingCompany.Name = updatedCompany.Name;

return NoContent();
}

[HttpPost("{companyId}/employees")]
public ActionResult<Company> AddEmployee(string companyId, [FromBody] Employee employee)
{
var company = companies.Find(c => c.Id == companyId);
if (company == null)
{
return NotFound();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well: use 404 if company can not be found👍

}

//employee.Id = Guid.NewGuid().ToString();
company.Employees.Add(employee);

return Ok(employee);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we add new employee here, maybe [return Created(employee)] could be better

}

[HttpDelete("{companyId}/employees/{employeeId}")]
public ActionResult<Company> DeleteEmployee(string companyId, string employeeId)
{
var company = companies.Find(c => c.Id == companyId);
if (company == null)
{
return NotFound();
}

var employee = company.Employees.Find(e => e.Id == employeeId);
if (employee == null)
{
return NotFound();
}

company.Employees.Remove(employee);

return NoContent(); //bc delete doesnt return anything
}
}
}
7 changes: 6 additions & 1 deletion CompanyApi/CreateCompanyRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
{
public class CreateCompanyRequest
{
public required string Name { get; set; }
public CreateCompanyRequest(string name)
{
Name = name;
}

public string Name { get; set; }
}
}
16 changes: 16 additions & 0 deletions CompanyApi/Employee.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Xml.Linq;

namespace CompanyApi
{
public class Employee
{
public Employee(string name)
{
Id = Guid.NewGuid().ToString();
Name = name;
}

public string Id { get; set; }
public string Name { get; set; }
}
}
39 changes: 38 additions & 1 deletion CompanyApi/apis.http
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,41 @@ Content-Type: application/json; charset=utf-8
### Case1: Sucess, 204 NO Content
### Case2: 404 Company NOT Found

######################################################################################
######################################################################################

## AC6 add employee to a specific company
PUT https://{{hostname}}:{{port}}/api/Companies/{companyID}/employee
Content-Type: application/json; charset=utf-8

Company:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: not need this json for company, we find related company by companyID in the URL

{
"name": Google
}

employee:
{
"name": Eleanor
}
### Response:
### Case1: Sucess, 200 ok, with the employee name
### Case2: 404 Company NOT Found

######################################################################################

## AC7 delete a specific employee from a specific company
PUT https://{{hostname}}:{{port}}/api/Companies/{companyID}/employee/{employeeID}
Content-Type: application/json; charset=utf-8

Company:
{
"name": Google
}

employee:
{
"name": Eleanor
}
### Response:
### Case1: success, 204 no content
### Case2: 404 Company NOT Found
### Case3: 404 emloyee NOT Found

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be improved: we also need to design api for AC 8-10

148 changes: 148 additions & 0 deletions CompanyApiTest/CompanyApiTest.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
using CompanyApi;
using CompanyApi.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Testing;
using Newtonsoft.Json;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;

namespace CompanyApiTest
Expand Down Expand Up @@ -84,5 +88,149 @@ private async Task ClearDataAsync()
{
await httpClient.DeleteAsync("/api/companies");
}

[Fact]
public async Task Should_return_all_companies_with_status_200_when_GetAll_given_without_company_name()
{
// Given
await ClearDataAsync();
var companyGiven = new CreateCompanyRequest("BlueSky Digital Media");
await httpClient.PostAsJsonAsync("api/companies", companyGiven);

// When
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync("api/companies");

// Then
Assert.Equal(HttpStatusCode.OK, httpResponseMessage.StatusCode); //ok = 200
//Assert.Equal(companyGiven,await httpResponseMessage.Content.ReadFromJsonAsync<ListCompany>>());

}

[Fact]
public async Task Should_return_company_name_with_status_200_when_Get_given_company_name_and_company_exist()
{
await ClearDataAsync();
var companyGiven = new CreateCompanyRequest("BlueSky Digital Media");
var createResponse = await httpClient.PostAsync(
"/api/companies",
SerializeObjectToContent(companyGiven));
var company = await createResponse.Content.ReadFromJsonAsync<Company>();
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync("api/companies" + $"/{company?.Id}");
var companyGet = await httpResponseMessage.Content.ReadFromJsonAsync<Company>();

// Then
Assert.Equal(company?.Id, companyGet?.Id);
Assert.Equal(HttpStatusCode.OK, httpResponseMessage.StatusCode);
}

[Fact]
public async Task Should_return_status_404_when_Get_given_company_name_and_company_do_not_exist()
{
await ClearDataAsync();

HttpResponseMessage httpResponseMessage = await httpClient.GetAsync("api/companies/blueSky Digital Media");

Assert.Equal(HttpStatusCode.NotFound, httpResponseMessage.StatusCode); //NotFound = 404
}

[Fact]
public async Task Should_Returns_Correct_PageSize_and_PageIndex_when_GetCompanies_Given_PageSize_and_PageIndex()
{
var companyGiven1 = new CreateCompanyRequest("BlueSky Digital Media");
var companyGiven2 = new CreateCompanyRequest("Hyperoptics");
await httpClient.PostAsJsonAsync("api/companies", companyGiven1);
await httpClient.PostAsJsonAsync("api/companies", companyGiven2);

var httpResponseMessage = await httpClient.GetAsync("/api/companies?pageIndex=1&pageSize=2");
List<Company>? companies = await httpResponseMessage.Content.ReadFromJsonAsync<List<Company>>();

Assert.Equal(HttpStatusCode.OK, httpResponseMessage.StatusCode);
Assert.Equal("BlueSky Digital Media", companies[0].Name);
Assert.Equal("Hyperoptics", companies[1].Name);
}

[Fact]
public async Task Should_return_status_204_When_Update_Given_updated_company_name()
{
await ClearDataAsync();
var companyGiven = new CreateCompanyRequest("BlueSky Digital Media");
var createResponse = await httpClient.PostAsync(
"/api/companies",
SerializeObjectToContent(companyGiven));
var company = await createResponse.Content.ReadFromJsonAsync<Company>();
var updatedCompany = new Company("Hyperoptics");

HttpResponseMessage httpResponseMessage = await httpClient.PutAsJsonAsync("api/companies" + $"/{company?.Id}", updatedCompany);

Assert.Equal(HttpStatusCode.NoContent, httpResponseMessage.StatusCode);
}

[Fact]
public async Task Should_return_status_404_When_Update_Given_unmatched_company_id()
{
var updatedCompany = new Company("Hyperoptics");

HttpResponseMessage httpResponseMessage = await httpClient.PutAsJsonAsync("api/companies/1", updatedCompany);

Assert.Equal(HttpStatusCode.NotFound, httpResponseMessage.StatusCode);
}

[Fact]
public async Task Should_Add_Employee_to_specific_company_When_AddEmployee_Given_()
{
await ClearDataAsync();
var companyGiven = new CreateCompanyRequest("BlueSky Digital Media");
var createResponse = await httpClient.PostAsync(
"/api/companies",
SerializeObjectToContent(companyGiven));
var company = await createResponse.Content.ReadFromJsonAsync<Company>();
var newEmployee = new Employee("Erika");

var httpResponseMessage = await httpClient.PostAsJsonAsync($"api/companies/{company.Id}/employees", newEmployee);

Employee? addedEmployee = await httpResponseMessage.Content.ReadFromJsonAsync<Employee>();

Assert.Equal("Erika", addedEmployee.Name);
Assert.Equal(HttpStatusCode.OK, httpResponseMessage.StatusCode);
}

[Fact]
public async Task Should_delete_specific_employee_when_DeleteEmployee_Given_employeeId_and_companyId()
{
await ClearDataAsync();
// create a company
var companyGiven = new CreateCompanyRequest("BlueSky Digital Media");
var createResponse = await httpClient.PostAsync(
"/api/companies",
SerializeObjectToContent(companyGiven));
var company = await createResponse.Content.ReadFromJsonAsync<Company>();

//create a employee of this company
var newEmployee = new Employee("Erika");
company.Employees.Add(newEmployee);
var httpResponseMessage = await httpClient.PostAsJsonAsync($"api/companies/{company.Id}/employees", newEmployee);
Employee? employee = await httpResponseMessage.Content.ReadFromJsonAsync<Employee>();

//delete employee
var response = await httpClient.DeleteAsync($"api/companies/{company.Id}/employees/{employee.Id}");

Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
}

[Fact]
public async Task Should_return_status_404_when_DeleteEmployee_Given_employeeId_not_valid()
{
await ClearDataAsync();
var companyGiven = new CreateCompanyRequest("BlueSky Digital Media");
var createResponse = await httpClient.PostAsync(
"/api/companies",
SerializeObjectToContent(companyGiven));
var company = await createResponse.Content.ReadFromJsonAsync<Company>();

var response = await httpClient.DeleteAsync($"api/companies/{company.Id}/employees/1");

Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

}
}