Skip to content
This repository was archived by the owner on Apr 26, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions features/get_cart_detail.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Feature: Get cart detail

Background:
Given the following products exist:
| sku | name | price |
| 001 | potatoes | 2.5 |
| 002 | water | 0.95 |
And there is a cart discount "free shipping" for 10 % with code "FREE-SHIPPING"
And I have a cart
And I add 2 units of product "001" to my cart
And I add 1 units of product "002" to my cart
And I apply "FREE-SHIPPING" discount to my cart

Scenario: Get cart details
When I send a "GET" request to "/carts/1"
Then the response status should be 200 with body:
"""
{
"id": 1,
"total": 5.36,
"lines": [
{
"sku": "001",
"name": "potatoes",
"quantity": 2
},
{
"sku": "002",
"name": "water",
"quantity": 1
}
],
"discounts": [
"free shipping"
]
}
"""
4 changes: 3 additions & 1 deletion src/application.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataSource, Repository } from "typeorm"
import { SnakeNamingStrategy } from "typeorm-naming-strategies"
import CartDiscountAdder from "./application/CartDiscountAdder"
import CartFetcher from "./application/CartFetcher"
import CartLineAdder from "./application/CartlineAdder"
import Server from "./config/Server"
import CartController from "./controller/CartController"
Expand All @@ -26,7 +27,8 @@ const productRepository: Repository<Product> = connection.getRepository(Product)
const discountRepository: Repository<Discount> = connection.getRepository(Discount)
const cartLineAdder: CartLineAdder = new CartLineAdder(cartRepository, productRepository)
const cartDiscountAdder: CartDiscountAdder = new CartDiscountAdder(cartRepository, discountRepository)
const cartController = new CartController(cartLineAdder, cartDiscountAdder)
const cartFetcher: CartFetcher = new CartFetcher(cartRepository)
const cartController = new CartController(cartLineAdder, cartDiscountAdder, cartFetcher)
const server: Server = new Server(process.env.WEB_PORT, [cartController])

connection.initialize()
Expand Down
52 changes: 52 additions & 0 deletions src/application/CartFetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Repository } from "typeorm"
import Cart from "../entity/Cart"
import CartLine from "../entity/CartLine"
import Discount from "../entity/Discount"


class CartFetcher {
private cartRepository: Repository<Cart>

constructor(cartRepository: Repository<Cart>) {
this.cartRepository = cartRepository
}

public async fetch(cartId: number): Promise<CartDetail> {
const cart: Cart = await this.cartRepository.findOneByOrFail({id: cartId})

return new CartDetail(
cart.id,
cart.totalPrice(),
cart.lines.map((line: CartLine) => new Line(line.product.sku, line.product.name, line.quantity)),
cart.discounts.map((discount: Discount) => discount.name)
)
}
}

class CartDetail {
public id: number
public total: number
public lines: Line[]
public discounts: string[]

constructor(id: number, total:number, lines: Line[], discounts: string[]) {
this.id = id
this.total = total
this.lines = lines
this.discounts = discounts
}
}

class Line {
public sku: string
public name: string
public quantity: number

constructor(sku: string, name: string, quantity: number) {
this.sku = sku
this.name = name
this.quantity = quantity
}
}

export default CartFetcher
14 changes: 13 additions & 1 deletion src/controller/CartController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { Application, Request, Response } from "express"
import Controller from "../config/Controller"
import CartDiscountAdder from "../application/CartDiscountAdder"
import CartLineAdder from "../application/CartlineAdder"
import CartFetcher from "../application/CartFetcher"

class CartController implements Controller {
private cartLineAdder: CartLineAdder
private cartDiscountAdder: CartDiscountAdder
private cartFetcher: CartFetcher

constructor(cartLineAdder: CartLineAdder, cartDiscountAdder: CartDiscountAdder) {
constructor(cartLineAdder: CartLineAdder, cartDiscountAdder: CartDiscountAdder, cartFetcher: CartFetcher) {
this.cartLineAdder = cartLineAdder
this.cartDiscountAdder = cartDiscountAdder
this.cartFetcher = cartFetcher
}

private addLine = async (request: Request, response: Response): Promise<void> => {
Expand All @@ -30,9 +33,18 @@ class CartController implements Controller {
response.status(200).send()
}

private recoverCartDetail = async (request: Request, response: Response): Promise<void> => {
const { id } = request.params

const cart = await this.cartFetcher.fetch(+id)

response.status(200).send(cart)
}

public addRoutes(app: Application): void {
app.post("/carts/:id/lines", this.addLine)
app.post("/carts/:id/discounts", this.addDiscount)
app.get("/carts/:id", this.recoverCartDetail)
}
}

Expand Down
35 changes: 35 additions & 0 deletions src/tests/steps/HttpSteps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { before, binding, then, when } from "cucumber-tsflow"
import axios, { Axios, AxiosResponse } from 'axios'
import assert from "assert"

@binding()
class HttpSteps {
private axios: Axios
private response: AxiosResponse|undefined;

constructor() {
this.axios = axios
}

@before()
public setUp(): void {
this.response = undefined;
}

@when("I send a {string} request to {string}")
public async sendARequestWithBodyToWith(method: string, path: string): Promise<void> {
this.response = await this.axios.request({
method: method,
baseURL: `http://${process.env.WEB_HOST}:${process.env.WEB_PORT}`,
url: path
})
}

@then("the response status should be {int} with body:")
public async theResponseStatusAndBodyShouldBe(status: number, body: string): Promise<void> {
assert.equal(this.response?.status, status)
assert.equal(JSON.stringify(this.response?.data), JSON.stringify(JSON.parse(body)))
}
}

export default HttpSteps