From ec0910383e48afb9e9d14db60b827125c66c668b Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 10 Aug 2023 15:04:22 -0500 Subject: [PATCH] Add initial data and analytics view (#366) The additional properties required for data and analytics UI/UX has yet to be determined. --- .../administration/dataAndAnalyticsViews.adoc | 120 +++++++ .../administration/directoryViews.adoc | 4 +- .../administration/discoveryViews.adoc | 2 +- .../asciidoc/administration/displayViews.adoc | 2 +- src/main/asciidoc/administration/themes.adoc | 2 +- src/main/asciidoc/index.adoc | 1 + .../defaults/AnalyticViewsDefaults.java | 35 ++ .../view/model/DataAndAnalyticsView.java | 12 + .../middleware/view/model/Layout.java | 2 +- .../model/repo/DataAndAnalyticsViewRepo.java | 10 + .../DataAndAnalyticViewEventHandler.java | 18 + .../defaults/dataAndanalyticViews.yml | 7 + .../middleware/view/ViewTestUtility.java | 95 +++++- .../DataAndAnalyticsViewControllerTest.java | 322 ++++++++++++++++++ .../view/model/DataAndAnalyticsViewTest.java | 80 +++++ .../repo/DataAndAnalyticsViewRepoTest.java | 34 ++ 16 files changed, 739 insertions(+), 7 deletions(-) create mode 100644 src/main/asciidoc/administration/dataAndAnalyticsViews.adoc create mode 100644 src/main/java/edu/tamu/scholars/middleware/defaults/AnalyticViewsDefaults.java create mode 100644 src/main/java/edu/tamu/scholars/middleware/view/model/DataAndAnalyticsView.java create mode 100644 src/main/java/edu/tamu/scholars/middleware/view/model/repo/DataAndAnalyticsViewRepo.java create mode 100644 src/main/java/edu/tamu/scholars/middleware/view/model/repo/handler/DataAndAnalyticViewEventHandler.java create mode 100644 src/main/resources/defaults/dataAndanalyticViews.yml create mode 100644 src/test/java/edu/tamu/scholars/middleware/view/controller/DataAndAnalyticsViewControllerTest.java create mode 100644 src/test/java/edu/tamu/scholars/middleware/view/model/DataAndAnalyticsViewTest.java create mode 100644 src/test/java/edu/tamu/scholars/middleware/view/model/repo/DataAndAnalyticsViewRepoTest.java diff --git a/src/main/asciidoc/administration/dataAndAnalyticsViews.adoc b/src/main/asciidoc/administration/dataAndAnalyticsViews.adoc new file mode 100644 index 000000000..225cdef78 --- /dev/null +++ b/src/main/asciidoc/administration/dataAndAnalyticsViews.adoc @@ -0,0 +1,120 @@ +=== Data And Analytics Views + +This section describes the data and analytics views of the application. This object is a persistent representation of a data and analytics UI. + +==== Data And Analytics + +This displays a list of all the data and analytics view objects based on parameters like page, size or sort feature based on name, collection etc as shown in *Request Parameters*. + +===== Request Parameters +include::../{snippets}/dataAndAnalyticsViews/directory/request-parameters.adoc[] + +===== Response Fields +include::../{snippets}/dataAndAnalyticsViews/directory/response-fields.adoc[] + +===== Sample Request +include::../{snippets}/dataAndAnalyticsViews/directory/http-request.adoc[] + +===== Sample Response +include::../{snippets}/dataAndAnalyticsViews/directory/http-response.adoc[] + +===== CURL Sample +include::../{snippets}/dataAndAnalyticsViews/directory/curl-request.adoc[] + +==== Create + +A data and analytics view is created by adding a fields like _name_, _collection_ etc along with other variables as shown in the *Request Fields*. + +===== Request Fields +include::../{snippets}/dataAndAnalyticsViews/create/request-fields.adoc[] + +===== Response Fields +include::../{snippets}/dataAndAnalyticsViews/create/response-fields.adoc[] + +===== Sample Request +include::../{snippets}/dataAndAnalyticsViews/create/http-request.adoc[] + +===== Sample Response +include::../{snippets}/dataAndAnalyticsViews/create/http-response.adoc[] + +===== CURL Sample +include::../{snippets}/dataAndAnalyticsViews/create/curl-request.adoc[] + +==== Delete + +A data and analytics view can be deleted by passing the _dataAndAnalyticsView id_ as a path parameter. This will return a *NO_CONTENT (204)* http status code as shown in the *Sample Response*. + +===== Path Parameters +include::../{snippets}/dataAndAnalyticsViews/delete/path-parameters.adoc[] + +===== Sample Request +include::../{snippets}/dataAndAnalyticsViews/delete/http-request.adoc[] + +===== Sample Response +include::../{snippets}/dataAndAnalyticsViews/delete/http-response.adoc[] + +===== CURL Sample +include::../{snippets}/dataAndAnalyticsViews/delete/curl-request.adoc[] + +==== Find by Id + +A user can find a data and analytics view by providing _dataAndAnalyticsView id_ as a path parameter. This returns a json response displaying the *HttpStatus.OK(200)* message along with the data and analytics view object as shown in the *Sample Response*. + +===== Path Parameters +include::../{snippets}/dataAndAnalyticsViews/find-by-id/path-parameters.adoc[] + +===== Response Fields +include::../{snippets}/dataAndAnalyticsViews/find-by-id/response-fields.adoc[] + +===== Sample Request +include::../{snippets}/dataAndAnalyticsViews/find-by-id/http-request.adoc[] + +===== Sample Response +include::../{snippets}/dataAndAnalyticsViews/find-by-id/http-response.adoc[] + +===== CURL Sample +include::../{snippets}/dataAndAnalyticsViews/find-by-id/curl-request.adoc[] + +==== Patch + +This helps an admin user to partially update a data and analytics view. This process utilizes the http patch protocol. + +===== Path Parameters +include::../{snippets}/dataAndAnalyticsViews/patch/path-parameters.adoc[] + +===== Request Parameters +include::../{snippets}/dataAndAnalyticsViews/patch/request-parameters.adoc[] + +===== Response Fields +include::../{snippets}/dataAndAnalyticsViews/patch/response-fields.adoc[] + +===== Sample Request +include::../{snippets}/dataAndAnalyticsViews/patch/http-request.adoc[] + +===== Sample Response +include::../{snippets}/dataAndAnalyticsViews/patch/http-response.adoc[] + +===== CURL Sample +include::../{snippets}/dataAndAnalyticsViews/patch/curl-request.adoc[] + +==== Update + +This helps an admin user to update a specifc data and analytics view based on the _dataAndAnalyticsView id_ provided in the path parameter. This utilizes the http put protocol. + +===== Path Parameters +include::../{snippets}/dataAndAnalyticsViews/update/path-parameters.adoc[] + +===== Request Fields +include::../{snippets}/dataAndAnalyticsViews/update/request-fields.adoc[] + +===== Response Fields +include::../{snippets}/dataAndAnalyticsViews/update/response-fields.adoc[] + +===== Sample Request +include::../{snippets}/dataAndAnalyticsViews/update/http-request.adoc[] + +===== Sample Response +include::../{snippets}/dataAndAnalyticsViews/update/http-response.adoc[] + +===== CURL Sample +include::../{snippets}/dataAndAnalyticsViews/update/curl-request.adoc[] diff --git a/src/main/asciidoc/administration/directoryViews.adoc b/src/main/asciidoc/administration/directoryViews.adoc index 3cfd5f689..688d60282 100644 --- a/src/main/asciidoc/administration/directoryViews.adoc +++ b/src/main/asciidoc/administration/directoryViews.adoc @@ -1,6 +1,6 @@ === Directory Views -This section describes about the directory views of the application. This object is a persistent representation of a directory UI. +This section describes the directory views of the application. This object is a persistent representation of a directory UI. ==== Directory @@ -117,4 +117,4 @@ include::../{snippets}/directoryViews/update/http-request.adoc[] include::../{snippets}/directoryViews/update/http-response.adoc[] ===== CURL Sample -include::../{snippets}/directoryViews/update/curl-request.adoc[] +include::../{snippets}/directoryViews/update/curl-request.adoc[] \ No newline at end of file diff --git a/src/main/asciidoc/administration/discoveryViews.adoc b/src/main/asciidoc/administration/discoveryViews.adoc index b0cf1bde8..9b385b45d 100644 --- a/src/main/asciidoc/administration/discoveryViews.adoc +++ b/src/main/asciidoc/administration/discoveryViews.adoc @@ -1,6 +1,6 @@ === Discovery Views -This section describes about the discovery views of the application. This object is a persistent representation of a discovery view. +This section describes the discovery views of the application. This object is a persistent representation of a discovery view. ==== Directory diff --git a/src/main/asciidoc/administration/displayViews.adoc b/src/main/asciidoc/administration/displayViews.adoc index e80917938..9b536b2ee 100644 --- a/src/main/asciidoc/administration/displayViews.adoc +++ b/src/main/asciidoc/administration/displayViews.adoc @@ -1,6 +1,6 @@ === Display Views -This section describes about the display views of the application. This object is a persistent representation of a display UI. +This section describes the display views of the application. This object is a persistent representation of a display UI. ==== Directory diff --git a/src/main/asciidoc/administration/themes.adoc b/src/main/asciidoc/administration/themes.adoc index 080d3870b..eee2cf1d9 100644 --- a/src/main/asciidoc/administration/themes.adoc +++ b/src/main/asciidoc/administration/themes.adoc @@ -1,6 +1,6 @@ === Themes -This section describes about the "look and feel" of the application. This object is a collection of properties like the header, logo, footer, color, size, styles etc. +This section describes the "look and feel" of the application. This object is a collection of properties like the header, logo, footer, color, size, styles etc. The default theme view is seen in the *Sample Response*. ==== Directory diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index f26aa8655..740ed577f 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -42,6 +42,7 @@ include::auth/user.adoc[] == Administration +include::administration/dataAndAnalyticsViews.adoc[] include::administration/directoryViews.adoc[] include::administration/discoveryViews.adoc[] include::administration/displayViews.adoc[] diff --git a/src/main/java/edu/tamu/scholars/middleware/defaults/AnalyticViewsDefaults.java b/src/main/java/edu/tamu/scholars/middleware/defaults/AnalyticViewsDefaults.java new file mode 100644 index 000000000..b9f574712 --- /dev/null +++ b/src/main/java/edu/tamu/scholars/middleware/defaults/AnalyticViewsDefaults.java @@ -0,0 +1,35 @@ +package edu.tamu.scholars.middleware.defaults; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.core.type.TypeReference; + +import edu.tamu.scholars.middleware.view.model.DataAndAnalyticsView; +import edu.tamu.scholars.middleware.view.model.repo.DataAndAnalyticsViewRepo; + +@Service +public class AnalyticViewsDefaults extends AbstractDefaults { + + public AnalyticViewsDefaults() { + super(); + } + + @Override + public String path() { + return "classpath:defaults/dataAndanalyticViews.yml"; + } + + @Override + public List read(InputStream is) throws IOException { + List views = mapper.readValue(is, new TypeReference>() {}); + for (DataAndAnalyticsView view : views) { + loadTemplateMap(view.getTemplates()); + } + return views; + } + +} diff --git a/src/main/java/edu/tamu/scholars/middleware/view/model/DataAndAnalyticsView.java b/src/main/java/edu/tamu/scholars/middleware/view/model/DataAndAnalyticsView.java new file mode 100644 index 000000000..3412c98e0 --- /dev/null +++ b/src/main/java/edu/tamu/scholars/middleware/view/model/DataAndAnalyticsView.java @@ -0,0 +1,12 @@ +package edu.tamu.scholars.middleware.view.model; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity +@Table(name = "data_and_analytics_views") +public class DataAndAnalyticsView extends CollectionView { + + private static final long serialVersionUID = 2912876591264398726L; + +} diff --git a/src/main/java/edu/tamu/scholars/middleware/view/model/Layout.java b/src/main/java/edu/tamu/scholars/middleware/view/model/Layout.java index 133e54a2f..cf30324e9 100644 --- a/src/main/java/edu/tamu/scholars/middleware/view/model/Layout.java +++ b/src/main/java/edu/tamu/scholars/middleware/view/model/Layout.java @@ -1,5 +1,5 @@ package edu.tamu.scholars.middleware.view.model; public enum Layout { - LIST, GRID + CONTAINER, GRID, LIST } diff --git a/src/main/java/edu/tamu/scholars/middleware/view/model/repo/DataAndAnalyticsViewRepo.java b/src/main/java/edu/tamu/scholars/middleware/view/model/repo/DataAndAnalyticsViewRepo.java new file mode 100644 index 000000000..0f9030f89 --- /dev/null +++ b/src/main/java/edu/tamu/scholars/middleware/view/model/repo/DataAndAnalyticsViewRepo.java @@ -0,0 +1,10 @@ +package edu.tamu.scholars.middleware.view.model.repo; + +import org.springframework.data.rest.core.annotation.RepositoryRestResource; + +import edu.tamu.scholars.middleware.view.model.DataAndAnalyticsView; + +@RepositoryRestResource +public interface DataAndAnalyticsViewRepo extends ViewRepo { + +} diff --git a/src/main/java/edu/tamu/scholars/middleware/view/model/repo/handler/DataAndAnalyticViewEventHandler.java b/src/main/java/edu/tamu/scholars/middleware/view/model/repo/handler/DataAndAnalyticViewEventHandler.java new file mode 100644 index 000000000..8113d340e --- /dev/null +++ b/src/main/java/edu/tamu/scholars/middleware/view/model/repo/handler/DataAndAnalyticViewEventHandler.java @@ -0,0 +1,18 @@ +package edu.tamu.scholars.middleware.view.model.repo.handler; + +import org.springframework.data.rest.core.annotation.RepositoryEventHandler; + +import edu.tamu.scholars.middleware.view.model.DataAndAnalyticsView; +import edu.tamu.scholars.middleware.view.model.DirectoryView; + +@RepositoryEventHandler(DataAndAnalyticsView.class) +public class DataAndAnalyticViewEventHandler extends ViewEventHandler { + + public static final String DATA_AND_ANALYTICS_VIEWS_CHANNEL = "/queue/data-and-analytics-views"; + + @Override + protected String getChannel() { + return DATA_AND_ANALYTICS_VIEWS_CHANNEL; + } + +} diff --git a/src/main/resources/defaults/dataAndanalyticViews.yml b/src/main/resources/defaults/dataAndanalyticViews.yml new file mode 100644 index 000000000..e95ef6064 --- /dev/null +++ b/src/main/resources/defaults/dataAndanalyticViews.yml @@ -0,0 +1,7 @@ +--- +- name: Publications by Academic Age Group + layout: CONTAINER +- name: Research by UN SDG + layout: CONTAINER +- name: Download Profile Summaries by Department + layout: CONTAINER diff --git a/src/test/java/edu/tamu/scholars/middleware/view/ViewTestUtility.java b/src/test/java/edu/tamu/scholars/middleware/view/ViewTestUtility.java index 416668341..84e1db48a 100644 --- a/src/test/java/edu/tamu/scholars/middleware/view/ViewTestUtility.java +++ b/src/test/java/edu/tamu/scholars/middleware/view/ViewTestUtility.java @@ -9,6 +9,7 @@ import edu.tamu.scholars.middleware.model.OpKey; import edu.tamu.scholars.middleware.view.model.Boost; +import edu.tamu.scholars.middleware.view.model.DataAndAnalyticsView; import edu.tamu.scholars.middleware.view.model.DirectoryView; import edu.tamu.scholars.middleware.view.model.DiscoveryView; import edu.tamu.scholars.middleware.view.model.DisplaySectionView; @@ -29,7 +30,99 @@ public class ViewTestUtility { - public static String MOCK_VIEW_NAME = "People"; + public static String MOCK_VIEW_NAME = "View"; + + public static DataAndAnalyticsView getMockDataAndAnalyticsView() { + DataAndAnalyticsView dataAndAnalyticsView = new DataAndAnalyticsView(); + + dataAndAnalyticsView.setName(MOCK_VIEW_NAME); + dataAndAnalyticsView.setLayout(Layout.GRID); + + Map templates = new HashMap(); + templates.put("default", "

Element template from WSYWIG

"); + + dataAndAnalyticsView.setTemplates(templates); + + List styles = new ArrayList(); + + styles.add("color: maroon;"); + + dataAndAnalyticsView.setStyles(styles); + + List fields = new ArrayList(); + + fields.add("title"); + + dataAndAnalyticsView.setFields(fields); + + List facets = new ArrayList(); + + Facet facet = new Facet(); + + facet.setName("Name"); + facet.setField("name"); + facet.setType(FacetType.STRING); + facet.setSort(FacetSort.COUNT); + facet.setDirection(Direction.DESC); + facet.setPageSize(20); + facet.setPageNumber(1); + + facets.add(facet); + + dataAndAnalyticsView.setFacets(facets); + + List filters = new ArrayList(); + + Filter filter = new Filter(); + + filter.setField("type"); + filter.setValue("FacultyMember"); + + filters.add(filter); + + dataAndAnalyticsView.setFilters(filters); + + List boosts = new ArrayList(); + + Boost boost = new Boost(); + + boost.setField("name"); + boost.setValue(2.0f); + + boosts.add(boost); + + dataAndAnalyticsView.setBoosts(boosts); + + List sorting = new ArrayList(); + + Sort sort = new Sort(); + sort.setField("name"); + sort.setDirection(Direction.ASC); + + sorting.add(sort); + + dataAndAnalyticsView.setSort(sorting); + + List exporting = new ArrayList(); + + ExportField idExport = new ExportField(); + + idExport.setColumnHeader("Id"); + idExport.setValuePath("id"); + + exporting.add(idExport); + + ExportField nameExport = new ExportField(); + + nameExport.setColumnHeader("Name"); + nameExport.setValuePath("name"); + + exporting.add(nameExport); + + dataAndAnalyticsView.setExport(exporting); + + return dataAndAnalyticsView; + } public static DirectoryView getMockDirectoryView() { DirectoryView directoryView = new DirectoryView(); diff --git a/src/test/java/edu/tamu/scholars/middleware/view/controller/DataAndAnalyticsViewControllerTest.java b/src/test/java/edu/tamu/scholars/middleware/view/controller/DataAndAnalyticsViewControllerTest.java new file mode 100644 index 000000000..fe3191577 --- /dev/null +++ b/src/test/java/edu/tamu/scholars/middleware/view/controller/DataAndAnalyticsViewControllerTest.java @@ -0,0 +1,322 @@ +package edu.tamu.scholars.middleware.view.controller; + +import static edu.tamu.scholars.middleware.view.ViewTestUtility.MOCK_VIEW_NAME; +import static edu.tamu.scholars.middleware.view.ViewTestUtility.getMockDataAndAnalyticsView; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.springframework.hateoas.MediaTypes.HAL_JSON_VALUE; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import javax.servlet.http.Cookie; + +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; + +import com.fasterxml.jackson.core.JsonProcessingException; + +import edu.tamu.scholars.middleware.auth.model.User; +import edu.tamu.scholars.middleware.utility.ConstraintDescriptionsHelper; +import edu.tamu.scholars.middleware.view.ResourceViewIntegrationTest; +import edu.tamu.scholars.middleware.view.model.DataAndAnalyticsView; +import edu.tamu.scholars.middleware.view.model.repo.DataAndAnalyticsViewRepo; + +public class DataAndAnalyticsViewControllerTest extends ResourceViewIntegrationTest { + + private static final ConstraintDescriptionsHelper describeDataAndAnalyticsView = new ConstraintDescriptionsHelper(DataAndAnalyticsView.class); + + @Test + public void testCreateDataAndAnalyticsView() throws JsonProcessingException, Exception { + // @formatter:off + performCreateDataAndAnalyticsView() + .andDo( + document( + "dataAndAnalyticsViews/create", + requestFields( + describeDataAndAnalyticsView.withField("name", "The name of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("layout", "The layout of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("templates", "The result templates of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("styles", "An array of result style strings of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("fields", "An array of fields of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("facets", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("filters", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("boosts", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("sort", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("export", "An array of <>.") + ), + links( + linkWithRel("self").description("Canonical link for this resource."), + linkWithRel("dataAndAnalyticsView").description("The Data And Analytics View link for this resource.") + ), + responseFields( + describeDataAndAnalyticsView.withField("name", "The name of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("layout", "The layout of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("templates", "The result templates of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("styles", "An array of result style strings of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("fields", "An array of fields of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("facets", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("filters", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("boosts", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("sort", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("export", "An array of <>."), + subsectionWithPath("_links").description("<> to other resources.") + ) + ) + ); + // @formatter:on + } + + @Test + public void testUpdateDataAndAnalyticsView() throws JsonProcessingException, Exception { + performCreateDataAndAnalyticsView(); + + // @formatter:off + performUpdateDataAndAnalyticsView() + .andDo( + document( + "dataAndAnalyticsViews/update", + pathParameters( + describeDataAndAnalyticsView.withParameter("id", "The Data And Analytics View id.") + ), + requestFields( + describeDataAndAnalyticsView.withField("id", "The Data And Analytics View id."), + describeDataAndAnalyticsView.withField("name", "The name of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("layout", "The layout of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("templates", "The result templates of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("styles", "An array of result style strings of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("fields", "An array of fields of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("facets", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("filters", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("boosts", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("sort", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("export", "An array of <>.") + ), + links( + linkWithRel("self").description("Canonical link for this resource."), + linkWithRel("dataAndAnalyticsView").description("The Data And Analytics View link for this resource.") + ), + responseFields( + describeDataAndAnalyticsView.withField("name", "The name of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("layout", "The layout of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("templates", "The result templates of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("styles", "An array of result style strings of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("fields", "An array of fields of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("facets", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("filters", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("boosts", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("sort", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("export", "An array of <>."), + subsectionWithPath("_links").description("<> to other resources.") + ) + ) + ); + // @formatter:on + } + + @Test + public void testPatchTheme() throws JsonProcessingException, Exception { + performCreateDataAndAnalyticsView(); + DataAndAnalyticsView dataAndAnalyticsView = viewRepo.findByName(MOCK_VIEW_NAME).get(); + + // @formatter:off + mockMvc.perform( + patch("/dataAndAnalyticsViews/{id}", dataAndAnalyticsView.getId()) + .content("{\"name\": \"Organizations\"}") + .cookie(loginAdmin())) + .andExpect(status().isOk()) + .andExpect(content().contentType(HAL_JSON_VALUE)) + .andExpect(jsonPath("name", equalTo("Organizations"))) + .andDo( + document( + "dataAndAnalyticsViews/patch", + pathParameters( + describeDataAndAnalyticsView.withParameter("id", "The Data And Analytics View id.") + ), + requestParameters( + describeDataAndAnalyticsView.withParameter("id", "The Data And Analytics View id.").optional(), + describeDataAndAnalyticsView.withParameter("name", "The name of the Data And Analytics View.").optional(), + describeDataAndAnalyticsView.withParameter("layout", "The layout of the Data And Analytics View.").optional(), + describeDataAndAnalyticsView.withParameter("templates", "The result templates of the Data And Analytics View.").optional(), + describeDataAndAnalyticsView.withParameter("styles", "An array of result style strings of the Data And Analytics View.").optional(), + describeDataAndAnalyticsView.withParameter("fields", "An array of fields of the Data And Analytics View.").optional(), + describeDataAndAnalyticsView.withParameter("facets", "An array of <>.").optional(), + describeDataAndAnalyticsView.withParameter("filters", "An array of <>.").optional(), + describeDataAndAnalyticsView.withParameter("boosts", "An array of <>.").optional(), + describeDataAndAnalyticsView.withParameter("sort", "An array of <>.").optional(), + describeDataAndAnalyticsView.withParameter("export", "An array of <>.").optional() + ), + links( + linkWithRel("self").description("Canonical link for this resource."), + linkWithRel("dataAndAnalyticsView").description("The Data And Analytics View link for this resource.") + ), + responseFields( + describeDataAndAnalyticsView.withField("name", "The name of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("layout", "The layout of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("templates", "The result templates of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("styles", "An array of result style strings of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("fields", "An array of fields of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("facets", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("filters", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("boosts", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("sort", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("export", "An array of <>."), + subsectionWithPath("_links").description("<> to other resources.") + ) + ) + ); + // @formatter:on + } + + @Test + public void testGetDataAndAnalyticsView() throws JsonProcessingException, Exception { + performCreateDataAndAnalyticsView(); + DataAndAnalyticsView dataAndAnalyticsView = viewRepo.findByName(MOCK_VIEW_NAME).get(); + // @formatter:off + mockMvc.perform( + get("/dataAndAnalyticsViews/{id}", dataAndAnalyticsView.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(HAL_JSON_VALUE)) + .andExpect(jsonPath("name", equalTo(MOCK_VIEW_NAME))) + .andDo( + document( + "dataAndAnalyticsViews/find-by-id", + pathParameters( + describeDataAndAnalyticsView.withParameter("id", "The Theme id.") + ), + links( + linkWithRel("self").description("Canonical link for this resource."), + linkWithRel("dataAndAnalyticsView").description("The Data And Analytics View link for this resource.") + ), + responseFields( + describeDataAndAnalyticsView.withField("name", "The name of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("layout", "The layout of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("templates", "The result templates of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("styles", "An array of result style strings of the Data And Analytics View."), + describeDataAndAnalyticsView.withField("fields", "An array of fields of the Data And Analytics View."), + describeDataAndAnalyticsView.withSubsection("facets", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("filters", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("boosts", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("sort", "An array of <>."), + describeDataAndAnalyticsView.withSubsection("export", "An array of <>."), + subsectionWithPath("_links").description("<> to other resources.") + ) + ) + ); + // @formatter:on + } + + @Test + public void testGetDataAndAnalyticsViews() throws JsonProcessingException, Exception { + performCreateDataAndAnalyticsView(); + // @formatter:off + mockMvc.perform( + get("/dataAndAnalyticsViews").param("page", "0").param("size", "20").param("sort", "name")) + .andExpect(status().isOk()) + .andExpect(content().contentType(HAL_JSON_VALUE)) + .andExpect(jsonPath("page.size", equalTo(20))) + .andExpect(jsonPath("page.totalElements", equalTo(1))) + .andExpect(jsonPath("page.totalPages", equalTo(1))) + .andExpect(jsonPath("page.number", equalTo(1))) + .andExpect(jsonPath("_embedded.dataAndAnalyticsViews[0].name", equalTo(MOCK_VIEW_NAME))) + .andDo( + document( + "dataAndAnalyticsViews/directory", + requestParameters( + parameterWithName("page").description("The page number."), + parameterWithName("size").description("The page size."), + parameterWithName("sort").description("The page sort.") + ), + links( + linkWithRel("self").description("Canonical link for this resource."), + linkWithRel("profile").description("The ALPS profile for this resource.") + ), + responseFields( + subsectionWithPath("_embedded.dataAndAnalyticsViews").description("An array of <>."), + subsectionWithPath("_links").description("<> to other resources."), + subsectionWithPath("page").description("Page details for <>.") + ) + ) + ); + // @formatter:on + } + + @Test + public void testDeleteTheme() throws JsonProcessingException, Exception { + performCreateDataAndAnalyticsView(); + DataAndAnalyticsView dataAndAnalyticsView = viewRepo.findByName(MOCK_VIEW_NAME).get(); + // @formatter:off + mockMvc.perform( + delete("/dataAndAnalyticsViews/{id}", dataAndAnalyticsView.getId()) + .cookie(loginAdmin())) + .andExpect(status().isNoContent()) + .andDo( + document( + "dataAndAnalyticsViews/delete", + pathParameters( + parameterWithName("id").description("The Data And Analytics View id") + ) + ) + ); + // @formatter:on + } + + protected Cookie loginAdmin() throws Exception { + User user = getMockAdmin(); + MvcResult directory = mockMvc.perform(post("/login").param("username", user.getEmail()).param("password", "HelloWorld123!")).andReturn(); + return directory.getResponse().getCookie("SESSION"); + } + + private ResultActions performCreateDataAndAnalyticsView() throws JsonProcessingException, Exception { + createMockAdmin(); + DataAndAnalyticsView dataAndAnalyticsView = getMockView(); + + // @formatter:off + return mockMvc.perform( + post("/dataAndAnalyticsViews") + .content(objectMapper.writeValueAsString(dataAndAnalyticsView)) + .contentType(MediaType.APPLICATION_JSON) + .cookie(loginAdmin())) + .andExpect(status().isCreated()) + .andExpect(content().contentType(HAL_JSON_VALUE) + ); + // @formatter:on + } + + private ResultActions performUpdateDataAndAnalyticsView() throws JsonProcessingException, Exception { + DataAndAnalyticsView dataAndAnalyticsView = viewRepo.findByName(MOCK_VIEW_NAME).get(); + dataAndAnalyticsView.setName("Organizations"); + // dataAndAnalyticsView.setCollection("organizations"); + + // @formatter:off + return mockMvc.perform( + put("/dataAndAnalyticsViews/{id}", dataAndAnalyticsView.getId()) + .content(objectMapper.writeValueAsString(dataAndAnalyticsView)) + .cookie(loginAdmin())) + .andExpect(status().isOk()) + .andExpect(content().contentType(HAL_JSON_VALUE) + ); + // @formatter:on + } + + @Override + protected DataAndAnalyticsView getMockView() { + return getMockDataAndAnalyticsView(); + } + +} diff --git a/src/test/java/edu/tamu/scholars/middleware/view/model/DataAndAnalyticsViewTest.java b/src/test/java/edu/tamu/scholars/middleware/view/model/DataAndAnalyticsViewTest.java new file mode 100644 index 000000000..d1c1e8ff3 --- /dev/null +++ b/src/test/java/edu/tamu/scholars/middleware/view/model/DataAndAnalyticsViewTest.java @@ -0,0 +1,80 @@ +package edu.tamu.scholars.middleware.view.model; + +import static edu.tamu.scholars.middleware.view.ViewTestUtility.MOCK_VIEW_NAME; +import static edu.tamu.scholars.middleware.view.ViewTestUtility.getMockDataAndAnalyticsView; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +public class DataAndAnalyticsViewTest { + + @Test + public void testDefaultConstructor() { + DataAndAnalyticsView dataAndAnalyticsView = new DataAndAnalyticsView(); + assertNotNull(dataAndAnalyticsView); + assertNotNull(dataAndAnalyticsView.getFacets()); + assertNotNull(dataAndAnalyticsView.getFilters()); + assertTrue(dataAndAnalyticsView.getFacets().isEmpty()); + assertTrue(dataAndAnalyticsView.getFilters().isEmpty()); + assertTrue(dataAndAnalyticsView.getBoosts().isEmpty()); + assertTrue(dataAndAnalyticsView.getSort().isEmpty()); + assertTrue(dataAndAnalyticsView.getExport().isEmpty()); + } + + @Test + public void testGettersAndSetters() { + DataAndAnalyticsView dataAndAnalyticsView = getMockDataAndAnalyticsView(); + dataAndAnalyticsView.setId(1L); + + assertEquals(1L, dataAndAnalyticsView.getId(), 1); + assertEquals(MOCK_VIEW_NAME, dataAndAnalyticsView.getName()); + assertEquals(Layout.GRID, dataAndAnalyticsView.getLayout()); + + assertTrue(dataAndAnalyticsView.getTemplates().containsKey("default")); + assertEquals("

Element template from WSYWIG

", dataAndAnalyticsView.getTemplates().get("default")); + + assertEquals(1, dataAndAnalyticsView.getStyles().size()); + assertEquals("color: maroon;", dataAndAnalyticsView.getStyles().get(0)); + + assertEquals(1, dataAndAnalyticsView.getFields().size()); + assertEquals("title", dataAndAnalyticsView.getFields().get(0)); + + assertEquals(1, dataAndAnalyticsView.getFacets().size()); + assertEquals("Name", dataAndAnalyticsView.getFacets().get(0).getName()); + assertEquals("name", dataAndAnalyticsView.getFacets().get(0).getField()); + assertEquals(FacetType.STRING, dataAndAnalyticsView.getFacets().get(0).getType()); + assertEquals(FacetSort.COUNT, dataAndAnalyticsView.getFacets().get(0).getSort()); + assertEquals(Sort.Direction.DESC, dataAndAnalyticsView.getFacets().get(0).getDirection()); + assertEquals(20, dataAndAnalyticsView.getFacets().get(0).getPageSize()); + assertEquals(1, dataAndAnalyticsView.getFacets().get(0).getPageNumber()); + assertTrue(dataAndAnalyticsView.getFacets().get(0).isCollapsed()); + assertFalse(dataAndAnalyticsView.getFacets().get(0).isHidden()); + + assertEquals(1, dataAndAnalyticsView.getFilters().size()); + assertEquals("type", dataAndAnalyticsView.getFilters().get(0).getField()); + assertEquals("FacultyMember", dataAndAnalyticsView.getFilters().get(0).getValue()); + + assertEquals(1, dataAndAnalyticsView.getBoosts().size()); + assertEquals("name", dataAndAnalyticsView.getBoosts().get(0).getField()); + assertEquals(2.0f, dataAndAnalyticsView.getBoosts().get(0).getValue()); + + assertEquals(1, dataAndAnalyticsView.getSort().size()); + assertEquals("name", dataAndAnalyticsView.getSort().get(0).getField()); + assertEquals(Direction.ASC, dataAndAnalyticsView.getSort().get(0).getDirection()); + + assertEquals(2, dataAndAnalyticsView.getExport().size()); + assertEquals("Id", dataAndAnalyticsView.getExport().get(0).getColumnHeader()); + assertEquals("id", dataAndAnalyticsView.getExport().get(0).getValuePath()); + assertEquals("Name", dataAndAnalyticsView.getExport().get(1).getColumnHeader()); + assertEquals("name", dataAndAnalyticsView.getExport().get(1).getValuePath()); + } + +} diff --git a/src/test/java/edu/tamu/scholars/middleware/view/model/repo/DataAndAnalyticsViewRepoTest.java b/src/test/java/edu/tamu/scholars/middleware/view/model/repo/DataAndAnalyticsViewRepoTest.java new file mode 100644 index 000000000..772e24a60 --- /dev/null +++ b/src/test/java/edu/tamu/scholars/middleware/view/model/repo/DataAndAnalyticsViewRepoTest.java @@ -0,0 +1,34 @@ +package edu.tamu.scholars.middleware.view.model.repo; + +import static edu.tamu.scholars.middleware.view.ViewTestUtility.getMockDataAndAnalyticsView; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import edu.tamu.scholars.middleware.config.model.MiddlewareConfig; +import edu.tamu.scholars.middleware.view.model.DataAndAnalyticsView; + +public class DataAndAnalyticsViewRepoTest extends ViewRepoTest { + + @TestConfiguration + static class DataAndAnalyticsViewRepoTestContextConfiguration { + + @Bean + public MiddlewareConfig middlewareConfig() { + return new MiddlewareConfig(); + } + + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + } + + @Override + protected DataAndAnalyticsView getMockView() { + return getMockDataAndAnalyticsView(); + } + +}