Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(medusa): Implement premises of the creation flow of an order edit #2187

Merged
merged 1 commit into from
Sep 16, 2022
Merged
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
135 changes: 133 additions & 2 deletions integration-tests/api/__tests__/admin/order-edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,16 @@ describe("[MEDUSA_FF_ORDER_EDITING] /admin/order-edits", () => {

await simpleLineItemFactory(dbConnection, {
id: lineItemUpdateId,
order_id: orderEdit.order_id,
order_id: null,
variant_id: product1.variants[0].id,
unit_price: 1000,
quantity: 2,
})
await simpleLineItemFactory(dbConnection, {
id: lineItemCreateId,
order_id: orderEdit.order_id,
order_id: null,
variant_id: product3.variants[0].id,
unit_price: 100,
quantity: 2,
})

Expand Down Expand Up @@ -175,6 +177,13 @@ describe("[MEDUSA_FF_ORDER_EDITING] /admin/order-edits", () => {
removed_items: expect.arrayContaining([
expect.objectContaining({ id: lineItemId2, quantity: 1 }),
]),
shipping_total: 0,
gift_card_total: 0,
gift_card_tax_total: 0,
discount_total: 0,
tax_total: 0,
total: 2200,
subtotal: 2200,
})
)
expect(response.status).toEqual(200)
Expand Down Expand Up @@ -292,4 +301,126 @@ describe("[MEDUSA_FF_ORDER_EDITING] /admin/order-edits", () => {
})
})
})

describe("POST /admin/order-edits", () => {
let orderId
const prodId1 = IdMap.getId("prodId1")
const prodId2 = IdMap.getId("prodId2")
const lineItemId1 = IdMap.getId("line-item-1")
const lineItemId2 = IdMap.getId("line-item-2")

beforeEach(async () => {
await adminSeeder(dbConnection)

const product1 = await simpleProductFactory(dbConnection, {
id: prodId1,
})
const product2 = await simpleProductFactory(dbConnection, {
id: prodId2,
})

const order = await simpleOrderFactory(dbConnection, {
email: "test@testson.com",
tax_rate: null,
fulfillment_status: "fulfilled",
payment_status: "captured",
region: {
id: "test-region",
name: "Test region",
tax_rate: 12.5,
},
line_items: [
{
id: lineItemId1,
variant_id: product1.variants[0].id,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
},
{
id: lineItemId2,
variant_id: product2.variants[0].id,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
},
],
})
orderId = order.id
})

afterEach(async () => {
const db = useDb()
return await db.teardown()
})

it("creates and order edit", async () => {
const api = useApi()

const response = await api.post(
`/admin/order-edits/`,
{
order_id: orderId,
internal_note: "This is an internal note",
},
adminHeaders
)

expect(response.status).toEqual(200)
expect(response.data.order_edit).toEqual(
expect.objectContaining({
order_id: orderId,
created_by: "admin_user",
requested_by: null,
canceled_by: null,
confirmed_by: null,
internal_note: "This is an internal note",
items: expect.arrayContaining([
expect.objectContaining({
id: lineItemId1,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
}),
expect.objectContaining({
id: lineItemId2,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
}),
]),
shipping_total: 0,
gift_card_total: 0,
gift_card_tax_total: 0,
discount_total: 0,
tax_total: 0,
total: 2000,
subtotal: 2000,
})
)
})

it("throw an error if an active order edit already exists", async () => {
const api = useApi()

const payload = {
order_id: orderId,
internal_note: "This is an internal note",
}

await api.post(`/admin/order-edits/`, payload, adminHeaders)
const err = await api
.post(`/admin/order-edits/`, payload, adminHeaders)
.catch((e) => e)

expect(err.message).toBe("Request failed with status code 400")
expect(err.response.data.message).toBe(
`An active order edit already exists for the order ${payload.order_id}`
)
})
})
})
13 changes: 11 additions & 2 deletions integration-tests/api/__tests__/store/order-edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,16 @@ describe("[MEDUSA_FF_ORDER_EDITING] /store/order-edits", () => {

await simpleLineItemFactory(dbConnection, {
id: lineItemUpdateId,
order_id: orderEdit.order_id,
order_id: null,
variant_id: product1.variants[0].id,
unit_price: 1000,
quantity: 2,
})
await simpleLineItemFactory(dbConnection, {
id: lineItemCreateId,
order_id: orderEdit.order_id,
order_id: null,
variant_id: product3.variants[0].id,
unit_price: 100,
quantity: 2,
})

Expand Down Expand Up @@ -168,6 +170,13 @@ describe("[MEDUSA_FF_ORDER_EDITING] /store/order-edits", () => {
removed_items: expect.arrayContaining([
expect.objectContaining({ id: lineItemId2, quantity: 1 }),
]),
shipping_total: 0,
gift_card_total: 0,
gift_card_tax_total: 0,
discount_total: 0,
tax_total: 0,
total: 2200,
subtotal: 2200,
})
)

Expand Down
15 changes: 12 additions & 3 deletions packages/medusa-js/src/resources/admin/order-edits.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
AdminOrdersEditsRes,
AdminOrderEditDeleteRes
AdminOrderEditDeleteRes,
AdminOrderEditsRes,
AdminPostOrderEditsReq,
} from "@medusajs/medusa"
import { ResponsePromise } from "../../typings"
import BaseResource from "../base"
Expand All @@ -9,11 +10,19 @@ class AdminOrderEditsResource extends BaseResource {
retrieve(
id: string,
customHeaders: Record<string, any> = {}
): ResponsePromise<AdminOrdersEditsRes> {
): ResponsePromise<AdminOrderEditsRes> {
const path = `/admin/order-edits/${id}`
return this.client.request("GET", path, undefined, {}, customHeaders)
}

create(
payload: AdminPostOrderEditsReq,
customHeaders: Record<string, any> = {}
): ResponsePromise<AdminOrderEditsRes> {
const path = `/admin/order-edits`
return this.client.request("POST", path, payload, {}, customHeaders)
}

delete(
id: string,
customHeaders: Record<string, any> = {}
Expand Down
12 changes: 12 additions & 0 deletions packages/medusa-react/mocks/handlers/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,18 @@ export const adminHandlers = [
)
}),

rest.post("/admin/order-edits/", (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json({
order_edit: {
...fixtures.get("order_edit"),
...(req.body as any),
},
})
)
}),

rest.get("/store/order-edits/:id", (req, res, ctx) => {
const { id } = req.params
return res(
Expand Down
20 changes: 19 additions & 1 deletion packages/medusa-react/src/hooks/admin/order-edits/mutations.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
import {
AdminOrderEditDeleteRes,
AdminOrderEditsRes,
AdminPostOrderEditsReq,
} from "@medusajs/medusa"
import { Response } from "@medusajs/medusa-js"
import { useMutation, UseMutationOptions, useQueryClient } from "react-query"
import { adminOrderEditsKeys } from "."
import { useMedusa } from "../../../contexts/medusa"
import { buildOptions } from "../../utils/buildOptions"
import { useMedusa } from "../../../contexts"

export const useAdminCreateOrderEdit = (
options?: UseMutationOptions<
Response<AdminOrderEditsRes>,
Error,
AdminPostOrderEditsReq
>
) => {
const { client } = useMedusa()
const queryClient = useQueryClient()
return useMutation(
(payload: AdminPostOrderEditsReq) =>
client.admin.orderEdits.create(payload),
buildOptions(queryClient, adminOrderEditsKeys.lists(), options)
)
}

export const useAdminDeleteOrderEdit = (
id: string,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AdminOrdersEditsRes } from "@medusajs/medusa"
import { AdminOrderEditsRes } from "@medusajs/medusa"
import { queryKeysFactory } from "../../utils"
import { UseQueryOptionsWrapper } from "../../../types"
import { Response } from "@medusajs/medusa-js"
Expand All @@ -13,7 +13,7 @@ type OrderEditQueryKeys = typeof adminOrderEditsKeys
export const useAdminOrderEdit = (
id: string,
options?: UseQueryOptionsWrapper<
Response<AdminOrdersEditsRes>,
Response<AdminOrderEditsRes>,
Error,
ReturnType<OrderEditQueryKeys["detail"]>
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useAdminDeleteOrderEdit } from "../../../../src/"
import {
useAdminCreateOrderEdit,
useAdminDeleteOrderEdit,
} from "../../../../src/"
import { renderHook } from "@testing-library/react-hooks"
import { fixtures } from "../../../../mocks/data"
import { createWrapper } from "../../../utils"
import { fixtures } from "../../../../mocks/data"

describe("useAdminDelete hook", () => {
test("Deletes an order edit", async () => {
Expand All @@ -11,7 +14,6 @@ describe("useAdminDelete hook", () => {
})

result.current.mutate()

await waitFor(() => result.current.isSuccess)

expect(result.current.data.response.status).toEqual(200)
Expand All @@ -24,3 +26,30 @@ describe("useAdminDelete hook", () => {
)
})
})

describe("useAdminCreateOrderEdit hook", () => {
test("Created an order edit", async () => {
const { result, waitFor } = renderHook(() => useAdminCreateOrderEdit(), {
wrapper: createWrapper(),
})

const payload = {
order_id: "ord_1",
internal_note: "This is an internal note",
}

result.current.mutate(payload)

await waitFor(() => result.current.isSuccess)

expect(result.current.data.response.status).toEqual(200)
expect(result.current.data).toEqual(
expect.objectContaining({
order_edit: {
...fixtures.get("order_edit"),
...payload,
},
})
)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { IdMap } from "medusa-test-utils"
import { request } from "../../../../../helpers/test-request"
import { orderEditServiceMock } from "../../../../../services/__mocks__/order-edit"
import OrderEditingFeatureFlag from "../../../../../loaders/feature-flags/order-editing"

describe("POST /admin/order-edits", () => {
describe("successfully create an order edit", () => {
const orderId = IdMap.getId("order-edit-order-id-test")
const internalNote = "test internal note"
let subject

beforeAll(async () => {
subject = await request("POST", "/admin/order-edits", {
payload: {
order_id: orderId,
internal_note: internalNote,
},
adminSession: {
jwt: {
userId: IdMap.getId("admin_user"),
},
},
flags: [OrderEditingFeatureFlag],
})
})

afterAll(async () => {
jest.clearAllMocks()
})

it("returns 200", () => {
expect(subject.status).toEqual(200)
})

it("calls order edit service create", () => {
expect(orderEditServiceMock.create).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.create).toHaveBeenCalledWith(
{
order_id: orderId,
internal_note: internalNote,
},
{
loggedInUserId: IdMap.getId("admin_user"),
}
)
})
})
})
Loading