JavaScript · Cypress
Stock trading with Cypress
A watchlist with prices that tick every second, market and limit orders with buying-power, holdings and price-band checks, a confirm step, and a portfolio with live P&L. Simulated — no real money.
App under test
📊 TradeX
- URL
- /apps/trading
- Login
- TX1001 / Trade@123
- Trading PIN
- 2468
- Starting cash
- ₹5,00,000
- Brokerage
- ₹20 / order
- Limit band
- ±10% of LTP
Scenarios to automate
Work top to bottom — each one adds a new technique.
- 1
Login + trading PIN
BeginnerClient ID + password (tx-login-id, tx-password, tx-login), then a 4-digit PIN (tx-code, tx-verify). Wrong details show attempts left in tx-login-error; 3 failures lock the form (tx-unlock).
- 2
Asserting live data
Intermediateprice-* changes every second — assert format (₹ + 2 decimals) or that it changed, never an exact value.
- 3
Search & watchlist
Beginnersymbol-search → add-<SYM> adds a watch-row; remove-<SYM> deletes it.
- 4
Quantity validation
Beginner0, decimals or text in order-qty show error-order-qty.
- 5
Buying power
IntermediateOrder more than cash allows; the error tells you the affordable quantity.
- 6
Limit band
IntermediateA limit price more than 10% away from LTP is rejected in error-limit-price.
- 7
Buy then sell
AdvancedBuy at market, then sell part of the holding; holding-qty-<SYM> and cash reconcile (with ₹20 brokerage).
- 8
Open limit orders
AdvancedPlace a limit order near LTP; it may fill on its own — poll order-status or cancel-<id> it.
- 9
Sell more than held
Beginnerside-sell with a quantity above your holding shows “You only hold N share(s)”.
Sample Cypress suite
A working starting point that finds elements every way Cypress can — by role, label, text, id, name, CSS, XPath and data-testid — so you practice them all. Pick your language, switch to data-testid only to compare, or try your own in the Locator Playground.
Cypress runs inside the browser, so it only supports JavaScript and TypeScript — there is no Python, Java or C# version of Cypress. For those languages, see Selenium or Playwright.
// Uses the getByTestId custom command from the Cypress setup (cypress/support/commands.js).
// Locators in this suite: cy.contains ×9 · #id ×3 · [name] ×1 · [aria-label] ×1 · getByTestId ×12
describe('TradeX — simulated trading', () => {
it('buys and partly sells a stock', () => {
cy.visit('/apps/trading');
// Sign in first
cy.get('#tx-login-id').type('TX1001');
cy.get('[name="tx-password"]').type('Trade@123');
cy.contains('button', 'Continue').click();
cy.getByTestId('tx-code').type('2468');
cy.contains('button', 'Verify & continue').click();
cy.getByTestId('price-INFY').should('be.visible');
cy.get('[aria-label="Search stocks"]').type('tata m');
cy.getByTestId('add-TATAMOTORS').click();
cy.getByTestId('price-TATAMOTORS').should('be.visible');
cy.getByTestId('trade-INFY').click();
cy.location('pathname').should('include', '/apps/trading/trade/INFY');
cy.contains('button', 'Buy').click();
cy.contains('button', 'MarketFill now at LTP').click();
cy.get('#order-qty').type('10');
cy.getByTestId('review-order').click();
cy.getByTestId('review-qty').should('contain', '10');
cy.contains('button', 'Confirm').click();
cy.getByTestId('order-result').should('contain', 'Filled');
cy.contains('a', 'Portfolio').click();
cy.getByTestId('holding-qty-INFY').should('contain', '10');
// Sell part of the position
cy.contains('a', 'Sell').click();
cy.get('#order-qty').type('4');
cy.getByTestId('review-order').click();
cy.contains('button', 'Confirm').click();
cy.getByTestId('order-result').should('contain', 'Sold 4 INFY');
cy.contains('a', 'Portfolio').click();
cy.getByTestId('holding-qty-INFY').should('contain', '6');
});
});