Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructure Cypress Code file #9682

Merged
merged 1 commit into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 85 additions & 1 deletion cypress/docs/cypress.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,92 @@
# Cypress Guidelines

## File Structure

```
cypress/
├── docs/
│ └── cypress.md
├── e2e/ # Test files grouped by modules
│ ├── patient/ # Patient module tests
│ │ ├── search.cy.ts
│ │ ├── create.cy.ts
│ │ └── edit.cy.ts
│ ├── facility/ # Facility module tests
│ │ ├── list.cy.ts
│ │ └── details.cy.ts
│ └── user/ # User module tests
│ ├── login.cy.ts
│ └── profile.cy.ts
├── fixtures/ # Test data files by module
│ ├── patient/
│ │ └── patient-data.json
│ └── facility/
│ └── facility-data.json
├── pageObject/ # Page Objects by module
│ ├── patient/
│ │ ├── SearchPage.ts
│ │ └── CreatePage.ts
│ ├── facility/
│ │ ├── ListPage.ts
│ │ └── DetailsPage.ts
│ └── utils/ # Common helpers and global functions
│ ├── CommonActions.ts # Shared actions across pages
│ ├── CommonAssertions.ts # Shared assertions
│ └── GlobalHelpers.ts # Platform-wide utility functions
├── support/ # Core support files
│ ├── commands.ts # Custom Cypress commands
│ ├── e2e.ts # e2e test configuration
│ └── index.ts # Main support file
└── tsconfig.json
```

## Support Files

- `commands.ts`: Custom Cypress commands and their TypeScript definitions
- `e2e.ts`: e2e specific configurations and imports
- `index.ts`: Main support file that loads commands and configurations

## Page Objects Utils

The `pageObjects/utils` folder contains:

- Common helper functions used across different page objects
- Global utility functions for platform-wide operations
- Shared assertions and verifications
- Reusable action patterns

## Module-based Organization

Each module (patient, facility, user, etc.) should have its own:

- Test files in `e2e/<module-name>/`
- Page Objects in `pageObjects/<module-name>/`
- Fixtures in `fixtures/<module-name>/`

This organization helps:

- Keep related tests and page objects together
- Maintain clear separation between module-specific and common utilities
- Enable better code reuse through common utilities
- Keep core support files focused and minimal

## Core Principles

- Create, use and modify Reusable Commands and Functions for Cypress as needed
- Provide Id for the elements using data-cy attributes
- When interacting with a button, verify the button is enabled and visible before interacting with it
- when interacting with a button,verify the text of the button is correct
- when interacting with a button, verify the text of the button is correct
- Use Page Object Model for Cypress
- Use built-in assertions for Cypress
- Use beforeEach, afterEach and all relevant hooks for Cypress on every test file

## File Naming Conventions

- Test files: `feature-name.cy.ts`
- Page Objects: `FeatureNamePage.ts`
- Custom Commands: `feature-name.ts`
- Fixtures: `feature-name-data.json`

## Storage Management

- Use cy.saveLocalStorage() and cy.restoreLocalStorage() for Cypress
Expand All @@ -28,3 +105,10 @@
- Follow AAA pattern (Arrange, Act, Assert)
- Use fixtures for test data
- Implement custom commands for repetitive actions

### Code Editing Guidelines

- When suggesting code edits, provide only the relevant file and changes
- Don't create separate folders for each edit
- Keep the existing file structure intact
- Provide clear comments for what's being changed
30 changes: 30 additions & 0 deletions cypress/e2e/login_spec/loginpage.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { LoginPage } from "../../pageObject/auth/LoginPage";

describe("Login Page", () => {
const loginPage = new LoginPage();

beforeEach(() => {
cy.clearLocalStorage();
cy.saveLocalStorage();
cy.visit("/login");
});

afterEach(() => {
cy.saveLocalStorage();
});

it("should successfully login with admin credentials", () => {
loginPage.interceptLogin();
loginPage.loginByRole("admin");
loginPage.verifyLoginResponse();
cy.url().should("include", "/");
});

it("should display login form elements", () => {
loginPage.verifyFormElements();
});

it("should show validation errors for empty fields", () => {
loginPage.clickSubmit().verifyValidationErrors();
});
});
65 changes: 0 additions & 65 deletions cypress/e2e/public_spec/loginpage.cy.ts

This file was deleted.

60 changes: 60 additions & 0 deletions cypress/pageObject/auth/LoginPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
export class LoginPage {
private routes = {
login: "/api/v1/auth/login/",
};

interceptLogin() {
return cy.intercept("POST", this.routes.login).as("loginRequest");
}

verifyLoginResponse() {
return cy
.wait("@loginRequest")
.its("response.statusCode")
.should("eq", 200);
}

// Add selectors for existing elements
private readonly usernameInput = "[data-cy=username]";
private readonly passwordInput = "[data-cy=password]";
private readonly submitButton = "[data-cy=submit]";
private readonly errorMessage = ".text-red-500";

// Add new methods while keeping existing loginByRole
typeUsername(username: string) {
cy.get(this.usernameInput).type(username);
return this;
}

typePassword(password: string) {
cy.get(this.passwordInput).type(password);
return this;
}

clickSubmit() {
cy.get(this.submitButton).click();
return this;
}

verifyFormElements() {
cy.get(this.usernameInput).should("be.visible");
cy.get(this.passwordInput).should("be.visible");
cy.get(this.submitButton).should("be.visible");
return this;
}

verifyValidationErrors() {
cy.get(this.errorMessage).should("be.visible");
return this;
}

loginByRole(role: string) {
cy.visit("/login");
cy.fixture("users").then((users) => {
const user = users[role];
cy.get(this.usernameInput).type(user.username);
cy.get(this.passwordInput).type(user.password);
cy.get(this.submitButton).click();
});
}
}
58 changes: 0 additions & 58 deletions cypress/pageobject/utils/advanceFilterHelpers.ts

This file was deleted.

Loading
Loading