Skip to content

test(e2e): cover insufficient-funds bank-transfer withdrawal journey - #131

Open
devin-ai-integration[bot] wants to merge 1 commit into
developfrom
devin/1783472741-insufficient-funds-withdrawal
Open

devin-ai-integration[bot] wants to merge 1 commit into
developfrom
devin/1783472741-insufficient-funds-withdrawal

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jul 8, 2026

Copy link
Copy Markdown

Summary

Adds a Cypress E2E spec exercising the previously-untested "insufficient funds → automatic bank-transfer withdrawal" branch in debitPayAppBalance (backend/database.ts), which is currently marked /* istanbul ignore next */.

New file cypress/tests/ui/new-transaction-insufficient-funds.spec.ts mirrors the conventions in new-transaction.spec.ts (db:seed, createTransaction intercept, db:filter userssender = users[0]/receiver = users[1], loginByXstate). It submits a payment larger than the sender's balance via the cy.createTransaction custom command (driving the XState service directly to bypass form validation), using:

const amount = Math.ceil(sender.balance / 100) + 100; // dollars; balances stored in cents

Assertions:

  • completion step visible: new-transaction-create-another-transaction
  • sender balance reset to 0
  • a withdrawal bank transfer created for the sender
  • receiver credited by amount * 100 cents (Dinero + switchUserByXstate)

Note on the withdrawal assertion: seeded users already have a pre-existing deposit bank transfer, so cy.database("find", "banktransfers", { userId: sender.id }) returns that deposit (lodash _.find = first match) rather than the new withdrawal. The spec instead scopes the lookup to the created transaction via the @createTransaction response id:

cy.wait("@createTransaction").then((intercept) => {
  const transactionId = intercept.response!.body.transaction.id;
  cy.database("find", "banktransfers", { userId: sender.id, transactionId })
    .its("type").should("equal", "withdrawal");
});

No backend logic or istanbul ignore annotations were modified — the branch is exercised as-is.

Verification

  • yarn cypress:run --spec cypress/tests/ui/new-transaction-insufficient-funds.spec.ts → 1/1 passing
  • yarn cypress:run --spec cypress/tests/ui/new-transaction.spec.ts → 10/10 passing (no regressions)
  • yarn lint and yarn types clean

Link to Devin session: https://app.devin.ai/sessions/22155aaac3a1493399a682f15e8f7217
Requested by: @sheldonchincognition


Devin Review

Status Commit
⚪ Not started

Run Devin Review

Open in Devin Review (Staging)
Open in Devin Review

Co-Authored-By: sheldon.chin <sheldon.chin@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment on lines +57 to +59
const updatedAccountBalance = Dinero({
amount: ctx.receiver!.balance + amount * 100,
}).toFormat();

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Receiver balance assertion relies on stale seed-time snapshot

The expected receiver balance on line 57-58 is computed as ctx.receiver!.balance + amount * 100, where ctx.receiver!.balance is captured from the seed data in beforeEach. This works correctly because no other operation in the test modifies the receiver's balance before the assertion. However, this is a fragile pattern: if the seed data or test setup ever changes such that the receiver participates in other transactions before this point, the assertion would silently produce incorrect expected values. The same pattern is used in cypress/tests/ui/new-transaction.spec.ts:188-190, so this is consistent with the codebase convention.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +13 to +24
beforeEach(function () {
cy.task("db:seed");

cy.intercept("POST", "/transactions").as("createTransaction");

cy.database("filter", "users").then((users: User[]) => {
ctx.sender = users[0];
ctx.receiver = users[1];

return cy.loginByXstate(ctx.sender.username);
});
});

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Test omits several route intercepts present in the sibling test file

The existing new-transaction.spec.ts sets up intercepts for GET /users*, GET /users/search*, GET /notifications, GET /transactions/public, GET /transactions, and PATCH /transactions/* in its beforeEach. This new test only intercepts POST /transactions. Since this test uses cy.createTransaction() (which drives the state machine directly) rather than UI-based user search, the missing intercepts don't cause failures. However, the absence of GET /checkAuth aliased as @getUserProfile means the test can't cy.wait on it after transaction creation the way new-transaction.spec.ts:57 does — which is fine since this test doesn't attempt that wait. This is a deliberate simplification, not a bug.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants