package sagan.projects.support; import sagan.projects.Project; import sagan.projects.ProjectRelease; import sagan.projects.ProjectRelease.ReleaseStatus; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.json.JacksonJsonParser; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.http.MediaType; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import com.fasterxml.jackson.databind.ObjectMapper; import static junit.framework.TestCase.fail; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.operation.preprocess.Preprocessors.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import saganx.AbstractIntegrationTests; @AutoConfigureRestDocs(outputDir = "build/snippets") public class ProjectsMetadataApiTests extends AbstractIntegrationTests { @Autowired private ProjectMetadataService service; @Autowired private ObjectMapper mapper; private RestDocumentationResultHandler docs(String name) { return document(name, preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())); } @Test public void projectMetadata_respondsWithData() throws Exception { mockMvc .perform( MockMvcRequestBuilders .get("/project_metadata/spring-framework")) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("application/json")) .andDo(docs("project")); } @Test public void projectMetadata_respondsWithJavascript() throws Exception { mockMvc .perform( MockMvcRequestBuilders .get("/project_metadata/spring-framework?callback=a_function_name")) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("application/javascript")) .andDo(docs("callback")); } @Test public void projectMetadata_respondsWithCallback_andData() throws Exception { List<Object> releases = getAndCheckProjectReleases("spring-framework", "Spring Framework"); checkCurrentRelease(releases); checkMilestone(releases); } @Test public void projectMetadata_withSnapshot() throws Exception { List<Object> releases = getAndCheckProjectReleases("spring-security-kerberos", "Spring Security Kerberos"); checkSnapshot(releases); } @Test public void projectMetadata_addRelease() throws Exception { ProjectRelease release = new ProjectRelease("1.2.3.BUILD-SNAPSHOT", ReleaseStatus.SNAPSHOT, false, "http://example.com/{version}", "http://example.com/api/{version}", "org.springframework", "spring-core"); mockMvc .perform( MockMvcRequestBuilders .post("/project_metadata/spring-framework/releases").content(mapper.writeValueAsString( getRelease(release))) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("application/json")) .andExpect(content().string(containsString("http://example.com/1.2.3.BUILD-SNAPSHOT"))) .andDo(docs("add_release")); } @Test public void projectMetadata_updateRelease() throws Exception { Project project = service.getProject("spring-framework"); ProjectRelease release = project.getProjectReleases().iterator().next().createWithVersionPattern(); release.setVersion("1.2.3.RELEASE"); mockMvc .perform( MockMvcRequestBuilders .post("/project_metadata/spring-framework/releases").content(mapper.writeValueAsString( getRelease(release))) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("application/json")) .andExpect(content().string(containsString("/spring/docs/1.2.3.RELEASE"))) .andExpect(content().string(not(containsString("null")))) .andDo(docs("add_release")); } @Test public void projectMetadata_getRelease() throws Exception { Project project = service.getProject("spring-framework"); mockMvc .perform( MockMvcRequestBuilders .get("/project_metadata/spring-framework/releases/" + project.getProjectReleases() .iterator() .next().getVersion())) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("application/json")) .andDo(docs("get_release")); } @Test public void projectMetadata_updateProject() throws Exception { Project project = service.getProject("spring-framework"); List<Map<String, Object>> releases = new ArrayList<>(); for (ProjectRelease release : project.getProjectReleases()) { release = release.createWithVersionPattern(); Map<String, Object> map = getRelease(release); releases.add(map); } project.getProjectReleases().iterator().next().setVersion("1.2.8.RELEASE"); mockMvc .perform( MockMvcRequestBuilders .put("/project_metadata/spring-framework/releases").content(mapper.writeValueAsString( releases)) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("application/json")) .andDo(docs("update_project")); } private Map<String, Object> getRelease(ProjectRelease release) { Map<String, Object> map = new LinkedHashMap<>(); map.put("groupId", release.getGroupId()); map.put("artifactId", release.getArtifactId()); map.put("version", release.getVersion()); map.put("releaseStatus", release.getReleaseStatus()); if (release.isCurrent()) { map.put("current", true); } map.put("refDocUrl", release.getRefDocUrl()); map.put("apiDocUrl", release.getApiDocUrl()); if (release.getRepository() != null) { map.put("repository", release.getRepository()); } return map; } @Test public void projectMetadata_getMissingRelease() throws Exception { mockMvc .perform( MockMvcRequestBuilders .get("/project_metadata/spring-framework/releases/FOO")) .andExpect(status().isNotFound()); } @Test public void projectMetadata_deleteRelease() throws Exception { Project project = service.getProject("spring-framework"); mockMvc .perform( MockMvcRequestBuilders .delete("/project_metadata/spring-framework/releases/" + project.getProjectReleases() .iterator() .next().getVersion())) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("application/json")) .andDo(docs("delete_release")); } public List<Object> getAndCheckProjectReleases(String projectId, String expectedProjectName) throws Exception { MvcResult result = mockMvc.perform( MockMvcRequestBuilders.get("/project_metadata/" + projectId + "?callback=a_function_name")).andReturn(); String content = result.getResponse().getContentAsString(); String functionNameRegex = "^([^(]*)\\((.*)\\);$"; Matcher matcher = Pattern.compile(functionNameRegex).matcher(content); if (matcher.find()) { assertThat(matcher.group(1), equalTo("/**/a_function_name")); Map<String, Object> projectMetadata = new JacksonJsonParser().parseMap(matcher.group(2)); assertThat((String) projectMetadata.get("name"), equalTo(expectedProjectName)); @SuppressWarnings("unchecked") List<Object> list = (List<Object>) projectMetadata.get("projectReleases"); return list; } else { fail(String.format("no match found: %s", content)); return null; } } private void checkCurrentRelease(List<Object> releases) { @SuppressWarnings("unchecked") Map<String, Object> release = (Map<String, Object>) releases.get(0); assertThat((String) release.get("version"), equalTo("4.0.1.BUILD-SNAPSHOT")); assertThat( (String) release.get("refDocUrl"), equalTo("http://docs.spring.io/spring/docs/4.0.1.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/")); assertThat((String) release.get("apiDocUrl"), equalTo("http://docs.spring.io/spring/docs/4.0.1.BUILD-SNAPSHOT/javadoc-api/")); assertThat((Boolean) release.get("preRelease"), equalTo(false)); assertThat((Boolean) release.get("current"), equalTo(false)); assertThat((Boolean) release.get("generalAvailability"), equalTo(false)); assertThat((Boolean) release.get("snapshot"), equalTo(true)); Map<String, Object> repository = getRepository(release); assertThat(repository, notNullValue()); } private void checkMilestone(List<Object> releases) { @SuppressWarnings("unchecked") Map<String, Object> release = (Map<String, Object>) releases.get(1); assertThat((String) release.get("version"), equalTo("4.0.0.RELEASE")); assertThat((String) release.get("refDocUrl"), equalTo("http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/htmlsingle/")); assertThat((String) release.get("apiDocUrl"), equalTo("http://docs.spring.io/spring/docs/4.0.0.RELEASE/javadoc-api/")); assertThat((Boolean) release.get("preRelease"), equalTo(false)); assertThat((Boolean) release.get("current"), equalTo(true)); assertThat((Boolean) release.get("generalAvailability"), equalTo(true)); assertThat((Boolean) release.get("snapshot"), equalTo(false)); } private void checkSnapshot(List<Object> releases) { @SuppressWarnings("unchecked") Map<String, Object> release = (Map<String, Object>) releases.get(0); assertThat((String) release.get("version"), equalTo("1.0.0.CI-SNAPSHOT")); assertThat((String) release.get("refDocUrl"), equalTo("http://docs.spring.io/spring-security-kerberos/docs/1.0.0.CI-SNAPSHOT/reference/html")); assertThat((String) release.get("apiDocUrl"), equalTo("http://docs.spring.io/spring-security-kerberos/docs/1.0.0.CI-SNAPSHOT/api/")); assertThat((Boolean) release.get("preRelease"), equalTo(false)); assertThat((Boolean) release.get("current"), equalTo(false)); assertThat((Boolean) release.get("generalAvailability"), equalTo(false)); assertThat((Boolean) release.get("snapshot"), equalTo(true)); Map<String, Object> repository = getRepository(release); assertThat((String) repository.get("id"), equalTo("spring-snapshots")); assertThat((String) repository.get("name"), equalTo("Spring Snapshots")); assertThat((String) repository.get("url"), equalTo("https://repo.spring.io/libs-snapshot")); assertThat((Boolean) repository.get("snapshotsEnabled"), equalTo(true)); } private Map<String, Object> getRepository(Map<String, Object> release) { @SuppressWarnings("unchecked") Map<String, Object> map = (Map<String, Object>) release.get("repository"); return map; } }