Skip to content
Open
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
177 changes: 177 additions & 0 deletions E2E_SEEDING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# E2E Organization Seeding

## Overview

This is the first implementation of dedicated E2E testing seeding. Previously, E2E tests were running against the default organization, which caused conflicts with manual testing and introduced noise depending on the environment.

## What Changed

### Before (No Dedicated E2E Setup)
- E2E tests ran against the default organization
- Constant conflicts with manual testing setup
- Manually induced noise depending on the environment
- No isolation between E2E tests and development data

### After (First E2E Implementation)
- Dedicated E2E Testing Tenant and Organization
- Seeds only organization-specific data within existing database
- Creates E2E-specific users with different emails to avoid conflicts
- Adds essential tags and employee levels for testing
- Complete isolation from development data

## How It Works

### 1. Database Connection
- Connects to existing database (no reset)
- Uses same database as development/production

### 2. Tenant Creation
- Creates "E2E Testing Tenant" if it doesn't exist
- Reuses existing tenant if found

### 3. Organization Creation
- Creates "E2E Testing Organization" if it doesn't exist
- Reuses existing organization if found
- Sets as default organization for the tenant

### 4. Essential Data Seeding
- Creates tag types and tags for testing
- Creates employee levels for testing
- Minimal data for fast test execution

## Usage

### For CI/CD
```bash
# Seed organization data for e2e testing
yarn seed:e2e

# Start API (will skip auto-seeding due to E2E_TESTING=true)
E2E_TESTING=true yarn start:api

# Run e2e tests
yarn start:e2e
```

### For Development
```bash
# Seed organization data
yarn seed:e2e

# Start API with e2e testing
E2E_TESTING=true yarn start:api
```

## Reset Functionality

### Why Reset is Needed
Sometimes you need to completely reset the E2E testing environment to ensure a clean state. This is especially useful when:
- Tests have modified data that affects other tests
- You want to ensure a fresh start for testing
- Debugging test issues that might be caused by accumulated data

### Reset Command
The most efficient way to reset E2E data is using the combined reset command:

```bash
# Reset E2E data (cleanup + seed in one operation)
yarn reset:e2e
```

### How Reset Works
The reset command:
1. **Cleans up existing E2E data** (organization, tenant, users, all related entities)
2. **Seeds fresh E2E data** (new organization, users, essential data)
3. **Runs internally** without rebuilding dependencies multiple times

### Individual Commands
You can also run cleanup and seed separately if needed:

```bash
# Clean up existing E2E data only
yarn cleanup:e2e

# Seed fresh E2E data only
yarn seed:e2e
```

### Performance Benefits
- **Reset**: Single dependency build, single database connection
- **Separate commands**: Multiple dependency builds, multiple database connections

## Cleanup

### Why Cleanup is Complex
Removing an organization and all its related data is complex due to the many database relationships. The E2E organization has relationships with:
- 60+ organization-scoped entities (extending `TenantOrganizationBaseEntity`)
- User relationships (default organization, last organization)
- Many-to-many relationships with tags, skills, etc.
- Cascade relationships that need to be handled properly

### Cleanup Script
A comprehensive cleanup script is available to safely remove all E2E testing data:

```bash
# Remove all E2E testing data
yarn cleanup:e2e
```

The cleanup script will:
1. **Delete organization-scoped entities**: Removes all data from 60+ entities that belong to the E2E organization
2. **Delete E2E-specific users**: Removes the three E2E users with their unique emails
3. **Delete the E2E organization**: Removes the organization itself
4. **Delete the E2E tenant**: Only if no other organizations exist for that tenant

### What Gets Cleaned Up
- ✅ E2E Testing Organization
- ✅ E2E Testing Tenant (if no other organizations)
- ✅ E2E-specific users (`e2e.admin@dspot.com.pl`, `e2e.local.admin@dspot.com.pl`, `e2e.employee@dspot.com.pl`)
- ✅ All organization-scoped data (tasks, timesheets, activities, etc.)
- ✅ All related entities (tags, skills, projects, teams, etc.)

### Safety Features
- **Idempotent**: Can be run multiple times safely
- **Selective**: Only removes E2E-specific data
- **Logging**: Provides detailed logs of what was deleted
- **Error handling**: Continues even if some entities fail to delete

## Benefits

1. **No Database Conflicts**: Uses existing database, no separate files
2. **Faster Setup**: No need to reset entire database
3. **Better Isolation**: Organization-level isolation
4. **Reusable**: Can run multiple times safely
5. **CI/CD Friendly**: Simple one-command seeding
6. **Complete Cleanup**: Comprehensive cleanup script available
7. **Efficient Reset**: Combined cleanup and seed in one operation

## Data Created

- ✅ E2E Testing Tenant
- ✅ E2E Testing Organization (default)
- ✅ E2E-specific users (different emails to avoid conflicts)
- ✅ Tag Types and Tags
- ✅ Employee Levels
- ❌ No demo or random data

## E2E User Credentials

### **E2E Super Admin**
- Email: `e2e.admin@dspot.com.pl`
- Password: `admin`

### **E2E Local Admin**
- Email: `e2e.local.admin@dspot.com.pl`
- Password: `admin`

### **E2E Employee**
- Email: `e2e.employee@dspot.com.pl`
- Password: `123456`

## Environment Variables

The seeding respects these environment variables:
- `E2E_TESTING=true` - Prevents automatic API seeding
- `DB_TYPE` - Database type (better-sqlite3, postgres, mysql)
- `DB_PATH` - Database path (for SQLite)
- `DB_HOST`, `DB_PORT`, etc. - Database connection settings
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"seed:build": "yarn ng run api:seed",
"seed:all": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=14000 yarn ts-node -r tsconfig-paths/register --project apps/api/tsconfig.app.json src/seed-all.ts",
"seed:module": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=14000 yarn ts-node -r tsconfig-paths/register --project apps/api/tsconfig.app.json src/seed-module.ts --name",
"seed:e2e": "cross-env NODE_ENV=development NODE_OPTIONS=--max-old-space-size=14000 yarn ts-node -r tsconfig-paths/register --project apps/api/tsconfig.app.json src/seed-e2e.ts",
"seed:all:build": "yarn ng run api:seed-all",
"seed:prod": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=14000 yarn ts-node -r tsconfig-paths/register --project apps/api/tsconfig.app.json src/seed.ts",
"seed:prod:build": "yarn ng run api:seed -c=production"
Expand Down
21 changes: 21 additions & 0 deletions apps/api/src/cleanup-e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Logger } from '@nestjs/common';
import { cleanupE2E } from '@gauzy/core';
import { pluginConfig } from './plugin-config';

const logger = new Logger('GZY - CleanupE2E');

/**
* E2E Cleanup Script
*
* This script removes all E2E testing data from the database:
* - E2E Testing Organization and all its related data
* - E2E Testing Tenant (if no other organizations exist)
* - E2E-specific users
* - All organization-scoped data for E2E organization
*
* Usage: yarn cleanup:e2e
*/
cleanupE2E(pluginConfig).catch((error) => {
logger.error(`Error cleaning up e2e data: ${error}`);
process.exit(1);
});
22 changes: 22 additions & 0 deletions apps/api/src/reset-e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Logger } from '@nestjs/common';
import { resetE2E } from '@gauzy/core';
import { pluginConfig } from './plugin-config';

const logger = new Logger('GZY - ResetE2E');

/**
* E2E Reset Script
*
* This script resets all E2E testing data by:
* 1. Cleaning up existing E2E data (organization, tenant, users, etc.)
* 2. Seeding fresh E2E data
*
* This is more efficient than running cleanup and seed separately
* as it doesn't require rebuilding dependencies multiple times.
*
* Usage: yarn reset:e2e
*/
resetE2E(pluginConfig).catch((error) => {
logger.error(`Error resetting e2e data: ${error}`);
process.exit(1);
});
21 changes: 21 additions & 0 deletions apps/api/src/seed-e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Logger } from '@nestjs/common';
import { seedE2E } from '@gauzy/core';
import { pluginConfig } from './plugin-config';

const logger = new Logger('GZY - SeedE2E');

/**
* E2E Organization Seeding Script
*
* This script seeds only organization-specific data within an existing database
* for e2e testing purposes. It creates:
* - E2E Testing Tenant (if not exists)
* - E2E Testing Organization (if not exists)
* - Essential tags and employee levels for testing
*
* Usage: yarn seed:e2e
*/
seedE2E(pluginConfig).catch((error) => {
logger.error(`Error seeding e2e organization data: ${error}`);
process.exit(1);
});
75 changes: 75 additions & 0 deletions apps/gauzy-e2e/E2E_CREDENTIALS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# E2E Testing Credentials

This document outlines the credentials used for E2E testing in the Cypress project.

## Updated Credentials

The E2E testing credentials have been updated to avoid conflicts with the default development users.

### **E2E Super Admin**
- **Email**: `e2e.admin@dspot.com.pl`
- **Password**: `admin`
- **Role**: Super Admin
- **Used in**: Main login tests, admin functionality tests

### **E2E Local Admin**
- **Email**: `e2e.local.admin@dspot.com.pl`
- **Password**: `admin`
- **Role**: Local Admin
- **Used in**: Profile editing tests, admin management tests

### **E2E Employee**
- **Email**: `e2e.employee@dspot.com.pl`
- **Password**: `123456`
- **Role**: Employee
- **Used in**: Employee functionality tests, time tracking tests

## Files Updated

### `LoginPageData.ts`
```typescript
export const LoginPageData = {
TitleText: 'DSpot ERP',
email: 'e2e.admin@dspot.com.pl', // Updated
password: 'admin',
empEmail: 'e2e.employee@dspot.com.pl', // Updated
empPassword: '123456'
};
```

### `EditProfilePageData.ts`
```typescript
export const EditProfilePageData = {
preferredLanguage: 'English',
email: 'e2e.local.admin@dspot.com.pl', // Updated
password: 'admin',
firstName: 'E2E', // Updated
lastName: 'Local Admin' // Updated
};
```

## Benefits

1. **No Conflicts**: E2E users won't interfere with development users
2. **Isolated Testing**: Each test environment has its own users
3. **Predictable**: Same credentials every time tests run
4. **Multiple Roles**: Different user types for different test scenarios

## Usage in Tests

```typescript
// Login as E2E Super Admin
CustomCommands.login(loginPage, LoginPageData, dashboardPage);

// Login as E2E Employee
CustomCommands.loginAsEmployee(loginPage, dashboardPage, LoginPageData.empEmail, LoginPageData.empPassword);
```

## Database Seeding

These credentials are created by the E2E seeding process:
```bash
yarn seed:e2e
```

The seeding creates users with these exact email addresses in the "E2E Testing Organization".
23 changes: 12 additions & 11 deletions apps/gauzy-e2e/src/e2e/ManageEmployeesTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe('Manage employees test', { testIsolation: false }, () => {
it('Should be able to edit employee', () => {
manageEmployeesPage.filterByTag(tagName);
manageEmployeesPage.tableRowVisible();
manageEmployeesPage.selectTableRow(0);
manageEmployeesPage.selectLastTableRow();
manageEmployeesPage.editButtonVisible();
manageEmployeesPage.clickEditButton();
manageEmployeesPage.usernameEditInputVisible();
Expand All @@ -114,7 +114,7 @@ describe('Manage employees test', { testIsolation: false }, () => {
it('Should be able to end work', () => {
manageEmployeesPage.waitMessageToHide();
manageEmployeesPage.filterByTag(tagName);
manageEmployeesPage.selectTableRow(0);
manageEmployeesPage.selectLastTableRow();
manageEmployeesPage.endWorkButtonVisible();
manageEmployeesPage.clickEndWorkButton();
manageEmployeesPage.confirmEndWorkButtonVisible();
Expand All @@ -123,7 +123,7 @@ describe('Manage employees test', { testIsolation: false }, () => {
});
it('Should be able to delete employee', () => {
manageEmployeesPage.filterByTag(tagName);
manageEmployeesPage.selectTableRow(0);
manageEmployeesPage.selectLastTableRow();
manageEmployeesPage.deleteButtonVisible();
manageEmployeesPage.clickDeleteButton();
manageEmployeesPage.confirmDeleteButtonVisible();
Expand All @@ -134,15 +134,15 @@ describe('Manage employees test', { testIsolation: false }, () => {
});
it('Should be able to copy invite link', () => {
manageEmployeesPage.clickManageInviteButton();
manageEmployeesPage.selectTableRow(0);
manageEmployeesPage.selectTableRowsWithProject(ManageEmployeesPageData.defaultProject);
manageEmployeesPage.copyLinkButtonVisible();
manageEmployeesPage.clickCopyLinkButton();
manageEmployeesPage.waitMessageToHide();
manageEmployeesPage.selectTableRow(0); //unselect
manageEmployeesPage.selectLastTableRow(); //unselect
});
it('Should be able to resend invite', () => {
manageEmployeesPage.clickManageInviteButton();
manageEmployeesPage.selectTableRow(0);
manageEmployeesPage.selectTableRowsWithProject(ManageEmployeesPageData.defaultProject);
manageEmployeesPage.resendInviteButtonVisible();
manageEmployeesPage.clickResendInviteButton();
manageEmployeesPage.confirmResendInviteButtonVisible();
Expand All @@ -151,10 +151,11 @@ describe('Manage employees test', { testIsolation: false }, () => {
});
it('Should be able to delete invite', () => {
manageEmployeesPage.clickManageInviteButton();
manageEmployeesPage.selectTableRow(0);
manageEmployeesPage.deleteInviteButtonVisible();
manageEmployeesPage.clickDeleteInviteButton();
manageEmployeesPage.confirmDeleteInviteButtonVisible();
manageEmployeesPage.clickConfirmDeleteInviteButton();
manageEmployeesPage.selectTableRowsWithProject(ManageEmployeesPageData.defaultProject);
manageEmployeesPage.deleteInviteButtonVisible();
manageEmployeesPage.clickDeleteInviteButton();
manageEmployeesPage.confirmDeleteInviteButtonVisible();
manageEmployeesPage.clickConfirmDeleteInviteButton();
manageEmployeesPage.waitMessageToHide();
});
});
Loading