From 7e109b72eb4eee45be50f5217ea4d8d541a6edfa Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 11:52:59 +0200 Subject: [PATCH 01/11] cleanup --- features/steps/common_steps.ts | 8 +++++--- features/steps/register_vehicle_steps.ts | 8 +++++--- src/Domain/Models/Fleet.ts | 4 +++- src/Infra/Primary/CLI/create.ts | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/features/steps/common_steps.ts b/features/steps/common_steps.ts index 214ef86..f12a554 100644 --- a/features/steps/common_steps.ts +++ b/features/steps/common_steps.ts @@ -7,11 +7,13 @@ import { registerVehicleInUserFleet } from "./register_vehicle_steps"; import { generateFrenchPlateNumber } from "../../tests/Utils/generateFrenchPlateNumber"; Given("my fleet", async function (): Promise { - const user: User = User.create(crypto.randomUUID()); - this.context = { user, repository: new InMemoryFleetRepository() }; + this.context = { + user: User.create(crypto.randomUUID()), + repository: new InMemoryFleetRepository(), + }; this.context.fleetId = await initializeFleetForUser( this.context.repository, - user, + this.context.user, ); }); diff --git a/features/steps/register_vehicle_steps.ts b/features/steps/register_vehicle_steps.ts index d56d6d0..c52fd91 100644 --- a/features/steps/register_vehicle_steps.ts +++ b/features/steps/register_vehicle_steps.ts @@ -8,14 +8,16 @@ import { User } from "../../src/Domain/Models/User"; import { Vehicle } from "../../src/Domain/Models/Vehicle"; import { VehicleAlreadyRegisteredError } from "../../src/Domain/Errors/VehicleAlreadyRegisteredError"; -// Third group: Helpers -import { initializeFleetForUser } from "./shared/initializeFleetForUser"; -import { retrieveFleet } from "./shared/retrieveFleet"; +// Third group: App import { RegisterVehicle, RegisterVehicleHandler, } from "../../src/App/Commands/registerVehicle"; +// Fourth group: Helpers +import { initializeFleetForUser } from "./shared/initializeFleetForUser"; +import { retrieveFleet } from "./shared/retrieveFleet"; + Given("the fleet of another user", async function (): Promise { this.context.otherUser = User.create(crypto.randomUUID()); this.context.otherFleetId = await initializeFleetForUser( diff --git a/src/Domain/Models/Fleet.ts b/src/Domain/Models/Fleet.ts index 87ec03c..0567008 100644 --- a/src/Domain/Models/Fleet.ts +++ b/src/Domain/Models/Fleet.ts @@ -46,7 +46,9 @@ export class Fleet { this.vehicles.push(vehicle); } - private ensureVehicleIsNotAlreadyRegistered(vehiclePlateNumber: string) { + private ensureVehicleIsNotAlreadyRegistered( + vehiclePlateNumber: string, + ): void { const existingVehicle = this.findVehicleByPlateNumber(vehiclePlateNumber); if (existingVehicle) diff --git a/src/Infra/Primary/CLI/create.ts b/src/Infra/Primary/CLI/create.ts index b4696bb..285a01b 100644 --- a/src/Infra/Primary/CLI/create.ts +++ b/src/Infra/Primary/CLI/create.ts @@ -22,6 +22,6 @@ export const createFleetCommand: CommandModule = { const handler = new InitializeFleetHandler(repository); const fleetId = await handler.handle(initializeFleet); - console.log(fleetId); // TODO: Add a sentence to successfully created fleet + console.log(fleetId); }, }; From dca0ba3dc21f3e3c2e989022e65b80e3f130d4fb Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 14:14:23 +0200 Subject: [PATCH 02/11] clean: cucumber register vehicle tests --- INSTRUCTIONS.md | 3 +-- features/steps/register_vehicle_steps.ts | 22 ++++++++++++++-------- features/steps/shared/retrieveFleet.ts | 12 ------------ 3 files changed, 15 insertions(+), 22 deletions(-) delete mode 100644 features/steps/shared/retrieveFleet.ts diff --git a/INSTRUCTIONS.md b/INSTRUCTIONS.md index a06c290..e53f7ec 100644 --- a/INSTRUCTIONS.md +++ b/INSTRUCTIONS.md @@ -101,8 +101,7 @@ We use Domain Driven Design (DDD) and encourage its application, but all archite - Ask yourself: how many entities do I have? - Ask yourself: how many Commands? Queries? - At this stage, you don't need to persist data anywhere other than **in memory**. -- Here's an indication of the expected number of line of codes for implementations - in **PHP** and **JavaScript**: +- Here's an indication of the expected number of line of codes for implementations in **PHP** and **JavaScript**: ### Step 2 diff --git a/features/steps/register_vehicle_steps.ts b/features/steps/register_vehicle_steps.ts index c52fd91..ef6b2b0 100644 --- a/features/steps/register_vehicle_steps.ts +++ b/features/steps/register_vehicle_steps.ts @@ -4,6 +4,7 @@ import { World } from "cucumber"; import { expect } from "chai"; // Second group: Domain +import { Fleet } from "../../src/Domain/Models/Fleet"; import { User } from "../../src/Domain/Models/User"; import { Vehicle } from "../../src/Domain/Models/Vehicle"; import { VehicleAlreadyRegisteredError } from "../../src/Domain/Errors/VehicleAlreadyRegisteredError"; @@ -16,7 +17,7 @@ import { // Fourth group: Helpers import { initializeFleetForUser } from "./shared/initializeFleetForUser"; -import { retrieveFleet } from "./shared/retrieveFleet"; +import { GetFleet, GetFleetHandler } from "../../src/App/Queries/getFleet"; Given("the fleet of another user", async function (): Promise { this.context.otherUser = User.create(crypto.randomUUID()); @@ -53,14 +54,9 @@ When( Then( "this vehicle should be part of my vehicle fleet", async function (): Promise { - const fleet = await retrieveFleet( - this.context.repository, - this.context.fleetId, - ); + const fleet = await getFleet(this.context); - const vehiclePlateNumber: string = fleet.vehicles - .map((v: Vehicle): string => v.plateNumber) - .toString(); + const vehiclePlateNumber = getVehiclePlateNumber(fleet); expect(vehiclePlateNumber).to.deep.include( this.context.vehicle.plateNumber, @@ -100,3 +96,13 @@ async function registerVehicleInOtherUserFleet(context: World): Promise { const handler = new RegisterVehicleHandler(context.repository); await handler.handle(registerVehicleCommand); } + +async function getFleet(context: World) { + const getFleetQuery = new GetFleet(context.fleetId); + const handler = new GetFleetHandler(context.repository); + return await handler.handle(getFleetQuery); +} + +function getVehiclePlateNumber(fleet: Fleet): string { + return fleet.vehicles.map((v: Vehicle): string => v.plateNumber).toString(); +} diff --git a/features/steps/shared/retrieveFleet.ts b/features/steps/shared/retrieveFleet.ts deleted file mode 100644 index 7836253..0000000 --- a/features/steps/shared/retrieveFleet.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Fleet } from "../../../src/Domain/Models/Fleet"; -import { FleetRepository } from "../../../src/Domain/Ports/FleetRepository"; -import { GetFleet, GetFleetHandler } from "../../../src/App/Queries/getFleet"; - -export async function retrieveFleet( - repository: FleetRepository, - fleetId: string, -): Promise { - const getFleetQuery = new GetFleet(fleetId); - const handler = new GetFleetHandler(repository); - return await handler.handle(getFleetQuery); -} From e2f3fd76a871b36730bcb3c95063a40ccdad2fed Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 14:29:31 +0200 Subject: [PATCH 03/11] clean: refactor park vehicle steps --- features/steps/park_vehicle_steps.ts | 41 ++++++++++--------- .../steps/shared/parkVehicleAtLocation.ts | 21 ---------- 2 files changed, 21 insertions(+), 41 deletions(-) delete mode 100644 features/steps/shared/parkVehicleAtLocation.ts diff --git a/features/steps/park_vehicle_steps.ts b/features/steps/park_vehicle_steps.ts index 62e3727..083c9e2 100644 --- a/features/steps/park_vehicle_steps.ts +++ b/features/steps/park_vehicle_steps.ts @@ -1,13 +1,18 @@ // First group: Testing framework import { Given, Then, When } from "@cucumber/cucumber"; +import { World } from "cucumber"; import { expect } from "chai"; // Second group: Domain import { Location } from "../../src/Domain/Models/Location"; import { VehicleAlreadyParkedAtThisLocationError } from "../../src/Domain/Errors/VehicleAlreadyParkedAtThisLocationError"; -// Third group: Helpers -import { parkVehicleAtLocation } from "./shared/parkVehicleAtLocation"; +// Third group: App +import { + ParkVehicle, + ParkVehicleHandler, +} from "../../src/App/Commands/parkVehicle"; + import { retrieveLocation } from "./shared/retrieveLocation"; Given("a location", async function (): Promise { @@ -17,34 +22,20 @@ Given("a location", async function (): Promise { Given( "my vehicle has been parked in this location", async function (): Promise { - await parkVehicleAtLocation( - this.context.repository, - this.context.fleetId, - this.context.vehicle.plateNumber, - this.context.location, - ); + await parkVehicleInFleetAtThisLocation(this.context); }, ); When("I park my vehicle at this location", async function (): Promise { - await parkVehicleAtLocation( - this.context.repository, - this.context.fleetId, - this.context.vehicle.plateNumber, - this.context.location, - ); + await parkVehicleInFleetAtThisLocation(this.context); }); When( "I try to park my vehicle at this location", async function (): Promise { try { - await parkVehicleAtLocation( - this.context.repository, - this.context.fleetId, - this.context.vehicle.plateNumber, - this.context.location, - ); + await parkVehicleInFleetAtThisLocation(this.context); + this.context.parkingAttemptError = null; } catch (error) { this.context.parkingAttemptError = error; @@ -77,3 +68,13 @@ Then( expect(this.context.parkingAttemptError).to.deep.equal(expected); }, ); + +async function parkVehicleInFleetAtThisLocation(context: World) { + const parkVehicleCommand = new ParkVehicle( + context.fleetId, + context.vehicle.plateNumber, + context.location, + ); + const handler = new ParkVehicleHandler(context.repository); + await handler.handle(parkVehicleCommand); +} diff --git a/features/steps/shared/parkVehicleAtLocation.ts b/features/steps/shared/parkVehicleAtLocation.ts deleted file mode 100644 index 65f720a..0000000 --- a/features/steps/shared/parkVehicleAtLocation.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Location } from "../../../src/Domain/Models/Location"; -import { FleetRepository } from "../../../src/Domain/Ports/FleetRepository"; -import { - ParkVehicle, - ParkVehicleHandler, -} from "../../../src/App/Commands/parkVehicle"; - -export async function parkVehicleAtLocation( - repository: FleetRepository, - fleetId: string, - vehiclePlateNumber: string, - location: Location, -): Promise { - const parkVehicleCommand = new ParkVehicle( - fleetId, - vehiclePlateNumber, - location, - ); - const handler = new ParkVehicleHandler(repository); - await handler.handle(parkVehicleCommand); -} From de02c69933e7546aca4eaa827c5175176520e80b Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 14:35:56 +0200 Subject: [PATCH 04/11] clean: refactor park vehicle steps --- features/steps/park_vehicle_steps.ts | 21 ++++++++++++++------- features/steps/register_vehicle_steps.ts | 4 ++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/features/steps/park_vehicle_steps.ts b/features/steps/park_vehicle_steps.ts index 083c9e2..dfe3059 100644 --- a/features/steps/park_vehicle_steps.ts +++ b/features/steps/park_vehicle_steps.ts @@ -12,8 +12,10 @@ import { ParkVehicle, ParkVehicleHandler, } from "../../src/App/Commands/parkVehicle"; - -import { retrieveLocation } from "./shared/retrieveLocation"; +import { + GetLocation, + GetLocationHandler, +} from "../../src/App/Queries/getLocation"; Given("a location", async function (): Promise { this.context.location = Location.create(48.8566, 2.3522); @@ -46,11 +48,7 @@ When( Then( "the known location of my vehicle should verify this location", async function (): Promise { - const actualLocation = await retrieveLocation( - this.context.repository, - this.context.fleetId, - this.context.vehicle.plateNumber, - ); + const actualLocation = await getLocation(this.context); expect(actualLocation).to.deep.equal(this.context.location); }, @@ -78,3 +76,12 @@ async function parkVehicleInFleetAtThisLocation(context: World) { const handler = new ParkVehicleHandler(context.repository); await handler.handle(parkVehicleCommand); } + +async function getLocation(context: World): Promise { + const getLocationQuery = new GetLocation( + context.fleetId, + context.vehicle.plateNumber, + ); + const handler = new GetLocationHandler(context.repository); + return await handler.handle(getLocationQuery); +} diff --git a/features/steps/register_vehicle_steps.ts b/features/steps/register_vehicle_steps.ts index ef6b2b0..f3c4a4d 100644 --- a/features/steps/register_vehicle_steps.ts +++ b/features/steps/register_vehicle_steps.ts @@ -14,10 +14,10 @@ import { RegisterVehicle, RegisterVehicleHandler, } from "../../src/App/Commands/registerVehicle"; +import { GetFleet, GetFleetHandler } from "../../src/App/Queries/getFleet"; // Fourth group: Helpers import { initializeFleetForUser } from "./shared/initializeFleetForUser"; -import { GetFleet, GetFleetHandler } from "../../src/App/Queries/getFleet"; Given("the fleet of another user", async function (): Promise { this.context.otherUser = User.create(crypto.randomUUID()); @@ -97,7 +97,7 @@ async function registerVehicleInOtherUserFleet(context: World): Promise { await handler.handle(registerVehicleCommand); } -async function getFleet(context: World) { +async function getFleet(context: World): Promise { const getFleetQuery = new GetFleet(context.fleetId); const handler = new GetFleetHandler(context.repository); return await handler.handle(getFleetQuery); From 1d31c30233b4b018fe2375fd08e778ca984ab177 Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 15:11:50 +0200 Subject: [PATCH 05/11] clean: refactor common and register vehicle --- features/steps/common_steps.ts | 45 ++++++++++++++----- features/steps/register_vehicle_steps.ts | 22 ++++++--- .../steps/shared/initializeFleetForUser.ts | 15 ------- features/steps/shared/retrieveLocation.ts | 16 ------- tests/Utils/generateFrenchPlateNumber.ts | 6 --- 5 files changed, 50 insertions(+), 54 deletions(-) delete mode 100644 features/steps/shared/initializeFleetForUser.ts delete mode 100644 features/steps/shared/retrieveLocation.ts delete mode 100644 tests/Utils/generateFrenchPlateNumber.ts diff --git a/features/steps/common_steps.ts b/features/steps/common_steps.ts index f12a554..9420705 100644 --- a/features/steps/common_steps.ts +++ b/features/steps/common_steps.ts @@ -1,20 +1,26 @@ +// First group: Testing import { Given } from "@cucumber/cucumber"; +import { World } from "cucumber"; +import { registerVehicleInUserFleet } from "./register_vehicle_steps"; + +// Second group: Domain import { User } from "../../src/Domain/Models/User"; import { Vehicle } from "../../src/Domain/Models/Vehicle"; + +// Third group: App +import { + InitializeFleet, + InitializeFleetHandler, +} from "../../src/App/Commands/initializeFleet"; + +// Fourth group: Infra import { InMemoryFleetRepository } from "../../src/Infra/Secondary/Repositories/InMemoryFleetRepository"; -import { initializeFleetForUser } from "./shared/initializeFleetForUser"; -import { registerVehicleInUserFleet } from "./register_vehicle_steps"; -import { generateFrenchPlateNumber } from "../../tests/Utils/generateFrenchPlateNumber"; Given("my fleet", async function (): Promise { - this.context = { - user: User.create(crypto.randomUUID()), - repository: new InMemoryFleetRepository(), - }; - this.context.fleetId = await initializeFleetForUser( - this.context.repository, - this.context.user, - ); + this.context ??= {}; + this.context.repository = new InMemoryFleetRepository(); + await initializeUser(this.context); + await initializeFleetForUser(this.context); }); Given("a vehicle", async function (): Promise { @@ -27,3 +33,20 @@ Given( await registerVehicleInUserFleet(this.context); }, ); + +async function initializeUser(context: World): Promise { + context.user = User.create(crypto.randomUUID()); +} + +export async function initializeFleetForUser(context: World): Promise { + const initializeFleet = new InitializeFleet(context.user.id); + const handler = new InitializeFleetHandler(context.repository); + context.fleetId = await handler.handle(initializeFleet); +} + +function generateFrenchPlateNumber(): string { + const letters = () => + String.fromCharCode(65 + Math.floor(Math.random() * 26)); + const digits = () => Math.floor(100 + Math.random() * 900); // 3 digits from 100 to 999 + return `${letters()}${letters()}-${digits()}-${letters()}${letters()}`; +} diff --git a/features/steps/register_vehicle_steps.ts b/features/steps/register_vehicle_steps.ts index f3c4a4d..2a43b42 100644 --- a/features/steps/register_vehicle_steps.ts +++ b/features/steps/register_vehicle_steps.ts @@ -17,14 +17,14 @@ import { import { GetFleet, GetFleetHandler } from "../../src/App/Queries/getFleet"; // Fourth group: Helpers -import { initializeFleetForUser } from "./shared/initializeFleetForUser"; +import { + InitializeFleet, + InitializeFleetHandler, +} from "../../src/App/Commands/initializeFleet"; Given("the fleet of another user", async function (): Promise { - this.context.otherUser = User.create(crypto.randomUUID()); - this.context.otherFleetId = await initializeFleetForUser( - this.context.repository, - this.context.otherUser, - ); + await initializeOtherUser(this.context); + await initializeFleetForOtherUser(this.context); }); Given( @@ -75,6 +75,16 @@ Then( }, ); +async function initializeOtherUser(context: World): Promise { + context.otherUser = User.create(crypto.randomUUID()); +} + +async function initializeFleetForOtherUser(context: World): Promise { + const initializeFleet = new InitializeFleet(context.otherUser.id); + const handler = new InitializeFleetHandler(context.repository); + context.otherFleetId = await handler.handle(initializeFleet); +} + export async function registerVehicleInUserFleet( context: World, ): Promise { diff --git a/features/steps/shared/initializeFleetForUser.ts b/features/steps/shared/initializeFleetForUser.ts deleted file mode 100644 index 89300f1..0000000 --- a/features/steps/shared/initializeFleetForUser.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { FleetRepository } from "../../../src/Domain/Ports/FleetRepository"; -import { - InitializeFleet, - InitializeFleetHandler, -} from "../../../src/App/Commands/initializeFleet"; -import { User } from "../../../src/Domain/Models/User"; - -export async function initializeFleetForUser( - repository: FleetRepository, - user: User, -): Promise { - const initializeFleet = new InitializeFleet(user.id); - const handler = new InitializeFleetHandler(repository); - return await handler.handle(initializeFleet); -} diff --git a/features/steps/shared/retrieveLocation.ts b/features/steps/shared/retrieveLocation.ts deleted file mode 100644 index 086db26..0000000 --- a/features/steps/shared/retrieveLocation.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Location } from "../../../src/Domain/Models/Location"; -import { FleetRepository } from "../../../src/Domain/Ports/FleetRepository"; -import { - GetLocation, - GetLocationHandler, -} from "../../../src/App/Queries/getLocation"; - -export async function retrieveLocation( - repository: FleetRepository, - fleetId: string, - vehiclePlateNumber: string, -): Promise { - const getLocationQuery = new GetLocation(fleetId, vehiclePlateNumber); - const handler = new GetLocationHandler(repository); - return await handler.handle(getLocationQuery); -} diff --git a/tests/Utils/generateFrenchPlateNumber.ts b/tests/Utils/generateFrenchPlateNumber.ts deleted file mode 100644 index 1f4d5af..0000000 --- a/tests/Utils/generateFrenchPlateNumber.ts +++ /dev/null @@ -1,6 +0,0 @@ -export function generateFrenchPlateNumber(): string { - const letters = () => - String.fromCharCode(65 + Math.floor(Math.random() * 26)); - const digits = () => Math.floor(100 + Math.random() * 900); // 3 digits from 100 to 999 - return `${letters()}${letters()}-${digits()}-${letters()}${letters()}`; -} From 85cb1d4d5b96bb969cd0d72b024c5f29a42a9708 Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 15:36:44 +0200 Subject: [PATCH 06/11] clean: added before to initialize context --- features/steps/common_steps.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/features/steps/common_steps.ts b/features/steps/common_steps.ts index 9420705..2fdd423 100644 --- a/features/steps/common_steps.ts +++ b/features/steps/common_steps.ts @@ -1,5 +1,5 @@ // First group: Testing -import { Given } from "@cucumber/cucumber"; +import { Before, Given } from "@cucumber/cucumber"; import { World } from "cucumber"; import { registerVehicleInUserFleet } from "./register_vehicle_steps"; @@ -16,15 +16,18 @@ import { // Fourth group: Infra import { InMemoryFleetRepository } from "../../src/Infra/Secondary/Repositories/InMemoryFleetRepository"; +Before(function (): void { + this.context = {}; +}); + Given("my fleet", async function (): Promise { - this.context ??= {}; this.context.repository = new InMemoryFleetRepository(); await initializeUser(this.context); await initializeFleetForUser(this.context); }); Given("a vehicle", async function (): Promise { - this.context.vehicle = Vehicle.create(generateFrenchPlateNumber()); + await initializeVehicle(this.context); }); Given( @@ -44,6 +47,10 @@ export async function initializeFleetForUser(context: World): Promise { context.fleetId = await handler.handle(initializeFleet); } +async function initializeVehicle(context: World): Promise { + context.vehicle = Vehicle.create(generateFrenchPlateNumber()); +} + function generateFrenchPlateNumber(): string { const letters = () => String.fromCharCode(65 + Math.floor(Math.random() * 26)); From c1a21f360d82f08dec3786e5c20e3f976b64cc81 Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 15:42:30 +0200 Subject: [PATCH 07/11] clean: imports --- features/steps/register_vehicle_steps.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/features/steps/register_vehicle_steps.ts b/features/steps/register_vehicle_steps.ts index 2a43b42..2a29b9c 100644 --- a/features/steps/register_vehicle_steps.ts +++ b/features/steps/register_vehicle_steps.ts @@ -10,18 +10,16 @@ import { Vehicle } from "../../src/Domain/Models/Vehicle"; import { VehicleAlreadyRegisteredError } from "../../src/Domain/Errors/VehicleAlreadyRegisteredError"; // Third group: App +import { + InitializeFleet, + InitializeFleetHandler, +} from "../../src/App/Commands/initializeFleet"; import { RegisterVehicle, RegisterVehicleHandler, } from "../../src/App/Commands/registerVehicle"; import { GetFleet, GetFleetHandler } from "../../src/App/Queries/getFleet"; -// Fourth group: Helpers -import { - InitializeFleet, - InitializeFleetHandler, -} from "../../src/App/Commands/initializeFleet"; - Given("the fleet of another user", async function (): Promise { await initializeOtherUser(this.context); await initializeFleetForOtherUser(this.context); From c8ed8ed5e87b4c85baecf92fb2067a161e4ae20e Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 15:51:14 +0200 Subject: [PATCH 08/11] clean: added inferred types --- tests/FizzBuzz/fizzBuzz.ts | 8 +++++--- .../Secondary/prismaFleetRepository.test.ts | 18 ++++++++++-------- tests/Infra/Secondary/resetDB.ts | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/FizzBuzz/fizzBuzz.ts b/tests/FizzBuzz/fizzBuzz.ts index 1f87073..1760870 100644 --- a/tests/FizzBuzz/fizzBuzz.ts +++ b/tests/FizzBuzz/fizzBuzz.ts @@ -9,9 +9,11 @@ export const fizzBuzz = (input: number): string => { return input.toString(); }; -const isMultipleOf = (divisor: number) => (input: number) => - input % divisor === 0; +const isMultipleOf = + (divisor: number) => + (input: number): boolean => + input % divisor === 0; const isMultipleOf3 = isMultipleOf(3); const isMultipleOf5 = isMultipleOf(5); -const isMultipleOf15 = (input: number) => +const isMultipleOf15 = (input: number): boolean => isMultipleOf3(input) && isMultipleOf5(input); diff --git a/tests/Infra/Secondary/prismaFleetRepository.test.ts b/tests/Infra/Secondary/prismaFleetRepository.test.ts index 7affe18..a50887f 100644 --- a/tests/Infra/Secondary/prismaFleetRepository.test.ts +++ b/tests/Infra/Secondary/prismaFleetRepository.test.ts @@ -1,33 +1,34 @@ import { beforeEach, describe, expect, it } from "vitest"; import { Fleet } from "../../../src/Domain/Models/Fleet"; +import { Vehicle } from "../../../src/Domain/Models/Vehicle"; import { PrismaFleetRepository } from "../../../src/Infra/Secondary/Repositories/PrismaFleetRepository"; import { fleet, updatedFleet } from "../../Domain/fleetFixtures"; import { resetDB } from "./resetDB"; -describe("PrismaFleetRepository", () => { - beforeEach(async () => { +describe("PrismaFleetRepository", (): void => { + beforeEach(async (): Promise => { await resetDB(); }); - it("should save and get a fleet", async function () { + it("should save and get a fleet", async function (): Promise { const repository = new PrismaFleetRepository(); await repository.save(fleet()); - const retrievedFleet = await repository.findById(fleet().id); + const retrievedFleet: Fleet = await repository.findById(fleet().id); expect(sortFleetVehicles(retrievedFleet)).toStrictEqual( sortFleetVehicles(fleet()), ); }); - it("should update a fleet", async function () { + it("should update a fleet", async function (): Promise { const repository = new PrismaFleetRepository(); await repository.save(fleet()); await repository.save(updatedFleet()); - const retrievedFleet = await repository.findById(fleet().id); + const retrievedFleet: Fleet = await repository.findById(fleet().id); expect(sortFleetVehicles(retrievedFleet)).toStrictEqual( sortFleetVehicles(updatedFleet()), @@ -39,8 +40,9 @@ describe("PrismaFleetRepository", () => { throw new Error("Fleet is undefined"); } - const sortedVehicles = [...fleet.vehicles].sort((a, b) => - a.plateNumber.localeCompare(b.plateNumber), + const sortedVehicles: Vehicle[] = [...fleet.vehicles].sort( + (a: Vehicle, b: Vehicle): number => + a.plateNumber.localeCompare(b.plateNumber), ); return Fleet.create(fleet.id, fleet.userId, sortedVehicles); } diff --git a/tests/Infra/Secondary/resetDB.ts b/tests/Infra/Secondary/resetDB.ts index f3d3a26..6b675fc 100644 --- a/tests/Infra/Secondary/resetDB.ts +++ b/tests/Infra/Secondary/resetDB.ts @@ -1,6 +1,6 @@ import { prisma } from "../../../src/Infra/Secondary/client"; -export async function resetDB() { +export async function resetDB(): Promise { console.log("Resetting database..."); await prisma.vehiclesInFleets.deleteMany(); await prisma.fleet.deleteMany(); From 5f52e3393bb8c0965068677892d60e6d7760e00a Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 15:56:07 +0200 Subject: [PATCH 09/11] clean: added inferred types --- tests/Component/fleet.test.ts | 26 +++++++++---------- tests/Domain/fleetFixtures.ts | 12 ++++----- tests/Domain/location.test.ts | 8 +++--- .../Secondary/prismaFleetRepository.test.ts | 4 +-- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/Component/fleet.test.ts b/tests/Component/fleet.test.ts index 3945e61..8052d1c 100644 --- a/tests/Component/fleet.test.ts +++ b/tests/Component/fleet.test.ts @@ -1,56 +1,56 @@ -import { beforeEach, describe, expect, it } from "vitest"; import { execSync } from "node:child_process"; +import { beforeEach, describe, expect, it } from "vitest"; import { resetDB } from "../Infra/Secondary/resetDB"; -const test = (args: string) => { +const test = (args: string): string => { return execSync(`node ./dist/src/cli.js ${args}`).toString(); }; -describe("Fleet", () => { - beforeEach(async () => { +describe("Fleet", (): void => { + beforeEach(async (): Promise => { await resetDB(); }); it("Nominal case", async (): Promise => { - const fleetId = createFleet(); + const fleetId: string = createFleet(); expect(fleetId.length).toBeGreaterThan(0); - const registerResponse = registerVehicle(fleetId); + const registerResponse: string = registerVehicle(fleetId); expect(registerResponse).toContain(fleetId); expect(registerResponse).toContain("AB-123-CD"); - const updateLocationResponse = parkVehicle(fleetId); + const updateLocationResponse: string = parkVehicle(fleetId); expect(updateLocationResponse).toContain(fleetId); expect(updateLocationResponse).toContain("AB-123-CD"); expect(updateLocationResponse).toContain("latitude: 48.8566"); expect(updateLocationResponse).toContain("longitude: 2.3522"); - const localizeVehicleResponse = localizeVehicle(fleetId); + const localizeVehicleResponse: string = localizeVehicle(fleetId); expect(localizeVehicleResponse).toContain(fleetId); expect(localizeVehicleResponse).toContain("AB-123-CD"); expect(localizeVehicleResponse).toContain("latitude: 48.8566"); expect(localizeVehicleResponse).toContain("longitude: 2.3522"); expect(localizeVehicleResponse).toContain("altitude: 10"); - const updateLocationAgainResponse = parkVehicle(fleetId); + const updateLocationAgainResponse: string = parkVehicle(fleetId); expect(updateLocationAgainResponse).toContain( `Error: Vehicle AB-123-CD of ${fleetId} is already parked at latitude: 48.8566, longitude: 2.3522, altitude: 10`, ); }); - function createFleet() { + function createFleet(): string { return test("create 2228").trim(); } - function registerVehicle(fleetId: string) { + function registerVehicle(fleetId: string): string { return test(`register-vehicle ${fleetId} AB-123-CD`); } - function parkVehicle(fleetId: string) { + function parkVehicle(fleetId: string): string { return test(`update-location ${fleetId} AB-123-CD 48.8566 2.3522 10`); } - function localizeVehicle(fleetId: string) { + function localizeVehicle(fleetId: string): string { return test(`localize-vehicle ${fleetId} AB-123-CD`); } }); diff --git a/tests/Domain/fleetFixtures.ts b/tests/Domain/fleetFixtures.ts index 29d6978..b99a712 100644 --- a/tests/Domain/fleetFixtures.ts +++ b/tests/Domain/fleetFixtures.ts @@ -2,7 +2,7 @@ import { Vehicle } from "../../src/Domain/Models/Vehicle"; import { Location } from "../../src/Domain/Models/Location"; import { Fleet } from "../../src/Domain/Models/Fleet"; -export function fleet() { +export function fleet(): Fleet { return Fleet.create("7ed14d0d-6401-4b81-a06b-de9655e6f29e", "2345", [ vehicleAWithoutLocation(), vehicleB(), @@ -10,7 +10,7 @@ export function fleet() { ]); } -export function updatedFleet() { +export function updatedFleet(): Fleet { return Fleet.create("7ed14d0d-6401-4b81-a06b-de9655e6f29e", "2345", [ vehicleAWithLocation(), vehicleB(), @@ -18,18 +18,18 @@ export function updatedFleet() { ]); } -export function vehicleAWithoutLocation() { +export function vehicleAWithoutLocation(): Vehicle { return Vehicle.create("AD-5648-MN"); } -export function vehicleAWithLocation() { +export function vehicleAWithLocation(): Vehicle { return Vehicle.create("AD-5648-MN", Location.create(35.1234, 3.4567)); } -export function vehicleB() { +export function vehicleB(): Vehicle { return Vehicle.create("BG-5147-AD", Location.create(34.9999, 7.0978)); } -export function vehicleC() { +export function vehicleC(): Vehicle { return Vehicle.create("GE-1234-TD", Location.create(48.8566, 2.3522, 105)); } diff --git a/tests/Domain/location.test.ts b/tests/Domain/location.test.ts index a30975d..ad7e311 100644 --- a/tests/Domain/location.test.ts +++ b/tests/Domain/location.test.ts @@ -1,15 +1,15 @@ import { describe, expect, it } from "vitest"; import { Location } from "../../src/Domain/Models/Location"; -describe("Location", () => { +describe("Location", (): void => { it("should create a location without altitude", (): void => { - const location = Location.create(48.8566, 2.3522); + const location: Location = Location.create(48.8566, 2.3522); expect(location.altitude).toBe(0); }); it("should be equal to another location's latitude, longitude, altitude", (): void => { - const aLocation = Location.create(48.8566, 2.3522, 100); - const sameLocation = Location.create(48.8566, 2.3522, 100); + const aLocation: Location = Location.create(48.8566, 2.3522, 100); + const sameLocation: Location = Location.create(48.8566, 2.3522, 100); expect(sameLocation.equals(aLocation)).toBeTruthy(); }); }); diff --git a/tests/Infra/Secondary/prismaFleetRepository.test.ts b/tests/Infra/Secondary/prismaFleetRepository.test.ts index a50887f..7b195b0 100644 --- a/tests/Infra/Secondary/prismaFleetRepository.test.ts +++ b/tests/Infra/Secondary/prismaFleetRepository.test.ts @@ -1,9 +1,9 @@ import { beforeEach, describe, expect, it } from "vitest"; +import { fleet, updatedFleet } from "../../Domain/fleetFixtures"; +import { resetDB } from "./resetDB"; import { Fleet } from "../../../src/Domain/Models/Fleet"; import { Vehicle } from "../../../src/Domain/Models/Vehicle"; import { PrismaFleetRepository } from "../../../src/Infra/Secondary/Repositories/PrismaFleetRepository"; -import { fleet, updatedFleet } from "../../Domain/fleetFixtures"; -import { resetDB } from "./resetDB"; describe("PrismaFleetRepository", (): void => { beforeEach(async (): Promise => { From cf9470f443bfa38d8bdd2cfb5a70f528e51d4b43 Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Sat, 7 Jun 2025 16:08:22 +0200 Subject: [PATCH 10/11] clean & update prisma --- package-lock.json | 72 ++++++++++++++++----------------- package.json | 4 +- src/Infra/Primary/CLI/create.ts | 2 +- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/package-lock.json b/package-lock.json index a8920aa..d051194 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@eslint/js": "^9.27.0", - "@prisma/client": "^6.8.2", + "@prisma/client": "^6.9.0", "chalk": "^5.4.1", "yargs": "^17.7.2" }, @@ -24,7 +24,7 @@ "eslint-config-prettier": "^10.1.2", "eslint-plugin-prettier": "^5.2.6", "prettier": "^3.5.3", - "prisma": "^6.8.2", + "prisma": "^6.9.0", "ts-node": "^10.9.2", "typescript": "^5.8.3", "typescript-eslint": "^8.31.0", @@ -1183,9 +1183,9 @@ } }, "node_modules/@prisma/client": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.8.2.tgz", - "integrity": "sha512-5II+vbyzv4si6Yunwgkj0qT/iY0zyspttoDrL3R4BYgLdp42/d2C8xdi9vqkrYtKt9H32oFIukvyw3Koz5JoDg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.9.0.tgz", + "integrity": "sha512-Gg7j1hwy3SgF1KHrh0PZsYvAaykeR0PaxusnLXydehS96voYCGt1U5zVR31NIouYc63hWzidcrir1a7AIyCsNQ==", "hasInstallScript": true, "license": "Apache-2.0", "engines": { @@ -1205,9 +1205,9 @@ } }, "node_modules/@prisma/config": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.8.2.tgz", - "integrity": "sha512-ZJY1fF4qRBPdLQ/60wxNtX+eu89c3AkYEcP7L3jkp0IPXCNphCYxikTg55kPJLDOG6P0X+QG5tCv6CmsBRZWFQ==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.9.0.tgz", + "integrity": "sha512-Wcfk8/lN3WRJd5w4jmNQkUwhUw0eksaU/+BlAJwPQKW10k0h0LC9PD/6TQFmqKVbHQL0vG2z266r0S1MPzzhbA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { @@ -1215,53 +1215,53 @@ } }, "node_modules/@prisma/debug": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.8.2.tgz", - "integrity": "sha512-4muBSSUwJJ9BYth5N8tqts8JtiLT8QI/RSAzEogwEfpbYGFo9mYsInsVo8dqXdPO2+Rm5OG5q0qWDDE3nyUbVg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.9.0.tgz", + "integrity": "sha512-bFeur/qi/Q+Mqk4JdQ3R38upSYPebv5aOyD1RKywVD+rAMLtRkmTFn28ZuTtVOnZHEdtxnNOCH+bPIeSGz1+Fg==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/engines": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.8.2.tgz", - "integrity": "sha512-XqAJ//LXjqYRQ1RRabs79KOY4+v6gZOGzbcwDQl0D6n9WBKjV7qdrbd042CwSK0v0lM9MSHsbcFnU2Yn7z8Zlw==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.9.0.tgz", + "integrity": "sha512-im0X0bwDLA0244CDf8fuvnLuCQcBBdAGgr+ByvGfQY9wWl6EA+kRGwVk8ZIpG65rnlOwtaWIr/ZcEU5pNVvq9g==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.8.2", - "@prisma/engines-version": "6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e", - "@prisma/fetch-engine": "6.8.2", - "@prisma/get-platform": "6.8.2" + "@prisma/debug": "6.9.0", + "@prisma/engines-version": "6.9.0-10.81e4af48011447c3cc503a190e86995b66d2a28e", + "@prisma/fetch-engine": "6.9.0", + "@prisma/get-platform": "6.9.0" } }, "node_modules/@prisma/engines-version": { - "version": "6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e.tgz", - "integrity": "sha512-Rkik9lMyHpFNGaLpPF3H5q5TQTkm/aE7DsGM5m92FZTvWQsvmi6Va8On3pWvqLHOt5aPUvFb/FeZTmphI4CPiQ==", + "version": "6.9.0-10.81e4af48011447c3cc503a190e86995b66d2a28e", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.9.0-10.81e4af48011447c3cc503a190e86995b66d2a28e.tgz", + "integrity": "sha512-Qp9gMoBHgqhKlrvumZWujmuD7q4DV/gooEyPCLtbkc13EZdSz2RsGUJ5mHb3RJgAbk+dm6XenqG7obJEhXcJ6Q==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/fetch-engine": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.8.2.tgz", - "integrity": "sha512-lCvikWOgaLOfqXGacEKSNeenvj0n3qR5QvZUOmPE2e1Eh8cMYSobxonCg9rqM6FSdTfbpqp9xwhSAOYfNqSW0g==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.9.0.tgz", + "integrity": "sha512-PMKhJdl4fOdeE3J3NkcWZ+tf3W6rx3ht/rLU8w4SXFRcLhd5+3VcqY4Kslpdm8osca4ej3gTfB3+cSk5pGxgFg==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.8.2", - "@prisma/engines-version": "6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e", - "@prisma/get-platform": "6.8.2" + "@prisma/debug": "6.9.0", + "@prisma/engines-version": "6.9.0-10.81e4af48011447c3cc503a190e86995b66d2a28e", + "@prisma/get-platform": "6.9.0" } }, "node_modules/@prisma/get-platform": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.8.2.tgz", - "integrity": "sha512-vXSxyUgX3vm1Q70QwzwkjeYfRryIvKno1SXbIqwSptKwqKzskINnDUcx85oX+ys6ooN2ATGSD0xN2UTfg6Zcow==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.9.0.tgz", + "integrity": "sha512-/B4n+5V1LI/1JQcHp+sUpyRT1bBgZVPHbsC4lt4/19Xp4jvNIVcq5KYNtQDk5e/ukTSjo9PZVAxxy9ieFtlpTQ==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.8.2" + "@prisma/debug": "6.9.0" } }, "node_modules/@rollup/rollup-android-arm-eabi": { @@ -4474,15 +4474,15 @@ } }, "node_modules/prisma": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.8.2.tgz", - "integrity": "sha512-JNricTXQxzDtRS7lCGGOB4g5DJ91eg3nozdubXze3LpcMl1oWwcFddrj++Up3jnRE6X/3gB/xz3V+ecBk/eEGA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.9.0.tgz", + "integrity": "sha512-resJAwMyZREC/I40LF6FZ6rZTnlrlrYrb63oW37Gq+U+9xHwbyMSPJjKtM7VZf3gTO86t/Oyz+YeSXr3CmAY1Q==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/config": "6.8.2", - "@prisma/engines": "6.8.2" + "@prisma/config": "6.9.0", + "@prisma/engines": "6.9.0" }, "bin": { "prisma": "build/index.js" diff --git a/package.json b/package.json index a770653..002f367 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "ISC", "dependencies": { "@eslint/js": "^9.27.0", - "@prisma/client": "^6.8.2", + "@prisma/client": "^6.9.0", "chalk": "^5.4.1", "yargs": "^17.7.2" }, @@ -18,7 +18,7 @@ "eslint-config-prettier": "^10.1.2", "eslint-plugin-prettier": "^5.2.6", "prettier": "^3.5.3", - "prisma": "^6.8.2", + "prisma": "^6.9.0", "ts-node": "^10.9.2", "typescript": "^5.8.3", "typescript-eslint": "^8.31.0", diff --git a/src/Infra/Primary/CLI/create.ts b/src/Infra/Primary/CLI/create.ts index 285a01b..3a4a7f6 100644 --- a/src/Infra/Primary/CLI/create.ts +++ b/src/Infra/Primary/CLI/create.ts @@ -13,7 +13,7 @@ export const createFleetCommand: CommandModule = { type: "string", describe: "User ID", }), - handler: async (argv) => { + handler: async (argv): Promise => { const { userId } = argv; const repository = new PrismaFleetRepository(); From f84e2c770418c4a485ca47249e6a4339de33644e Mon Sep 17 00:00:00 2001 From: Johana Lavigne Date: Wed, 11 Jun 2025 11:08:10 +0200 Subject: [PATCH 11/11] cleanup --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1df2c8c..4f1946f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fleet Management System - Fulll Technical Test +# Fleet Management System ## Overview