mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-05-04 08:02:47 +00:00
UTOP-bot: improved tests in OwnerControllerTests.java
This commit is contained in:
parent
e30d8e83ba
commit
b380c41bc5
1 changed files with 243 additions and 244 deletions
|
@ -14,248 +14,247 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.samples.petclinic.owner;
|
package org.springframework.samples.petclinic.owner;
|
||||||
|
|
||||||
import org.assertj.core.util.Lists;
|
import org.assertj.core.util.Lists;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.condition.DisabledInNativeImage;
|
import org.junit.jupiter.api.condition.DisabledInNativeImage;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.test.context.aot.DisabledInAotMode;
|
import org.springframework.test.context.aot.DisabledInAotMode;
|
||||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.empty;
|
import static org.hamcrest.Matchers.empty;
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
import static org.hamcrest.Matchers.hasItem;
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
import static org.hamcrest.Matchers.hasProperty;
|
import static org.hamcrest.Matchers.hasProperty;
|
||||||
import static org.hamcrest.Matchers.hasSize;
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for {@link OwnerController}
|
* Test class for {@link OwnerController}
|
||||||
*
|
*
|
||||||
* Authors: Colin But, Wick Dynex
|
* Authors: Colin But, Wick Dynex
|
||||||
*/
|
*/
|
||||||
@WebMvcTest(OwnerController.class)
|
@WebMvcTest(OwnerController.class)
|
||||||
@DisabledInNativeImage
|
@DisabledInNativeImage
|
||||||
@DisabledInAotMode
|
@DisabledInAotMode
|
||||||
class OwnerControllerTests {
|
class OwnerControllerTests {
|
||||||
|
|
||||||
private static final int TEST_OWNER_ID = 1;
|
private static final int TEST_OWNER_ID = 1;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MockMvc mockMvc;
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
@MockitoBean
|
@MockitoBean
|
||||||
private OwnerRepository owners;
|
private OwnerRepository owners;
|
||||||
|
|
||||||
private Owner george() {
|
private Owner george() {
|
||||||
Owner george = new Owner();
|
Owner george = new Owner();
|
||||||
george.setId(TEST_OWNER_ID);
|
george.setId(TEST_OWNER_ID);
|
||||||
george.setFirstName("George");
|
george.setFirstName("George");
|
||||||
george.setLastName("Franklin");
|
george.setLastName("Franklin");
|
||||||
george.setAddress("110 W. Liberty St.");
|
george.setAddress("110 W. Liberty St.");
|
||||||
george.setCity("Madison");
|
george.setCity("Madison");
|
||||||
george.setTelephone("6085551023");
|
george.setTelephone("6085551023");
|
||||||
Pet max = new Pet();
|
Pet max = new Pet();
|
||||||
PetType dog = new PetType();
|
PetType dog = new PetType();
|
||||||
dog.setName("dog");
|
dog.setName("dog");
|
||||||
max.setType(dog);
|
max.setType(dog);
|
||||||
max.setName("Max");
|
max.setName("Max");
|
||||||
max.setBirthDate(LocalDate.now());
|
max.setBirthDate(LocalDate.now());
|
||||||
george.addPet(max);
|
george.addPet(max);
|
||||||
max.setId(1);
|
max.setId(1);
|
||||||
return george;
|
return george;
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
Owner george = george();
|
Owner george = george();
|
||||||
given(this.owners.findByLastNameStartingWith(eq("Franklin"), any(Pageable.class)))
|
given(this.owners.findByLastNameStartingWith(eq("Franklin"), any(Pageable.class)))
|
||||||
.willReturn(new PageImpl<>(Lists.newArrayList(george)));
|
.willReturn(new PageImpl<>(Lists.newArrayList(george)));
|
||||||
|
|
||||||
given(this.owners.findAll(any(Pageable.class))).willReturn(new PageImpl<>(Lists.newArrayList(george)));
|
given(this.owners.findAll(any(Pageable.class))).willReturn(new PageImpl<>(Lists.newArrayList(george)));
|
||||||
|
|
||||||
given(this.owners.findById(TEST_OWNER_ID)).willReturn(Optional.of(george));
|
given(this.owners.findById(TEST_OWNER_ID)).willReturn(Optional.of(george));
|
||||||
Visit visit = new Visit();
|
Visit visit = new Visit();
|
||||||
visit.setDate(LocalDate.now());
|
visit.setDate(LocalDate.now());
|
||||||
george.getPet("Max").getVisits().add(visit);
|
george.getPet("Max").getVisits().add(visit);
|
||||||
|
|
||||||
// Added assertion to cover the branch where the pet is not found
|
// Added assertion to cover the branch where the pet is not found
|
||||||
assertNull(george.getPet("NonExistent"), "Expected getPet to return null when pet is not found");
|
assertNull(george.getPet("NonExistent"), "Expected getPet to return null when pet is not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testInitCreationForm() throws Exception {
|
void testInitCreationForm() throws Exception {
|
||||||
mockMvc.perform(get("/owners/new"))
|
mockMvc.perform(get("/owners/new"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(model().attributeExists("owner"))
|
.andExpect(model().attributeExists("owner"))
|
||||||
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
|
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testProcessCreationFormSuccess() throws Exception {
|
void testProcessCreationFormSuccess() throws Exception {
|
||||||
mockMvc
|
mockMvc
|
||||||
.perform(post("/owners/new").param("firstName", "Joe")
|
.perform(post("/owners/new").param("firstName", "Joe")
|
||||||
.param("lastName", "Bloggs")
|
.param("lastName", "Bloggs")
|
||||||
.param("address", "123 Caramel Street")
|
.param("address", "123 Caramel Street")
|
||||||
.param("city", "London")
|
.param("city", "London")
|
||||||
.param("telephone", "1316761638"))
|
.param("telephone", "1316761638"))
|
||||||
.andExpect(status().is3xxRedirection());
|
.andExpect(status().is3xxRedirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testProcessCreationFormHasErrors() throws Exception {
|
void testProcessCreationFormHasErrors() throws Exception {
|
||||||
mockMvc
|
mockMvc
|
||||||
.perform(post("/owners/new").param("firstName", "Joe").param("lastName", "Bloggs").param("city", "London"))
|
.perform(post("/owners/new").param("firstName", "Joe").param("lastName", "Bloggs").param("city", "London"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(model().attributeHasErrors("owner"))
|
.andExpect(model().attributeHasErrors("owner"))
|
||||||
.andExpect(model().attributeHasFieldErrors("owner", "address"))
|
.andExpect(model().attributeHasFieldErrors("owner", "address"))
|
||||||
.andExpect(model().attributeHasFieldErrors("owner", "telephone"))
|
.andExpect(model().attributeHasFieldErrors("owner", "telephone"))
|
||||||
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
|
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testInitFindForm() throws Exception {
|
void testInitFindForm() throws Exception {
|
||||||
mockMvc.perform(get("/owners/find"))
|
mockMvc.perform(get("/owners/find"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(model().attributeExists("owner"))
|
.andExpect(model().attributeExists("owner"))
|
||||||
.andExpect(view().name("owners/findOwners"));
|
.andExpect(view().name("owners/findOwners"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testProcessFindFormSuccess() throws Exception {
|
void testProcessFindFormSuccess() throws Exception {
|
||||||
Page<Owner> tasks = new PageImpl<>(Lists.newArrayList(george(), new Owner()));
|
Page<Owner> tasks = new PageImpl<>(Lists.newArrayList(george(), new Owner()));
|
||||||
when(this.owners.findByLastNameStartingWith(anyString(), any(Pageable.class))).thenReturn(tasks);
|
when(this.owners.findByLastNameStartingWith(anyString(), any(Pageable.class))).thenReturn(tasks);
|
||||||
mockMvc.perform(get("/owners?page=1")).andExpect(status().isOk()).andExpect(view().name("owners/ownersList"));
|
mockMvc.perform(get("/owners?page=1")).andExpect(status().isOk()).andExpect(view().name("owners/ownersList"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testProcessFindFormByLastName() throws Exception {
|
void testProcessFindFormByLastName() throws Exception {
|
||||||
Page<Owner> tasks = new PageImpl<>(Lists.newArrayList(george()));
|
Page<Owner> tasks = new PageImpl<>(Lists.newArrayList(george()));
|
||||||
when(this.owners.findByLastNameStartingWith(eq("Franklin"), any(Pageable.class))).thenReturn(tasks);
|
when(this.owners.findByLastNameStartingWith(eq("Franklin"), any(Pageable.class))).thenReturn(tasks);
|
||||||
mockMvc.perform(get("/owners?page=1").param("lastName", "Franklin"))
|
mockMvc.perform(get("/owners?page=1").param("lastName", "Franklin"))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andExpect(view().name("redirect:/owners/" + TEST_OWNER_ID));
|
.andExpect(view().name("redirect:/owners/" + TEST_OWNER_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testProcessFindFormNoOwnersFound() throws Exception {
|
void testProcessFindFormNoOwnersFound() throws Exception {
|
||||||
Page<Owner> tasks = new PageImpl<>(Lists.newArrayList());
|
Page<Owner> tasks = new PageImpl<>(Lists.newArrayList());
|
||||||
when(this.owners.findByLastNameStartingWith(eq("Unknown Surname"), any(Pageable.class))).thenReturn(tasks);
|
when(this.owners.findByLastNameStartingWith(eq("Unknown Surname"), any(Pageable.class))).thenReturn(tasks);
|
||||||
mockMvc.perform(get("/owners?page=1").param("lastName", "Unknown Surname"))
|
mockMvc.perform(get("/owners?page=1").param("lastName", "Unknown Surname"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(model().attributeHasFieldErrors("owner", "lastName"))
|
.andExpect(model().attributeHasFieldErrors("owner", "lastName"))
|
||||||
.andExpect(model().attributeHasFieldErrorCode("owner", "lastName", "notFound"))
|
.andExpect(model().attributeHasFieldErrorCode("owner", "lastName", "notFound"))
|
||||||
.andExpect(view().name("owners/findOwners"));
|
.andExpect(view().name("owners/findOwners"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testInitUpdateOwnerForm() throws Exception {
|
void testInitUpdateOwnerForm() throws Exception {
|
||||||
mockMvc.perform(get("/owners/{ownerId}/edit", TEST_OWNER_ID))
|
mockMvc.perform(get("/owners/{ownerId}/edit", TEST_OWNER_ID))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(model().attributeExists("owner"))
|
.andExpect(model().attributeExists("owner"))
|
||||||
.andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin"))))
|
.andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin"))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("firstName", is("George"))))
|
.andExpect(model().attribute("owner", hasProperty("firstName", is("George"))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St."))))
|
.andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St."))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("city", is("Madison"))))
|
.andExpect(model().attribute("owner", hasProperty("city", is("Madison"))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023"))))
|
.andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023"))))
|
||||||
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
|
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testProcessUpdateOwnerFormSuccess() throws Exception {
|
void testProcessUpdateOwnerFormSuccess() throws Exception {
|
||||||
mockMvc
|
mockMvc
|
||||||
.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID).param("firstName", "Joe")
|
.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID).param("firstName", "Joe")
|
||||||
.param("lastName", "Bloggs")
|
.param("lastName", "Bloggs")
|
||||||
.param("address", "123 Caramel Street")
|
.param("address", "123 Caramel Street")
|
||||||
.param("city", "London")
|
.param("city", "London")
|
||||||
.param("telephone", "1616291589"))
|
.param("telephone", "1616291589"))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andExpect(view().name("redirect:/owners/{ownerId}"));
|
.andExpect(view().name("redirect:/owners/{ownerId}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testProcessUpdateOwnerFormUnchangedSuccess() throws Exception {
|
void testProcessUpdateOwnerFormUnchangedSuccess() throws Exception {
|
||||||
mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID))
|
mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andExpect(view().name("redirect:/owners/{ownerId}"));
|
.andExpect(view().name("redirect:/owners/{ownerId}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testProcessUpdateOwnerFormHasErrors() throws Exception {
|
void testProcessUpdateOwnerFormHasErrors() throws Exception {
|
||||||
mockMvc
|
mockMvc
|
||||||
.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID).param("firstName", "Joe")
|
.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID).param("firstName", "Joe")
|
||||||
.param("lastName", "Bloggs")
|
.param("lastName", "Bloggs")
|
||||||
.param("address", "")
|
.param("address", "")
|
||||||
.param("telephone", ""))
|
.param("telephone", ""))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(model().attributeHasErrors("owner"))
|
.andExpect(model().attributeHasErrors("owner"))
|
||||||
.andExpect(model().attributeHasFieldErrors("owner", "address"))
|
.andExpect(model().attributeHasFieldErrors("owner", "address"))
|
||||||
.andExpect(model().attributeHasFieldErrors("owner", "telephone"))
|
.andExpect(model().attributeHasFieldErrors("owner", "telephone"))
|
||||||
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
|
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testShowOwner() throws Exception {
|
void testShowOwner() throws Exception {
|
||||||
mockMvc.perform(get("/owners/{ownerId}", TEST_OWNER_ID))
|
mockMvc.perform(get("/owners/{ownerId}", TEST_OWNER_ID))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin"))))
|
.andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin"))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("firstName", is("George"))))
|
.andExpect(model().attribute("owner", hasProperty("firstName", is("George"))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St."))))
|
.andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St."))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("city", is("Madison"))))
|
.andExpect(model().attribute("owner", hasProperty("city", is("Madison"))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023"))))
|
.andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023"))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("pets", not(empty()))))
|
.andExpect(model().attribute("owner", hasProperty("pets", not(empty()))))
|
||||||
.andExpect(model().attribute("owner",
|
.andExpect(model().attribute("owner",
|
||||||
hasProperty("pets", hasItem(hasProperty("visits", hasSize(greaterThan(0)))))))
|
hasProperty("pets", hasItem(hasProperty("visits", hasSize(greaterThan(0)))))))
|
||||||
.andExpect(view().name("owners/ownerDetails"))
|
.andExpect(view().name("owners/ownerDetails"))
|
||||||
.andExpect(result -> {
|
.andExpect(result -> {
|
||||||
Owner owner = (Owner) result.getModelAndView().getModel().get("owner");
|
Owner owner = (Owner) result.getModelAndView().getModel().get("owner");
|
||||||
// New assertion to exercise the negative branch of getPet
|
// New assertion to exercise the negative branch of getPet
|
||||||
assertNull(owner.getPet("NonExistent"), "Expected getPet to return null when pet is not found");
|
assertNull(owner.getPet("NonExistent"), "Expected getPet to return null when pet is not found");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProcessUpdateOwnerFormWithIdMismatch() throws Exception {
|
public void testProcessUpdateOwnerFormWithIdMismatch() throws Exception {
|
||||||
int pathOwnerId = 1;
|
int pathOwnerId = 1;
|
||||||
|
|
||||||
Owner owner = new Owner();
|
Owner owner = new Owner();
|
||||||
owner.setId(2);
|
owner.setId(2);
|
||||||
owner.setFirstName("John");
|
owner.setFirstName("John");
|
||||||
owner.setLastName("Doe");
|
owner.setLastName("Doe");
|
||||||
owner.setAddress("Center Street");
|
owner.setAddress("Center Street");
|
||||||
owner.setCity("New York");
|
owner.setCity("New York");
|
||||||
owner.setTelephone("0123456789");
|
owner.setTelephone("0123456789");
|
||||||
|
|
||||||
when(owners.findById(pathOwnerId)).thenReturn(Optional.of(owner));
|
when(owners.findById(pathOwnerId)).thenReturn(Optional.of(owner));
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.post("/owners/{ownerId}/edit", pathOwnerId).flashAttr("owner", owner))
|
mockMvc.perform(MockMvcRequestBuilders.post("/owners/{ownerId}/edit", pathOwnerId).flashAttr("owner", owner))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andExpect(redirectedUrl("/owners/" + pathOwnerId + "/edit"))
|
.andExpect(redirectedUrl("/owners/" + pathOwnerId + "/edit"))
|
||||||
.andExpect(flash().attributeExists("error"));
|
.andExpect(flash().attributeExists("error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue