The Talent500 Blog
SafeTest

SafeTest: A Novel Approach to Front-End Testing

SafeTest is an innovative library that presents a fresh perspective on end-to-end (E2E) testing specifically for web-based user interface (UI) applications. This article explores the challenges associated with traditional UI testing and how SafeTest aims to overcome them.

The Challenges of Traditional UI Testing

UI testing has traditionally relied on unit testing or integration testing methods. Each approach comes with its own set of trade-offs, forcing developers to choose between controlling the test fixture and setup or managing the test driver.

  • Unit Testing: Tools such as react-testing-library allow developers to maintain control over rendering and service behavior. However, this control comes at the cost of interaction with an actual page, leading to several issues:
    • Difficulty interacting with complex UI elements, such as dropdown components.
    • Inability to test Cross-Origin Resource Sharing (CORS) setups or GraphQL calls.
    • Lack of visibility into z-index issues that affect button clickability.
    • Complex and unintuitive test authoring and debugging processes.
  • Integration Testing: Tools like Cypress and Playwright provide greater control over the browser environment but sacrifice the ability to instrument the app’s bootstrapping code. This leads to challenges such as:
    • Difficulty making calls to alternative API endpoints without custom network layer rules.
    • Inability to assert on spies/mocks or execute code within the app.
    • Complicated testing scenarios, such as simulating dark mode or waiting for long timers.

In response to these challenges, solutions like E2E Component Testing have emerged from tools like Cypress and Playwright. However, these tools still face limitations due to their architecture, particularly when dealing with complex enterprise applications that may involve OAuth or intricate build pipelines.

Welcome to SafeTest

SafeTest addresses these traditional UI testing challenges through a novel approach. The core concept involves injecting hooks during the application bootstrapping stage that enable tests to run seamlessly. This method ensures no measurable impact on regular app usage since SafeTest employs lazy loading to dynamically load tests only when needed. Once integrated, developers can utilize Playwright to execute regular tests while maintaining optimal browser control.

This innovative approach unlocks several exciting features:

  • Deep Linking: Access specific tests without running a node test server.
  • Two-Way Communication: Facilitate interaction between the browser and test context.
  • Playwright Features: Leverage all developer experience features provided by Playwright, excluding those from @playwright/test.
  • Enhanced Reporting: Generate video recordings of tests, trace views, and pause functionality for experimenting with different page selectors/actions.
  • Assertions on Spies: Make assertions on spies in both the browser and node context.

Test Examples with SafeTest

SafeTest is designed for familiarity, allowing users accustomed to UI testing frameworks to feel at home. Below are examples demonstrating how to test an entire application and specific components using SafeTest:

import { describe, it, expect } from 'safetest/jest';
import { render } from 'safetest/react';

describe('my app', () => {
it('loads the main page', async () => {
const { page } = await render();
await expect(page.getByText('Welcome to the app')).toBeVisible();
expect(await page.screenshot()).toMatchImageSnapshot();
});
});

Testing a specific component is equally straightforward:

import { describe, it, expect, browserMock } from 'safetest/jest';
import { render } from 'safetest/react';

describe('Header component', () => {
it('has a normal mode', async () => {
const { page } = await render(<Header />);
await expect(page.getByText('Admin')).not.toBeVisible();
});

it('has an admin mode', async () => {
const { page } = await render(<Header admin={true} />);
await expect(page.getByText('Admin')).toBeVisible();
});

it('calls the logout handler when signing out', async () => {
const spy = browserMock.fn();
const { page } = await render(<Header handleLogout={spy} />);
await page.getByText('logout').click();
expect(await spy).toHaveBeenCalledWith();
});
});

SafeTest utilizes React Context for value overrides during tests. This feature allows developers to modify components easily for testing purposes. For example:

import { useAsync } from 'react-use';
import { fetchPerson } from './api/person';

export const People: React.FC = () => {
const { data: people, loading, error } = useAsync(fetchPeople);

if (loading) return <Loader />;
if (error) return <ErrorPage error={error} />;
return <Table data={data} rows={...} />;
}

By introducing an override:

import { fetchPerson } from './api/person';
import { createOverride } from 'safetest/react';

const FetchPerson = createOverride(fetchPerson);

export const People: React.FC = () => {
const fetchPeople = FetchPerson.useValue();

const { data: people, loading, error } = useAsync(fetchPeople);

if (loading) return <Loader />;
if (error) return <ErrorPage error={error} />;
return <Table data={data} rows={...} />;
}

Reporting Capabilities

SafeTest includes robust reporting features that automatically link video replays and provide access to Playwright’s trace viewer. Users can deep link directly to tested components for enhanced analysis.

SafeTest in Corporate Environments

Many corporations require authentication for their applications. This often complicates local testing environments. SafeTest can be adapted by creating wrappers that facilitate automatic user generation and authentication management.

For example:

While this article highlights SafeTest’s compatibility with React applications, it is not limited to this framework. SafeTest also supports Vue, Svelte, Angular, Next.js, and Gatsby. It operates using either Jest or Vitest based on your project setup.

Conclusion

SafeTest stands out as a powerful testing framework gaining traction in organizations like Netflix. It simplifies test authoring while providing detailed reports on failures complete with playback links. As it continues to evolve, SafeTest promises significant advancements in UI testing methodologies. Feedback and contributions are welcomed as it seeks to revolutionize front-end testing practices.

Read more such articles from our Newsletter here.

0
Avatar

prachi kothiyal

Add comment