A professional, scalable UI test automation framework built with Cypress and TypeScript. This project demonstrates modern test automation best practices for validating critical user-facing flows on the Tangerine Bank website using the Page Object Model (POM) design pattern.
Note: This is a demo/reference implementation showcasing framework architecture and automation strategies.
This repository serves as a reference implementation for enterprise-grade test automation engineering, demonstrating:
- Maintainability: Clear separation of concerns (Test Logic vs. UI Interaction) using Page Object Model
- Scalability: Structured architecture to support multiple test streams and environments
- Type Safety: Leveraging TypeScript for compile-time checks, self-documenting code, and IDE autocompletion
- Reporting: Integrated Allure Reports for comprehensive test execution insights
- Real-World Patterns: Demonstrates actual patterns used in production SDET teams
| Tool | Version | Purpose |
|---|---|---|
| Cypress | ^15.12.0 | End-to-End test runner with built-in debugging |
| TypeScript | ^5.3.0 | Static typing for robust code and better IDE support |
| Node.js | v14+ | JavaScript runtime environment |
| Allure Reports | ^2.38.0 | Comprehensive test reporting and analytics |
The framework adheres to the Page Object Model (POM) pattern, decoupling test logic from page UI interactions.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Test Specification (.cy.ts) β
β "When user logs in, dashboard loads" β
ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β (imports & uses)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Page Object (TangerineLoginPage.ts) β
β - CSS Selectors β
β - Action Methods (clickLogin, fillUsername, etc.) β
ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β (wraps)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Cypress Commands (cy.click(), cy.type(), etc.) β
ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β (interacts with)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Browser / Application Under Test β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Readability: Tests read like business requirements, not technical scripts
- Reusability: UI interactions defined once, reused across all tests
- Resilience: UI changes isolated to Page Objectsβtests remain stable
- Maintainability: Clear responsibility boundaries reduce test maintenance burden
sloth-javascript/
βββ cypress/
β βββ e2e/ # Test specifications
β β βββ homepage.cy.ts # Homepage tests
β β βββ login.cy.ts # Login flow tests
β β βββ register.cy.ts # Registration tests
β βββ support/ # Global configuration
β β βββ commands.ts # Custom Cypress commands
β β βββ e2e.ts # Test setup/teardown
β βββ downloads/ # Downloaded files (test artifacts)
β
βββ src/
β βββ config.ts # Test credentials & environment config
β βββ pages/ # Page Object Models
β βββ TangerineHomePage.ts # Homepage interactions
β βββ TangerineLoginPage.ts # Login page interactions
β βββ TangerineRegisterPage.ts # Registration page interactions
β
βββ cypress/allure-report/ # Generated test reports
βββ cypress.config.ts # Cypress configuration
βββ tsconfig.json # TypeScript configuration
βββ package.json # Dependencies & scripts
βββ README.md # This file
- Node.js v14 or higher (Download)
- npm v6 or higher (comes with Node.js)
- Modern browser (Chrome/Edge/Firefox)
-
Clone the repository:
git clone https://github.com/YOUR-USERNAME/sloth-javascript.git cd sloth-javascript -
Install dependencies:
npm install
-
Run tests in interactive mode:
npm run cypress:open
This opens the Cypress Test Runner where you can:
- Select individual test files to run
- Watch tests execute in real-time
- Debug with DevTools
- View detailed failure messages
Environment Variables:
# Run tests against a specific environment
BASE_URL=https://www.tangerine.ca/en/personal npm testTest Credentials: Edit src/config.ts to update test user credentials (currently set to demo values):
export const testCredentials = {
user: {
clientId: "12345678",
pin: "123456",
},
invalidUser: {
clientId: "87654321",
pin: "654321",
},
};
β οΈ Security Note: Store sensitive credentials in environment variables (.env), not in source code for production setups.
Interactive Modeβopen Cypress Test Runner:
npm run cypress:openHeadless Modeβrun all tests in terminal:
npm test
# or
npm run cypress:runRun specific test file:
npx cypress run --spec "cypress/e2e/login.cy.ts"Run tests with specific grep tags:
npx cypress run --env grep="@smoke"Run against different environments:
BASE_URL=https://staging.tangerine.ca npm testRetry failed tests (configured to 2 retries in headless mode):
Tests automatically retry on failure in cypress run modeβsee cypress.config.ts for retry settings.
File: src/pages/TangerineLoginPage.ts
Encapsulates all selectors and interactions for the login page:
export class TangerineLoginPage {
private clientIdInput = 'input[data-testid="clientId"]';
private pinInput = 'input[data-testid="pin"]';
private loginButton = 'button[type="submit"]';
private errorMessage = '[role="alert"]';
visit() {
cy.visit("/login");
}
fillClientId(clientId: string) {
cy.get(this.clientIdInput).type(clientId);
}
fillPin(pin: string) {
cy.get(this.pinInput).type(pin);
}
clickLogin() {
cy.get(this.loginButton).click();
}
getErrorMessage() {
return cy.get(this.errorMessage);
}
}File: cypress/e2e/login.cy.ts
Tests business logic using the page object:
import { TangerineLoginPage } from "../../src/pages/TangerineLoginPage";
import { testCredentials } from "../../src/config";
describe("Tangerine Login", () => {
const login = new TangerineLoginPage();
beforeEach(() => {
login.visit();
});
it("should successfully login with valid credentials", () => {
login.fillClientId(testCredentials.user.clientId);
login.fillPin(testCredentials.user.pin);
login.clickLogin();
cy.url().should("include", "/dashboard");
cy.contains("Welcome").should("be.visible");
});
it("should show error with invalid credentials", () => {
login.fillClientId(testCredentials.invalidUser.clientId);
login.fillPin(testCredentials.invalidUser.pin);
login.clickLogin();
login.getErrorMessage()
.should("be.visible")
.and("contain", "Invalid credentials");
});
});| Test Suite | Status | Purpose |
|---|---|---|
| Homepage | β | Validates homepage loads, logo visible, navigation works |
| Login | β | Tests valid/invalid login flows, error handling |
| Registration | β | Validates user registration with form validation |
This project includes Allure Reports integration for comprehensive test execution analytics.
After running tests, generate and view the Allure report:
# Generate the report
npm run allure:generate
# Open the report in browser
npm run allure:openDirect CLI equivalents:
npx allure generate cypress/allure-results --clean -o cypress/allure-report
npx allure open cypress/allure-reportOr run tests and generate report in one command:
npm test && npm run allure:generate && npm run allure:open- π Test execution timeline and trends
- β /β Pass/fail statistics and breakdown
- π Test retry information
- π· Screenshots and logs for failed tests
- β±οΈ Performance metrics (test duration)
- π Test categorization (Behaviors, Suites, Severity)
Report Location: cypress/allure-report/index.html (generated locally after running allure:generate)
Issue: Command not found: npx
- Solution: Ensure Node.js and npm are installed:
node --version && npm --version
Issue: Tests timeout or hang
- Solution: Check
cypress.config.tstimeout settings (currently 10s for commands, 120s for page load) - Try increasing values if target site is slow
Common causes:
- Elements changed on target website (Tangerine may update the site)
- Dynamic content not fully loaded before assertions
- Solution: Update selectors in src/pages/ Page Objects, add waits if needed
Issue: allure: command not found
- Solution: Run
npm installto install allure-commandline dependency
Issue: Empty report
- Solution: Ensure tests ran with
npm test(not just opening in GUI). Checkcypress/allure-results/directory exists with JSON files.
src/config.ts are hardcoded for reference. In production, use environment variables or secure secret management (e.g., GitHub Secrets, HashiCorp Vault).
- β Page Object Model (POM) for maintainable tests
- β TypeScript for type-safe test code
- β Separation of Concerns (tests vs. page interactions vs. config)
- β Retry Logic for flaky test resilience
- β Comprehensive Reporting with Allure
- β Custom Commands in Cypress for reusable actions
- β Viewport Configuration for consistent rendering
- CI/CD Pipeline (GitHub Actions)
- Cross-browser testing (Firefox, Safari)
- Performance baseline testing
- Visual regression testing
- API mocking for isolated component tests
Weipeng Zheng
Senior QA Automation Engineer / SDET
Specializing in UI Automation (Cypress, Playwright, Selenium), Test Architecture, and Framework Design.
GitHub: github.com/466725
This project is licensed under the MIT License. Feel free to use it as a reference for your own test automation frameworks.
Contributions are welcome! Please read CONTRIBUTING.md for guidelines on:
- Opening issues and feature requests
- Branching and commit message conventions
- Adding new tests and page objects
- Submitting pull requests
Please also review our Code of Conduct before contributing.
See SECURITY.md for how to report vulnerabilities and security best practices for this project.