|
|
3 months ago | |
|---|---|---|
| .. | ||
| data-factory | 3 months ago | |
| helpers | 3 months ago | |
| tests | 3 months ago | |
| .env.example | 3 months ago | |
| .eslintrc.js | 3 months ago | |
| README.md | 3 months ago | |
| compose.e2e.yml | 3 months ago | |
| package.json | 3 months ago | |
| playwright.config.mjs | 3 months ago | |
| tsconfig.json | 3 months ago | |
| types.d.ts | 3 months ago | |
README.md
Ghost End-To-End Test Suite
This test suite runs automated browser tests against a running Ghost instance to ensure critical user journeys work correctly.
Quick Start
Prerequisites
- Docker and Docker Compose installed
- Node.js and Yarn installed
Running Tests
From the repository root:
# Install dependencies
yarn
# Build Docker images
yarn docker:build
# Run the e2e tests
yarn test:e2e
Running Specific Tests
Within e2e folder, run one of the following commands:
# All tests
yarn test
# Specific test file
yarn test specific/folder/testfile.spec.ts
# Matching a pattern
yarn test --grep "homepage"
# With browser visible (for debugging)
yarn test --debug
Tests Development
The test suite is organized into separate directories for different areas/functions:
Current Test Suites
tests/public/- Public-facing site tests (homepage, posts, etc.)tests/admin/- Ghost admin panel tests (login, content creation, settings)
We can decide on additional sub-folders as we go.
Example structure for admin tests:
tests/admin/
├── login.spec.ts
├── posts.spec.ts
└── settings.spec.ts
Project folder structure can be seen below:
e2e/
├── tests/ # All the tests
│ ├── public/ # Public site tests
│ │ └── testname.spec.ts # Test cases
│ ├── admin/ # Admin site tests
│ │ └── testname.spec.ts # Test cases
│ ├── global.setup.ts # Global setup script
│ ├── global.teardown.ts # Global teardown script
│ └── .eslintrc.js # Test-specific ESLint config
├── helpers/ # All helpers that support the tests, utilities, fixtures, page objects etc.
│ ├── playwright/ # Playwright specific helpers
│ │ └── fixture.ts # Playwright fixtures
│ ├── pages/ # Page Object Models
│ │ └── HomePage.ts # Page Object
│ ├── utils/ # Utils
│ │ └── math.ts # Math related utils
│ └── index.ts # Main exports
├── playwright.config.mjs # Playwright configuration
├── package.json # Dependencies and scripts
└── tsconfig.json # TypeScript configuration
Writing Tests
Tests use Playwright Test framework with page objects. Aim to format tests in Arrange Act Assert style - it will help you with directions when writing your tests.
test.describe('Ghost Homepage', () => {
test('loads correctly', async ({page}) => {
// ARRANGE - setup fixtures, create helpers, prepare things that helps will need to be executed
const homePage = new HomePage(page);
// ACT - do the actions you need to do, to verify certain behaviour
await homePage.goto();
// ASSERT
await expect(homePage.title).toBeVisible();
});
});
Using Page Objects
Page objects encapsulate page elements, and interactions. To read more about them, check this link out and this link.
// Create a page object for admin login
export class AdminLoginPage {
private pageUrl:string;
constructor(private page: Page) {
this.pageUrl = '/ghost'
}
async goto(urlToVisit = this.pageUrl) {
await this.page.goto(urlToVisit);
}
async login(email: string, password: string) {
await this.page.fill('[name="identification"]', email);
await this.page.fill('[name="password"]', password);
await this.page.click('button[type="submit"]');
}
}
Global Setup and Teardown
Tests use Project Dependencies to define special tests as global setup and teardown tests:
- Global Setup:
tests/global.setup.ts- runs once before all tests - Global Teardown:
tests/global.teardown.ts- runs once after all tests
Playwright Fixtures
Playwright Fixtures are defined in helpers/playwright/fixture.ts and provide reusable test setup/teardown logic.
For example, a ghostInstance fixture creates a new Ghost instance with its own database for each test, to ensure isolation between tests.
Test Isolation
Test isolation is extremely important to avoid flaky tests that are hard to debug. For the most part, you shouldn't have to worry about this when writing tests, because each test gets a fresh Ghost instance with its own database:
- Global setup (
tests/global.setup.ts):- Starts shared services (MySQL, Tinybird, etc.)
- Runs Ghost migrations to create a template database
- Saves a snapshot of the template database using
mysqldump
- Before each test (
helpers/playwright/fixture.ts):- Creates a new database by restoring from the template snapshot
- Starts a new Ghost container connected to the new database
- After each test (
helpers/playwright/fixture.ts):- Stops and removes the Ghost container
- Drops the test database
- Global teardown (
tests/global.teardown.ts):- Stops and removes shared services
Best Practices
- Use page object patterns to separate page elements, actions on the pages, complex logic from tests. They should help you make them more readable and UI elements reusable.
- Add meaningful assertions beyond just page loads. Keep assertions in tests.
- Use
data-testidattributes for reliable element selection, in case you cannot locate elements in a simple way. Example:page.getByLabel('User Name'). Avoid, css, xpath locators - they make tests brittle. - Clean up test data when tests modify Ghost state
- Group related tests in describe blocks
CI Integration
Tests run automatically in GitHub Actions on every PR and commit to main.
CI Process
- Setup: Ubuntu runner with Node.js and MySQL
- Docker Build & Push: Build Ghost image and push to GitHub Container Registry
- Pull Images: Pull Ghost, MySQL, Tinybird, etc. images
- Test Execution:
- Wait for Ghost to be ready
- Run Playwright tests
- Upload test artifacts
Available Scripts
From the e2e directory:
# Run all tests
yarn test
# Run TypeScript type checking
yarn test:types
# Lint code and tests
yarn lint
# Build (for utilities)
yarn build
yarn dev # Watch mode for TypeScript compilation
Resolving issues
Test Failures
- Screenshots: Playwright captures screenshots on failure
- Traces: Available in
test-results/directory - Debug Mode: Run with
yarn test --debugoryarn test --uito see browser - Verbose Logging: Check CI logs for detailed error information