DELETE an extension with postman rout. Now test cases for integration testing added

This commit is contained in:
MathewFrancis 2025-04-15 17:54:11 +05:30
parent b5340b118e
commit 5b21caa7fa
22 changed files with 309 additions and 6 deletions

View File

@ -13,7 +13,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"id\": \"1005\",\n \"transport\": \"transport-udp\",\n \"aors\": \"1005\",\n \"auth\": \"1005\",\n \"context\": \"default\",\n \"disallow\": \"all\",\n \"allow\": \"ulaw,alaw\",\n \"directMedia\": \"no\",\n \"connectedLineMethod\": null,\n \"callerid\": null,\n \"dtmfMode\": null,\n \"mohsuggest\": \"default\",\n \"mailboxes\": null\n}\n\n// {\n// \"id\": \"1004\",\n// \"transport\": \"transport-udp\",\n// \"aors\": \"1004\",\n// \"auth\": \"1004\",\n// \"context\": \"default\",\n// \"disallow\": \"all\",\n// \"allow\": \"ulaw,alaw\",\n// \"directMedia\": \"no\",\n// \"connectedLineMethod\": null,\n// \"callerid\": \"User <1004>\",\n// \"dtmfMode\": null,\n// \"mohsuggest\": \"default\",\n// \"mailboxes\": \"1004@default\"\n// }",
"raw": "{\n \"id\": \"1005\",\n// \"transport\": \"transport-udp\",\n// \"context\": \"default\",\n// \"disallow\": \"all\",\n// \"allow\": \"ulaw,alaw\",\n// \"directMedia\": \"no\",\n \"connectedLineMethod\": null,\n \"callerid\": null,\n \"dtmfMode\": null,\n// \"mohsuggest\": \"default\",\n \"mailboxes\": null\n}\n\n// {\n// \"id\": \"1004\",\n// \"transport\": \"transport-udp\",\n// \"aors\": \"1004\",\n// \"auth\": \"1004\",\n// \"context\": \"default\",\n// \"disallow\": \"all\",\n// \"allow\": \"ulaw,alaw\",\n// \"directMedia\": \"no\",\n// \"connectedLineMethod\": null,\n// \"callerid\": \"User <1004>\",\n// \"dtmfMode\": null,\n// \"mohsuggest\": \"default\",\n// \"mailboxes\": \"1004@default\"\n// }",
"options": {
"raw": {
"language": "json"
@ -94,7 +94,7 @@
"response": []
},
{
"name": "New Request",
"name": "SetAORS",
"request": {
"method": "POST",
"header": [],
@ -121,6 +121,32 @@
}
},
"response": []
},
{
"name": "DeleteExtension",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "http://localhost:8081/cezen/delete_extension?sipNumber=testEndPoint",
"protocol": "http",
"host": [
"localhost"
],
"port": "8081",
"path": [
"cezen",
"delete_extension"
],
"query": [
{
"key": "sipNumber",
"value": "testEndPoint"
}
]
}
},
"response": []
}
]
}

View File

@ -3,6 +3,8 @@ package com.example.cezenPBX.DAO;
import com.example.cezenPBX.DTO.ReturnStatus;
import com.example.cezenPBX.entity.*;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@ -40,6 +42,11 @@ public class BasicAsteriskOpsDAO implements CezenPbxOpsDAO {
@Transactional
public ReturnStatus saveAnExtension(ExtensionsTable extensionsTable) {
int priorityNumber = getTheHighestPriorityNumberByEndpoint(extensionsTable.getExtension());
// it's the first entry set priority to 1
if(priorityNumber == 0) extensionsTable.setPriority(1);
//save only if endpoint exists
return persistOnlyIfEndpointExists(extensionsTable);
}
@ -74,4 +81,35 @@ public class BasicAsteriskOpsDAO implements CezenPbxOpsDAO {
return new ReturnStatus(true, endpoint + " Persisted ", "");
}
// this gets the
@Override
public int getTheHighestPriorityNumberByEndpoint(String endpoint) {
// fetches the highest priority
String query = "SELECT MAX(e.priority) FROM ExtensionsTable AS e WHERE e.extension = :endpoint";
//get the highest priority
try{
TypedQuery<Integer> queryResult = this.entityManager.createQuery(query, Integer.class);
queryResult.setParameter("endpoint", endpoint);
return queryResult.getSingleResult();
}catch (Exception e){
// that means endpoint doesnt exist yet
return 0;
}
}
// delete extension by endoint
@Override
@Transactional
public boolean deleteAnExtensionPoint(String endpoint) {
Query query = this.entityManager.createQuery("DELETE FROM ExtensionsTable e WHERE e.extension = :extension");
query.setParameter("extension", endpoint);
return query.executeUpdate() == 1;
}
}

View File

@ -15,4 +15,8 @@ public interface CezenPbxOpsDAO {
ReturnStatus setThePasswordForSipEndpoint(PsAuths psAuths);
ReturnStatus setTheAorsForTheEndPoint(PsAors psAors);
int getTheHighestPriorityNumberByEndpoint(String endpoint);
boolean deleteAnExtensionPoint(String endpoint);
}

View File

@ -3,10 +3,7 @@ import com.example.cezenPBX.DTO.*;
import com.example.cezenPBX.service.BasicPbxServiceInterface;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/cezen")
@ -77,4 +74,10 @@ public class CezenPbxController {
psAorsDTO.maxContacts()
);
}
@DeleteMapping("/delete_extension")
public boolean deleteExtensionBySipNumber(@RequestParam String sipNumber){
return this.basicPbxServiceInterface.deleteByExtension(sipNumber);
}
}

View File

@ -37,3 +37,26 @@ public class PsAors implements PBXentiry{
this.maxContacts = maxContacts;
}
}
// bellow can also work
//@Table(name = "ps_aors")
//@Entity
//public record PsAors(
// @Id
// @Column(name = "id")
// String extension,
//
// @Column(name = "max_contacts")
// int maxContacts
//) implements PBXentiry{
//
// public PsAors() {
// this("",0);
//
// }
//
// @Override
// public String getExtension() {
// return this.extension;
// }
//}

View File

@ -38,6 +38,9 @@ public class PsAuths implements PBXentiry{
this.realm = realm;
}
public PsAuths() {
}
public String getExtension() {
return extension;
}

View File

@ -94,4 +94,10 @@ public class BasicPbxService implements BasicPbxServiceInterface {
return new ReturnStatus(false, "Endpoint and password already set ",e.getMessage());
}
}
@Override
public boolean deleteByExtension(String extensionNumber) {
return this.cezenPbxOpsDAO.deleteAnExtensionPoint(extensionNumber);
}
}

View File

@ -16,4 +16,6 @@ public interface BasicPbxServiceInterface {
public ReturnStatus addAPasswordForEndpoint(String id, String authType, String userName, String password, String md5Cred, String realm);
public ReturnStatus setAors(String id, int maxContacts);
public boolean deleteByExtension(String extensionNumber);
}

View File

@ -0,0 +1,198 @@
package com.example.cezenPBX.controller;
import com.example.cezenPBX.DTO.ReturnStatus;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.*;
import java.util.List;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class PbxControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
static HttpEntity<String> stringBasedRequest;
static HttpEntity<String> extensionEndpoint;
@BeforeAll
public static void createAnEndpoint() throws JSONException {
JSONObject endpointDetails = new JSONObject();
endpointDetails.put("id","testEndpoint");
// endpointDetails.put("transport","");
// endpointDetails.put("context","");
// endpointDetails.put("disallow","");
// endpointDetails.put("allow","");
// endpointDetails.put("directMedia","");
endpointDetails.put("connectedLineMethod",null);
endpointDetails.put("callerid",null);
endpointDetails.put("dtmfMode",null);
// endpointDetails.put("mohsuggest","");
endpointDetails.put("mailboxes",null);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
stringBasedRequest = new HttpEntity<>(endpointDetails.toString(), headers);
//Arrange
JSONObject extensionDetails = new JSONObject();
extensionDetails.put("context","default");
extensionDetails.put("extension","testEndpoint");
extensionDetails.put("priority","5");
extensionDetails.put("app","Dial");
extensionDetails.put("appdata","PJSIP/1005,20,m(default)");
extensionEndpoint = new HttpEntity<String>(extensionDetails.toString(), headers);
}
// test will create an testEndpoint endpoint
@Test
@DisplayName("User can be created")
@Order(1)
void testIfEndpointCanBeCreatedWithValidInput() {
// Act
ResponseEntity<String> response = this.restTemplate.postForEntity("/cezen/add_user", stringBasedRequest, String.class);
// Assert
Assertions.assertEquals(HttpStatus.OK, response.getStatusCode(), () -> "Wrong Status Code");
}
//duplicate entry must return false
@Test
@DisplayName("Duplicate values must result in false")
@Order(2)
void integrationTest_duplicateValurSubmission_ThrowsAnException() {
// Act
ResponseEntity<String> response = this.restTemplate.postForEntity("/cezen/add_user", stringBasedRequest, String.class);
String responseBody = response.getBody();
// Assert
Assertions.assertEquals(HttpStatus.OK, response.getStatusCode(), () -> "Wrong Status Code");
Assertions.assertEquals("false", responseBody, () -> "must return false when value already exists");
}
// test for extension
// if SIP end point doesn't exist then return a json ReturnStatus object with false in it
@Test
@DisplayName("For no SIP endpoint Should return ReturnStatus object with false in it")
public void extensionTest_tryingToAddAnExtensionIfSipEndpointDoesntExist_returnAReturnStatusObjectWithFalseInIt() throws JSONException, JsonProcessingException {
//Arrange
JSONObject extensionDetails = new JSONObject();
extensionDetails.put("context","default");
extensionDetails.put("extension","NoEndPointEver");
extensionDetails.put("priority","5");
extensionDetails.put("app","Dial");
extensionDetails.put("appdata","PJSIP/1005,20,m(default)");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
HttpEntity<String> extensionEndpoint = new HttpEntity<String>(extensionDetails.toString(), headers);
//Act
ResponseEntity<String> response = this.restTemplate.postForEntity("/cezen/add_extension", extensionEndpoint, String.class);
System.out.println(response.getBody());
ObjectMapper mapper = new ObjectMapper();
ReturnStatus status = mapper.readValue(response.getBody(), ReturnStatus.class);
//Assert
Assertions.assertFalse(status.status(), () -> "Wrong Status flag expected false in return ");
Assertions.assertEquals("Create Endpoint for NoEndPointEver", status.message(), () -> "Wrong message for given input");
}
@Test
@DisplayName("For no SIP endpoint Should return ReturnStatus object with false in it")
@Order(3)
public void extensionTest_addingANewExtension_StatusMessageMustReturnTrueInIt() throws JSONException, JsonProcessingException {
//Act
ResponseEntity<String> responseFromExtension = this.restTemplate.postForEntity("/cezen/add_extension", extensionEndpoint, String.class);
System.out.println(responseFromExtension.getBody());
ObjectMapper mapper = new ObjectMapper();
ReturnStatus statusFromExtension = mapper.readValue(responseFromExtension.getBody(), ReturnStatus.class);
//Assert
Assertions.assertTrue(statusFromExtension.status(), () -> "Wrong Status flag expected True in returnStatus first extension entry");
Assertions.assertEquals("testEndpoint Persisted ", statusFromExtension.message(), () -> "Wrong message for given input");
}
@Test
@DisplayName("Duplicate entry of extension")
@Order(4)
public void extensionTest_addingANewExtension_StatusMessageMustReturnFalseInIt() throws JSONException, JsonProcessingException {
//Act
ResponseEntity<String> responseFromExtension = this.restTemplate.postForEntity("/cezen/add_extension", extensionEndpoint, String.class);
System.out.println(responseFromExtension.getBody());
ObjectMapper mapper = new ObjectMapper();
ReturnStatus statusFromExtension = mapper.readValue(responseFromExtension.getBody(), ReturnStatus.class);
//Assert
Assertions.assertFalse(statusFromExtension.status(), () -> "Wrong Status flag expected false in returnStatus for duplicate entry ");
Assertions.assertEquals("Data likely already exists or DB issue", statusFromExtension.message(), () -> "Wrong message for given input expected Data likely already exists or DB issue");
}
// delete the created testEndpoint value
@Test
@DisplayName("Delete an Extension with endpoint testEndpoint must return true")
@Order(5)
public void extensionTest_deletingAnExtension_ifExistsWillReturnTrue(){
// Arrange
String url = "/cezen/delete_extension?sipNumber=testEndPoint";
//Act
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Void> requestEntity = new HttpEntity<>(headers);
ResponseEntity<Boolean> response = restTemplate.exchange(
url,
HttpMethod.DELETE,
requestEntity,
Boolean.class
);
// if the extension exists
Assertions.assertTrue(response.getBody());
response = restTemplate.exchange(
url,
HttpMethod.DELETE,
requestEntity,
Boolean.class
);
// when deleted it won't exist so the endpoint must return false
Assertions.assertFalse(response.getBody());
}
}