Last active
November 17, 2023 07:10
-
-
Save durre/e1781dc56fd7591859394db918a81b8e to your computer and use it in GitHub Desktop.
A bit more extensive example to go with the article, https://durre.se/you-might-not-need-javascript-classes. Here we wire "everything" up and show how it can be tested.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createOrderDao } from './orderDao' | |
import { createProductDao } from './productDao' | |
import { createPaymentService } from './paymentService' | |
import { createOrderService } from './orderService' | |
const orderDao = createOrderDao() | |
const productDao = createProductDao() | |
const paymentService = createPaymentService() | |
const orderService = createOrderService({ orderDao, productDao, paymentService }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createPlaceOrder } from './placeOrder' | |
type OrderServiceDependencies = { | |
productDao: ProductDao; | |
orderDao: OrderDao; | |
paymentService: PaymentService; | |
}; | |
export const createOrderService = (dependencies: OrderServiceDependencies) => { | |
const { productDao, orderDao, paymentService } = dependencies; | |
return { | |
placeOrder: createPlaceOrder({ | |
getProductsById: productDao.getProductsById, | |
chargeCreditCard: paymentService.chargeCreditCard, | |
saveOrder: orderDao.savedOrder | |
}) | |
}; | |
}; | |
type OrderService = ReturnType<typeof createOrderService>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const getProductsById = jest.fn(() => | |
Promise.resolve([{ price: 10, id: "1" }]) | |
); | |
const chargeCreditCard = jest.fn(); | |
const saveOrder = jest.fn(); | |
const customerInfo: CustomerInfo = { creditCard: "1234 111 111" }; | |
const placeOrder = createPlaceOrder({ | |
getProductsById, | |
chargeCreditCard, | |
saveOrder | |
}); | |
describe("placeOrder", () => { | |
test("places order successfully", async () => { | |
const order: Order = { productIds: ["1"], id: "1" }; | |
await placeOrder(order, customerInfo); | |
expect(getProductsById).toHaveBeenCalledWith(order.productIds); | |
expect(chargeCreditCard).toHaveBeenCalledWith(10, customerInfo.creditCard); | |
expect(saveOrder).toHaveBeenCalled(); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type PlaceOrderDependencies = { | |
getProductsById: (ids: string[]) => Promise<Product[]>; | |
chargeCreditCard: (amount: number, creditCard: string) => Promise<Receipt>; | |
saveOrder: (order: Order, receipt: Receipt) => Promise<Order>; | |
}; | |
const sumTotalPrice = (products: Product[]) => | |
products.reduce((acc, curr) => acc + curr.price, 0); | |
export const createPlaceOrder = | |
(deps: PlaceOrderDependencies) => | |
async (order: Order, customerInfo: CustomerInfo) => { | |
const { getProductsById, chargeCreditCard, saveOrder } = deps; | |
const products = await getProductsById(order.productIds); | |
const receipt = await chargeCreditCard( | |
sumTotalPrice(products), | |
customerInfo.creditCard | |
); | |
return saveOrder(order, receipt); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Product = { | |
id: string; | |
price: number; | |
}; | |
type Order = { | |
id: string; | |
productIds: string[]; | |
}; | |
type CustomerInfo = { | |
creditCard: string; | |
}; | |
// I think you get the idea anyway, right? | |
type Receipt = any; | |
type OrderDao = any; | |
type ProductDao = any; | |
type PaymentService = any; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment