Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/GoogleForCreators/web-stories-wp/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Web Stories plugin includes comprehensive test coverage across multiple test types:
  • PHP Unit Tests - Testing PHP backend functionality
  • JavaScript Unit Tests - Testing React components and utilities
  • Integration Tests - Browser-based integration tests with Karma
  • E2E Tests - End-to-end tests with Puppeteer

PHP Unit Tests

PHP tests use PHPUnit and the WordPress PHPUnit Test Suite.

Running PHP Tests

npm run test:php

PHP Test Structure

PHP tests are organized in:
  • tests/phpunit/unit/ - Unit tests
  • tests/phpunit/integration/ - Integration tests
Configuration files:
  • phpunit.xml.dist - Unit tests configuration
  • phpunit-integration.xml.dist - Integration tests (single site)
  • phpunit-integration-multisite.xml.dist - Integration tests (multisite)

Writing PHP Tests

namespace Google\Web_Stories\Tests;

class Story_Post_Type_Test extends \WP_UnitTestCase {
  
  public function test_post_type_registration() {
    $post_type = get_post_type_object( 'web-story' );
    $this->assertNotNull( $post_type );
    $this->assertEquals( 'web-story', $post_type->name );
  }
}
The project uses WP Test Utils for improved cross-version compatibility with PHPUnit.

JavaScript Unit Tests

JavaScript tests use Jest with Testing Library.

Running JavaScript Tests

npm run test:js

JavaScript Test Configuration

Tests are configured in tests/js/jest.config.js. Key testing libraries:
  • Jest - Test runner and assertion library
  • @testing-library/react - React component testing
  • @testing-library/react-hooks - React hooks testing
  • jest-dom - Custom DOM matchers
  • jest-extended - Additional matchers
Both jest-dom and jest-extended have a toBeEmpty assertion. If you want the one from jest-dom, use toBeEmptyNode instead.

Writing JavaScript Tests

File location: If a component resides in foo/bar/baz.js, place tests in foo/bar/tests/baz.js. Test naming convention:
import { sum } from '../sum';

describe('sum', () => {
  it('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
  });
});
Testing React components:
import { render, screen } from '@testing-library/react';
import { Button } from '../button';

describe('Button', () => {
  it('renders with correct text', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByRole('button')).toHaveTextContent('Click me');
  });
});

Custom Matchers

The project includes custom AMP validation matchers:
  • toBeValidAMP
  • toBeValidAMPStoryPage
  • toBeValidAMPStoryElement

Test Utils

Custom test utilities are available in testUtils folders:
  • renderWithTheme - Render components with theme provider
  • Component-specific test helpers
See packages/*/src/testUtils/ for available utilities.

Code Coverage

Generate and view code coverage:
npm run test:js:coverage
The coverage report will automatically open in your browser at build/logs/lcov-report/index.html.

Integration Tests (Karma)

Integration tests use Karma with Jasmine to run tests in real browsers.

Running Karma Tests

npm run test:karma:story-editor -- --headless --viewport=1600:1000

Karma Configuration

  • karma-story-editor.config.cjs - Story editor tests
  • karma-dashboard.config.cjs - Dashboard tests
Tests are located in:
  • packages/story-editor/src/karma/ - Story editor integration tests
  • packages/dashboard/src/karma/ - Dashboard integration tests

Custom Karma Matchers

Available custom matchers:
  • toBeEmpty
  • toHaveFocus
  • toHaveStyle
  • toHaveTextContent
  • toHaveProperty
  • toBeOneOf
  • toHaveNoViolations (accessibility testing)

Debugging Karma Tests

1

Focus the test

Change it to fit for the test you want to debug:
fit('should do something', async () => {
  // test code
});
2

Add pause command

Add await karmaPause() where you want to pause:
fit('should do something', async () => {
  // test setup
  await karmaPause();
  // remaining test code
});
3

Run in watch mode

npm run test:karma:story-editor:watch
4

Open debug view

Click “DEBUG” button in the Karma window to open http://localhost:9876/debug.html
5

Debug in DevTools

Open DevTools and execute karmaResume() in the console to continue

E2E Tests (Puppeteer)

End-to-end tests use Puppeteer with Jest to test the full user experience.

Running E2E Tests

npm run test:e2e

E2E Test Configuration

Configuration: packages/e2e-tests/src/jest.config.js Tests location: packages/e2e-tests/src/specs/ Test utilities: packages/e2e-test-utils/src/
E2E tests run serially (--runInBand) to avoid conflicts, as they share the same WordPress instance.

Using Custom WordPress URL

By default, E2E tests use the Docker environment. To use a different WordPress installation:
WP_BASE_URL=https://web-stories.local npm run test:e2e

Debugging E2E Tests

Non-headless mode:
PUPPETEER_HEADLESS=false npm run test:e2e
Slow down interactions:
PUPPETEER_SLOWMO=200 npm run test:e2e
Node debugger:
npm run test:e2e:debug
Debug browser context:
PUPPETEER_DEVTOOLS=true PUPPETEER_HEADLESS=false npm run test:e2e:debug

Writing E2E Tests

import {
  createNewStory,
  insertStoryTitle,
  publishStory,
} from '@web-stories-wp/e2e-test-utils';

describe('Story Creation', () => {
  it('should create a new story', async () => {
    await createNewStory();
    await insertStoryTitle('My Test Story');
    await publishStory();
    
    await expect(page).toMatchElement('.editor-post-publish-panel__header-published');
  });
});

E2E Test Utilities

Common utilities from @web-stories-wp/e2e-test-utils:
  • createNewStory() - Create a new story
  • insertStoryTitle() - Set story title
  • publishStory() - Publish the story
  • uploadMedia() - Upload media files
  • And many more…
See packages/e2e-test-utils/src/ for all available utilities.

Test Plugins

Utility plugins for testing specific scenarios can be added to packages/e2e-tests/src/plugins/ and activated during tests.

Common Testing Mistakes

JavaScript/E2E:
  • Missing await on statements/assertions
  • Not waiting for elements to be present and visible before interacting
  • Race conditions in async operations
General:
  • Overusing snapshot tests instead of specific assertions
  • Not cleaning up test state between tests
  • Testing implementation details instead of behavior

Useful Testing Resources

JavaScript Testing

E2E Testing

Next Steps

Contributing

Learn how to contribute your changes

Architecture

Understand the project structure