diff --git a/Backend/mapping/build.gradle b/Backend/mapping/build.gradle index 83ea218..0711309 100644 --- a/Backend/mapping/build.gradle +++ b/Backend/mapping/build.gradle @@ -1,6 +1,7 @@ buildscript { ext { springBootVersion = '2.0.5.RELEASE' + mapstructVersion = "1.5.5.Final" } repositories { mavenCentral() @@ -23,8 +24,22 @@ repositories { mavenCentral() } - dependencies { + implementation "org.mapstruct:mapstruct:${mapstructVersion}" + implementation "io.springfox:springfox-swagger2:2.7.0" + implementation "io.springfox:springfox-swagger-ui:2.7.0" + testImplementation "org.testng:testng:6.10", "org.easytesting:fest-assert:1.4", "org.assertj:assertj-core:3.24.2" + annotationProcessor "org.mapstruct:mapstruct-processor:1.5.5.Final" compile('org.springframework.boot:spring-boot-starter-web') testCompile('org.springframework.boot:spring-boot-starter-test') } + +tasks.withType(JavaCompile) { + options.compilerArgs = [ + '-Amapstruct.suppressGeneratorTimestamp=true' + ] +} + +test { + useTestNG() +} \ No newline at end of file diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/Application.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/Application.java index 871507a..0caf2c1 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/Application.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/Application.java @@ -2,11 +2,27 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; @SpringBootApplication +@EnableSwagger2 //http://localhost:8080/swagger-ui.html public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } + + @Bean + public Docket mappingApi() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build(); + } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/ArticleMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/ArticleMapper.java deleted file mode 100644 index 687e1fc..0000000 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/ArticleMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.staffinghub.coding.challenges.mapping.mappers; - -import com.staffinghub.coding.challenges.mapping.models.db.Article; -import com.staffinghub.coding.challenges.mapping.models.dto.ArticleDto; -import org.springframework.stereotype.Component; - -@Component -public class ArticleMapper { - - public ArticleDto map(Article article){ - //TODO - return new ArticleDto(); - } - - public Article map(ArticleDto articleDto) { - // Nicht Teil dieser Challenge. - return new Article(); - } -} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/IArticleMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/IArticleMapper.java new file mode 100644 index 0000000..2243e59 --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/IArticleMapper.java @@ -0,0 +1,75 @@ +package com.staffinghub.coding.challenges.mapping.mappers; + +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMappableBlock; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMappableBlockDto; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.MasterMapper; +import com.staffinghub.coding.challenges.mapping.models.db.Article; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.ArticleBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.ArticleDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.*; +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +@Mapper(componentModel = "spring") +public abstract class IArticleMapper { + + @Autowired + protected MasterMapper masterMapper; + + @Mapping(target="blocks", expression = "java(getArticleBlocks(dto.getBlocks()))") + @Mapping(target = "lastModified", ignore = true) + @Mapping(target = "lastModifiedBy", ignore = true) + public abstract Article toArticle(ArticleDto dto); + + @InheritInverseConfiguration + @Mapping(target="blocks", expression = "java(getArticleBlocksDto(article.getBlocks()))") + public abstract ArticleDto toArticleDto(Article article); + + @Named("getArticleBlocks") + protected Set getArticleBlocks(Collection articleBlockDtos) { + return articleBlockDtos + .stream() + .map(block -> { + if (Objects.isNull(block)) { + return null; + } + + if (block instanceof IMappableBlock) { + return block.map(masterMapper); + } + + // TODO: Add exception handler to mitigate the need to use a try catch. + throw new UnsupportedOperationException(String.format("Failed to map %s as it's not implementing Mappable Article Dto Block", block.getClass())); + }) + .collect(Collectors.toSet()); + } + + @Named("getArticleBlocksDto") + protected Collection getArticleBlocksDto(Set article) { + return article + .stream() + .map(block -> { + if (Objects.isNull(block)) { + return null; + } + + if (block instanceof IMappableBlockDto) { + return block.map(masterMapper); + } + + // TODO: Add exception handler to mitigate the need to use a try catch. + throw new UnsupportedOperationException(String.format("Failed to map %s as it's not implementing Mappable Article Block", block.getClass())); + }) + .sorted(Comparator.comparingLong(articleBlock -> articleBlock.getSortIndex())) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMainArticleBlockDtoMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMainArticleBlockDtoMapper.java new file mode 100644 index 0000000..282fd37 --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMainArticleBlockDtoMapper.java @@ -0,0 +1,17 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks; + +import com.staffinghub.coding.challenges.mapping.models.db.blocks.*; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.*; + +public interface IMainArticleBlockDtoMapper { + + ArticleBlockDto map(ArticleBlock entity); + + GalleryBlockDto map(GalleryBlock entity); + + ImageBlockDto map(ImageBlock entity); + + TextBlockDto map(TextBlock entity); + + VideoBlockDto map(VideoBlock entity); +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMainArticleBlockMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMainArticleBlockMapper.java new file mode 100644 index 0000000..97b5797 --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMainArticleBlockMapper.java @@ -0,0 +1,17 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks; + +import com.staffinghub.coding.challenges.mapping.models.db.blocks.*; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.*; + +public interface IMainArticleBlockMapper { + + ArticleBlock map(ArticleBlockDto entity); + + GalleryBlock map(GalleryBlockDto entity); + + ImageBlock map(ImageBlockDto entity); + + TextBlock map(TextBlockDto entity); + + VideoBlock map(VideoBlockDto entity); +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMappableBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMappableBlock.java new file mode 100644 index 0000000..4388fbc --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMappableBlock.java @@ -0,0 +1,7 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks; + +import com.staffinghub.coding.challenges.mapping.models.db.blocks.ArticleBlock; + +public interface IMappableBlock { + ArticleBlock map(IMainArticleBlockMapper mapper); +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMappableBlockDto.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMappableBlockDto.java new file mode 100644 index 0000000..446f6f6 --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/IMappableBlockDto.java @@ -0,0 +1,7 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks; + +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.ArticleBlockDto; + +public interface IMappableBlockDto { + ArticleBlockDto map(IMainArticleBlockDtoMapper mapper); +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/MasterMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/MasterMapper.java new file mode 100644 index 0000000..4f56c4a --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/MasterMapper.java @@ -0,0 +1,80 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks; + +import com.staffinghub.coding.challenges.mapping.mappers.IArticleMapper; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers.*; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.*; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MasterMapper implements IMainArticleBlockDtoMapper, IMainArticleBlockMapper { + + @Autowired + private IGalleryBlockMapper galleryBlockMapper; + + @Autowired + private IImageBlockMapper imageBlockMapper; + + @Autowired + private ITextBlockMapper textBlockMapper; + + @Autowired + private IVideoBlockMapper videoBlockMapper; + + // + + @Override + public ArticleBlockDto map(ArticleBlock entity) { + return null; + } + + @Override + public GalleryBlockDto map(GalleryBlock entity) { + return galleryBlockMapper.toGalleryBlockDto(entity); + } + + @Override + public ImageBlockDto map(ImageBlock entity) { + return imageBlockMapper.toImageBlockDto(entity); + } + + @Override + public TextBlockDto map(TextBlock entity) { + return textBlockMapper.toTextBlockDto(entity); + } + + @Override + public VideoBlockDto map(VideoBlock entity) { + return videoBlockMapper.toVideoBlockDto(entity); + } + // + + // + + @Override + public ArticleBlock map(ArticleBlockDto entity) { + return null; + } + + @Override + public GalleryBlock map(GalleryBlockDto entity) { + return galleryBlockMapper.toGalleryBlock(entity); + } + + @Override + public ImageBlock map(ImageBlockDto entity) { + return imageBlockMapper.toImageBlock(entity); + } + + @Override + public TextBlock map(TextBlockDto entity) { + return textBlockMapper.toTextBlock(entity); + } + + @Override + public VideoBlock map(VideoBlockDto entity) { + return videoBlockMapper.toVideoBlock(entity); + } + // +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IGalleryBlockMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IGalleryBlockMapper.java new file mode 100644 index 0000000..4688d08 --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IGalleryBlockMapper.java @@ -0,0 +1,13 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers; + +import com.staffinghub.coding.challenges.mapping.models.db.blocks.GalleryBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.GalleryBlockDto; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface IGalleryBlockMapper { + + GalleryBlock toGalleryBlock(GalleryBlockDto galleryBlockDto); + + GalleryBlockDto toGalleryBlockDto(GalleryBlock galleryBlock); +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IImageBlockMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IImageBlockMapper.java new file mode 100644 index 0000000..70603cf --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IImageBlockMapper.java @@ -0,0 +1,13 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers; + +import com.staffinghub.coding.challenges.mapping.models.db.blocks.ImageBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.ImageBlockDto; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface IImageBlockMapper { + + ImageBlock toImageBlock(ImageBlockDto imageBlockDto); + + ImageBlockDto toImageBlockDto(ImageBlock imageBlock); +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/ITextBlockMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/ITextBlockMapper.java new file mode 100644 index 0000000..ca20b65 --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/ITextBlockMapper.java @@ -0,0 +1,13 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers; + +import com.staffinghub.coding.challenges.mapping.models.db.blocks.TextBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.TextBlockDto; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface ITextBlockMapper { + + TextBlock toTextBlock(TextBlockDto textBlockDto); + + TextBlockDto toTextBlockDto(TextBlock textBlock); +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IVideoBlockMapper.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IVideoBlockMapper.java new file mode 100644 index 0000000..9d4c57a --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/mappers/blocks/mappers/IVideoBlockMapper.java @@ -0,0 +1,13 @@ +package com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers; + +import com.staffinghub.coding.challenges.mapping.models.db.blocks.VideoBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.VideoBlockDto; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface IVideoBlockMapper { + + VideoBlock toVideoBlock(VideoBlockDto videoBlockDto); + + VideoBlockDto toVideoBlockDto(VideoBlock videoBlock); +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/ArticleBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/ArticleBlock.java index bfae022..ee9170a 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/ArticleBlock.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/ArticleBlock.java @@ -1,6 +1,10 @@ package com.staffinghub.coding.challenges.mapping.models.db.blocks; -public abstract class ArticleBlock { +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockDtoMapper; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMappableBlockDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.ArticleBlockDto; + +public abstract class ArticleBlock implements IMappableBlockDto { private int sortIndex; @@ -11,4 +15,8 @@ public int getSortIndex() { public void setSortIndex(int sortIndex) { this.sortIndex = sortIndex; } + + public ArticleBlockDto map(IMainArticleBlockDtoMapper mapper) { + return mapper.map(this); + } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/GalleryBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/GalleryBlock.java index 4c8c94c..ac566ad 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/GalleryBlock.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/GalleryBlock.java @@ -1,6 +1,8 @@ package com.staffinghub.coding.challenges.mapping.models.db.blocks; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockDtoMapper; import com.staffinghub.coding.challenges.mapping.models.db.Image; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.GalleryBlockDto; import java.util.List; @@ -15,4 +17,8 @@ public List getImages() { public void setImages(List images) { this.images = images; } + + public GalleryBlockDto map(IMainArticleBlockDtoMapper mapper) { + return mapper.map(this); + } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/ImageBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/ImageBlock.java index 00f536f..7500c20 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/ImageBlock.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/ImageBlock.java @@ -1,6 +1,8 @@ package com.staffinghub.coding.challenges.mapping.models.db.blocks; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockDtoMapper; import com.staffinghub.coding.challenges.mapping.models.db.Image; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.ImageBlockDto; public class ImageBlock extends ArticleBlock { @@ -13,4 +15,8 @@ public Image getImage() { public void setImage(Image image) { this.image = image; } + + public ImageBlockDto map(IMainArticleBlockDtoMapper mapper) { + return mapper.map(this); + } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/TextBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/TextBlock.java index ae60f69..2bac110 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/TextBlock.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/TextBlock.java @@ -1,5 +1,8 @@ package com.staffinghub.coding.challenges.mapping.models.db.blocks; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockDtoMapper; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.TextBlockDto; + public class TextBlock extends ArticleBlock { private String text; @@ -11,4 +14,8 @@ public String getText() { public void setText(String text) { this.text = text; } + + public TextBlockDto map(IMainArticleBlockDtoMapper mapper) { + return mapper.map(this); + } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/VideoBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/VideoBlock.java index 97236f0..9e84918 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/VideoBlock.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/db/blocks/VideoBlock.java @@ -1,5 +1,8 @@ package com.staffinghub.coding.challenges.mapping.models.db.blocks; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockDtoMapper; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.VideoBlockDto; + public class VideoBlock extends ArticleBlock { private String url; @@ -21,4 +24,8 @@ public VideoBlockType getType() { public void setType(VideoBlockType type) { this.type = type; } + + public VideoBlockDto map(IMainArticleBlockDtoMapper mapper) { + return mapper.map(this); + } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ArticleBlockDto.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ArticleBlockDto.java index 0c12a92..d8758e2 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ArticleBlockDto.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ArticleBlockDto.java @@ -1,6 +1,10 @@ package com.staffinghub.coding.challenges.mapping.models.dto.blocks; -public class ArticleBlockDto { +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockMapper; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMappableBlock; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.ArticleBlock; + +public class ArticleBlockDto implements IMappableBlock { private int sortIndex; public int getSortIndex() { @@ -10,4 +14,9 @@ public int getSortIndex() { public void setSortIndex(int sortIndex) { this.sortIndex = sortIndex; } -} + + @Override + public ArticleBlock map(IMainArticleBlockMapper mapper) { + return mapper.map(this); + } +} \ No newline at end of file diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/GalleryBlockDto.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/GalleryBlockDto.java index 0dccf49..c810768 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/GalleryBlockDto.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/GalleryBlockDto.java @@ -1,5 +1,7 @@ package com.staffinghub.coding.challenges.mapping.models.dto.blocks; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockMapper; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.GalleryBlock; import com.staffinghub.coding.challenges.mapping.models.dto.ImageDto; import java.util.List; @@ -15,4 +17,9 @@ public List getImages() { public void setImages(List images) { this.images = images; } + + @Override + public GalleryBlock map(IMainArticleBlockMapper mapper) { + return mapper.map(this); + } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ImageBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ImageBlock.java deleted file mode 100644 index ab844b6..0000000 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ImageBlock.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.staffinghub.coding.challenges.mapping.models.dto.blocks; - -import com.staffinghub.coding.challenges.mapping.models.dto.ImageDto; - -public class ImageBlock extends ArticleBlockDto { - - private ImageDto image; - - public ImageDto getImage() { - return image; - } - - public void setImage(ImageDto image) { - this.image = image; - } -} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ImageBlockDto.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ImageBlockDto.java new file mode 100644 index 0000000..16b082a --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/ImageBlockDto.java @@ -0,0 +1,23 @@ +package com.staffinghub.coding.challenges.mapping.models.dto.blocks; + +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockMapper; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.ImageBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.ImageDto; + +public class ImageBlockDto extends ArticleBlockDto { + + private ImageDto image; + + public ImageDto getImage() { + return image; + } + + public void setImage(ImageDto image) { + this.image = image; + } + + @Override + public ImageBlock map(IMainArticleBlockMapper mapper) { + return mapper.map(this); + } +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/TextBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/TextBlock.java deleted file mode 100644 index 75535f4..0000000 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/TextBlock.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.staffinghub.coding.challenges.mapping.models.dto.blocks; - -public class TextBlock extends ArticleBlockDto { - - private String text; - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } -} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/TextBlockDto.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/TextBlockDto.java new file mode 100644 index 0000000..49d9a78 --- /dev/null +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/TextBlockDto.java @@ -0,0 +1,22 @@ +package com.staffinghub.coding.challenges.mapping.models.dto.blocks; + +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockMapper; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.TextBlock; + +public class TextBlockDto extends ArticleBlockDto { + + private String text; + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + @Override + public TextBlock map(IMainArticleBlockMapper mapper) { + return mapper.map(this); + } +} diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/VideoBlock.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/VideoBlockDto.java similarity index 59% rename from Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/VideoBlock.java rename to Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/VideoBlockDto.java index 8a5ce1f..c240b7f 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/VideoBlock.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/models/dto/blocks/VideoBlockDto.java @@ -1,8 +1,10 @@ package com.staffinghub.coding.challenges.mapping.models.dto.blocks; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.IMainArticleBlockMapper; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.VideoBlock; import com.staffinghub.coding.challenges.mapping.models.db.blocks.VideoBlockType; -public class VideoBlock extends ArticleBlockDto { +public class VideoBlockDto extends ArticleBlockDto { private String url; @@ -23,4 +25,9 @@ public VideoBlockType getType() { public void setType(VideoBlockType type) { this.type = type; } + + @Override + public VideoBlock map(IMainArticleBlockMapper mapper) { + return mapper.map(this); + } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/repositories/ArticleRepository.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/repositories/ArticleRepository.java index aa53c71..1f3d46a 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/repositories/ArticleRepository.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/repositories/ArticleRepository.java @@ -91,6 +91,6 @@ private Image createImage(Long imageId){ result.setLastModifiedBy("Max Mustermann"); result.setImageSize(ImageSize.LARGE); result.setUrl("https://someurl.com/image/" + imageId); - return null; + return result; } } diff --git a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/services/ArticleService.java b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/services/ArticleService.java index 4f2b17d..4ee394d 100644 --- a/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/services/ArticleService.java +++ b/Backend/mapping/src/main/java/com/staffinghub/coding/challenges/mapping/services/ArticleService.java @@ -1,43 +1,60 @@ package com.staffinghub.coding.challenges.mapping.services; -import com.staffinghub.coding.challenges.mapping.mappers.ArticleMapper; +import com.staffinghub.coding.challenges.mapping.mappers.IArticleMapper; import com.staffinghub.coding.challenges.mapping.models.db.Article; import com.staffinghub.coding.challenges.mapping.models.dto.ArticleDto; import com.staffinghub.coding.challenges.mapping.repositories.ArticleRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; +import org.springframework.web.server.ResponseStatusException; -import java.util.ArrayList; +import javax.swing.text.html.Option; +import java.util.Comparator; import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; @Service public class ArticleService { private final ArticleRepository repository; - private final ArticleMapper mapper; + private final IArticleMapper mapper; @Autowired - public ArticleService(ArticleRepository repository, ArticleMapper mapper) { + public ArticleService(ArticleRepository repository, IArticleMapper mapper) { this.repository = repository; this.mapper = mapper; } public List list() { - final List
articles = repository.all(); - //TODO - return new ArrayList<>(); + return repository + .all() + .stream() + .map(mapper::toArticleDto) + .collect(Collectors.toList()); } public ArticleDto articleForId(Long id) { - final Article article = repository.findBy(id); - //TODO - return new ArticleDto(); + // This isn't a good solution, ideally connecting to a database allows us to query for a single entity. + Optional
article = repository + .all() + .stream() + .filter(x -> x.getId().equals(id)) + .findFirst(); + + if (!article.isPresent()) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Entity not found."); + } + + return mapper.toArticleDto(article.get()); } public ArticleDto create(ArticleDto articleDto) { - final Article create = mapper.map(articleDto); + final Article create = mapper.toArticle(articleDto); repository.create(create); - return mapper.map(create); + return mapper.toArticleDto(create); } } diff --git a/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/ArticleMapperUnitTests.java b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/ArticleMapperUnitTests.java new file mode 100644 index 0000000..1591624 --- /dev/null +++ b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/ArticleMapperUnitTests.java @@ -0,0 +1,159 @@ +package com.staffinghub.coding.challenges.mapping.mappers; + +import com.staffinghub.coding.challenges.mapping.ApplicationTests; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.MasterMapper; +import com.staffinghub.coding.challenges.mapping.models.db.Article; +import com.staffinghub.coding.challenges.mapping.models.db.Image; +import com.staffinghub.coding.challenges.mapping.models.db.ImageSize; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.*; +import com.staffinghub.coding.challenges.mapping.models.dto.ArticleDto; +import com.staffinghub.coding.challenges.mapping.models.dto.ImageDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.*; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ArticleMapperUnitTests extends ApplicationTests { + + @Autowired + private IArticleMapper articleMapper; + + @Autowired + private MasterMapper masterMapper; + + @Test + public void toArticleDto() { + final Article article = getArticle(); + + ArticleDto resultingDto = articleMapper.toArticleDto(article); + + assertThat(resultingDto) + .usingRecursiveComparison() + .isEqualTo(getArticleDto()); + } + + @Test + public void toArticle() { + final ArticleDto articleDto = getArticleDto(); + + Article resulting = articleMapper.toArticle(articleDto); + + Article expectedArticle = getArticle(); + + assertThat(resulting) + .usingRecursiveComparison() + .ignoringFields("lastModifiedBy", "lastModified", "blocks") + .isEqualTo(expectedArticle); + } + + /** + * Creates a dummy article dto object to be used for testing. + * + * @return {@link ArticleDto} + */ + private static ArticleDto getArticleDto() { + Long id = 1001L; + final ArticleDto articleDto = new ArticleDto(); + articleDto.setId(id); + articleDto.setAuthor("Max Mustermann"); + articleDto.setDescription("Article Description " + id); + articleDto.setTitle("Article Nr.: " + id); + + final Collection articleBlockDtoCollection = new HashSet<>(); + + final TextBlockDto textBlock = new TextBlockDto(); + textBlock.setText("Some Text for " + id); + textBlock.setSortIndex(0); + articleBlockDtoCollection.add(textBlock); + + final ImageDto imageResult = new ImageDto(); + imageResult.setId(1L); + imageResult.setImageSize(ImageSize.LARGE); + imageResult.setUrl("https://someurl.com/image/" + 1L); + + final ImageBlockDto imageBlock = new ImageBlockDto(); + imageBlock.setImage(imageResult); + textBlock.setSortIndex(1); + articleBlockDtoCollection.add(imageBlock); + + final VideoBlockDto videoBlock = new VideoBlockDto(); + videoBlock.setType(VideoBlockType.YOUTUBE); + videoBlock.setUrl("https://youtu.be/myvideo"); + videoBlock.setSortIndex(2); + articleBlockDtoCollection.add(videoBlock); + + final ImageDto imageResult2 = new ImageDto(); + imageResult2.setId(101L); + imageResult2.setImageSize(ImageSize.MEDIUM); + imageResult2.setUrl("https://someurl.com/image/" + 101L); + + List images = Arrays.asList(imageResult, imageResult2); + + final GalleryBlockDto galleryBlock = new GalleryBlockDto(); + galleryBlock.setImages(images); + galleryBlock.setSortIndex(3); + articleBlockDtoCollection.add(galleryBlock); + articleDto.setBlocks(articleBlockDtoCollection); + return articleDto; + } + + /** + * Creates a dummy article object to be used for testing. + * + * @return {@link Article} + */ + private static Article getArticle() { + Long id = 1001L; + final Article article = new Article(); + article.setId(id); + article.setAuthor("Max Mustermann"); + article.setDescription("Article Description " + id); + article.setTitle("Article Nr.: " + id); + article.setLastModifiedBy("Hans Müller"); + article.setLastModified(new Date()); + + final Set articleBlockSet = new HashSet<>(); + + final TextBlock textBlock = new TextBlock(); + textBlock.setText("Some Text for " + id); + textBlock.setSortIndex(0); + articleBlockSet.add(textBlock); + + final Image imageResult = new Image(); + imageResult.setId(1L); + imageResult.setLastModified(new Date()); + imageResult.setLastModifiedBy("Max Mustermann"); + imageResult.setImageSize(ImageSize.LARGE); + imageResult.setUrl("https://someurl.com/image/" + 1L); + + final ImageBlock imageBlock = new ImageBlock(); + imageBlock.setImage(imageResult); + textBlock.setSortIndex(1); + articleBlockSet.add(imageBlock); + + final VideoBlock videoBlock = new VideoBlock(); + videoBlock.setType(VideoBlockType.YOUTUBE); + videoBlock.setUrl("https://youtu.be/myvideo"); + videoBlock.setSortIndex(2); + articleBlockSet.add(videoBlock); + + final Image imageResult2 = new Image(); + imageResult2.setId(101L); + imageResult2.setLastModified(new Date()); + imageResult2.setLastModifiedBy("Wesley Buck"); + imageResult2.setImageSize(ImageSize.MEDIUM); + imageResult2.setUrl("https://someurl.com/image/" + 101L); + + List images = Arrays.asList(imageResult, imageResult2); + + final GalleryBlock galleryBlock = new GalleryBlock(); + galleryBlock.setImages(images); + galleryBlock.setSortIndex(3); + articleBlockSet.add(galleryBlock); + article.setBlocks(articleBlockSet); + return article; + } +} \ No newline at end of file diff --git a/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/GalleryBlockMapperUnitTest.java b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/GalleryBlockMapperUnitTest.java new file mode 100644 index 0000000..a7ce610 --- /dev/null +++ b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/GalleryBlockMapperUnitTest.java @@ -0,0 +1,98 @@ +package com.staffinghub.coding.challenges.mapping.mappers; + +import com.staffinghub.coding.challenges.mapping.ApplicationTests; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers.IGalleryBlockMapper; +import com.staffinghub.coding.challenges.mapping.models.db.Image; +import com.staffinghub.coding.challenges.mapping.models.db.ImageSize; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.GalleryBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.ImageDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.GalleryBlockDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.ImageBlockDto; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GalleryBlockMapperUnitTest extends ApplicationTests { + + @Autowired + private IGalleryBlockMapper galleryBlockMapper; + + @Test + public void toGalleryBlockDto() { + final GalleryBlock galleryBlock = getGalleryBlock(); + + GalleryBlockDto galleryBlockDto = galleryBlockMapper.toGalleryBlockDto(galleryBlock); + + assertThat(galleryBlockDto) + .usingRecursiveComparison() + .isEqualTo(getGalleryBlockDto()); + } + + @Test + public void toGalleryBlock() { + final GalleryBlockDto galleryBlockDto = getGalleryBlockDto(); + + GalleryBlock resulting = galleryBlockMapper.toGalleryBlock(galleryBlockDto); + + GalleryBlock expectedGalleryBlock = getGalleryBlock(); + + assertThat(resulting) + .usingRecursiveComparison() + .ignoringFields("lastModifiedBy", "lastModified") + .isEqualTo(expectedGalleryBlock); + } + + /** + * Creates a dummy gallery block object to be used for testing. + * + * @return {@link GalleryBlock} + */ + private static GalleryBlock getGalleryBlock() { + final Image imageResult = new Image(); + imageResult.setId(1L); + imageResult.setImageSize(ImageSize.LARGE); + imageResult.setUrl("https://someurl.com/image/" + 1L); + + final Image imageResult2 = new Image(); + imageResult2.setId(101L); + imageResult2.setImageSize(ImageSize.MEDIUM); + imageResult2.setUrl("https://someurl.com/image/" + 101L); + + List images = Arrays.asList(imageResult, imageResult2); + + final GalleryBlock galleryBlock = new GalleryBlock(); + galleryBlock.setImages(images); + galleryBlock.setSortIndex(3); + + return galleryBlock; + } + + /** + * Creates a dummy gallery block dto object to be used for testing. + * + * @return {@link GalleryBlockDto} + */ + private static GalleryBlockDto getGalleryBlockDto() { + final ImageDto imageResult = new ImageDto(); + imageResult.setId(1L); + imageResult.setImageSize(ImageSize.LARGE); + imageResult.setUrl("https://someurl.com/image/" + 1L); + + final ImageDto imageResult2 = new ImageDto(); + imageResult2.setId(101L); + imageResult2.setImageSize(ImageSize.MEDIUM); + imageResult2.setUrl("https://someurl.com/image/" + 101L); + + List images = Arrays.asList(imageResult, imageResult2); + + final GalleryBlockDto galleryBlock = new GalleryBlockDto(); + galleryBlock.setImages(images); + galleryBlock.setSortIndex(3); + + return galleryBlock; + } +} diff --git a/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/ImageBlockMapperUnitTest.java b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/ImageBlockMapperUnitTest.java new file mode 100644 index 0000000..ed23f48 --- /dev/null +++ b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/ImageBlockMapperUnitTest.java @@ -0,0 +1,77 @@ +package com.staffinghub.coding.challenges.mapping.mappers; + +import com.staffinghub.coding.challenges.mapping.ApplicationTests; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers.IImageBlockMapper; +import com.staffinghub.coding.challenges.mapping.models.db.Image; +import com.staffinghub.coding.challenges.mapping.models.db.ImageSize; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.ImageBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.ImageDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.ImageBlockDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.TextBlockDto; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ImageBlockMapperUnitTest extends ApplicationTests { + + @Autowired + private IImageBlockMapper imageBlockMapper; + + @Test + public void toImageBlock() { + final ImageBlockDto imageBlockDto = getImageBlockDto(); + + ImageBlock imageBlock = imageBlockMapper.toImageBlock(imageBlockDto); + + assertThat(imageBlock) + .usingRecursiveComparison() + .isEqualTo(getImageBlock()); + } + + @Test + public void toImageBlockDto() { + + final ImageBlock imageBlock = getImageBlock(); + + ImageBlockDto imageBlockdto = imageBlockMapper.toImageBlockDto(imageBlock); + + assertThat(imageBlockdto) + .usingRecursiveComparison() + .isEqualTo(getImageBlockDto()); + } + + /** + * Creates a dummy image block object to be used for testing. + * + * @return {@link ImageBlock} + */ + private static ImageBlock getImageBlock() { + final Image imageResult = new Image(); + imageResult.setId(1L); + imageResult.setImageSize(ImageSize.LARGE); + imageResult.setUrl("https://someurl.com/image/" + 1L); + + + final ImageBlock imageBlock = new ImageBlock(); + imageBlock.setImage(imageResult); + return imageBlock; + } + + /** + * Creates a dummy image block dto object to be used for testing. + * + * @return {@link ImageBlockDto} + */ + private static ImageBlockDto getImageBlockDto() { + final ImageDto imageResult = new ImageDto(); + imageResult.setId(1L); + imageResult.setImageSize(ImageSize.LARGE); + imageResult.setUrl("https://someurl.com/image/" + 1L); + + final ImageBlockDto imageBlock = new ImageBlockDto(); + imageBlock.setImage(imageResult); + + return imageBlock; + } +} diff --git a/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/TextBlockMapperUnitTest.java b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/TextBlockMapperUnitTest.java new file mode 100644 index 0000000..e3c5413 --- /dev/null +++ b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/TextBlockMapperUnitTest.java @@ -0,0 +1,63 @@ +package com.staffinghub.coding.challenges.mapping.mappers; + +import com.staffinghub.coding.challenges.mapping.ApplicationTests; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers.ITextBlockMapper; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.TextBlock; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.VideoBlock; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.TextBlockDto; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TextBlockMapperUnitTest extends ApplicationTests { + + @Autowired + private ITextBlockMapper textBlockMapper; + + @Test + public void toTextBlock() { + final TextBlockDto textBlockDto = getTextBlockDto(); + + TextBlock textBlock = textBlockMapper.toTextBlock(textBlockDto); + + assertThat(textBlock) + .usingRecursiveComparison() + .isEqualTo(getTextBlock()); + } + + @Test + public void toTextBlockDto() { + final TextBlock textBlock = getTextBlock(); + + TextBlockDto textBlockDto = textBlockMapper.toTextBlockDto(textBlock); + + assertThat(textBlockDto) + .usingRecursiveComparison() + .isEqualTo(getTextBlockDto()); + } + + /** + * Creates a dummy text block object to be used for testing. + * + * @return {@link TextBlock} + */ + private static TextBlock getTextBlock() { + final TextBlock textBlock = new TextBlock(); + textBlock.setText("Some Text"); + textBlock.setSortIndex(0); + return textBlock; + } + + /** + * Creates a dummy text block dto object to be used for testing. + * + * @return {@link TextBlockDto} + */ + private static TextBlockDto getTextBlockDto() { + final TextBlockDto textBlock = new TextBlockDto(); + textBlock.setText("Some Text"); + textBlock.setSortIndex(0); + return textBlock; + } +} diff --git a/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/VideoBlockMapperUnitTest.java b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/VideoBlockMapperUnitTest.java new file mode 100644 index 0000000..b0c5504 --- /dev/null +++ b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/mappers/VideoBlockMapperUnitTest.java @@ -0,0 +1,66 @@ +package com.staffinghub.coding.challenges.mapping.mappers; + +import com.staffinghub.coding.challenges.mapping.ApplicationTests; +import com.staffinghub.coding.challenges.mapping.mappers.blocks.mappers.IVideoBlockMapper; +import com.staffinghub.coding.challenges.mapping.models.db.Article; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.VideoBlock; +import com.staffinghub.coding.challenges.mapping.models.db.blocks.VideoBlockType; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.VideoBlockDto; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.assertj.core.api.Assertions.assertThat; + +public class VideoBlockMapperUnitTest extends ApplicationTests { + + @Autowired + private IVideoBlockMapper videoBlockMapper; + + @Test + public void toVideoBlock() { + final VideoBlockDto videoBlockDto = getVideoBlockDto(); + + VideoBlock videoBlock = videoBlockMapper.toVideoBlock(videoBlockDto); + + assertThat(videoBlock) + .usingRecursiveComparison() + .isEqualTo(getVideoBlock()); + } + + @Test + public void toVideoBlockDto() { + final VideoBlock videoBlock = getVideoBlock(); + + VideoBlockDto videoBlockDto = videoBlockMapper.toVideoBlockDto(videoBlock); + + assertThat(videoBlockDto) + .usingRecursiveComparison() + .isEqualTo(getVideoBlockDto()); + } + + /** + * Creates a dummy video block object to be used for testing. + * + * @return {@link VideoBlock} + */ + private static VideoBlock getVideoBlock() { + final VideoBlock videoBlock = new VideoBlock(); + videoBlock.setType(VideoBlockType.YOUTUBE); + videoBlock.setUrl("https://youtu.be/myvideo"); + videoBlock.setSortIndex(2); + return videoBlock; + } + + /** + * Creates a dummy video block dto object to be used for testing. + * + * @return {@link VideoBlockDto} + */ + private static VideoBlockDto getVideoBlockDto() { + final VideoBlockDto videoBlock = new VideoBlockDto(); + videoBlock.setType(VideoBlockType.YOUTUBE); + videoBlock.setUrl("https://youtu.be/myvideo"); + videoBlock.setSortIndex(2); + return videoBlock; + } +} diff --git a/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/services/ArticleServiceIntegrationTest.java b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/services/ArticleServiceIntegrationTest.java new file mode 100644 index 0000000..7d4b3fb --- /dev/null +++ b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/services/ArticleServiceIntegrationTest.java @@ -0,0 +1,63 @@ +package com.staffinghub.coding.challenges.mapping.services; + +import com.staffinghub.coding.challenges.mapping.ApplicationTests; +import com.staffinghub.coding.challenges.mapping.models.dto.ArticleDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.ArticleBlockDto; +import com.staffinghub.coding.challenges.mapping.models.dto.blocks.TextBlockDto; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.server.ResponseStatusException; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.testng.Assert.assertThrows; + +public class ArticleServiceIntegrationTest extends ApplicationTests { + + @Autowired + private ArticleService articleService; + + @Test + public void getListOrdered() { + List items = articleService.list(); + assertFalse(items.isEmpty()); + + for (ArticleDto block: items) { + List arr = block.getBlocks().stream().sorted(Comparator.comparingLong(articleBlock -> articleBlock.getSortIndex())).collect(Collectors.toList()); + + assertThat(block.getBlocks()).usingRecursiveComparison().isEqualTo(arr); + } + } + + @Test + public void getArticleForIdSuccessfully() { + ArticleDto unMapped = articleService.articleForId(1001l); + assertNotNull(unMapped); + } + + @Test + public void getArticleForIdUnsuccessfully() { + assertThrows(ResponseStatusException.class, () -> articleService.articleForId(-1l)); + } + + @Test + public void createArticleForIdSuccessfully() { + ArticleDto articleDto = new ArticleDto(); + articleDto.setTitle("Test title"); + articleDto.setDescription("Test description"); + articleDto.setAuthor("Test author"); + TextBlockDto textBlockDto = new TextBlockDto(); + textBlockDto.setText("Test block"); + articleDto.setBlocks(Arrays.asList(textBlockDto)); + + ArticleDto savedDto = articleService.create(articleDto); + assertNotNull(savedDto); + assertThat(savedDto).usingRecursiveComparison().isEqualTo(articleDto); + } +} diff --git a/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/services/ArticleServiceUnitTest.java b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/services/ArticleServiceUnitTest.java new file mode 100644 index 0000000..2f84568 --- /dev/null +++ b/Backend/mapping/src/test/java/com/staffinghub/coding/challenges/mapping/services/ArticleServiceUnitTest.java @@ -0,0 +1,91 @@ +package com.staffinghub.coding.challenges.mapping.services; + +import com.staffinghub.coding.challenges.mapping.mappers.IArticleMapper; +import com.staffinghub.coding.challenges.mapping.models.db.Article; +import com.staffinghub.coding.challenges.mapping.models.dto.ArticleDto; +import com.staffinghub.coding.challenges.mapping.repositories.ArticleRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.server.ResponseStatusException; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.testng.Assert.assertThrows; + +@RunWith(SpringRunner.class) +public class ArticleServiceUnitTest { + + @Mock + private ArticleRepository repository; + + @Mock + private IArticleMapper mapper; + + @InjectMocks + private ArticleService articleService; + + @Test + public void getList() { + doReturn(Arrays.asList(createDummyArticle(999L))).when(repository).all(); + doReturn(new ArticleDto()).when(mapper).toArticleDto(any()); + + List items = articleService.list(); + assertFalse(items.isEmpty()); + } + + @Test + public void getArticleForIdSuccessfully() { + long articleId = 999L; + + doReturn(Arrays.asList(createDummyArticle(articleId))).when(repository).all(); + doReturn(new ArticleDto()).when(mapper).toArticleDto(any()); + + ArticleDto unMapped = articleService.articleForId(articleId); + assertNotNull(unMapped); + } + + @Test + public void getArticleForIdUnsuccessfully() { + doReturn(Arrays.asList(createDummyArticle(999L))).when(repository).all(); + doReturn(new ArticleDto()).when(mapper).toArticleDto(any()); + + assertThrows(ResponseStatusException.class, () -> articleService.articleForId(-1l)); + } + + @Test + public void createArticleForIdSuccessfully() { + doReturn(new ArticleDto()).when(mapper).toArticleDto(any()); + + ArticleDto articleDto = new ArticleDto(); + ArticleDto savedDto = articleService.create(articleDto); + assertNotNull(savedDto); + assertThat(savedDto).usingRecursiveComparison().isEqualTo(articleDto); + } + + /** + * Creates a dummy article object to be used for testing. + * + * @param id {@link Long} + * @return {@link Article} + */ + private Article createDummyArticle(Long id) { + final Article result = new Article(); + result.setId(id); + result.setAuthor("Max Mustermann"); + result.setDescription("Article Description " + id); + result.setTitle("Article Nr.: " + id); + result.setLastModifiedBy("Hans Müller"); + result.setLastModified(new Date()); + return result; + } +}