diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6709891..fb4c0ed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ checkRun: checkStyle: stage: test - script: ./gradlew check + script: ./gradlew check -x test deploy: stage: deploy diff --git a/.gitlab/issue_templates/feature.md b/.gitlab/issue_templates/feature.md index ba3e298..c9e1757 100644 --- a/.gitlab/issue_templates/feature.md +++ b/.gitlab/issue_templates/feature.md @@ -1,31 +1,29 @@ ## Краткое описание задачи -``` + Что требуется сделать -``` + ## `Опционально` Список верстаемых страниц -``` + Будут затронуты страницы: * page1.html * page2.html * page3.html -``` ## `Опционально` Список затрагиваемых модулей -``` + При реализации задачи потребуется также реализовать методы контроллера -``` + ## `Опционально` Список реализуемых функций -``` + После выполнения задачи станет доступным: * просмотр `entity_name` * редактирование `entity_name` * валидация `entity_name` -``` ## `Опционально` Сценарии работы -``` + Сценарий просмотра: 1. Зайти на главную страницу приложения 2. Перейти в раздел `section_name` @@ -38,13 +36,11 @@ 3. Перейти к списку `entity_name` 4. Выбрать нужную `entity_name` и нажать на нее 5. Внести нужные правки в поля и сохранить -``` ## Описание конечного результата, дающего возможность проверки выполнения задачи: компоненты проекта, сценарии работы -``` + * Сверстаны страницы page1.hml, page2.hml, page3.hml * Реализован контроллер для обслуживания страниц * Сохранение в БД еще не реализовано * Валидация происходит по полям `field1, field2` * Сценарий просмотра проверяется при ручном внечении записей в БД -``` \ No newline at end of file diff --git a/build.gradle b/build.gradle index ffc7d0a..38de2c7 100644 --- a/build.gradle +++ b/build.gradle @@ -114,9 +114,6 @@ dependencies { compile group: 'org.liquibase', name: 'liquibase-core', version: '3.5.3' compile group: 'com.mattbertolini', name: 'liquibase-slf4j', version: '2.0.0' - compile group: 'org.apache.poi', name: 'poi', version: '3.9' - compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.9' - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.7' compile group: 'org.webjars', name: 'bootstrap', version: '4.1.0' @@ -125,8 +122,10 @@ dependencies { compile group: 'org.webjars.npm', name: 'jquery.easing', version: '1.4.1' compile group: 'org.webjars', name: 'font-awesome', version: '4.7.0' - compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.5.0' - compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.5.0' + compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.6.0' + compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.6.0' testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test' + testCompile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.3.1' + } \ No newline at end of file diff --git a/src/main/java/ru/ulstu/core/error/XlsLoadException.java b/src/main/java/ru/ulstu/core/error/XlsLoadException.java deleted file mode 100644 index 372731f..0000000 --- a/src/main/java/ru/ulstu/core/error/XlsLoadException.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.ulstu.core.error; - -public class XlsLoadException extends Exception { - public XlsLoadException(String s) { - super(s); - } -} diff --git a/src/main/java/ru/ulstu/core/error/XlsParseException.java b/src/main/java/ru/ulstu/core/error/XlsParseException.java deleted file mode 100644 index fe8c4b3..0000000 --- a/src/main/java/ru/ulstu/core/error/XlsParseException.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.ulstu.core.error; - -public class XlsParseException extends Exception { - public XlsParseException(String s) { - super(s); - } -} diff --git a/src/main/java/ru/ulstu/core/service/TreeService.java b/src/main/java/ru/ulstu/core/service/TreeService.java deleted file mode 100644 index 1e3d4a0..0000000 --- a/src/main/java/ru/ulstu/core/service/TreeService.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.ulstu.core.service; - -import org.springframework.stereotype.Service; -import ru.ulstu.core.model.TreeDto; -import ru.ulstu.core.model.TreeEntity; - -import java.util.List; -import java.util.function.Predicate; - -@Service -public class TreeService { - public TreeDto getTree(String rootName, List rootItems) { - return addChildNode(new TreeDto(rootName), rootItems, element -> true); - } - - public TreeDto getTree(String rootName, List rootItems, Predicate filterPredicate) { - return addChildNode(new TreeDto(rootName), rootItems, filterPredicate); - } - - private TreeDto addChildNode(TreeDto currentRoot, List children, Predicate filterPredicate) { - if (children != null) { - children.stream() - .filter(filterPredicate) - .forEach(item -> { - TreeDto newNode = new TreeDto(item); - currentRoot.getChildren().add(addChildNode(newNode, item.getChildren(), filterPredicate)); - }); - } - return currentRoot; - } -} diff --git a/src/main/java/ru/ulstu/core/service/XlsDocumentBuilder.java b/src/main/java/ru/ulstu/core/service/XlsDocumentBuilder.java deleted file mode 100644 index d70d86e..0000000 --- a/src/main/java/ru/ulstu/core/service/XlsDocumentBuilder.java +++ /dev/null @@ -1,207 +0,0 @@ -package ru.ulstu.core.service; - -import org.apache.poi.POIXMLDocument; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.RegionUtil; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import ru.ulstu.core.error.XlsParseException; - -import java.io.*; - -public class XlsDocumentBuilder { - private static final int DEFAULT_SHEET_NUM = 0; - private File documentFile; - private Workbook workBook; - private Sheet currentSheet; - - /** - * Constructor for reading and writing data from/to *.[xls|xlsx] document - * - * @param file contains existing document for reading or new document to save - */ - public XlsDocumentBuilder(File file) throws IOException, XlsParseException { - this.documentFile = file; - if (file.exists()) { - workBook = getWorkBook(file); - currentSheet = workBook.getSheetAt(DEFAULT_SHEET_NUM); - } else { - workBook = new XSSFWorkbook(); - currentSheet = workBook.createSheet(); - } - } - - private Workbook getWorkBook(File file) throws XlsParseException, IOException { - InputStream inputStream = new PushbackInputStream(new FileInputStream(file), 4096); - if (isXlsx(inputStream)) { - return new XSSFWorkbook(inputStream); - } else if (isExcel(inputStream)) { - return new HSSFWorkbook(inputStream); - } - throw new XlsParseException("Wrong document format"); - } - - /** - * Change active sheet to write or read data - * - * @param index index of sheet to activate - */ - public XlsDocumentBuilder setActiveSheet(int index) { - workBook.setActiveSheet(index); - currentSheet = workBook.getSheetAt(index); - return this; - } - - /** - * Create new sheet in document and set it active - * - * @param sheetName - */ - public XlsDocumentBuilder insertNewSheet(String sheetName) { - currentSheet = workBook.createSheet(sheetName); - workBook.setActiveSheet(getSheetCount() - 1); - return this; - } - - public XlsDocumentBuilder insertNewSheet(String sheetName, int order) { - insertNewSheet(sheetName); - workBook.setSheetOrder(sheetName, order); - return this; - } - - /** - * Returns number of sheet in document - * - * @return sheets count - */ - public int getSheetCount() { - return workBook.getNumberOfSheets(); - } - - /** - * Returns number of rows in sheet - * - * @return rows count - */ - public int getRowCount() { - return currentSheet.getLastRowNum(); - } - - /** - * Returns number of columns in sheet - * - * @return columns count - */ - public int getColumnCount() { - Row row = currentSheet.getRow(getRowCount()); - if (row == null) { - return 0; - } - return row.getLastCellNum() - 1; - } - - /** - * Returns converted to string representation of cell value - * - * @param rowIndex row index of current sheet - * @param colIndex column index of current sheet - * @return string value of cell - */ - public String getCellAsString(int rowIndex, int colIndex) { - Cell cell = currentSheet.getRow(rowIndex).getCell(colIndex); - cell.setCellType(Cell.CELL_TYPE_STRING); - return cell.getStringCellValue(); - } - - /** - * Sets string cell value - * - * @param rowIndex row index of current sheet - * @param colIndex column index of current sheet - */ - public XlsDocumentBuilder setCellValue(int rowIndex, int colIndex, String value) { - if (currentSheet.getRow(rowIndex) == null) { - currentSheet.createRow(rowIndex); - } - if (currentSheet.getRow(rowIndex).getCell(colIndex) == null) { - currentSheet.getRow(rowIndex).createCell(colIndex); - } - Cell cell = currentSheet.getRow(rowIndex).getCell(colIndex); - cell.setCellValue(value); - setColumnAutosize(colIndex, colIndex); - return this; - } - - public XlsDocumentBuilder setCellValue(int rowIndex, int colIndex, int value) { - return setCellValue(rowIndex, colIndex, String.valueOf(value)); - } - - public XlsDocumentBuilder setCellValue(int rowIndex, int colIndex, long value) { - return setCellValue(rowIndex, colIndex, String.valueOf(value)); - } - - /** - * Save current file - */ - public XlsDocumentBuilder save() throws IOException { - OutputStream out = new FileOutputStream(documentFile); - workBook.write(out); - return this; - } - - private boolean isExcel(InputStream i) throws IOException { - return (POIFSFileSystem.hasPOIFSHeader(i) || POIXMLDocument.hasOOXMLHeader(i)); - } - - private boolean isXlsx(InputStream i) throws IOException { - return POIXMLDocument.hasOOXMLHeader(i); - } - - public int getActiveSheetIndex() { - return workBook.getActiveSheetIndex(); - } - - public XlsDocumentBuilder mergeCells(int rowFrom, int rowTo, int colFrom, int colTo) { - currentSheet.addMergedRegion(new CellRangeAddress(rowFrom, rowTo, colFrom, colTo)); - return this; - } - - public void setRegionBorderWithMedium(int rowFrom, int rowTo, int colFrom, int colTo) { - for (int row = rowFrom; row < rowTo; row++) { - for (int col = colFrom; col <= colTo; col++) { - CellRangeAddress cellRangeAddress = new CellRangeAddress(row, row, col, col); - RegionUtil.setBorderBottom(CellStyle.BORDER_THIN, cellRangeAddress, currentSheet, workBook); - RegionUtil.setBorderLeft(CellStyle.BORDER_THIN, cellRangeAddress, currentSheet, workBook); - RegionUtil.setBorderRight(CellStyle.BORDER_THIN, cellRangeAddress, currentSheet, workBook); - RegionUtil.setBorderTop(CellStyle.BORDER_THIN, cellRangeAddress, currentSheet, workBook); - } - } - } - - public XlsDocumentBuilder setColumnAutosize(int from, int to) { - for (int col = from; col <= to; col++) { - currentSheet.autoSizeColumn(col, true); - } - return this; - } - - public XlsDocumentBuilder setRowAutosize(int from, int to) { - CellStyle style = workBook.createCellStyle(); - style.setWrapText(true); - for (int row = from; row <= to; row++) { - for (int col = 0; col <= currentSheet.getRow(row).getLastCellNum(); col++) { - if (currentSheet.getRow(row).getCell(col) != null) { - currentSheet.getRow(row).getCell(col).setCellStyle(style); - } - } - } - return this; - } - - public XlsDocumentBuilder deleteSheet(int index) { - workBook.removeSheetAt(index); - return this; - } -} diff --git a/src/main/java/ru/ulstu/project/controller/ProjectController.java b/src/main/java/ru/ulstu/project/controller/ProjectController.java new file mode 100644 index 0000000..3244ccb --- /dev/null +++ b/src/main/java/ru/ulstu/project/controller/ProjectController.java @@ -0,0 +1,49 @@ +package ru.ulstu.project.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import ru.ulstu.project.model.Project; +import ru.ulstu.project.model.ProjectDto; +import ru.ulstu.project.service.ProjectService; +import springfox.documentation.annotations.ApiIgnore; + +import java.util.List; + +@Controller() +@RequestMapping(value = "/projects") +@ApiIgnore +public class ProjectController { + private final ProjectService projectService; + + public ProjectController(ProjectService projectService) { + this.projectService = projectService; + } + + @GetMapping("/dashboard") + public void getDashboard(ModelMap modelMap) { + modelMap.put("projects", projectService.findAllDto()); + } + + @GetMapping("/projects") + public void getProjects(ModelMap modelMap) { + modelMap.put("projects", projectService.findAllDto()); + } + + @GetMapping("/project") + public void getProject(ModelMap modelMap, @RequestParam(value = "id") Integer id) { + if (id != null && id > 0) { + modelMap.put("projectDto", projectService.findOneDto(id)); + } else { + modelMap.put("projectDto", new ProjectDto()); + } + } + + @ModelAttribute("allStatuses") + public List getProjectStatuses() { + return projectService.getProjectStatuses(); + } +} diff --git a/src/main/java/ru/ulstu/project/model/Project.java b/src/main/java/ru/ulstu/project/model/Project.java index 06722a1..2e0e86c 100644 --- a/src/main/java/ru/ulstu/project/model/Project.java +++ b/src/main/java/ru/ulstu/project/model/Project.java @@ -3,24 +3,60 @@ package ru.ulstu.project.model; import org.hibernate.validator.constraints.NotBlank; import ru.ulstu.core.model.BaseEntity; import ru.ulstu.deadline.model.Deadline; +import ru.ulstu.grant.model.Grant; import javax.persistence.CascadeType; import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.OneToMany; +import javax.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; @Entity public class Project extends BaseEntity { + public enum ProjectStatus { + APPLICATION("Заявка"), + ON_COMPETITION("Отправлен на конкурс"), + SUCCESSFUL_PASSAGE("Успешное прохождение"), + IN_WORK("В работе"), + COMPLETED("Завершен"), + FAILED("Провалены сроки"); + + private String statusName; + + ProjectStatus(String statusName) { + this.statusName = statusName; + } + + public String getStatusName() { + return statusName; + } + } @NotBlank private String title; + @Enumerated(value = EnumType.STRING) + private ProjectStatus status = ProjectStatus.APPLICATION; + + @NotNull + private String description; + @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "project_id") private List deadlines = new ArrayList<>(); + @ManyToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "grant_id") + private Grant grant; + + @NotNull + private String repository; + public String getTitle() { return title; } @@ -29,6 +65,38 @@ public class Project extends BaseEntity { this.title = title; } + public ProjectStatus getStatus() { + return status; + } + + public void setStatus(ProjectStatus status) { + this.status = status; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Grant getGrant() { + return grant; + } + + public void setGrant(Grant grant) { + this.grant = grant; + } + + public String getRepository() { + return repository; + } + + public void setRepository(String repository) { + this.repository = repository; + } + public List getDeadlines() { return deadlines; } diff --git a/src/main/java/ru/ulstu/project/model/ProjectDto.java b/src/main/java/ru/ulstu/project/model/ProjectDto.java index db7fc75..6c83d59 100644 --- a/src/main/java/ru/ulstu/project/model/ProjectDto.java +++ b/src/main/java/ru/ulstu/project/model/ProjectDto.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.hibernate.validator.constraints.NotEmpty; import ru.ulstu.deadline.model.Deadline; +import ru.ulstu.grant.model.GrantDto; import java.util.ArrayList; import java.util.List; @@ -13,8 +14,11 @@ public class ProjectDto { @NotEmpty private String title; - + private Project.ProjectStatus status; + private String description; private List deadlines = new ArrayList<>(); + private GrantDto grant; + private String repository; public ProjectDto() { } @@ -26,9 +30,17 @@ public class ProjectDto { @JsonCreator public ProjectDto(@JsonProperty("id") Integer id, @JsonProperty("title") String title, + @JsonProperty("status") Project.ProjectStatus status, + @JsonProperty("description") String description, + @JsonProperty("grant") GrantDto grant, + @JsonProperty("repository") String repository, @JsonProperty("deadlines") List deadlines) { this.id = id; this.title = title; + this.status = status; + this.description = description; + this.grant = grant; + this.repository = repository; this.deadlines = deadlines; } @@ -36,6 +48,10 @@ public class ProjectDto { public ProjectDto(Project project) { this.id = project.getId(); this.title = project.getTitle(); + this.status = project.getStatus(); + this.description = project.getDescription(); + this.grant = project.getGrant() == null ? null : new GrantDto(project.getGrant()); + this.repository = project.getRepository(); this.deadlines = project.getDeadlines(); } @@ -55,6 +71,38 @@ public class ProjectDto { this.title = title; } + public Project.ProjectStatus getStatus() { + return status; + } + + public void setStatus(Project.ProjectStatus status) { + this.status = status; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public GrantDto getGrant() { + return grant; + } + + public void setGrant(GrantDto grant) { + this.grant = grant; + } + + public String getRepository() { + return repository; + } + + public void setRepository(String repository) { + this.repository = repository; + } + public List getDeadlines() { return deadlines; } diff --git a/src/main/java/ru/ulstu/project/service/ProjectService.java b/src/main/java/ru/ulstu/project/service/ProjectService.java index b54a60a..99d8919 100644 --- a/src/main/java/ru/ulstu/project/service/ProjectService.java +++ b/src/main/java/ru/ulstu/project/service/ProjectService.java @@ -2,17 +2,21 @@ package ru.ulstu.project.service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.thymeleaf.util.StringUtils; import ru.ulstu.deadline.service.DeadlineService; import ru.ulstu.project.model.Project; import ru.ulstu.project.model.ProjectDto; import ru.ulstu.project.repository.ProjectRepository; +import java.util.Arrays; import java.util.List; import static org.springframework.util.ObjectUtils.isEmpty; +import static ru.ulstu.core.util.StreamApiUtils.convert; @Service public class ProjectService { + private final static int MAX_DISPLAY_SIZE = 40; private final ProjectRepository projectRepository; private final DeadlineService deadlineService; @@ -27,6 +31,20 @@ public class ProjectService { return projectRepository.findAll(); } + public List findAllDto() { + List projects = convert(findAll(), ProjectDto::new); + projects.forEach(projectDto -> projectDto.setTitle(StringUtils.abbreviate(projectDto.getTitle(), MAX_DISPLAY_SIZE))); + return projects; + } + + public ProjectDto findOneDto(Integer id) { + return new ProjectDto(projectRepository.findOne(id)); + } + + public List getProjectStatuses() { + return Arrays.asList(Project.ProjectStatus.values()); + } + @Transactional public Project create(ProjectDto projectDto) { Project newProject = copyFromDto(new Project(), projectDto); diff --git a/src/main/resources/db/changelog-20190418_000000-schema.xml b/src/main/resources/db/changelog-20190418_000000-schema.xml new file mode 100644 index 0000000..31cf21c --- /dev/null +++ b/src/main/resources/db/changelog-20190418_000000-schema.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index 47ab806..7c3ac6d 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -24,6 +24,7 @@ + diff --git a/src/main/resources/drivers/chromedriver b/src/main/resources/drivers/chromedriver new file mode 100644 index 0000000..02ff671 Binary files /dev/null and b/src/main/resources/drivers/chromedriver differ diff --git a/src/main/resources/drivers/chromedriver.exe b/src/main/resources/drivers/chromedriver.exe new file mode 100644 index 0000000..28a4067 Binary files /dev/null and b/src/main/resources/drivers/chromedriver.exe differ diff --git a/src/main/resources/drivers/geckodriver b/src/main/resources/drivers/geckodriver new file mode 100644 index 0000000..ba1da8c Binary files /dev/null and b/src/main/resources/drivers/geckodriver differ diff --git a/src/main/resources/drivers/geckodriver.exe b/src/main/resources/drivers/geckodriver.exe new file mode 100644 index 0000000..6208aa8 Binary files /dev/null and b/src/main/resources/drivers/geckodriver.exe differ diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 827df08..6bb134e 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -40,7 +40,7 @@
- +
diff --git a/src/main/resources/templates/projects/dashboard.html b/src/main/resources/templates/projects/dashboard.html new file mode 100644 index 0000000..882c202 --- /dev/null +++ b/src/main/resources/templates/projects/dashboard.html @@ -0,0 +1,24 @@ + + + + + +
+
+
+
+

Проекты

+
+
+
+ +
+ +
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/projects/fragments/projectLineFragment.html b/src/main/resources/templates/projects/fragments/projectLineFragment.html new file mode 100644 index 0000000..3605273 --- /dev/null +++ b/src/main/resources/templates/projects/fragments/projectLineFragment.html @@ -0,0 +1,18 @@ + + + + + + +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/projects/fragments/projectNavigationFragment.html b/src/main/resources/templates/projects/fragments/projectNavigationFragment.html new file mode 100644 index 0000000..75dfff6 --- /dev/null +++ b/src/main/resources/templates/projects/fragments/projectNavigationFragment.html @@ -0,0 +1,26 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/projects/fragments/projectStatusFragment.html b/src/main/resources/templates/projects/fragments/projectStatusFragment.html new file mode 100644 index 0000000..e5da374 --- /dev/null +++ b/src/main/resources/templates/projects/fragments/projectStatusFragment.html @@ -0,0 +1,31 @@ + + + + + + + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/projects/project.html b/src/main/resources/templates/projects/project.html new file mode 100644 index 0000000..3d356a7 --- /dev/null +++ b/src/main/resources/templates/projects/project.html @@ -0,0 +1,141 @@ + + + + + + + +
+ +
+
+
+
+

Редактирование проекта

+
+
+
+
+
+
+
+
+ +
+ + +

Incorrect title

+

+
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ +
+ +
+ + +

Incorrect repository link

+

+
+ +
+ +
+ +
+ +
+
+ +
+
+ + +
+
+

Incorrect title

+
+
+ +
+ +
+ +
+ +
+
+
+ +
+
+
+ + +
+
+
+ +
+
+
+
+ + +
+ + diff --git a/src/main/resources/templates/projects/projects.html b/src/main/resources/templates/projects/projects.html new file mode 100644 index 0000000..fd19383 --- /dev/null +++ b/src/main/resources/templates/projects/projects.html @@ -0,0 +1,33 @@ + + + + + +
+
+ +
+
+
+
+

Проекты

+
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+ + diff --git a/src/test/java/IndexPageTest.java b/src/test/java/IndexPageTest.java new file mode 100644 index 0000000..1817240 --- /dev/null +++ b/src/test/java/IndexPageTest.java @@ -0,0 +1,52 @@ +import com.google.common.collect.ImmutableMap; +import core.PageObject; +import core.TestTemplate; +import org.assertj.core.api.Assertions; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import paper.PaperPage; +import paper.PapersDashboardPage; +import paper.PapersPage; +import ru.ulstu.NgTrackerApplication; +import ru.ulstu.configuration.ApplicationProperties; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = NgTrackerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +public class IndexPageTest extends TestTemplate { + private final Map> navigationHolder = ImmutableMap.of( + new PapersPage(), Arrays.asList("СТАТЬИ", "/papers/papers"), + new PaperPage(), Arrays.asList("РЕДАКТИРОВАНИЕ СТАТЬИ", "/papers/paper?id=0"), + new PapersDashboardPage(), Arrays.asList("СТАТЬИ", "/papers/dashboard") + ); + + @Autowired + private ApplicationProperties applicationProperties; + + @Test + public void testStartApplication() { + getContext().goTo(applicationProperties.getBaseUrl()); + Assertions + .assertThat(getContext().getTitle()) + .isEqualTo("NG-Tracker"); + } + + @Test + public void testModulesNavigation() { + navigationHolder.entrySet() + .stream() + .forEach(navigationEntry -> { + getContext().goTo(applicationProperties.getBaseUrl() + navigationEntry.getValue().get(1)); + PageObject pageObject = getContext().initPage(navigationEntry.getKey()); + Assertions + .assertThat(pageObject.getSubTitle()) + .isEqualToIgnoringCase(navigationEntry.getValue().get(0)); + }); + } +} diff --git a/src/test/java/context/ChromeContext.java b/src/test/java/context/ChromeContext.java new file mode 100644 index 0000000..899d51d --- /dev/null +++ b/src/test/java/context/ChromeContext.java @@ -0,0 +1,27 @@ +package context; + +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; + +public class ChromeContext extends Context { + private final static String WINDOWS_DRIVER = "chromedriver.exe"; + private final static String LINUX_DRIVER = "chromedriver"; + private final static String DRIVER_TYPE = "webdriver.chrome.driver"; + + @Override + protected void createDriver() { + final ChromeOptions chromeOptions = new ChromeOptions(); + chromeOptions.addArguments("--headless"); + driver = new ChromeDriver(chromeOptions); + } + + @Override + protected String getDriverExecutable(boolean isWindows) { + return isWindows ? WINDOWS_DRIVER : LINUX_DRIVER; + } + + @Override + protected String getDriverType() { + return DRIVER_TYPE; + } +} diff --git a/src/test/java/context/Context.java b/src/test/java/context/Context.java new file mode 100644 index 0000000..b32c08e --- /dev/null +++ b/src/test/java/context/Context.java @@ -0,0 +1,67 @@ +package context; + +import core.PageObject; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.WebDriver; + +import java.util.concurrent.TimeUnit; + +//import org.openqa.selenium.support.PageFactory; + +public abstract class Context { + private final static String DRIVER_LOCATION = "drivers/%s"; + + protected WebDriver driver; + + protected WebDriver getDriver() { + if (driver != null) { + return driver; + } + throw new IllegalStateException("WebDriver is not initialized"); + } + + public void start() { + System.setProperty(getDriverType(), getDriverExecutablePath()); + + createDriver(); + // это плохая инструкция для автотестов, т.к. лучше задавать для конкретного элемента или кейса + getDriver().manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); + } + + public void close() { + if (driver != null) { + driver.quit(); + } + } + + public void goTo(String url) { + getDriver().get(url); + } + + public String getTitle() { + return getDriver().getTitle(); + } + + public T initPage(T pageObject) { + return (T) pageObject.setDriver(getDriver()); + } + + protected abstract void createDriver(); + + protected abstract String getDriverType(); + + protected abstract String getDriverExecutable(boolean windows); + + private String getDriverExecutablePath() { + return Context.class.getClassLoader().getResource( + String.format(DRIVER_LOCATION, getDriverExecutable(isWindows()))).getFile(); + } + + private boolean isWindows() { + return System.getProperty("os.name").toLowerCase().contains("windows"); + } + + public void setSize(Dimension dimension) { + driver.manage().window().setSize(dimension); + } +} diff --git a/src/test/java/context/FirefoxContext.java b/src/test/java/context/FirefoxContext.java new file mode 100644 index 0000000..1d5c163 --- /dev/null +++ b/src/test/java/context/FirefoxContext.java @@ -0,0 +1,24 @@ +package context; + +import org.openqa.selenium.firefox.FirefoxDriver; + +public class FirefoxContext extends Context { + private final static String WINDOWS_DRIVER = "geckodriver.exe"; + private final static String LINUX_DRIVER = "geckodriver"; + private final static String DRIVER_TYPE = "webdriver.gecko.driver"; + + @Override + protected void createDriver() { + driver = new FirefoxDriver(); + } + + @Override + protected String getDriverExecutable(boolean isWindows) { + return isWindows ? WINDOWS_DRIVER : LINUX_DRIVER; + } + + @Override + protected String getDriverType() { + return DRIVER_TYPE; + } +} diff --git a/src/test/java/core/PageObject.java b/src/test/java/core/PageObject.java new file mode 100644 index 0000000..d1fae83 --- /dev/null +++ b/src/test/java/core/PageObject.java @@ -0,0 +1,14 @@ +package core; + +import org.openqa.selenium.WebDriver; + +public abstract class PageObject { + protected WebDriver driver; + + public abstract String getSubTitle(); + + public PageObject setDriver(WebDriver driver) { + this.driver = driver; + return this; + } +} diff --git a/src/test/java/core/TestTemplate.java b/src/test/java/core/TestTemplate.java new file mode 100644 index 0000000..a72a8c9 --- /dev/null +++ b/src/test/java/core/TestTemplate.java @@ -0,0 +1,29 @@ +package core; + +import context.ChromeContext; +import context.Context; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.openqa.selenium.Dimension; + +public abstract class TestTemplate { + private static Context context; + + public static Context getContext() { + return context; + } + + @BeforeClass + public static void setup() { + context = new ChromeContext(); + context.start(); + context.setSize(new Dimension(1600, 900)); + } + + @AfterClass + public static void quit() { + if (context != null) { + context.close(); + } + } +} diff --git a/src/test/java/paper/PaperPage.java b/src/test/java/paper/PaperPage.java new file mode 100644 index 0000000..9c3c357 --- /dev/null +++ b/src/test/java/paper/PaperPage.java @@ -0,0 +1,11 @@ +package paper; + +import core.PageObject; +import org.openqa.selenium.By; + +public class PaperPage extends PageObject { + + public String getSubTitle() { + return driver.findElement(By.tagName("h2")).getText(); + } +} diff --git a/src/test/java/paper/PapersDashboardPage.java b/src/test/java/paper/PapersDashboardPage.java new file mode 100644 index 0000000..51d7cb8 --- /dev/null +++ b/src/test/java/paper/PapersDashboardPage.java @@ -0,0 +1,11 @@ +package paper; + +import core.PageObject; +import org.openqa.selenium.By; + +public class PapersDashboardPage extends PageObject { + + public String getSubTitle() { + return driver.findElement(By.tagName("h2")).getText(); + } +} diff --git a/src/test/java/paper/PapersPage.java b/src/test/java/paper/PapersPage.java new file mode 100644 index 0000000..f191d9b --- /dev/null +++ b/src/test/java/paper/PapersPage.java @@ -0,0 +1,11 @@ +package paper; + +import core.PageObject; +import org.openqa.selenium.By; + +public class PapersPage extends PageObject { + + public String getSubTitle() { + return driver.findElement(By.tagName("h2")).getText(); + } +}