Skip to content

Commit

Permalink
fix(deserialization): error message is different when invalid data is…
Browse files Browse the repository at this point in the history
… passed for payment method data (#4022)
  • Loading branch information
Narayanbhat166 authored Mar 8, 2024
1 parent f5697f3 commit f1fe295
Show file tree
Hide file tree
Showing 20 changed files with 718 additions and 97 deletions.
81 changes: 79 additions & 2 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1095,12 +1095,19 @@ mod payment_method_data_serde {
#[serde(untagged)]
enum __Inner {
RewardString(String),
OptionalPaymentMethod(Box<PaymentMethodDataRequest>),
OptionalPaymentMethod(serde_json::Value),
}

let deserialize_to_inner = __Inner::deserialize(deserializer)?;
match deserialize_to_inner {
__Inner::OptionalPaymentMethod(value) => Ok(Some(*value)),
__Inner::OptionalPaymentMethod(value) => {
let parsed_value = serde_json::from_value::<PaymentMethodDataRequest>(value)
.map_err(|serde_json_error| {
serde::de::Error::custom(serde_json_error.to_string())
})?;

Ok(Some(parsed_value))
}
__Inner::RewardString(inner_string) => {
let payment_method_data = match inner_string.as_str() {
"reward" => PaymentMethodData::Reward,
Expand Down Expand Up @@ -4048,3 +4055,73 @@ pub enum PaymentLinkStatusWrap {
PaymentLinkStatus(PaymentLinkStatus),
IntentStatus(api_enums::IntentStatus),
}

#[cfg(test)]
mod payments_request_api_contract {
#![allow(clippy::unwrap_used)]
#![allow(clippy::panic)]
use std::str::FromStr;

use super::*;

#[test]
fn test_successful_card_deser() {
let payments_request = r#"
{
"amount": 6540,
"currency": "USD",
"payment_method": "card",
"payment_method_data": {
"card": {
"card_number": "4242424242424242",
"card_exp_month": "10",
"card_exp_year": "25",
"card_holder_name": "joseph Doe",
"card_cvc": "123"
}
}
}
"#;

let expected_card_number_string = "4242424242424242";
let expected_card_number = CardNumber::from_str(expected_card_number_string).unwrap();

let payments_request = serde_json::from_str::<PaymentsRequest>(payments_request);
assert!(payments_request.is_ok());

if let PaymentMethodData::Card(card_data) = payments_request
.unwrap()
.payment_method_data
.unwrap()
.payment_method_data
{
assert_eq!(card_data.card_number, expected_card_number);
} else {
panic!("Received unexpected response")
}
}

#[test]
fn test_successful_payment_method_reward() {
let payments_request = r#"
{
"amount": 6540,
"currency": "USD",
"payment_method": "reward",
"payment_method_data": "reward",
"payment_method_type": "evoucher"
}
"#;

let payments_request = serde_json::from_str::<PaymentsRequest>(payments_request);
assert!(payments_request.is_ok());
assert_eq!(
payments_request
.unwrap()
.payment_method_data
.unwrap()
.payment_method_data,
PaymentMethodData::Reward
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Validate status 400
pm.test("[POST]::/payments - Status code is 400", function () {
pm.response.to.be.error
});

// Validate if response header has matching content-type
pm.test("[POST]::/payments - Content-Type is application/json", function () {
pm.expect(pm.response.headers.get("Content-Type")).to.include(
"application/json",
);
});

// Validate if response has JSON Body
pm.test("[POST]::/payments - Response has JSON Body", function () {
pm.response.to.have.jsonBody();
});

// Set response object as internal variable
let jsonData = {};
try {
jsonData = pm.response.json();
} catch (e) { }

pm.test("[POST]::/payments - Response has appropriate error message", function () {
pm.expect(jsonData.error.message).eql("Invalid card_cvc length");
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"options": {
"raw": {
"language": "json"
}
},
"raw_json_formatted": {
"amount": 6540,
"currency": "USD",
"payment_method": "card",
"payment_method_data": {
"card": {
"card_number": "4242424242424242",
"card_exp_month": "10",
"card_exp_year": "25",
"card_holder_name": "joseph Doe",
"card_cvc": ""
}
}
}
},
"url": {
"raw": "{{baseUrl}}/payments",
"host": ["{{baseUrl}}"],
"path": ["payments"]
},
"description": "Create a Payment to ensure api contract is intact"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"eventOrder": [
"event.test.js",
"event.prerequest.js"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Validate status 400
pm.test("[POST]::/payments - Status code is 400", function () {
pm.response.to.be.error
});

// Validate if response header has matching content-type
pm.test("[POST]::/payments - Content-Type is application/json", function () {
pm.expect(pm.response.headers.get("Content-Type")).to.include(
"application/json",
);
});

// Validate if response has JSON Body
pm.test("[POST]::/payments - Response has JSON Body", function () {
pm.response.to.have.jsonBody();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"options": {
"raw": {
"language": "json"
}
},
"raw_json_formatted": {
"amount": 6540,
"currency": "USD",
"payment_method": "card",
"payment_method_data": {
"card": {
"card_number": "1234",
"card_exp_month": "10",
"card_exp_year": "25",
"card_holder_name": "joseph Doe",
"card_cvc": "123"
}
}
}
},
"url": {
"raw": "{{baseUrl}}/payments",
"host": ["{{baseUrl}}"],
"path": ["payments"]
},
"description": "Create a Payment to ensure api contract is intact"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"eventOrder": [
"event.test.js",
"event.prerequest.js"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Validate status 400
pm.test("[POST]::/payments - Status code is 400", function () {
pm.response.to.be.error
});

// Validate if response header has matching content-type
pm.test("[POST]::/payments - Content-Type is application/json", function () {
pm.expect(pm.response.headers.get("Content-Type")).to.include(
"application/json",
);
});

// Validate if response has JSON Body
pm.test("[POST]::/payments - Response has JSON Body", function () {
pm.response.to.have.jsonBody();
});

// Set response object as internal variable
let jsonData = {};
try {
jsonData = pm.response.json();
} catch (e) { }

pm.test("[POST]::/payments - Response has appropriate error message", function () {
pm.expect(jsonData.error.message).eql("Invalid Expiry Month");
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"options": {
"raw": {
"language": "json"
}
},
"raw_json_formatted": {
"amount": 6540,
"currency": "USD",
"payment_method": "card",
"payment_method_data": {
"card": {
"card_number": "4242424242424242",
"card_exp_month": "13",
"card_exp_year": "69",
"card_holder_name": "joseph Doe",
"card_cvc": "123"
}
}
}
},
"url": {
"raw": "{{baseUrl}}/payments",
"host": ["{{baseUrl}}"],
"path": ["payments"]
},
"description": "Create a Payment to ensure api contract is intact"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"eventOrder": [
"event.test.js",
"event.prerequest.js"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Validate status 400
pm.test("[POST]::/payments - Status code is 400", function () {
pm.response.to.be.error
});

// Validate if response header has matching content-type
pm.test("[POST]::/payments - Content-Type is application/json", function () {
pm.expect(pm.response.headers.get("Content-Type")).to.include(
"application/json",
);
});

// Validate if response has JSON Body
pm.test("[POST]::/payments - Response has JSON Body", function () {
pm.response.to.have.jsonBody();
});

// Set response object as internal variable
let jsonData = {};
try {
jsonData = pm.response.json();
} catch (e) { }

if (jsonData?.error?.message) {
pm.test(
"[POST]::/payments - Content check for error message to equal `Invalid Expiry Year`",
function () {
pm.expect(jsonData.error.message).to.eql("Invalid Expiry Year");
},
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"options": {
"raw": {
"language": "json"
}
},
"raw_json_formatted": {
"amount": 6540,
"currency": "USD",
"payment_method": "card",
"payment_method_data": {
"card": {
"card_number": "4242424242424242",
"card_exp_month": "10",
"card_exp_year": "22",
"card_holder_name": "joseph Doe",
"card_cvc": "123"
}
}
}
},
"url": {
"raw": "{{baseUrl}}/payments",
"host": ["{{baseUrl}}"],
"path": ["payments"]
},
"description": "Create a Payment to ensure api contract is intact"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"eventOrder": [
"event.test.js",
"event.prerequest.js"
]
}
Loading

0 comments on commit f1fe295

Please sign in to comment.