@easytesttool/easytest
v2.1.0
Published
A simple and intuitive test automation framework - Pure EasyTest Technology! No Playwright, No Puppeteer.
Maintainers
Readme
✨ Features
| Feature | Description | |---------|-------------| | 🚀 Zero Dependencies | Uses native browser protocols (CDP, Marionette). No heavy downloads. | | ⚡ Blazing Fast | Direct browser communication for faster test execution. | | 📱 Mobile Ready | Native iOS/Android testing + device emulation. | | 🌐 Cross-Browser | Chrome, Firefox, Safari, Edge with same API. | | 📊 Beautiful Reports | Built-in Allure reports with pie charts. | | 📧 Notifications | Email, Slack, Teams integration included. | | 🔄 Parallel Testing | Workers, sharding, and retry out of the box. | | 🎯 TypeScript First | Full type safety and IntelliSense. |
📦 Installation
npm install @easytesttool/easytest🚀 Quick Start
import { describe, test, expect, createBrowser, beforeAll, afterAll } from '@easytesttool/easytest';
describe('My First Test', () => {
let browser;
beforeAll(async () => {
browser = createBrowser();
await browser.launch();
});
afterAll(async () => {
await browser.close();
});
test('should navigate to example.com', async () => {
await browser.goto('https://example.com');
const title = await browser.title();
expect(title).toContain('Example');
const heading = await browser.$('h1');
expect(await heading.text()).toBe('Example Domain');
});
});# Run tests
npx easytest run
# Run with browser visible
npx easytest run --headed
# Run on specific browser
npx easytest run --browser firefox📱 Mobile Testing
// Device emulation
await browser.launch({ device: 'iPhone 14' });
// Native iOS app testing
import { iOSDriver } from '@easytesttool/easytest';
const ios = new iOSDriver();
await ios.launch('com.example.app');
// Native Android app testing
import { AndroidDriver } from '@easytesttool/easytest';
const android = new AndroidDriver();
await android.launch('com.example.app');📧 Built-in Notifications
import { NotificationManager } from '@easytesttool/easytest';
// Configure once
NotificationManager.configure({
slack: { webhookUrl: process.env.SLACK_WEBHOOK_URL },
teams: { webhookUrl: process.env.TEAMS_WEBHOOK_URL },
email: { smtp: { host: 'smtp.gmail.com', ... }, from: '[email protected]' }
});
// Send to all channels
await NotificationManager.sendResultsToAll({
total: 100,
passed: 95,
failed: 5,
duration: '5m 30s'
});📊 Allure Reports
import { AllureReporter } from '@easytesttool/easytest';
const reporter = new AllureReporter({ outputDir: './allure-results' });
// Automatically generates beautiful reports with:
// - Pie charts for pass/fail distribution
// - Test timelines
// - Screenshots on failure
// - Step-by-step breakdown⚡ Parallel Execution
# Run with 4 workers
npx easytest run --workers 4
# Shard across machines (CI/CD)
npx easytest run --shard 1/4
npx easytest run --shard 2/4
npx easytest run --shard 3/4
npx easytest run --shard 4/4🔧 Configuration
Create easytest.config.ts:
import { defineConfig } from '@easytesttool/easytest';
export default defineConfig({
testDir: './tests',
browser: 'chrome',
headless: true,
timeout: 30000,
retries: 2,
workers: 4,
reporter: ['html', 'allure']
});📚 Documentation
Visit EasyTest Docs for full documentation:
- Getting Started
- Browser Automation
- Element Interactions
- Assertions
- Mobile Testing
- Notifications
- CI/CD Integration
- API Reference
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
📄 License
MIT © EasyTest Team
🌐 Multi-Browser Testing
# Chrome (default)
npm run spec
# Firefox (requires geckodriver)
npm run spec:firefox
# Safari (macOS only, requires safaridriver)
npm run spec:safari📦 Installation
npm install easytest🚀 Quick Start
1. Create a test file
// tests/my-first-test.test.js
const { describe, test, expect, createBrowser, beforeAll, afterAll } = require('easytest');
describe('My First Test Suite', () => {
let browser;
beforeAll(async () => {
browser = createBrowser({ headless: true });
await browser.launch();
});
afterAll(async () => {
await browser.close();
});
test('should navigate to a website', async () => {
await browser.goto('https://example.com');
const title = await browser.title();
expect(title).toContain('Example');
});
test('should find and click elements', async () => {
const heading = await browser.find('h1');
const text = await heading.text();
expect(text).toBe('Example Domain');
});
});2. Run your tests
# Quick run commands (npm scripts)
npm run spec # Run all tests in headed mode (browser visible)
npm test # Run all tests in headless mode
npm run test:headed # Same as npm run spec
# CLI commands
npx easytest run # Run all tests
npx easytest run --headed # Run with browser visible
npx easytest run --headed --slow-mo 500 # Slow motion for debugging🖥️ NPM Scripts
| Command | Description |
|---------|-------------|
| npm run spec | Run all tests in headed mode (browser visible) |
| npm test | Run all tests in headless mode |
| npm run test:headed | Same as npm run spec |
| npm run build | Compile TypeScript to JavaScript |
| npm run watch | Watch mode for development |
📖 API Reference
Browser Methods
Navigation
// Navigate to URL
await browser.goto('https://example.com');
// Go back/forward
await browser.goBack();
await browser.goForward();
// Reload page
await browser.reload();
// Get current URL
const url = browser.url();
// Get page title
const title = await browser.title();Finding Elements
// By CSS selector
const element = await browser.find('#submit-button');
const elements = await browser.findAll('.list-item');
// By text content
const button = await browser.findByText('Submit');
// By placeholder
const input = await browser.findByPlaceholder('Enter email');
// By label
const field = await browser.findByLabel('Email Address');
// By test ID
const component = await browser.findByTestId('login-form');
// By role
const btn = await browser.findByRole('button', { name: 'Submit' });Actions
// Click
await browser.click('#button');
// Double click
await browser.doubleClick('#item');
// Type text
await browser.type('#input', 'Hello World');
// Clear and type (fill)
await browser.fill('#input', 'New value');
// Select dropdown option
await browser.select('#country', 'USA');
// Check/uncheck checkbox
await browser.check('#agree');
await browser.uncheck('#newsletter');
// Hover
await browser.hover('#menu');
// Press key
await browser.press('Enter');Waiting
// Wait for element
await browser.waitFor('#loading', { hidden: true });
// Wait for navigation
await browser.waitForNavigation();
// Wait for URL
await browser.waitForUrl('/dashboard');
// Wait fixed time (not recommended)
await browser.wait(1000);Screenshots
// Take screenshot
const path = await browser.screenshot();
// Full page screenshot
await browser.screenshot({ fullPage: true });
// Custom path
await browser.screenshot({ path: './my-screenshot.png' });Element Methods
const element = await browser.find('#my-element');
// Actions
await element.click();
await element.doubleClick();
await element.rightClick();
await element.type('text');
await element.fill('text');
await element.clear();
await element.hover();
await element.focus();
await element.blur();
await element.scrollIntoView();
// Form elements
await element.check();
await element.uncheck();
await element.select('value');
await element.selectByText('Option Text');
await element.uploadFile('/path/to/file');
// Get information
const text = await element.text();
const html = await element.html();
const value = await element.value();
const attr = await element.getAttribute('href');
const css = await element.getCssValue('color');
// State checks
const isVisible = await element.isVisible();
const isHidden = await element.isHidden();
const isEnabled = await element.isEnabled();
const isDisabled = await element.isDisabled();
const isChecked = await element.isChecked();
const isFocused = await element.isFocused();
const hasClass = await element.hasClass('active');
const hasAttr = await element.hasAttribute('disabled');
const containsText = await element.containsText('hello');
// Child elements
const child = await element.find('.child');
const children = await element.findAll('.children');
const parent = await element.parent();Assertions
Basic Assertions
expect(value).toBe(expected);
expect(value).toEqual(expected);
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeUndefined();
expect(value).toBeDefined();Number Assertions
expect(5).toBeGreaterThan(3);
expect(5).toBeGreaterThanOrEqual(5);
expect(3).toBeLessThan(5);
expect(3).toBeLessThanOrEqual(3);
expect(0.1 + 0.2).toBeCloseTo(0.3);String Assertions
expect('hello world').toContain('world');
expect('hello').toStartWith('hel');
expect('hello').toEndWith('lo');
expect('hello').toMatch(/^hel/);Array Assertions
expect([1, 2, 3]).toHaveLength(3);
expect([]).toBeEmpty();
expect([1, 2, 3]).toContain(2);
expect([1, 2, 3]).toContainAll([1, 3]);Object Assertions
expect({ a: 1 }).toHaveProperty('a');
expect({ a: 1 }).toHaveProperty('a', 1);
expect({ a: 1, b: 2 }).toMatchObject({ a: 1 });Negation
expect(5).not.toBe(3);
expect('hello').not.toContain('world');Element Assertions
const element = await browser.find('#button');
await expect(element).toBeVisible();
await expect(element).toBeHidden();
await expect(element).toBeEnabled();
await expect(element).toBeDisabled();
await expect(element).toBeChecked();
await expect(element).toBeFocused();
await expect(element).toHaveText('Click me');
await expect(element).toContainText('Click');
await expect(element).toHaveValue('hello');
await expect(element).toHaveAttribute('type', 'submit');
await expect(element).toHaveClass('btn-primary');Page Assertions
expectPage(browser).toHaveUrl('https://example.com');
await expectPage(browser).toHaveTitle('Example Domain');
await expectPage(browser).toContainText('Welcome');Test Hooks
describe('My Suite', () => {
beforeAll(async () => {
// Runs once before all tests
});
afterAll(async () => {
// Runs once after all tests
});
beforeEach(async () => {
// Runs before each test
});
afterEach(async () => {
// Runs after each test
});
test('my test', async () => {
// Test code
});
});Test Modifiers
// Skip a test
test.skip('skipped test', async () => {});
// Run only this test
test.only('focused test', async () => {});
// Skip a suite
describe.skip('skipped suite', () => {});
// Run only this suite
describe.only('focused suite', () => {});Steps
test('complex test with steps', async () => {
await step('Navigate to login page', async () => {
await browser.goto('/login');
});
await step('Fill in credentials', async () => {
await browser.fill('#email', '[email protected]');
await browser.fill('#password', 'password');
});
await step('Submit form', async () => {
await browser.click('#submit');
await browser.waitForNavigation();
});
});⚙️ Configuration
Create an easytest.config.js file in your project root:
module.exports = {
// Browser settings
browser: 'chromium',
headless: true,
slowMo: 0,
width: 1280,
height: 720,
// Test settings
testMatch: ['**/*.test.ts', '**/*.test.js'],
testIgnore: ['**/node_modules/**'],
timeout: 30000,
retries: 0,
// Reporter settings
reporter: 'html',
outputDir: './test-results',
screenshotsDir: './screenshots',
// Base URL
baseUrl: 'http://localhost:3000',
};🖥️ CLI Commands
# Run all tests
npx easytest run
# Run specific test files
npx easytest run --spec "tests/login.test.js"
# Run tests matching a pattern
npx easytest run --grep "login"
# Run in headed mode (see the browser)
npx easytest run --headed
# Slow down execution (great for debugging)
npx easytest run --headed --slow-mo 500
# Set retries for flaky tests
npx easytest run --retries 2
# Generate HTML report
npx easytest run --reporter html
# Initialize EasyTest in a project
npx easytest initCLI Options
| Option | Description |
|--------|-------------|
| --spec <pattern> | Test file pattern to run |
| --headed | Run browser in visible mode |
| --slow-mo <ms> | Slow down operations by milliseconds |
| --grep <pattern> | Filter tests by name |
| --retries <n> | Retry failed tests n times |
| --timeout <ms> | Test timeout in milliseconds |
| --reporter <type> | Reporter: console, html, json, all |
| --output <dir> | Output directory for reports |
📊 Reporters
Console Reporter (default)
Outputs results to the terminal with colors.
HTML Reporter
Generates a beautiful HTML report.
npx easytest run --reporter htmlJSON Reporter
Generates a JSON file with test results.
npx easytest run --reporter jsonAll Reporters
Generate all report types.
npx easytest run --reporter all🎯 Best Practices
Use descriptive test names
test('should display error message when login fails', async () => {});Use data-testid for reliable selectors
await browser.findByTestId('login-button');Use steps for complex tests
await step('Fill login form', async () => {});Clean up in afterEach/afterAll
afterAll(async () => { await browser.close(); });Avoid hard-coded waits
// ❌ Bad await browser.wait(5000); // ✅ Good await browser.waitFor('#element');
📝 License
MIT
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📚 Documentation
- Comparison with Other Tools - EasyTest vs Playwright, Selenium, Cypress
Made with ❤️ for developers who want simple, effective testing.
