Bug: [FEATURE] Add more default tests to the connector template



### Feature Description

For card payment method default unit tests should be generated while adding a connector using add_connector script.

### Possible Implementation

Add more test cases in connector-template/test.rs file, So that default test cases will be generated every time while adding a connector. If connector does not support any flow or payment method, then test cases for such scenarios can be removed from the test file. 

### Have you spent some time to check if this feature request has been raised before?

- [X] I checked and didn't find similar issue

### Have you read the Contributing Guidelines?

- [X] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

Yes I am willing to submit a PR!
diff --git a/connector-template/test.rs b/connector-template/test.rs
index 2efaabcd5b2..5926584c526 100644
--- a/connector-template/test.rs
+++ b/connector-template/test.rs
@@ -1,4 +1,3 @@
-use futures::future::OptionFuture;
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -7,9 +6,10 @@ use crate::{
     utils::{self, ConnectorActions},
 };
 
-struct {{project-name | downcase | pascal_case}};
-impl ConnectorActions for {{project-name | downcase | pascal_case}} {}
-impl utils::Connector for {{project-name | downcase | pascal_case}} {
+#[derive(Clone, Copy)]
+struct {{project-name | downcase | pascal_case}}Test;
+impl ConnectorActions for {{project-name | downcase | pascal_case}}Test {}
+impl utils::Connector for {{project-name | downcase | pascal_case}}Test {
     fn get_data(&self) -> types::api::ConnectorData {
         use router::connector::{{project-name | downcase | pascal_case}};
         types::api::ConnectorData {
@@ -22,70 +22,417 @@ impl utils::Connector for {{project-name | downcase | pascal_case}} {
     fn get_auth_token(&self) -> types::ConnectorAuthType {
         types::ConnectorAuthType::from(
             connector_auth::ConnectorAuthentication::new()
-                .{{project-name | downcase }}
+                .{{project-name | downcase}}
                 .expect("Missing connector authentication configuration"),
         )
     }
 
     fn get_name(&self) -> String {
-        "{{project-name | downcase }}".to_string()
+        "{{project-name | downcase}}".to_string()
     }
 }
 
+static CONNECTOR: {{project-name | downcase | pascal_case}}Test = {{project-name | downcase | pascal_case}}Test {};
+
+// Cards Positive Tests
+// Creates a payment using the manual capture flow (Non 3DS).
 #[actix_web::test]
 async fn should_only_authorize_payment() {
-    let response = {{project-name | downcase | pascal_case}} {}.authorize_payment(None).await.unwrap();
+    let response = CONNECTOR
+        .authorize_payment(None, None)
+        .await
+        .expect("Authorize payment response");
     assert_eq!(response.status, enums::AttemptStatus::Authorized);
 }
 
+// Captures a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_capture_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_capture_payment(None, None, None)
+        .await
+        .expect("Capture payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Charged);
+}
+
+// Partially captures a payment using the manual capture flow (Non 3DS).
 #[actix_web::test]
-async fn should_authorize_and_capture_payment() {
-    let response = {{project-name | downcase | pascal_case}} {}.make_payment(None).await.unwrap();
+async fn should_partially_capture_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_capture_payment(
+            None,
+            Some(types::PaymentsCaptureData {
+                amount_to_capture: Some(50),
+                ..utils::PaymentCaptureType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Capture payment response");
     assert_eq!(response.status, enums::AttemptStatus::Charged);
 }
 
+// Synchronizes a payment using the manual capture flow (Non 3DS).
 #[actix_web::test]
-async fn should_capture_already_authorized_payment() {
-    let connector = {{project-name | downcase | pascal_case}} {};
-    let authorize_response = connector.authorize_payment(None).await.unwrap();
-    assert_eq!(authorize_response.status, enums::AttemptStatus::Authorized);
+async fn should_sync_authorized_payment() {
+    let authorize_response = CONNECTOR
+        .authorize_payment(None, None)
+        .await
+        .expect("Authorize payment response");
     let txn_id = utils::get_connector_transaction_id(authorize_response);
-    let response: OptionFuture<_> = txn_id
-        .map(|transaction_id| async move {
-            connector.capture_payment(transaction_id, None).await.unwrap().status
-        })
-        .into();
-    assert_eq!(response.await.unwrap(), Some(enums::AttemptStatus::Charged));
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Authorized,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.unwrap(),
+                ),
+                encoded_data: None,
+                capture_method: None,
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
 }
 
+// Voids a payment using the manual capture flow (Non 3DS).
 #[actix_web::test]
-async fn should_fail_payment_for_incorrect_cvc() {
-    let response = {{project-name | downcase | pascal_case}} {}.make_payment(Some(types::PaymentsAuthorizeData {
-            payment_method_data: types::api::PaymentMethod::Card(api::CCard {
-                card_number: Secret::new("4024007134364842".to_string()),
-                ..utils::CCardType::default().0
+async fn should_void_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_void_payment(
+            None,
+            Some(types::PaymentsCancelData {
+                connector_transaction_id: String::from(""),
+                cancellation_reason: Some("requested_by_customer".to_string()),
             }),
-            ..utils::PaymentAuthorizeType::default().0
-        }))
-        .await.unwrap();
-    let x = response.response.unwrap_err();
+            None,
+        )
+        .await
+        .expect("Void payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Voided);
+}
+
+// Refunds a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_manually_captured_payment() {
+    let response = CONNECTOR
+        .capture_payment_and_refund(None, None, None, None)
+        .await
+        .unwrap();
     assert_eq!(
-        x.message,
-        "The card's security code failed verification.".to_string(),
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
     );
 }
 
+// Partially refunds a payment using the manual capture flow (Non 3DS).
 #[actix_web::test]
-async fn should_refund_succeeded_payment() {
-    let connector = {{project-name | downcase | pascal_case}} {};
-    //make a successful payment
-    let response = connector.make_payment(None).await.unwrap();
+async fn should_partially_refund_manually_captured_payment() {
+    let response = CONNECTOR
+        .capture_payment_and_refund(
+            None,
+            None,
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Synchronizes a refund using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_manually_captured_refund() {
+    let refund_response = CONNECTOR
+        .capture_payment_and_refund(None, None, None, None)
+        .await
+        .unwrap();
+    let response = CONNECTOR
+        .rsync_retry_till_status_matches(
+            enums::RefundStatus::Success,
+            refund_response.response.unwrap().connector_refund_id,
+            None,
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Creates a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_make_payment() {
+    let authorize_response = CONNECTOR.make_payment(None, None).await.unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+}
+
+// Synchronizes a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_auto_captured_payment() {
+    let authorize_response = CONNECTOR.make_payment(None, None).await.unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+    let txn_id = utils::get_connector_transaction_id(authorize_response);
+    assert_ne!(txn_id, None, "Empty connector transaction id");
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Charged,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.unwrap(),
+                ),
+                encoded_data: None,
+                capture_method: None,
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(response.status, enums::AttemptStatus::Charged,);
+}
+
+// Refunds a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_auto_captured_payment() {
+    let response = CONNECTOR
+        .make_payment_and_refund(None, None, None)
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Partially refunds a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_partially_refund_succeeded_payment() {
+    let refund_response = CONNECTOR
+        .make_payment_and_refund(
+            None,
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        refund_response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_succeeded_payment_multiple_times() {
+    CONNECTOR
+        .make_payment_and_multiple_refund(
+            None,
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            None,
+        )
+        .await;
+}
 
-    //try refund for previous payment
-    let transaction_id = utils::get_connector_transaction_id(response).unwrap(); 
-    let response = connector.refund_payment(transaction_id, None).await.unwrap();
+// Synchronizes a refund using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_refund() {
+    let refund_response = CONNECTOR
+        .make_payment_and_refund(None, None, None)
+        .await
+        .unwrap();
+    let response = CONNECTOR
+        .rsync_retry_till_status_matches(
+            enums::RefundStatus::Success,
+            refund_response.response.unwrap().connector_refund_id,
+            None,
+            None,
+        )
+        .await
+        .unwrap();
     assert_eq!(
         response.response.unwrap().refund_status,
         enums::RefundStatus::Success,
     );
 }
+
+// Cards Negative scenerios
+// Creates a payment with incorrect card number.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_card_number() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethod::Card(api::Card {
+                    card_number: Secret::new("1234567891011".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card number is incorrect.".to_string(),
+    );
+}
+
+// Creates a payment with empty card number.
+#[actix_web::test]
+async fn should_fail_payment_for_empty_card_number() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethod::Card(api::Card {
+                    card_number: Secret::new(String::from("")),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    let x = response.response.unwrap_err();
+    assert_eq!(
+        x.message,
+        "You passed an empty string for 'payment_method_data[card][number]'.",
+    );
+}
+
+// Creates a payment with incorrect CVC.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_cvc() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethod::Card(api::Card {
+                    card_cvc: Secret::new("12345".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's security code is invalid.".to_string(),
+    );
+}
+
+// Creates a payment with incorrect expiry month.
+#[actix_web::test]
+async fn should_fail_payment_for_invalid_exp_month() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethod::Card(api::Card {
+                    card_exp_month: Secret::new("20".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's expiration month is invalid.".to_string(),
+    );
+}
+
+// Creates a payment with incorrect expiry year.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_expiry_year() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethod::Card(api::Card {
+                    card_exp_year: Secret::new("2000".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's expiration year is invalid.".to_string(),
+    );
+}
+
+// Voids a payment using automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_fail_void_payment_for_auto_capture() {
+    let authorize_response = CONNECTOR.make_payment(None, None).await.unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+    let txn_id = utils::get_connector_transaction_id(authorize_response);
+    assert_ne!(txn_id, None, "Empty connector transaction id");
+    let void_response = CONNECTOR
+        .void_payment(txn_id.unwrap(), None, None)
+        .await
+        .unwrap();
+    assert_eq!(
+        void_response.response.unwrap_err().message,
+        "You cannot cancel this PaymentIntent because it has a status of succeeded."
+    );
+}
+
+// Captures a payment using invalid connector payment id.
+#[actix_web::test]
+async fn should_fail_capture_for_invalid_payment() {
+    let capture_response = CONNECTOR
+        .capture_payment("123456789".to_string(), None, None)
+        .await
+        .unwrap();
+    assert_eq!(
+        capture_response.response.unwrap_err().message,
+        String::from("No such payment_intent: '123456789'")
+    );
+}
+
+// Refunds a payment with refund amount higher than payment amount.
+#[actix_web::test]
+async fn should_fail_for_refund_amount_higher_than_payment_amount() {
+    let response = CONNECTOR
+        .make_payment_and_refund(
+            None,
+            Some(types::RefundsData {
+                refund_amount: 150,
+                ..utils::PaymentRefundType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
+    );
+}
+
+// Connector dependent test cases goes here
+
+// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests
diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs
index 1ffd970fd9b..b46db3f6e0f 100644
--- a/crates/router/tests/connectors/utils.rs
+++ b/crates/router/tests/connectors/utils.rs
@@ -187,6 +187,28 @@ pub trait ConnectorActions: Connector {
         call_connector(request, integration).await
     }
 
+    async fn capture_payment_and_refund(
+        &self,
+        authorize_data: Option<types::PaymentsAuthorizeData>,
+        capture_data: Option<types::PaymentsCaptureData>,
+        refund_data: Option<types::RefundsData>,
+        payment_info: Option<PaymentInfo>,
+    ) -> Result<types::RefundExecuteRouterData, Report<ConnectorError>> {
+        //make a successful payment
+        let response = self
+            .authorize_and_capture_payment(authorize_data, capture_data, payment_info.clone())
+            .await
+            .unwrap();
+        let txn_id = self.get_connector_transaction_id_from_capture_data(response);
+
+        //try refund for previous payment
+        tokio::time::sleep(Duration::from_secs(self.get_request_interval())).await; // to avoid 404 error
+        Ok(self
+            .refund_payment(txn_id.unwrap(), refund_data, payment_info)
+            .await
+            .unwrap())
+    }
+
     async fn make_payment_and_refund(
         &self,
         authorize_data: Option<types::PaymentsAuthorizeData>,
@@ -326,6 +348,19 @@ pub trait ConnectorActions: Connector {
             access_token: info.and_then(|a| a.access_token),
         }
     }
+
+    fn get_connector_transaction_id_from_capture_data(
+        &self,
+        response: types::PaymentsCaptureRouterData,
+    ) -> Option<String> {
+        match response.response {
+            Ok(types::PaymentsResponseData::TransactionResponse { resource_id, .. }) => {
+                resource_id.get_connector_transaction_id().ok()
+            }
+            Ok(types::PaymentsResponseData::SessionResponse { .. }) => None,
+            Err(_) => None,
+        }
+    }
 }
 
 async fn call_connector<

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates

## Description
For card payment method default unit tests should be generated while adding a connector using add_connector script.


### Additional Changes

- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!-- 
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
Add more test cases in connector-template/test.rs file, So that default test cases will be generated every time while adding a connector. If connector does not support any flow or payment method, then test cases for such scenarios can be removed from the test file.

Closes #467.

## How did you test it?
Tested by creating a new connector. As expected new test cases were generated in the test file.


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed submitted code
- [ ] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
