diff --git a/.changeset/young-laws-laugh.md b/.changeset/young-laws-laugh.md new file mode 100644 index 00000000..6b68c97b --- /dev/null +++ b/.changeset/young-laws-laugh.md @@ -0,0 +1,5 @@ +--- +"@labdigital/commercetools-mock": minor +--- + +Add support for as associate shopping lists diff --git a/src/repositories/as-associate.test.ts b/src/repositories/as-associate.test.ts index 35a8a0d6..6c91c315 100644 --- a/src/repositories/as-associate.test.ts +++ b/src/repositories/as-associate.test.ts @@ -1,3 +1,4 @@ +import type { ShoppingListDraft } from "@commercetools/platform-sdk"; import { describe, expect, test } from "vitest"; import type { Config } from "#src/config.ts"; import { InMemoryStorage } from "#src/storage/index.ts"; @@ -5,6 +6,7 @@ import { AsAssociateCartRepository, AsAssociateOrderRepository, AsAssociateQuoteRequestRepository, + AsAssociateShoppingListRepository, } from "./as-associate.ts"; import { CustomerRepository } from "./customer/index.ts"; @@ -123,4 +125,27 @@ describe("As Associate Repositories", () => { expect(retrieved).toBeDefined(); expect(retrieved?.id).toBe(quoteRequest.id); }); + + test("AsAssociateShoppingListRepository can create and retrieve shopping lists", () => { + const repository = new AsAssociateShoppingListRepository(config); + const ctx = { projectKey: "test-project" }; + + const shoppingListDraft: ShoppingListDraft = { + name: { "en-US": "My Shopping List" }, + }; + + const shoppingList = repository.create(ctx, shoppingListDraft); + expect(shoppingList.id).toBeDefined(); + expect(shoppingList.version).toBe(1); + + // Test query + const result = repository.query(ctx); + expect(result.count).toBe(1); + expect(result.results[0].id).toBe(shoppingList.id); + + // Test get + const retrieved = repository.get(ctx, shoppingList.id); + expect(retrieved).toBeDefined(); + expect(retrieved?.id).toBe(shoppingList.id); + }); }); diff --git a/src/repositories/as-associate.ts b/src/repositories/as-associate.ts index fb8b0b9b..484f4962 100644 --- a/src/repositories/as-associate.ts +++ b/src/repositories/as-associate.ts @@ -1,7 +1,9 @@ import { CartRepository } from "./cart/index.ts"; import { OrderRepository } from "./order/index.ts"; import { QuoteRequestRepository } from "./quote-request/index.ts"; +import { ShoppingListRepository } from "./shopping-list/index.ts"; export class AsAssociateOrderRepository extends OrderRepository {} export class AsAssociateCartRepository extends CartRepository {} export class AsAssociateQuoteRequestRepository extends QuoteRequestRepository {} +export class AsAssociateShoppingListRepository extends ShoppingListRepository {} diff --git a/src/repositories/index.ts b/src/repositories/index.ts index e34252ae..b7a96da8 100644 --- a/src/repositories/index.ts +++ b/src/repositories/index.ts @@ -4,6 +4,7 @@ import { AsAssociateCartRepository, AsAssociateOrderRepository, AsAssociateQuoteRequestRepository, + AsAssociateShoppingListRepository, } from "./as-associate.ts"; import { AssociateRoleRepository } from "./associate-role.ts"; import { AttributeGroupRepository } from "./attribute-group.ts"; @@ -53,6 +54,7 @@ export const createRepositories = (config: Config) => ({ cart: new AsAssociateCartRepository(config), order: new AsAssociateOrderRepository(config), "quote-request": new AsAssociateQuoteRequestRepository(config), + "shopping-list": new AsAssociateShoppingListRepository(config), }, "associate-role": new AssociateRoleRepository(config), "attribute-group": new AttributeGroupRepository(config), diff --git a/src/services/as-associate-shopping-list.test.ts b/src/services/as-associate-shopping-list.test.ts new file mode 100644 index 00000000..cb3ca2f6 --- /dev/null +++ b/src/services/as-associate-shopping-list.test.ts @@ -0,0 +1,58 @@ +import supertest from "supertest"; +import { describe, expect, test } from "vitest"; +import { CommercetoolsMock } from "../index.ts"; + +const ctMock = new CommercetoolsMock(); +const projectKey = "dummy"; +const customerId = "5fac8fca-2484-4b14-a1d1-cfdce2f8d3c4"; +const businessUnitKey = "test-business-unit"; + +describe("AsAssociateShoppingList", () => { + test("Create shopping list", async () => { + const draft = { + name: { en: "My list" }, + }; + const response = await supertest(ctMock.app) + .post( + `/${projectKey}/as-associate/${customerId}/in-business-unit/key=${businessUnitKey}/shopping-lists`, + ) + .send(draft); + + expect(response.status).toBe(201); + expect(response.body.id).toBeDefined(); + }); + + test("Get shopping list", async () => { + const createResponse = await supertest(ctMock.app) + .post( + `/${projectKey}/as-associate/${customerId}/in-business-unit/key=${businessUnitKey}/shopping-lists`, + ) + .send({ name: { en: "Groceries" } }); + + expect(createResponse.status).toBe(201); + + const response = await supertest(ctMock.app).get( + `/${projectKey}/as-associate/${customerId}/in-business-unit/key=${businessUnitKey}/shopping-lists/${createResponse.body.id}`, + ); + + expect(response.status).toBe(200); + expect(response.body).toEqual(createResponse.body); + }); + + test("Query shopping lists", async () => { + const createResponse = await supertest(ctMock.app) + .post( + `/${projectKey}/as-associate/${customerId}/in-business-unit/key=${businessUnitKey}/shopping-lists`, + ) + .send({ name: { en: "Errands" } }); + + expect(createResponse.status).toBe(201); + + const response = await supertest(ctMock.app).get( + `/${projectKey}/as-associate/${customerId}/in-business-unit/key=${businessUnitKey}/shopping-lists`, + ); + + expect(response.status).toBe(200); + expect(response.body.count).toBeGreaterThan(0); + }); +}); diff --git a/src/services/as-associate-shopping-list.ts b/src/services/as-associate-shopping-list.ts new file mode 100644 index 00000000..839708cd --- /dev/null +++ b/src/services/as-associate-shopping-list.ts @@ -0,0 +1,33 @@ +import { Router } from "express"; +import type { ShoppingListRepository } from "#src/repositories/shopping-list/index.ts"; +import AbstractService from "./abstract.ts"; + +export class AsAssociateShoppingListService extends AbstractService { + public repository: ShoppingListRepository; + + constructor(parent: Router, repository: ShoppingListRepository) { + super(parent); + this.repository = repository; + } + + getBasePath() { + return "shopping-lists"; + } + + registerRoutes(parent: Router) { + const basePath = this.getBasePath(); + const router = Router({ mergeParams: true }); + + this.extraRoutes(router); + + router.get("/", this.get.bind(this)); + router.get("/:id", this.getWithId.bind(this)); + + router.delete("/:id", this.deleteWithId.bind(this)); + + router.post("/", this.post.bind(this)); + router.post("/:id", this.postWithId.bind(this)); + + parent.use(`/${basePath}`, router); + } +} diff --git a/src/services/as-associate.ts b/src/services/as-associate.ts index 20ea4e55..30c342ff 100644 --- a/src/services/as-associate.ts +++ b/src/services/as-associate.ts @@ -3,15 +3,18 @@ import type { AsAssociateCartRepository, AsAssociateOrderRepository, AsAssociateQuoteRequestRepository, + AsAssociateShoppingListRepository, } from "#src/repositories/as-associate.ts"; import { AsAssociateCartService } from "./as-associate-cart.ts"; import { AsAssociateOrderService } from "./as-associate-order.ts"; import { AsAssociateQuoteRequestService } from "./as-associate-quote-request.ts"; +import { AsAssociateShoppingListService } from "./as-associate-shopping-list.ts"; type Repositories = { cart: AsAssociateCartRepository; order: AsAssociateOrderRepository; "quote-request": AsAssociateQuoteRequestRepository; + "shopping-list": AsAssociateShoppingListRepository; }; export class AsAssociateService { @@ -21,6 +24,7 @@ export class AsAssociateService { cart: AsAssociateCartService; order: AsAssociateOrderService; "quote-request": AsAssociateQuoteRequestService; + "shopping-list": AsAssociateShoppingListService; }; constructor(parent: Router, repositories: Repositories) { @@ -33,6 +37,10 @@ export class AsAssociateService { this.router, repositories["quote-request"], ), + "shopping-list": new AsAssociateShoppingListService( + this.router, + repositories["shopping-list"], + ), }; parent.use( "/as-associate/:associateId/in-business-unit/key=:businessUnitId",