Skip to content

Commit

Permalink
add unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
zylcom committed Feb 6, 2024
1 parent 8f106ff commit d4c1b21
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 99 deletions.
35 changes: 35 additions & 0 deletions __test__/order.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,38 @@ describe("POST /api/orders/:orderId/cancel", function () {
expect(result.body.errors).toBeDefined();
});
});

describe("GET /api/orders", function () {
let token;

beforeEach(async () => {
await createTestUser();

token = (await request.post("/api/users/login").send({ username, password })).body.data.token;
});

afterEach(async () => {
await removeTestUser();
});

it("should can get list order of guest user", async () => {
const guestUser = await request.get("/api/users/guest");
const cart = {
cartItems: [{ productSlug: "pizza-1", quantity: 1 }],
totalPrice: 10001,
};
const order = await request.post("/api/orders").query({ guest_uid: guestUser.body.data.guestUserId }).send({
cart,
customerDetails,
shippingDetails,
deliveryDetails,
});

const result = await request.get("/api/orders").query({ guest_uid: guestUser.body.data.guestUserId });

expect(result.status).toBe(200);
expect(result.body.data.length).toBeGreaterThan(0);
expect(result.body.data[0].id).toBe(order.body.data.id);
expect(result.body.data[0].name).toBe(order.body.data.name);
});
});
49 changes: 39 additions & 10 deletions __test__/payment.test.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,53 @@
import { request } from "./setup";
import { createPaymentTest, createTestUser, name, removeTestUser } from "./test-util";
import { createPaymentTest, createTestUser, password, removePaymentTest, removeTestUser, username } from "./test-util";

describe("GET /api/payment/:transactionId", function () {
let token;

describe("GET /api/payment/:sessionId", function () {
beforeEach(async () => {
await createTestUser();
await createPaymentTest();

token = (await request.post("/api/users/login").send({ username, password })).body.data.token;
});

afterEach(async () => {
await removePaymentTest();
await removeTestUser();
});

it("should can get payment data", async () => {
const guestUser = await request.get("/api/users/guest");

// await createPaymentTest(guestUser.body.data.guestUserId);
// const result = await request.get(`/api/payment/${sessionId}`).query({ guest_uid: guestUser.body.data.guestUserId });

/**
* Midtrans error
* data: {
* status_code: '500',
* status_message: 'Sorry. Our system is recovering from unexpected issues. Please retry.',
* id: 'a7e65186-ad58-4621-9f4b-4b9af41b87cb'
* }
*/
// const order = await request.get("/api/orders/76a1b635-5964-462d-a224-3a42008d9abb").set("Authorization", `Bearer ${token}`);
// const notificationJson = {
// transaction_time: "2023-12-23 16:42:13",
// transaction_status: "settlement",
// transaction_id: "d33d1747-f265-4a64-89b8-f02982e73032",
// store: "alfamart",
// status_message: "midtrans payment notification",
// status_code: "201",
// signature_key: "1753c8db0376d14e8d92ab14cc8a0b781f935e92e7ba848388e63c276403bb749a0bad9d34e61b3bfbeacb481658ce5e8edb1a98d642d540c5091fe961da9d54",
// payment_type: "cstore",
// payment_code: "3101101715649288",
// order_id: order.body.data.id,
// merchant_id: "G310191577",
// gross_amount: order.body.data.total,
// fraud_status: "accept",
// expiry_time: "2023-12-24 16:42:13",
// currency: "IDR",
// };
// await request.post("/api/webhook").send(notificationJson);
// const result = await request.get(`/api/payment/${notificationJson.transaction_id}`).set("Authorization", `Bearer ${token}`);
// expect(result.status).toBe(200);
// expect(result.body.data.guestId).toBe(guestUser.body.data.guestUserId);
// expect(result.body.data.checkoutSessionId).toBe(sessionId);
// expect(result.body.data.payment.name).toBe(name);
// expect(result.body.data.order.id).toBe(order.body.data.id);
// expect(result.body.data.signatureKey).toBe(notificationJson.signature_key);
// expect(result.body.data.transactionId).toBe(notificationJson.transaction_id);
});
});
48 changes: 40 additions & 8 deletions __test__/test-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ const tagsProduct = [
{ id: 2, name: "Tag 2", slug: "tag-2" },
{ id: 3, name: "Tag 3", slug: "tag-3" },
];
const shippingDetails = {
address: "adres",
detail: "home detail",
city: "jkbar",
state: "Jkt",
postalCode: "11224",
};
const deliveryDetails = {
method: "express",
cost: 5000,
};

const createManyCartItems = () => {
let items = [];
Expand Down Expand Up @@ -150,27 +161,47 @@ const removeTestReview = async () => {
await prismaClient.review.deleteMany({});
};

const createPaymentTest = async (guestId) => {
const createPaymentTest = async () => {
await prismaClient.order.create({
data: {
subTotal: 1001,
total: 1001,
items: { create: [{ price: 1001, productName: "Pizza-1", quantity: 1, product: { connect: { slug: "pizza-1" } } }] },
id: "76a1b635-5964-462d-a224-3a42008d9abb",
subTotal: 167500,
total: 167500,
name,
phone: phonenumberForm.number,
user: { connect: { username } },
items: { create: [{ price: 167500, productName: "Pizza-1", quantity: 1, product: { connect: { slug: "pizza-1" } } }] },
status: "complete",
shipment: {
create: {
...shippingDetails,
...deliveryDetails,
name,
phone: phonenumberForm.number,
},
},
payment: {
create: {
amount: 1001,
method: "card",
amount: 167500,
currency: "IDR",
signatureKey: "1753c8db0376d14e8d92ab14cc8a0b781f935e92e7ba848388e63c276403bb749a0bad9d34e61b3bfbeacb481658ce5e8edb1a98d642d540c5091fe961da9d54",
method: "alfamart",
username,
name,
paymentIntent: "pi_asd",
status: "paid",
},
},
guestId,
},
});
};

const removePaymentTest = async () => {
await prismaClient.payment.deleteMany({});
await prismaClient.shipment.deleteMany({});
await prismaClient.orderItem.deleteMany({});
await prismaClient.order.deleteMany({});
};

export {
createManyTestProducts,
createPaymentTest,
Expand All @@ -188,6 +219,7 @@ export {
productPrice,
productSlug,
removeManyCartItems,
removePaymentTest,
removeTestCategory,
removeTestProduct,
removeTestUser,
Expand Down
135 changes: 54 additions & 81 deletions src/services/webhook-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,36 @@ import { prismaClient } from "../app/database.js";
import { snap } from "../plugin/midtrans.js";

const webhook = async (notificationJson) => {
/**
{
transaction_time: '2023-12-23 16:42:13',
transaction_status: 'pending',
transaction_id: 'd33d1747-f265-4a64-89b8-f02982e73032',
store: 'alfamart',
status_message: 'midtrans payment notification',
status_code: '201',
signature_key: '96b99b66bf45f3736bbf202b6c97e5b0b2d66da819b4112a77b34afffc3e4155379fa740594c7225bf789468dab349101295af096fc22501a6e10456b49ca226',
payment_type: 'cstore',
payment_code: '3101101715649288',
order_id: '76a1b635-5964-462d-a224-3a42008d9abb',
merchant_id: 'G310191577',
gross_amount: '167500.00',
fraud_status: 'accept',
expiry_time: '2023-12-24 16:42:13',
currency: 'IDR'
}
*/

await snap.transaction
.notification(notificationJson)
.then(async (statusResponse) => {
console.log(statusResponse);

console.log(
`Transaction notification received.
await snap.transaction.notification(notificationJson).then(async (statusResponse) => {
console.log(
`Transaction notification received.
Order ID: ${statusResponse.order_id}.
Transaction status: ${statusResponse.transaction_status}.
Fraud status: ${statusResponse.fraud_status}`
);
);

if (statusResponse.transaction_status == "capture") {
// capture only applies to card transaction, which you need to check for the fraudStatus
if (fraudStatus == "challenge") {
// TODO set transaction status on your databaase to 'challenge'
await prismaClient.order.update({
where: { id: statusResponse.order_id },
data: {
status: "challenge",
payment: {
update: {
amount: +statusResponse.gross_amount,
method: notificationJson.payment_type,
status: "challenge",
signatureKey: statusResponse.signature_key,
store: statusResponse.store,
currency: statusResponse.currency,
transactionId: statusResponse.transaction_id,
},
},
},
});
} else if (fraudStatus == "accept") {
// TODO set transaction status on your databaase to 'success'
await prismaClient.order.update({
where: { id: statusResponse.order_id },
data: {
status: "success",
payment: {
update: {
amount: +statusResponse.gross_amount,
method: notificationJson.payment_type,
status: "paid",
signatureKey: statusResponse.signature_key,
store: statusResponse.store,
currency: statusResponse.currency,
transactionId: statusResponse.transaction_id,
},
if (statusResponse.transaction_status == "capture") {
// capture only applies to card transaction, which you need to check for the fraudStatus
if (fraudStatus == "challenge") {
// TODO set transaction status on your databaase to 'challenge'
await prismaClient.order.update({
where: { id: statusResponse.order_id },
data: {
status: "challenge",
payment: {
update: {
amount: +statusResponse.gross_amount,
method: notificationJson.payment_type,
status: "challenge",
signatureKey: statusResponse.signature_key,
store: statusResponse.store,
currency: statusResponse.currency,
transactionId: statusResponse.transaction_id,
},
},
});
}
} else if (statusResponse.transaction_status == "settlement") {
},
});
} else if (fraudStatus == "accept") {
// TODO set transaction status on your databaase to 'success'
await prismaClient.order.update({
where: { id: statusResponse.order_id },
Expand All @@ -94,20 +50,37 @@ const webhook = async (notificationJson) => {
},
},
});
} else if (statusResponse.transaction_status == "deny") {
// TODO you can ignore 'deny', because most of the time it allows payment retries
// and later can become success
} else if (statusResponse.transaction_status == "cancel" || statusResponse.transaction_status == "expire") {
// TODO set transaction status on your databaase to 'failure'
await prismaClient.order.update({ where: { id: statusResponse.order_id }, data: { status: "failure" } });
} else if (statusResponse.transaction_status == "pending") {
// TODO set transaction status on your databaase to 'pending' / waiting payment
await prismaClient.order.update({ where: { id: statusResponse.order_id }, data: { status: "pending" } });
}
})
.catch((error) => {
console.log(error);
});
} else if (statusResponse.transaction_status == "settlement") {
// TODO set transaction status on your databaase to 'success'
await prismaClient.order.update({
where: { id: statusResponse.order_id },
data: {
status: "success",
payment: {
update: {
amount: +statusResponse.gross_amount,
method: notificationJson.payment_type,
status: "paid",
signatureKey: statusResponse.signature_key,
store: statusResponse.store,
currency: statusResponse.currency,
transactionId: statusResponse.transaction_id,
},
},
},
});
} else if (statusResponse.transaction_status == "deny") {
// TODO you can ignore 'deny', because most of the time it allows payment retries
// and later can become success
} else if (statusResponse.transaction_status == "cancel" || statusResponse.transaction_status == "expire") {
// TODO set transaction status on your databaase to 'failure'
await prismaClient.order.update({ where: { id: statusResponse.order_id }, data: { status: "failure" } });
} else if (statusResponse.transaction_status == "pending") {
// TODO set transaction status on your databaase to 'pending' / waiting payment
await prismaClient.order.update({ where: { id: statusResponse.order_id }, data: { status: "pending" } });
}
});
};

export default { webhook };

0 comments on commit d4c1b21

Please sign in to comment.