From 68796d5ccea75c01d860ce8ed2e942b89288a7a0 Mon Sep 17 00:00:00 2001 From: roost-io Date: Mon, 6 Apr 2026 10:41:01 +0000 Subject: [PATCH] Functional (using Source code) (Java) generated by RoostGPT Using AI Model gpt-4.1 --- .../.roost/knowledge.json | 702 ++++++++++++++++++ .../gherkin_account_dashboard.feature | 140 ++++ ...herkin_payment_transaction_history.feature | 109 +++ .../gherkin_registration_verification.feature | 105 +++ .../gherkin_transact_operations.feature | 148 ++++ .../gherkin_user_login_logout.feature | 85 +++ Online-Banking-App-Spring-Boot/openapi.json | 492 ++++++++++++ .../test_docs/README.md | 24 + .../test_docs/api_flows.md | 152 ++++ .../test_docs/business_use_cases.md | 205 +++++ .../test_docs/test_coverage.md | 61 ++ 11 files changed, 2223 insertions(+) create mode 100644 Online-Banking-App-Spring-Boot/.roost/knowledge.json create mode 100644 Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_account_dashboard.feature create mode 100644 Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_payment_transaction_history.feature create mode 100644 Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_registration_verification.feature create mode 100644 Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_transact_operations.feature create mode 100644 Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_user_login_logout.feature create mode 100644 Online-Banking-App-Spring-Boot/openapi.json create mode 100644 Online-Banking-App-Spring-Boot/test_docs/README.md create mode 100644 Online-Banking-App-Spring-Boot/test_docs/api_flows.md create mode 100644 Online-Banking-App-Spring-Boot/test_docs/business_use_cases.md create mode 100644 Online-Banking-App-Spring-Boot/test_docs/test_coverage.md diff --git a/Online-Banking-App-Spring-Boot/.roost/knowledge.json b/Online-Banking-App-Spring-Boot/.roost/knowledge.json new file mode 100644 index 0000000..742632d --- /dev/null +++ b/Online-Banking-App-Spring-Boot/.roost/knowledge.json @@ -0,0 +1,702 @@ +{ + "endpoints": [ + { + "controller": "AccountController", + "basePath": "/account", + "endpoints": [ + { + "method": "POST", + "path": "/account/create_account", + "function": "createAccount", + "requestBody": { + "type": "object", + "fields": [ + "account_name", + "account_type" + ] + }, + "response": "User accounts (array/object); error message on failure", + "authRequired": true + } + ] + }, + { + "controller": "AppController", + "basePath": "/app", + "endpoints": [ + { + "method": "GET", + "path": "/app/dashboard", + "function": "getDashboard", + "parameters": [], + "response": "{ userAccounts: Account[], totalBalance: number }", + "authRequired": true + }, + { + "method": "GET", + "path": "/app/payment_history", + "function": "getPaymentHistory", + "parameters": [], + "response": "{ payment_history: PaymentHistory[] }", + "authRequired": true + }, + { + "method": "GET", + "path": "/app/transaction_history", + "function": "getTransactiontHistory", + "parameters": [], + "response": "{ transaction_history: TransactionHistory[] }", + "authRequired": true + }, + { + "method": "POST", + "path": "/app/account_transaction_history", + "function": "getAccountTransactiontHistory", + "requestBody": { + "type": "object", + "fields": [ + "account_id" + ] + }, + "response": "{ transaction_history: TransactionHistory[] }", + "authRequired": true + } + ] + }, + { + "controller": "AuthController", + "basePath": "", + "endpoints": [ + { + "method": "POST", + "path": "/login", + "function": "login", + "requestBody": { + "type": "object", + "fields": [ + "email", + "password" + ] + }, + "response": "{ message: string, access_token: string } | error message", + "authRequired": false + }, + { + "method": "GET", + "path": "/logout", + "function": "logout", + "parameters": [], + "response": "Logout success message", + "authRequired": true + } + ] + }, + { + "controller": "IndexController", + "basePath": "", + "endpoints": [ + { + "method": "GET", + "path": "/", + "function": "getIndex", + "parameters": [], + "response": "Plain string message", + "authRequired": false + }, + { + "method": "GET", + "path": "/verify", + "function": "getVerify", + "parameters": [ + { + "name": "token", + "in": "query", + "required": true + }, + { + "name": "code", + "in": "query", + "required": true + } + ], + "response": "{ message: string } | error message", + "authRequired": false + } + ] + }, + { + "controller": "RegisterController", + "basePath": "", + "endpoints": [ + { + "method": "POST", + "path": "/register", + "function": "registerUser", + "requestBody": { + "type": "object", + "fields": [ + "user (User model in body)", + "confirm_password (query param)" + ] + }, + "response": "{ message: string, user: User } | error messages", + "authRequired": false + } + ] + }, + { + "controller": "TransactController", + "basePath": "/transact", + "endpoints": [ + { + "method": "POST", + "path": "/transact/deposit", + "function": "deposit", + "requestBody": { + "type": "object", + "fields": [ + "deposit_amount", + "account_id" + ] + }, + "response": "{ message: string, accounts: Account[] } | error", + "authRequired": true + }, + { + "method": "POST", + "path": "/transact/transfer", + "function": "transfer", + "requestBody": { + "type": "TransferRequest" + }, + "response": "{ message: string, accounts: Account[] } | error", + "authRequired": true + }, + { + "method": "POST", + "path": "/transact/withdraw", + "function": "transfer", + "requestBody": { + "type": "object", + "fields": [ + "withdrawal_amount", + "account_id" + ] + }, + "response": "{ message: string, accounts: Account[] } | error", + "authRequired": true + }, + { + "method": "POST", + "path": "/transact/payment", + "function": "transfer", + "requestBody": { + "type": "PaymentRequest" + }, + "response": "{ message: string, accounts: Account[] } | error", + "authRequired": true + } + ] + } + ], + "models": [ + { + "name": "Account", + "fields": [ + { + "name": "account_id", + "type": "int" + }, + { + "name": "user_id", + "type": "int" + }, + { + "name": "account_number", + "type": "string" + }, + { + "name": "account_name", + "type": "string" + }, + { + "name": "account_type", + "type": "string" + }, + { + "name": "balance", + "type": "BigDecimal" + }, + { + "name": "create_at", + "type": "LocalDateTime" + }, + { + "name": "updated_at", + "type": "LocalDateTime" + } + ] + }, + { + "name": "Payment", + "fields": [ + { + "name": "payment_id", + "type": "int" + }, + { + "name": "account_id", + "type": "int" + }, + { + "name": "beneficiary", + "type": "string" + }, + { + "name": "beneficiary_acc_no", + "type": "string" + }, + { + "name": "amount", + "type": "double" + }, + { + "name": "reference_no", + "type": "string" + }, + { + "name": "status", + "type": "string" + }, + { + "name": "reason_code", + "type": "string" + }, + { + "name": "created_at", + "type": "LocalDateTime" + } + ] + }, + { + "name": "PaymentHistory", + "fields": [ + { + "name": "payment_id", + "type": "int" + }, + { + "name": "account_id", + "type": "int" + }, + { + "name": "beneficiary", + "type": "string" + }, + { + "name": "beneficiary_acc_no", + "type": "string" + }, + { + "name": "amount", + "type": "double" + }, + { + "name": "reference_no", + "type": "string" + }, + { + "name": "status", + "type": "string" + }, + { + "name": "reason_code", + "type": "string" + }, + { + "name": "created_at", + "type": "LocalDateTime" + } + ] + }, + { + "name": "PaymentRequest", + "fields": [ + { + "name": "beneficiary", + "type": "string" + }, + { + "name": "account_number", + "type": "string" + }, + { + "name": "account_id", + "type": "string" + }, + { + "name": "reference", + "type": "string" + }, + { + "name": "payment_amount", + "type": "string" + } + ] + }, + { + "name": "Transact", + "fields": [ + { + "name": "transaction_id", + "type": "int" + }, + { + "name": "account_id", + "type": "int" + }, + { + "name": "transaction_type", + "type": "string" + }, + { + "name": "amount", + "type": "double" + }, + { + "name": "source", + "type": "string" + }, + { + "name": "status", + "type": "string" + }, + { + "name": "reason_code", + "type": "string" + }, + { + "name": "created_at", + "type": "LocalDateTime" + } + ] + }, + { + "name": "TransactionHistory", + "fields": [ + { + "name": "transaction_id", + "type": "int" + }, + { + "name": "account_id", + "type": "int" + }, + { + "name": "transaction_type", + "type": "string" + }, + { + "name": "amount", + "type": "double" + }, + { + "name": "source", + "type": "string" + }, + { + "name": "status", + "type": "string" + }, + { + "name": "reason_code", + "type": "string" + }, + { + "name": "created_at", + "type": "LocalDateTime" + } + ] + }, + { + "name": "TransferRequest", + "fields": [ + { + "name": "sourceAccount", + "type": "string" + }, + { + "name": "targetAccount", + "type": "string" + }, + { + "name": "amount", + "type": "string" + } + ] + }, + { + "name": "User", + "fields": [ + { + "name": "user_id", + "type": "string" + }, + { + "name": "first_name", + "type": "string" + }, + { + "name": "last_name", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "password", + "type": "string" + }, + { + "name": "token", + "type": "string" + }, + { + "name": "code", + "type": "string" + }, + { + "name": "verified", + "type": "int" + }, + { + "name": "verified_at", + "type": "LocalDate" + }, + { + "name": "create_at", + "type": "LocalDateTime" + }, + { + "name": "updated_at", + "type": "LocalDateTime" + } + ] + } + ], + "dependencies": [], + "businessFlows": [ + { + "name": "User Registration", + "description": "Allows a new user to register an account in the banking application.", + "endpoints": [ + { + "controller": "RegisterController", + "function": "registerUser", + "path": "/register", + "method": "POST" + } + ], + "models": [ + "User" + ] + }, + { + "name": "User Login", + "description": "Authenticates a user and initiates a logged-in session with JWT for subsequent operations.", + "endpoints": [ + { + "controller": "AuthController", + "function": "login", + "path": "/login", + "method": "POST" + } + ], + "models": [ + "User" + ] + }, + { + "name": "User Logout", + "description": "Logs the current user out and invalidates their session.", + "endpoints": [ + { + "controller": "AuthController", + "function": "logout", + "path": "/logout", + "method": "GET" + } + ], + "models": [] + }, + { + "name": "Account Creation", + "description": "Creates a new bank account for an authenticated user.", + "endpoints": [ + { + "controller": "AccountController", + "function": "createAccount", + "path": "/account/create_account", + "method": "POST" + } + ], + "models": [ + "Account", + "User" + ] + }, + { + "name": "Dashboard & Balance Inquiry", + "description": "Fetches dashboard information, including all accounts and total balance for the user.", + "endpoints": [ + { + "controller": "AppController", + "function": "getDashboard", + "path": "/app/dashboard", + "method": "GET" + } + ], + "models": [ + "Account", + "User" + ] + }, + { + "name": "Payment History", + "description": "Fetches the list of payment operations for the current user.", + "endpoints": [ + { + "controller": "AppController", + "function": "getPaymentHistory", + "path": "/app/payment_history", + "method": "GET" + } + ], + "models": [ + "PaymentHistory" + ] + }, + { + "name": "Transaction History", + "description": "Fetches the list of transactions for the user, and for a specific account.", + "endpoints": [ + { + "controller": "AppController", + "function": "getTransactiontHistory", + "path": "/app/transaction_history", + "method": "GET" + }, + { + "controller": "AppController", + "function": "getAccountTransactiontHistory", + "path": "/app/account_transaction_history", + "method": "POST" + } + ], + "models": [ + "TransactionHistory" + ] + }, + { + "name": "Deposit Funds", + "description": "Deposits a specified amount of money into a user's account.", + "endpoints": [ + { + "controller": "TransactController", + "function": "deposit", + "path": "/transact/deposit", + "method": "POST" + } + ], + "models": [ + "Account" + ] + }, + { + "name": "Money Transfer", + "description": "Transfers funds from one account to another.", + "endpoints": [ + { + "controller": "TransactController", + "function": "transfer", + "path": "/transact/transfer", + "method": "POST" + } + ], + "models": [ + "Account", + "TransferRequest" + ] + }, + { + "name": "Withdraw Funds", + "description": "Withdraws a specified amount of money from a user's account.", + "endpoints": [ + { + "controller": "TransactController", + "function": "transfer", + "path": "/transact/withdraw", + "method": "POST" + } + ], + "models": [ + "Account" + ] + }, + { + "name": "Make Payment", + "description": "Processes a payment from a user's account to a beneficiary.", + "endpoints": [ + { + "controller": "TransactController", + "function": "transfer", + "path": "/transact/payment", + "method": "POST" + } + ], + "models": [ + "PaymentRequest", + "Account" + ] + }, + { + "name": "Email Verification", + "description": "Verifies a user's account using a token and verification code sent by email.", + "endpoints": [ + { + "controller": "IndexController", + "function": "getVerify", + "path": "/verify", + "method": "GET" + } + ], + "models": [ + "User" + ] + } + ], + "language": { + "language": "java" + }, + "buildTool": { + "buildTool": "maven" + }, + "framework": { + "framework": "spring-boot" + }, + "projectStructure": { + "srcDirs": [ + "src/main/java/com/beko/DemoBank_v1" + ], + "resourceDirs": [ + "src/main/resources" + ], + "webDirs": [ + "src/main/webapp/WEB-INF/jsp" + ], + "testDirs": [ + "src/test/java/com/beko/DemoBank_v1" + ] + } +} \ No newline at end of file diff --git a/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_account_dashboard.feature b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_account_dashboard.feature new file mode 100644 index 0000000..c846cec --- /dev/null +++ b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_account_dashboard.feature @@ -0,0 +1,140 @@ +Feature: Account Management and Dashboard + + Background: + Given the API is available + + # --- Account Creation --- + + @smoke + Scenario: Successfully create a new account + Given I am an authenticated user + When I send a POST request to /account/create_account with body: + | account_name | account_type | + | "Savings" | "savings" | + Then the response status should be 201 + And the response should contain an Account object with account_name "Savings" and account_type "savings" + + @regression + Scenario: Fail to create account when unauthenticated + Given I am not authenticated + When I send a POST request to /account/create_account with body: + | account_name | account_type | + | "Invalid" | "savings" | + Then the response status should be 401 + And the response should contain an error message indicating authentication is required + + @regression + Scenario: Fail to create account with missing required fields + Given I am an authenticated user + When I send a POST request to /account/create_account with body: + | account_type | + | "checking" | + Then the response status should be 400 + And the response should contain an error message for missing account_name + + @regression + Scenario: Fail to create account with invalid account_type + Given I am an authenticated user + When I send a POST request to /account/create_account with body: + | account_name | account_type | + | "Invalid" | "investment" | + Then the response status should be 400 + And the response should contain an error message for invalid account_type + + @regression + Scenario: Fail to create duplicate account with same name and type + Given I am an authenticated user + And I have already created an account with name "Personal" and type "savings" + When I send a POST request to /account/create_account with body: + | account_name | account_type | + | "Personal" | "savings" | + Then the response status should be 409 + And the response should contain an error message indicating duplicate account + + # --- Dashboard --- + + @smoke + Scenario: View dashboard with account summary + Given I am an authenticated user + And I have the following accounts: + | account_name | account_type | balance | + | "Main" | "checking" | 2500 | + | "Savings" | "savings" | 5000 | + When I send a GET request to /app/dashboard + Then the response status should be 200 + And the response should contain a list of userAccounts with 2 accounts + And the response should contain totalBalance equal to 7500 + + @regression + Scenario: Fail to view dashboard when unauthenticated + Given I am not authenticated + When I send a GET request to /app/dashboard + Then the response status should be 401 + And the response should contain an error message indicating authentication is required + + @smoke + Scenario: View dashboard when user has no accounts + Given I am an authenticated user + And I have no accounts + When I send a GET request to /app/dashboard + Then the response status should be 200 + And the response should contain userAccounts as an empty list + And the response should contain totalBalance equal to 0 + + @regression + Scenario: Handle internal server error when fetching dashboard + Given I am an authenticated user + And a backend error occurs while fetching dashboard data + When I send a GET request to /app/dashboard + Then the response status should be 500 + And the response should contain an error message indicating a server error + + # --- Edge Cases --- + + @regression + Scenario: Create account with name at maximum allowed length + Given I am an authenticated user + And the maximum allowed account name length is 255 characters + When I send a POST request to /account/create_account with body: + | account_name | account_type | + | "<255_char_string>" | "checking" | + Then the response status should be 201 + And the response should contain an Account object with the given name + + @regression + Scenario: Fail to create account with overly long account_name + Given I am an authenticated user + And the maximum allowed account name length is 255 characters + When I send a POST request to /account/create_account with body: + | account_name | account_type | + | "<256_char_string>" | "checking" | + Then the response status should be 400 + And the response should contain an error message for account_name length + + @regression + Scenario: Create multiple different accounts with the same name but different types + Given I am an authenticated user + And I have created an account with name "Holiday" and type "savings" + When I send a POST request to /account/create_account with body: + | account_name | account_type | + | "Holiday" | "checking" | + Then the response status should be 201 + And the response should contain an Account object with account_name "Holiday" and account_type "checking" + + @regression + Scenario: Balance calculation includes all user-owned accounts + Given I am an authenticated user + And I have the following accounts: + | account_name | account_type | balance | + | "USD" | "checking" | 1000 | + | "EUR" | "checking" | 2000 | + | "GBP" | "savings" | 3000 | + When I send a GET request to /app/dashboard + Then the response totalBalance should be 6000 + + @regression + Scenario: Dashboard displays only accounts owned by the user + Given I am user "alice" authenticated + And user "bob" has an account named "Joint" with balance 5000 + When "alice" sends a GET request to /app/dashboard + Then the response should not contain the "Joint" account owned by "bob" diff --git a/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_payment_transaction_history.feature b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_payment_transaction_history.feature new file mode 100644 index 0000000..81c28b7 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_payment_transaction_history.feature @@ -0,0 +1,109 @@ +Feature: Payment and Transaction History Endpoints + + Background: + Given a registered user exists + And the user possesses a valid authentication token + + @smoke @positive + Scenario: Successfully retrieve payment history for authenticated user + When the user sends a GET request to "/app/payment_history" with a valid token + Then the response status should be 200 + And the response body should contain a non-empty array of PaymentHistory objects + + @regression + Scenario: Authenticated user receives empty payment history collection + Given the user's payment history is empty + When the user sends a GET request to "/app/payment_history" with a valid token + Then the response status should be 200 + And the response body should contain an empty array + + @regression @negative + Scenario: Unauthorized request to payment history endpoint + When the user sends a GET request to "/app/payment_history" without a valid token + Then the response status should be 401 + And the response body should contain an unauthorized error message + + @regression @edgecase + Scenario: Large payment history list is handled correctly + Given the user has more than 1000 PaymentHistory records + When the user sends a GET request to "/app/payment_history" with a valid token + Then the response status should be 200 + And the response body should contain an array with more than 1000 PaymentHistory objects + + @regression @edgecase + Scenario: Corrupt or invalid PaymentHistory data is ignored + Given the user's payment history contains some invalid or incomplete records + When the user sends a GET request to "/app/payment_history" with a valid token + Then the response status should be 200 + And all objects in the response array should conform to the PaymentHistory model + + @smoke @positive + Scenario: Successfully retrieve transaction history for authenticated user + When the user sends a GET request to "/app/transaction_history" with a valid token + Then the response status should be 200 + And the response body should contain a non-empty array of TransactionHistory objects + + @regression + Scenario: Authenticated user receives empty transaction history collection + Given the user's transaction history is empty + When the user sends a GET request to "/app/transaction_history" with a valid token + Then the response status should be 200 + And the response body should contain an empty array + + @regression @negative + Scenario: Unauthorized request to transaction history endpoint + When the user sends a GET request to "/app/transaction_history" without a valid token + Then the response status should be 401 + And the response body should contain an unauthorized error message + + @smoke @positive + Scenario: Successfully retrieve account-specific transaction history + Given an account with id "12345" belongs to the user + When the user sends a POST request to "/app/account_transaction_history" with body { "account_id": "12345" } and a valid token + Then the response status should be 200 + And the response body should contain a non-empty array of TransactionHistory objects related to account "12345" + + @regression + Scenario: Account transaction history returns empty collection when no transactions exist + Given the user has an account with id "98765" and no transaction history + When the user sends a POST request to "/app/account_transaction_history" with body { "account_id": "98765" } and a valid token + Then the response status should be 200 + And the response body should contain an empty array + + @regression @negative + Scenario: Unauthorized request to account transaction history endpoint + When the user sends a POST request to "/app/account_transaction_history" with a valid account_id but no token + Then the response status should be 401 + And the response body should contain an unauthorized error message + + @regression @negative + Scenario: Requesting account transaction history for an account the user does not own + Given account with id "99999" does not belong to the user + When the user sends a POST request to "/app/account_transaction_history" with body { "account_id": "99999" } and a valid token + Then the response status should be 403 + And the response body should contain an authorization error message + + @regression @negative @edgecase + Scenario: Omitting account_id from request body returns error + When the user sends a POST request to "/app/account_transaction_history" with an empty body and a valid token + Then the response status should be 400 + And the response body should contain a validation error for missing account_id + + @regression @negative @edgecase + Scenario: Sending invalid account_id format returns error + When the user sends a POST request to "/app/account_transaction_history" with body { "account_id": "INVALID_ID!!" } and a valid token + Then the response status should be 400 + And the response body should contain a validation error for account_id + + @regression @edgecase + Scenario: Large transaction history list is handled correctly + Given the user has more than 1000 TransactionHistory records + When the user sends a GET request to "/app/transaction_history" with a valid token + Then the response status should be 200 + And the response body should contain an array with more than 1000 TransactionHistory objects + + @regression @edgecase + Scenario: System handles simultaneous requests for history endpoints gracefully + When the user sends multiple concurrent GET requests to "/app/payment_history" and "/app/transaction_history" with a valid token + Then all responses should have status 200 + And no data corruption or partial responses should occur diff --git a/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_registration_verification.feature b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_registration_verification.feature new file mode 100644 index 0000000..81e91d3 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_registration_verification.feature @@ -0,0 +1,105 @@ +Feature: User Registration and Email Verification for Banking System + + Background: + Given the registration endpoint is available at "/register" + And the verification endpoint is available at "/verify" + + @smoke @registration + Scenario: Successful user registration with valid data + When I submit a POST request to "/register" with a valid User model and confirm_password that matches the password + Then the response status should be 201 + And the response should include the registered user details + And the response should contain a success message + + @smoke @verification + Scenario: Successful email verification with valid token and code + Given I have registered and received a verification token and code + When I send a GET request to "/verify" with the valid token and code as query parameters + Then the response status should be 200 + And the response should include a verification success message + + @negative @registration + Scenario: Registration fails when required fields are missing + When I submit a POST request to "/register" with missing required fields in the User model + Then the response status should be 400 + And the response should contain an error describing the missing fields + + @negative @registration + Scenario: Registration fails when passwords do not match + When I submit a POST request to "/register" with mismatched password and confirm_password + Then the response status should be 400 + And the response should include an error message about password mismatch + + @negative @registration + Scenario: Registration fails with invalid field formats + When I submit a POST request to "/register" with an invalid email format in the User model + Then the response status should be 400 + And the response should include an error message about email format + + @negative @registration + Scenario: Registration fails when username is already taken + Given an existing user with username "johndoe" + When I submit a POST request to "/register" with the username "johndoe" + Then the response status should be 409 + And the response should include an error message about duplicate username + + @negative @verification + Scenario: Verification fails when token is missing + When I send a GET request to "/verify" with the code query parameter but missing the token + Then the response status should be 400 + And the response should include an error message about the missing token + + @negative @verification + Scenario: Verification fails when code is invalid + When I send a GET request to "/verify" with a valid token and an invalid code + Then the response status should be 400 + And the response should include an error message about invalid code + + @negative @verification + Scenario: Verification fails when token is expired + When I send a GET request to "/verify" with an expired token and valid code + Then the response status should be 410 + And the response should include an error message about token expiration + + @edge @registration + Scenario: Registration fails when password is exactly minimum allowed length + When I submit a POST request to "/register" with a password of exactly the minimum length allowed + Then the response status should be 201 + And the response should indicate registration is successful + + @edge @registration + Scenario: Registration fails when extra unexpected fields are provided + When I submit a POST request to "/register" with valid fields plus extra unexpected fields + Then the response status should be 400 + And the response should mention unexpected fields + + @edge @verification + Scenario: Verification fails when both token and code are blank + When I send a GET request to "/verify" with both token and code as blank values + Then the response status should be 400 + And the response should include an error message about missing required parameters + + @edge @registration + Scenario: Registration fails with extremely long field input + When I submit a POST request to "/register" with a username longer than the allowed maximum + Then the response status should be 400 + And the response should include an error message about field length constraints + + @edge @verification + Scenario: Verification fails when token and code are valid but already used + Given the user has already completed verification with the given token and code + When I send a GET request to "/verify" with the same token and code again + Then the response status should be 409 + And the response should include an error message about already verified + + @edge @registration + Scenario: Registration fails when fields have only whitespace + When I submit a POST request to "/register" with whitespace-only values for username, email, or password + Then the response status should be 400 + And the response should include an error message about invalid input + + @edge @registration + Scenario: Registration fails when confirm_password is missing + When I submit a POST request to "/register" without the confirm_password field + Then the response status should be 400 + And the response should include an error message about missing confirm_password diff --git a/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_transact_operations.feature b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_transact_operations.feature new file mode 100644 index 0000000..80f0f86 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_transact_operations.feature @@ -0,0 +1,148 @@ +Feature: Deposit Funds + As an authenticated user + I want to deposit funds into my bank account + So that I can increase my account balance + + @smoke + Scenario: Successful deposit to valid account + Given an authenticated user with account_id "ACC123" + When the user deposits 100.00 into account "ACC123" + Then the response should contain updated account information with increased balance + + @regression + Scenario: Deposit without authentication + Given an unauthenticated user + When the user attempts to deposit 50.00 into account "ACC123" + Then the response should be an authentication error + + @regression + Scenario: Deposit to a non-existent account + Given an authenticated user + When the user deposits 100.00 into account "INVALID_ACC" + Then the response should be an error indicating the account does not exist + + @edge + Scenario: Deposit a negative amount + Given an authenticated user with account_id "ACC123" + When the user deposits -10.00 into account "ACC123" + Then the response should be an error indicating invalid amount + + @edge + Scenario: Deposit a very large amount + Given an authenticated user with account_id "ACC123" + When the user deposits 1000000000.00 into account "ACC123" + Then the response should contain updated account information or a limit exceeded error + + +Feature: Money Transfer + As an authenticated user + I want to transfer funds between accounts + So that I can move my money as needed + + @smoke + Scenario: Successful transfer between two existing accounts + Given an authenticated user with accounts "ACC001" and "ACC002" + And "ACC001" has sufficient balance + When the user transfers 200.00 from "ACC001" to "ACC002" + Then the response should show the updated balances for both accounts + + @regression + Scenario: Transfer with invalid authentication + Given an unauthenticated user + When the user attempts to transfer 20.00 from "ACC001" to "ACC002" + Then the response should be an authentication error + + @regression + Scenario: Transfer with insufficient funds + Given an authenticated user with account "ACC001" having 10.00 balance + When the user transfers 50.00 from "ACC001" to "ACC002" + Then the response should be an error indicating insufficient funds + + @edge + Scenario: Transfer negative amount + Given an authenticated user with accounts "ACC001" and "ACC002" + When the user attempts to transfer -100.00 from "ACC001" to "ACC002" + Then the response should be an error indicating invalid amount + + @edge + Scenario: Transfer very large amount + Given an authenticated user with account "ACC001" having 2,000,000,000.00 balance + When the user transfers 1,500,000,000.00 from "ACC001" to "ACC002" + Then the response should show updated balances or a limit exceeded error + + +Feature: Withdraw Funds + As an authenticated user + I want to withdraw money from my bank account + So that I can access my funds + + @smoke + Scenario: Successful withdrawal from an account with sufficient funds + Given an authenticated user with account_id "ACC123" and balance 500.00 + When the user withdraws 100.00 from account "ACC123" + Then the response should contain account info with reduced balance + + @regression + Scenario: Withdrawal without authentication + Given an unauthenticated user + When the user attempts to withdraw 20.00 from account "ACC123" + Then the response should be an authentication error + + @regression + Scenario: Withdraw amount exceeding account balance + Given an authenticated user with account_id "ACC123" and balance 50.00 + When the user withdraws 100.00 from account "ACC123" + Then the response should be an error indicating insufficient funds + + @edge + Scenario: Withdraw negative amount + Given an authenticated user with account_id "ACC123" + When the user withdraws -50.00 from account "ACC123" + Then the response should be an error indicating invalid amount + + @edge + Scenario: Withdraw a very large amount + Given an authenticated user with account_id "ACC123" and large balance + When the user withdraws 1000000000.00 from account "ACC123" + Then the response should contain updated account information or a limit exceeded error + + +Feature: Make Payment + As an authenticated user + I want to make a payment from my account + So that I can pay bills or merchants + + @smoke + Scenario: Successful payment to a valid payee + Given an authenticated user with account_id "ACC789" and sufficient funds + And a valid PaymentRequest to payee "MERCHANT123" for 250.00 + When the user submits the payment + Then the response should contain updated account information with payment deducted + + @regression + Scenario: Payment with invalid authentication + Given an unauthenticated user + When the user submits a PaymentRequest + Then the response should be an authentication error + + @regression + Scenario: Payment with insufficient funds + Given an authenticated user with account_id "ACC789" and balance 10.00 + And a PaymentRequest to payee "MERCHANT123" for 100.00 + When the user submits the payment + Then the response should be an error indicating insufficient funds + + @edge + Scenario: Payment with negative amount + Given an authenticated user with account_id "ACC789" + And a PaymentRequest to payee "MERCHANT123" for -50.00 + When the user submits the payment + Then the response should be an error indicating invalid amount + + @edge + Scenario: Payment with very large amount + Given an authenticated user with account_id "ACC789" and large balance + And a PaymentRequest to payee "MERCHANT123" for 2000000000.00 + When the user submits the payment + Then the response should contain updated account information or a limit exceeded error + diff --git a/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_user_login_logout.feature b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_user_login_logout.feature new file mode 100644 index 0000000..ea17e08 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/gherkin_scenarios/gherkin_user_login_logout.feature @@ -0,0 +1,85 @@ +Feature: User Login and Logout API for Online Banking + + Background: + Given the API is available + + ## LOGIN ENDPOINT SCENARIOS + + @smoke + Scenario: Successful Login with valid credentials + Given a registered user exists with email "user@example.com" and password "Password123!" + When the client sends a POST request to "/login" with body: + | email | password | + | user@example.com | Password123! | + Then the response status should be 200 + And the response should contain a non-empty "access_token" + And the response "message" should be "Login successful" + + @regression + Scenario: Login fails with invalid email or password + Given a registered user exists with email "user@example.com" and password "Password123!" + When the client sends a POST request to "/login" with body: + | email | password | + | user@example.com | WrongPass | + Then the response status should be 401 + And the response "message" should be "Invalid email or password" + + @regression + Scenario: Login fails with missing required fields + When the client sends a POST request to "/login" with body: + | email | + | | + Then the response status should be 400 + And the response "message" should indicate "Missing required fields" + + @regression + Scenario: Login fails for unverified user + Given a user exists with email "unverified@example.com", password "Password123!", and not verified + When the client sends a POST request to "/login" with body: + | email | password | + | unverified@example.com | Password123! | + Then the response status should be 403 + And the response "message" should be "User not verified" + + @regression + Scenario: Login fails for locked-out user (edge case) + Given a user exists with email "locked@example.com", password "Password123!", and is locked out after multiple failed attempts + When the client sends a POST request to "/login" with body: + | email | password | + | locked@example.com | Password123! | + Then the response status should be 423 + And the response "message" should be "Account locked. Please contact support." + + @regression + Scenario: Login with extremely long email/password (boundary) + When the client sends a POST request to "/login" with an email over 255 characters and password over 100 characters + Then the response status should be 400 + And the response "message" should indicate "Invalid input length" + + ## LOGOUT ENDPOINT SCENARIOS + + @smoke + Scenario: Successful logout with valid token + Given a user is logged in and has a valid "access_token" + When the client sends a GET request to "/logout" with the "access_token" + Then the response status should be 200 + And the response "message" should be "Logout successful" + + @regression + Scenario: Logout fails with missing authentication token + When the client sends a GET request to "/logout" without an authentication header + Then the response status should be 401 + And the response "message" should be "Authorization required" + + @regression + Scenario: Logout fails with expired or invalid token + When the client sends a GET request to "/logout" with an expired or tampered "access_token" + Then the response status should be 401 + And the response "message" should be "Invalid or expired token" + + @regression + Scenario: Logout with already logged-out token (edge case) + Given a user has already logged out so their token is invalidated + When the client sends a GET request to "/logout" with the invalidated "access_token" + Then the response status should be 401 + And the response "message" should be "Invalid or expired token" diff --git a/Online-Banking-App-Spring-Boot/openapi.json b/Online-Banking-App-Spring-Boot/openapi.json new file mode 100644 index 0000000..9827a75 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/openapi.json @@ -0,0 +1,492 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "DemoBank API", + "version": "1.0.0" + }, + "paths": { + "/": { + "get": { + "summary": "API root", + "responses": { + "200": { + "description": "Root info", + "content": { + "application/json": { + "schema": { "type": "object" } + } + } + } + } + } + }, + "/login": { + "post": { + "summary": "User login", + "requestBody": { + "description": "Login credentials", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "username": { "type": "string" }, + "password": { "type": "string" } + }, + "required": ["username", "password"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful login", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "token": { "type": "string" }, + "user": { "$ref": "#/components/schemas/User" } + }, + "required": ["token", "user"] + } + } + } + }, + "401": { + "description": "Invalid credentials" + } + } + } + }, + "/logout": { + "get": { + "summary": "Logout", + "security": [{ "bearerAuth": [] }], + "responses": { + "200": { + "description": "Successfully logged out", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { "type": "string" } + } + } + } + } + } + } + } + }, + "/register": { + "post": { + "summary": "User registration", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "201": { + "description": "User registered", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Registration error" + } + } + } + }, + "/account/create_account": { + "post": { + "summary": "Create account", + "security": [{ "bearerAuth": [] }], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "account_type": { "type": "string" }, + "user_id": { "type": "integer" } + }, + "required": ["account_type", "user_id"] + } + } + } + }, + "responses": { + "201": { + "description": "Account created", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/Account" } + } + } + } + } + } + }, + "/app/dashboard": { + "get": { + "summary": "User dashboard", + "security": [{ "bearerAuth": [] }], + "responses": { + "200": { + "description": "Dashboard data", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "accounts": { + "type": "array", + "items": { "$ref": "#/components/schemas/Account" } + }, + "user": { "$ref": "#/components/schemas/User" } + }, + "required": ["accounts", "user"] + } + } + } + } + } + } + }, + "/app/payment_history": { + "get": { + "summary": "Payment history", + "security": [{ "bearerAuth": [] }], + "responses": { + "200": { + "description": "Array of payment history", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { "$ref": "#/components/schemas/PaymentHistory" } + } + } + } + } + } + } + }, + "/app/transaction_history": { + "get": { + "summary": "Transaction history", + "security": [{ "bearerAuth": [] }], + "responses": { + "200": { + "description": "Array of transaction history", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { "$ref": "#/components/schemas/TransactionHistory" } + } + } + } + } + } + } + }, + "/app/account_transaction_history": { + "post": { + "summary": "Account transaction history", + "security": [{ "bearerAuth": [] }], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "account_id": { "type": "integer" } + }, + "required": ["account_id"] + } + } + } + }, + "responses": { + "200": { + "description": "Array of transaction history for account", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { "$ref": "#/components/schemas/TransactionHistory" } + } + } + } + } + } + } + }, + "/transact/deposit": { + "post": { + "summary": "Make a deposit", + "security": [{ "bearerAuth": [] }], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "account_id": { "type": "integer" }, + "amount": { "type": "number" } + }, + "required": ["account_id", "amount"] + } + } + } + }, + "responses": { + "200": { + "description": "Deposit success", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/Transact" } + } + } + } + } + } + }, + "/transact/transfer": { + "post": { + "summary": "Transfer between accounts", + "security": [{ "bearerAuth": [] }], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/TransferRequest" } + } + } + }, + "responses": { + "200": { + "description": "Transfer success", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/Transact" } + } + } + } + } + } + }, + "/transact/withdraw": { + "post": { + "summary": "Withdraw from account", + "security": [{ "bearerAuth": [] }], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "account_id": { "type": "integer" }, + "amount": { "type": "number" } + }, + "required": ["account_id", "amount"] + } + } + } + }, + "responses": { + "200": { + "description": "Withdrawal success", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/Transact" } + } + } + } + } + } + }, + "/transact/payment": { + "post": { + "summary": "Send payment", + "security": [{ "bearerAuth": [] }], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/PaymentRequest" } + } + } + }, + "responses": { + "200": { + "description": "Payment processed", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { "type": "string" }, + "accounts": { + "type": "array", + "items": { "$ref": "#/components/schemas/Account" } + } + } + } + } + } + }, + "400": { + "description": "Payment error" + } + } + } + }, + "/verify": { + "get": { + "summary": "Verify a token and code", + "parameters": [ + { + "name": "token", + "in": "query", + "required": true, + "schema": { "type": "string" } + }, + { + "name": "code", + "in": "query", + "required": true, + "schema": { "type": "string" } + } + ], + "responses": { + "200": { + "description": "Verification status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "verified": { "type": "boolean" }, + "message": { "type": "string" } + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "user_id": { "type": "integer" }, + "username": { "type": "string" }, + "email": { "type": "string" }, + "full_name": { "type": "string" }, + "created_at": { "type": "string", "format": "date-time" } + }, + "required": ["user_id", "username", "email", "full_name", "created_at"] + }, + "Account": { + "type": "object", + "properties": { + "account_id": { "type": "integer" }, + "user_id": { "type": "integer" }, + "account_type": { "type": "string" }, + "balance": { "type": "number" }, + "created_at": { "type": "string", "format": "date-time" }, + "status": { "type": "string" } + }, + "required": ["account_id", "user_id", "account_type", "balance", "created_at", "status"] + }, + "PaymentRequest": { + "type": "object", + "properties": { + "from_account_id": { "type": "integer" }, + "to_account_id": { "type": "integer" }, + "amount": { "type": "number" }, + "description": { "type": "string" } + }, + "required": ["from_account_id", "to_account_id", "amount", "description"] + }, + "PaymentHistory": { + "type": "object", + "properties": { + "payment_id": { "type": "integer" }, + "from_account_id": { "type": "integer" }, + "to_account_id": { "type": "integer" }, + "amount": { "type": "number" }, + "performed_at": { "type": "string", "format": "date-time" }, + "status": { "type": "string" }, + "description": { "type": "string" } + }, + "required": ["payment_id", "from_account_id", "to_account_id", "amount", "performed_at", "status", "description"] + }, + "TransactionHistory": { + "type": "object", + "properties": { + "transaction_id": { "type": "integer" }, + "account_id": { "type": "integer" }, + "transaction_type": { "type": "string" }, + "amount": { "type": "number" }, + "timestamp": { "type": "string", "format": "date-time" }, + "description": { "type": "string" }, + "status": { "type": "string" } + }, + "required": ["transaction_id", "account_id", "transaction_type", "amount", "timestamp", "description", "status"] + }, + "Transact": { + "type": "object", + "properties": { + "transact_id": { "type": "integer" }, + "account_id": { "type": "integer" }, + "amount": { "type": "number" }, + "transaction_type": { "type": "string" }, + "timestamp": { "type": "string", "format": "date-time" }, + "status": { "type": "string" } + }, + "required": ["transact_id", "account_id", "amount", "transaction_type", "timestamp", "status"] + }, + "TransferRequest": { + "type": "object", + "properties": { + "from_account_id": { "type": "integer" }, + "to_account_id": { "type": "integer" }, + "amount": { "type": "number" } + }, + "required": ["from_account_id", "to_account_id", "amount"] + } + }, + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + } + } + } +} diff --git a/Online-Banking-App-Spring-Boot/test_docs/README.md b/Online-Banking-App-Spring-Boot/test_docs/README.md new file mode 100644 index 0000000..e35b82f --- /dev/null +++ b/Online-Banking-App-Spring-Boot/test_docs/README.md @@ -0,0 +1,24 @@ +# Test Documentation Index + +This directory contains comprehensive test documentation for the DemoBank banking system. Materials are cross-referenced to requirements, API contracts, and generated Gherkin features. + +## Contents + +- [Business Use Cases](business_use_cases.md) +- [API Flows](api_flows.md) +- [Test Coverage Analysis](test_coverage.md) + +## Additional Artifacts + +- Gherkin Feature Scenarios: [../gherkin_scenarios/] +- OpenAPI Spec: [../openapi.json] + +## How to Use + +- Use 'Business Use Cases' for mapping tested scenarios and flows to business requirements. +- Use 'API Flows' for reviewing process/sequence integration, error handling, and state transitions. +- Use 'Test Coverage Analysis' to assess coverage, gaps, and improvement priorities. + +--- + +All documentation is linked directly to discovered endpoints, flows, and models for traceability. diff --git a/Online-Banking-App-Spring-Boot/test_docs/api_flows.md b/Online-Banking-App-Spring-Boot/test_docs/api_flows.md new file mode 100644 index 0000000..a6b8391 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/test_docs/api_flows.md @@ -0,0 +1,152 @@ +# API Flows + +This section describes the end-to-end API flows for core DemoBank use cases, detailing stepwise API calls, data flow, important model state changes, and integration points. Each flow references the corresponding [Gherkin-tested scenarios](gherkin_scenarios/) and uses the [OpenAPI endpoints](../openapi.json) and [Data Models](../README.md). + +--- + +## 1. User Registration & Verification Flow +### Overview +A new user proceeds from registration, receives a verification code, and verifies their account to enable login. + +#### Stepwise Call Sequence + +1. **Register User** + - POST `/register` + - Input: email, password, name, optional KYC fields. + - Output: User record (`pending_verification`). Verification sent to email. +2. **Verify Email** + - GET `/verify?token=...&code=...` + - Input: verification code and token + - Output: Status updated to `active` (on success). +3. **Edge Cases & Error Handling** + - Invalid/expired code (400/410); already verified (409) + +#### Data Flow +- User created with status `pending_verification` +- On successful verification: status updated to `active` + +--- + +## 2. Login & Logout Flow +### Overview +Users authenticate using credentials and receive JWT token for session. + +#### Stepwise Call Sequence + +1. **Login** + - POST `/login` + - Input: email, password + - Output: access_token, user profile +2. **Edge/Error Cases** + - Wrong password (401); unverified/locked account (403/423/401) +3. **Logout** + - GET `/logout` (Authorization header) + - Output: Success message; token invalidated + +--- + +## 3. Dashboard Retrieval +### Overview +Authenticated users access dashboard for account overview. + +#### Stepwise Call Sequence + +1. **Fetch Dashboard** + - GET `/app/dashboard` (Authorization) + - Output: userAccounts, totalBalance, summary +2. **Edge Cases** + - Token invalid/expired (401); server errors (500) + +--- + +## 4. Account Creation Flow +### Overview +Authenticated users create new bank accounts for themselves. + +#### Stepwise Call Sequence + +1. **Create Account** + - POST `/account/create_account` + - Input: account_name, account_type + - Output: new Account object +2. **Edge Cases** + - Duplicate (409), missing fields (400), invalid type (400), unauthenticated (401) + +--- + +## 5. Payment & Transaction History Retrieval +### Overview +Users view all payment and transaction histories for their accounts. + +#### Stepwise Call Sequence + +1. **Get Payment History** + - GET `/app/payment_history` (Authorization) + - Output: list of PaymentHistory objects +2. **Get Transaction History** + - GET `/app/transaction_history` OR POST `/app/account_transaction_history` with account_id + - Output: list of TransactionHistory +3. **Edge Cases** + - Unauthorized (401), forbidden (403), invalid account_id (400) + - Empty collections handled gracefully + +--- + +## 6. Deposit Funds Flow +### Overview +User deposits funds into an account. + +#### Stepwise Call Sequence + +1. **Deposit** + - POST `/transact/deposit` + - Input: deposit_amount, account_id + - Output: updated Account object or deposit status +2. **Edge/Error** + - Unauthenticated (401), invalid account (404), invalid/negative amount (400) + +--- + +## 7. Withdrawal Flow +### Overview +Withdraw funds from a user account. + +#### Stepwise Call Sequence + +1. **Withdraw** + - POST `/transact/withdraw` + - Input: withdrawal_amount, account_id + - Output: updated Account, withdrawal status +2. **Edge Cases** + - Insufficient funds (409/422); unauthorized (401); invalid fields (400) + +--- + +## 8. Send Payment / Transfer Funds Flow +### Overview +Transfer money between accounts, or send payment to a payee. + +#### Stepwise Call Sequence + +1. **Transfer** + - POST `/transact/transfer` (TransferRequest) + - Input: sourceAccount, targetAccount, amount + - Output: updated accounts after transfer +2. **Payment** + - POST `/transact/payment` (PaymentRequest) + - Input: beneficiary, account_number, reference, payment_amount + - Output: payment status, updated accounts +3. **Edge Cases** + - Invalid/unauthenticated (401/403), insufficient funds (409), bad input (400) + +--- + +## Error Handling & Integration Points +- Authentication via JWT for all protected endpoints +- State transitions: Account balances, user status +- Integration: Email/SMS for verification, payment gateways for external payments +- Response codes: 200/201 (success), 400/401/403/409/422 (errors) + +--- + +*Flows map directly against Gherkin scenarios and OpenAPI endpoints/models for traceability.* diff --git a/Online-Banking-App-Spring-Boot/test_docs/business_use_cases.md b/Online-Banking-App-Spring-Boot/test_docs/business_use_cases.md new file mode 100644 index 0000000..4a99e28 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/test_docs/business_use_cases.md @@ -0,0 +1,205 @@ +# Business Use Cases + +This section details the end-to-end business use cases for DemoBank's online banking system, integrating system flows, user perspectives, business rules, actors, and acceptance criteria. Each use case ties directly to endpoints, tested scenarios (Gherkin feature summaries), and validated flows per the OpenAPI specification. + +--- + +## 1. Account Creation + +### User Stories + +- **As a new customer**, I want to create a bank account so that I can perform banking transactions online. +- **As a system admin**, I want to ensure all account creations are properly validated and logged. + +### Acceptance Criteria + +- The user provides all mandatory data (name, email, phone, password, etc.). +- The system verifies data validity and uniqueness (e.g., unique email/username). +- Upon success, the account is created in a 'pending verification' state. +- The user receives an account creation confirmation along with a verification process initiation. +- Error messages are presented for missing or invalid fields. + +### Business Rules & Constraints + +- All required fields must be supplied, and must pass format validation (e.g. valid email, password complexity). +- Duplicate email or phone numbers are not allowed. +- Created accounts remain inactive until verified. +- System must log attempts (both successful and failed) for audit purposes. + +### Actors + +- **Customer (User):** Initiates account creation. +- **Admin:** Monitors for compliance and addresses registration issues. +- **External Email/SMS Provider:** Delivers verification email/SMS. + +--- + +## 2. Registration & Verification + +### User Stories + +- **As a new user**, I want to register and verify my account so that I gain access to the online banking system. +- **As the system**, I want to enforce multi-factor account validation to improve security. + +### Acceptance Criteria + +- Upon registration, a verification code/link is sent via email/SMS. +- The user submits the correct verification code or clicks the verification link. +- Verified accounts are marked as 'active'; if fail, remain 'pending' or get 'locked' after maximum attempts. +- User receives confirmation of successful verification. +- Incorrect or expired codes result in a clear error message. + +### Business Rules & Constraints + +- Verification links/codes expire after a configured period (e.g., 24 hours). +- A maximum number of verification attempts is enforced. +- Upon repeated failure, account entry may be locked pending admin intervention. + +### Actors + +- **Customer (User):** Completes verification, receives notification. +- **External Email/SMS Provider:** Delivers verification. +- **Admin:** Unlocks or re-verifies accounts if needed. + +--- + +## 3. Login/Logout + +### User Stories + +- **As a registered user**, I want to securely log in and out so that my account and transactions are safe. +- **As the system**, I ensure inactive/locked accounts cannot log in. + +### Acceptance Criteria + +- User provides valid username and password. +- Only accounts that are both active and verified can log in. +- Upon success, a session or JWT token is issued. +- User can log out, which destroys the session/token. +- Incorrect credentials or locked accounts are rejected with appropriate error messages. + +### Business Rules & Constraints + +- Passwords must be stored securely (e.g., hashed & salted). +- Logins are logged for audit and fraud detection. +- After a configurable number of failed attempts, the account is locked. +- Password reset flow is available if user forgets password. + +### Actors + +- **Customer (User):** Authenticates to the system. +- **Admin:** Views login attempts, unlocks accounts. +- **Authentication Service:** Issues and validates tokens/session. + +--- + +## 4. Dashboard & Balance Inquiry + +### User Stories + +- **As a logged-in user**, I want to view my account dashboard and real-time balances so that I can manage my finances. +- **As the system**, I restrict dashboard/balance access to authenticated users only. + +### Acceptance Criteria + +- User is authenticated before access is granted. +- Dashboard displays current balances for all linked accounts. +- User sees recent activity summaries (last N transactions per account). +- Data is up-to-date and accurate per the account ledger. + +### Business Rules & Constraints + +- Balance information must reflect all cleared and pending transactions. +- Only accounts owned by a user are listed. +- No sensitive information beyond configured data is displayed. + +### Actors + +- **Customer (User):** Views dashboard and balances. +- **Account Service:** Computes and serves requested data. + +--- + +## 5. Deposit, Withdraw, Payment, & Transfer + +### User Stories + +- **As a user**, I want to deposit to, withdraw from, or transfer money between accounts, or make payments so that I can manage my finances. +- **As the system**, I enforce transaction limits, validate recipient/payee details, and ensure funds sufficiency. + +### Acceptance Criteria + +- Only logged-in, active, and verified users can initiate transactions. +- Transaction requests validate required fields, amount, and sufficient balance (for outgoing transactions). +- Deposits increase balance; withdrawals/payments/transfers debit accordingly. +- For transfers and payments, recipient info is checked (valid account/external payee). +- Transactions are atomic—either fully succeed (with updated balances & entry in transaction history), or failure is rolled back. +- User sees clear success or error confirmation, including reason for any failure. + +### Business Rules & Constraints + +- Minimum and maximum amounts per operation are enforced (configurable per bank policy). +- Overdrafts are not allowed unless account is configured explicitly. +- All transactions are timestamped and recorded in transaction history. +- Daily and per-transaction limits are enforced. +- Additional 2-factor confirmation may be required above certain thresholds. +- Suspicious or repeated failed attempts are logged and may trigger security rules. + +### Actors + +- **Customer (User):** Initiates all types of transactions. +- **Account Service:** Validates, processes, and records transactions. +- **Admin:** Monitors for fraud, reviews/approves flagged transactions. +- **External Payment Systems:** (for payment endpoints) Process external payments. + +--- + +## 6. Payment & Transaction History + +### User Stories + +- **As a user**, I want to review my transaction history so that I can track deposits, withdrawals, payments, and transfers. +- **As the system**, I ensure only the account owner can view sensitive transaction data. + +### Acceptance Criteria + +- User is authenticated and authorized for target account's data. +- The endpoint returns a paginated, filterable (by date/type/amount) list of all past transactions. +- Transaction data includes amount, type, date, status, and description. +- User can view transaction details and export summaries. + +### Business Rules & Constraints + +- Only account holders and authorized admins can view transaction details. +- Sensitive information (such as payee details for certain transaction types) is masked as per privacy policy. +- History reflects all cleared and pending transactions and is immutable. +- Transactions recorded in strict chronological order. + +### Actors + +- **Customer (User):** Reviews and exports transaction history. +- **Account Service:** Provides secure, filtered transaction data. +- **Admin:** Audits transaction records. + +--- + +## Actor Descriptions + +- **Customer (User):** Individual bank customers using the DemoBank online platform for personal financial management. +- **Admin:** Bank staff authorized to manage accounts, monitor for compliance/security, resolve user issues. +- **External Systems:** Trusted third parties such as payment gateways, SMS/email providers, and regulatory auditing systems. + +--- + +## General Business Rules & Constraints + +- All major user flows are protected by authentication and authorization per endpoint. +- Changes to user/profile/financial data are auditable and logged. +- Data privacy and security are enforced per financial regulations (e.g., PCI DSS, GDPR). +- All endpoints adhere to the API contract described in OpenAPI documentation. +- System must provide meaningful error codes and descriptions per failure case. +- All monetary operations use the system's currency configuration, and amounts are processed with correct precision/rounding. + +--- + +*End of Business Use Cases Section* diff --git a/Online-Banking-App-Spring-Boot/test_docs/test_coverage.md b/Online-Banking-App-Spring-Boot/test_docs/test_coverage.md new file mode 100644 index 0000000..3d0fb2f --- /dev/null +++ b/Online-Banking-App-Spring-Boot/test_docs/test_coverage.md @@ -0,0 +1,61 @@ +# Test Coverage Analysis + +## Overview + +This section analyzes the coverage provided by Gherkin feature tests against the DemoBank business flows, endpoints, and models, identifying gaps and areas requiring additional testing. + +--- + +### Mapping of Gherkin Scenarios to Endpoints + +| Business Flow | Endpoint | Covered | Notes | +|---------------------------------------|------------------------------------|---------|-----------------------------| +| Registration & Verification | /register, /verify | Full | Happy, negative, edge cases | +| Login/Logout | /login, /logout | Full | Auth, locked, expired token | +| Account Creation | /account/create_account | Full | All errors, edge cases | +| Dashboard & Balance Inquiry | /app/dashboard | Full | Empty, error, full balances | +| Payment History | /app/payment_history | Full | Large, invalid data, empty | +| Transaction History | /app/transaction_history, | Full | Edge, empty, forbidden | +| | /app/account_transaction_history | | | +| Deposit | /transact/deposit | Full | Negative, large, invalid | +| Withdrawal | /transact/withdraw | Full | Insufficient, large, edge | +| Payment | /transact/payment | Full | Auth, insufficient funds | +| Transfer | /transact/transfer | Full | Insufficient, edge | + + +### Coverage Gaps & Under-tested Areas + +- **Advanced Integration:** External payment processor failures, notification delivery, resilience not covered +- **Concurrency:** Simultaneous requests, race conditions and atomicity (covered minimally) +- **Edge Cases:** Some extreme parameter values (e.g., boundary/overflow in amounts, rapid submits) +- **Security:** RBAC and privilege escalation not explicitly covered; token tampering, session expiration +- **Performance:** Large-scale/fault scenarios (covered for history, but not for transactions/payment flows) +- **Data Privacy:** Masking/sanitization, info leakage not tested +- **Admin Flows:** No scenarios for admin endpoints or privileged actions + + +### Risk Areas & Recommendations + +- Add scenarios for multi-step integration (payment gateway failures, notification retries) +- Expand security tests: session expiry, token tampering, role/permission escalation +- Include admin flows: user/account management, privileged error paths +- Test error propagation in payment, withdrawal, transfer (e.g., partial failure, rollback) +- Edge values: maximum/minimum, outlier amounts, empty/overflow data +- Pairwise and concurrency: rapid submission, duplicate/atomic tests +- Audit and logging: ensure auditable traces for all major flows + +--- + +## Summary Table + +| Area | Coverage | Priority | +|------------------|---------|--------------| +| User Flows | High | Medium | +| Edge Cases | High | High | +| Integration | Medium | High | +| Security | Medium | High | +| Admin Flows | Low | High | + +--- + +*Linkage: All tests tie directly to business flows, API endpoints, and models as extracted from the codebase and OpenAPI specification. Immediate improvements should focus on resilience, security, integration, and admin/testing.*