Added intro items to API

This commit is contained in:
Thom Werring 2023-10-24 09:21:16 +02:00
parent ececd76e10
commit e6ebb0e4c1
7 changed files with 222 additions and 4 deletions

View file

@ -7,6 +7,8 @@ import { SkillDto } from "@/skills/skills.types";
import { ExperienceDto } from "@/experiences/experiences.types"; import { ExperienceDto } from "@/experiences/experiences.types";
import { EducationService } from "@/education/education.service"; import { EducationService } from "@/education/education.service";
import { EducationDto } from "@/education/education.types"; import { EducationDto } from "@/education/education.types";
import { IntroService } from "@/intro/intro.service";
import { IntroDto } from "@/intro/intro.types";
describe("AppController", () => { describe("AppController", () => {
let appController: AppController; let appController: AppController;
@ -14,11 +16,12 @@ describe("AppController", () => {
let skillsService: SkillsService; let skillsService: SkillsService;
let experiencesService: ExperiencesService; let experiencesService: ExperiencesService;
let educationService: EducationService; let educationService: EducationService;
let introService: IntroService;
beforeEach(async () => { beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({ const app: TestingModule = await Test.createTestingModule({
controllers: [AppController], controllers: [AppController],
providers: [AppService, SkillsService, ExperiencesService, EducationService], providers: [AppService, SkillsService, ExperiencesService, EducationService, IntroService],
}).compile(); }).compile();
appController = app.get<AppController>(AppController); appController = app.get<AppController>(AppController);
@ -26,6 +29,7 @@ describe("AppController", () => {
skillsService = app.get<SkillsService>(SkillsService); skillsService = app.get<SkillsService>(SkillsService);
experiencesService = app.get<ExperiencesService>(ExperiencesService); experiencesService = app.get<ExperiencesService>(ExperiencesService);
educationService = app.get<EducationService>(EducationService); educationService = app.get<EducationService>(EducationService);
introService = app.get<IntroService>(IntroService);
}); });
describe("root", () => { describe("root", () => {
@ -96,4 +100,20 @@ describe("AppController", () => {
expect(educationService.getMany).toBeCalled(); expect(educationService.getMany).toBeCalled();
}); });
}); });
describe("getIntros", () => {
it("Should return an Array of IntroDtos", () => {
const result: IntroDto[] = IntroDto.asDto([
{
name: "name",
value: "Bob Ross",
category: "Personal details",
},
]);
jest.spyOn(introService, "getMany").mockImplementation(() => result);
expect(appController.getIntros()).toBe(result);
expect(introService.getMany).toBeCalled();
});
});
}); });

View file

@ -7,15 +7,18 @@ import { SkillDto } from "@/skills/skills.types";
import { ExperienceDto } from "@/experiences/experiences.types"; import { ExperienceDto } from "@/experiences/experiences.types";
import { EducationDto } from "@/education/education.types"; import { EducationDto } from "@/education/education.types";
import { EducationService } from "@/education/education.service"; import { EducationService } from "@/education/education.service";
import { IntroDto } from "@/intro/intro.types";
import { IntroService } from "@/intro/intro.service";
@Controller() @Controller()
@ApiExtraModels(SkillDto, ExperienceDto, EducationDto) @ApiExtraModels(SkillDto, ExperienceDto, EducationDto, IntroDto)
export class AppController { export class AppController {
constructor( constructor(
private readonly appService: AppService, private readonly appService: AppService,
private readonly skillsService: SkillsService, private readonly skillsService: SkillsService,
private readonly experiencesService: ExperiencesService, private readonly experiencesService: ExperiencesService,
private readonly educationService: EducationService private readonly educationService: EducationService,
private readonly introService: IntroService
) {} ) {}
@Get() @Get()
@ -65,4 +68,18 @@ export class AppController {
getEducation(): readonly EducationDto[] { getEducation(): readonly EducationDto[] {
return this.educationService.getMany(); return this.educationService.getMany();
} }
@Get("intro")
@ApiTags("Intro")
@ApiOkResponse({
description: "Returns a list of introduction items",
schema: {
items: {
$ref: getSchemaPath(IntroDto),
},
},
})
getIntros(): readonly IntroDto[] {
return this.introService.getMany();
}
} }

View file

@ -4,10 +4,11 @@ import { AppService } from "@/app.service";
import { SkillsService } from "@/skills/skills.service"; import { SkillsService } from "@/skills/skills.service";
import { ExperiencesService } from "@/experiences/experiences.service"; import { ExperiencesService } from "@/experiences/experiences.service";
import { EducationService } from "@/education/education.service"; import { EducationService } from "@/education/education.service";
import { IntroService } from "@/intro/intro.service";
@Module({ @Module({
imports: [], imports: [],
controllers: [AppController], controllers: [AppController],
providers: [AppService, SkillsService, ExperiencesService, EducationService], providers: [AppService, SkillsService, ExperiencesService, EducationService, IntroService],
}) })
export class AppModule {} export class AppModule {}

View file

@ -0,0 +1,54 @@
import { IntroType } from "@/intro/intro.types";
export default {
getData: (): IntroType[] =>
[
{
category: "Personal details",
name: "Name",
value: "Thom Werring",
},
{
category: "Personal details",
name: "Gender",
value: "Male",
},
{
category: "Personal details",
name: "Address",
value: "Westerstraat 83\n1521ZB, Wormerveer",
},
{
category: "Personal details",
name: "Phone number",
value: "+31 6 37 65 08 49",
},
{
category: "Personal details",
name: "Date of birth",
value: "1990-06-05",
},
{
category: "Introduction",
name: "Professional introduction",
value: `I'm a software lead with 5+ years of experience in cloud-native development and Agile/Scrum methodologies. I'm passionate about building and leading high-performing teams to deliver scalable and reliable cloud-based applications. I have a proven track record of success in using Node.js, TypeScript, JavaScript, Docker, Kubernetes, AWS, DevOps, Git, microservices, and HAProxy to create and deploy innovative solutions.
Furthermore I'm also a strong communicator and collaborator, and I'm always looking for ways to improve my skills and knowledge. I'm excited about the future of cloud computing, and I'm eager to use my skills and experience to help others achieve their goals.`,
},
{
category: "Introduction",
name: "Personal introduction",
value: `My name is Thom Werring, a 33-year-old software developer with a passion for technology and problem-solving. I currently work at Saysimple as a senior developer.
Beyond the world of code, I'm a dedicated Judo practitioner, proudly holding a second-degree black belt. The discipline, strategic thinking, and respect instilled through Judo have profoundly enriched my life. And when I'm not grappling with code or opponents, I love the camaraderie and mental challenges of board games and tabletop games. They're the perfect way to unwind, get creative, and connect with friends.`,
},
{
category: "Hobbies",
name: "Judo",
value: "I'm a dedicated Judo practitioner, proudly holding a second-degree black belt. My commitment to Judo extends to teaching kids and young adults with mental or physical limitations. Their enthusiasm and determination as they embrace Judo is truly heartwarming.",
},
{
category: "Hobbies",
name: "Board and tabletop games",
value: "Board games and tabletop games are my favorite way to unwind and connect with friends. The mix of strategy, creativity, and camaraderie makes for unforgettable moments and lasting memories.",
},
] satisfies IntroType[],
};

View file

@ -0,0 +1,74 @@
import { Test, TestingModule } from "@nestjs/testing";
import { IntroService } from "@/intro/intro.service";
import introDataset from "@/intro/intro.dataset";
describe("IntroService", () => {
let service: IntroService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [IntroService],
}).compile();
jest.spyOn(introDataset, "getData").mockImplementation(() => [
{
category: "Personal details",
name: "Name",
value: "Bob ross",
},
{
category: "Personal details",
name: "Gender",
value: "Male",
},
{
category: "Personal details",
name: "Address",
value: "",
},
{
category: "Personal details",
name: "Phone number",
value: "+31 6 00 00 00 00",
},
{
category: "Personal details",
name: "Date of birth",
value: "1942-10-29",
},
{
category: "Hobbies",
name: "Painting",
value: "",
},
]);
service = module.get<IntroService>(IntroService);
});
it("should be defined", () => {
expect(service).toBeDefined();
});
describe("getMany method", () => {
it("should be defined", () => {
expect(service.getMany).toBeDefined();
});
it("should return an array with 6 entries", () => {
const intro = service.getMany();
expect(Array.isArray(intro)).toBe(true);
expect(intro.length).toBe(6);
});
it("should return a filtered array with 5 entries", () => {
const intro = service.getMany({
category: "Personal details",
});
expect(Array.isArray(intro)).toBe(true);
expect(intro.length).toBe(5);
});
});
});

View file

@ -0,0 +1,26 @@
import { Injectable } from "@nestjs/common";
import { IntroDto, IntroType } from "@/intro/intro.types";
import introDataset from "@/intro/intro.dataset";
@Injectable()
export class IntroService {
private readonly intro: readonly IntroDto[];
constructor() {
this.intro = IntroDto.asDto(introDataset.getData()).sort((introA, introB) =>
introA.category < introB.category ? 1 : -1
);
}
getMany(filter?: Partial<Omit<IntroType, "startDate" | "endDate">>) {
const filtersValues = Object.entries(filter ?? {}).map(([key, filterValue]) => [
key,
new RegExp(filterValue, "i"),
]) as Array<[keyof Omit<IntroType, "startDate" | "endDate">, RegExp]>;
if (!filter || filtersValues.length === 0) {
return this.intro;
}
return this.intro.filter((intro) => filtersValues.some(([key, filterValue]) => filterValue.test(intro[key])));
}
}

26
src/intro/intro.types.ts Normal file
View file

@ -0,0 +1,26 @@
import { ApiProperty } from "@nestjs/swagger";
import { DtoClass } from "@/common/dtoClass.factory";
export type IntroType = {
name: string;
value: string;
category: string;
};
export class IntroDto extends DtoClass<IntroType, IntroDto>() implements IntroType {
@ApiProperty()
readonly name: string;
@ApiProperty()
readonly value: string;
@ApiProperty()
readonly category: string;
constructor(intro: IntroType) {
super(intro);
Object.assign(this, {
name: intro.name,
value: intro.value,
category: intro.category,
});
}
}