Skip to content

Seeds and Fixtures

Paul Taylor edited this page Jan 19, 2022 · 3 revisions

Intro

Inspired by Laravel, WP Cypress includes a method of seeding your database with test data using seed classes. All seed classes are stored by default in the cypress/seeds directory unless specified otherwise in your configuration options. Seed classes may have any name you wish, but probably should follow some sensible convention, such as UserSeeder, etc. The name of the file, must match the name of the class as this is how we autoload and find the correct class when a seeder is ran. By default, a DefaultSeeder class is defined for you.

Writing a Seeder

A seeder class only contains one required method by default: run. This method is called when the cy.seed('<name-of-seeder>') cypress command is executed. The only exception to this is the DefaultSeeder which is always ran when creating a new environment or during teardown (when an environment is reset between tests). Within the run method, you may insert data into your database however you wish. However you may wish to use a Fixture to create data in a structured way with default dummy data.

Tip! A good place to execute a seed could be in a cypress hook. Learn More

As an example, let's look at how to create a post using a fixture in the DefaultSeeder class.

<?php

use WP_Cypress\Seeder\Seeder;
use WP_Cypress\Fixtures;

class DefaultSeeder extends Seeder {
	public function run() {
		$post = new Fixtures\Post( [
            'post_title' => 'Example Post using a Fixture'
        ] );

        $post->create( 1 );
	}
}

Creating a Fixture

Fixture classes are also stored in the seeds directory. Fixture classes may have any name you wish, but again, you should probably follow some sensible convention, such as CommentFixture.

A fixture needs two methods: defaults and generate. Defaults generate the default properties and the generate function performs the required logic that is ran on create to add a single record, whatever it may be, to your database. You can use some of WP_Cypress's utility functions to help and also when creating dummy data you have access to a Faker factory. You can read faker's documentation here.

<?php

use  WP_Cypress\Fixtures\Fixture;
use  WP_Cypress\Utils;

class ExampleCommentFixture extends Fixture {
	public function defaults() {
		return [
			'comment_post_ID'      => 1,
			'comment_author'       => 'admin',
			'comment_author_email' => '[email protected]',
			'comment_content'      => $this->faker->realText( 100 ),
			'user_id'              => 1,
			'comment_date'         => Utils\now(),
		];
	}

	public function generate() {
		$id = wp_insert_comment( array_merge( $this->defaults(), $this->properties ) );
	}
}

This will be autoloaded and can be executed in any seeder:

public function run() {
	( new Fixtures\Post([
		'import_id'  => 10,
		'post_title' => 'Post with Custom Comments',
	]) )->create();

	( new ExampleCommentFixture( [ 'comment_post_ID' => 10 ] ) )->create( 10 );
}

Calling Additional Seeders

Within any Seeder class, you may use the call method to execute additional seed classes. Using the call method allows you to break up your database seeding into multiple files so that no single seeder class becomes overwhelmingly large while allowing you to execute them in a particular order. Pass the name of the seeder class you wish to run:

public function run()
{
    $this->call([
        'MySeeder'
    ]);
}

Clean and Refreshing Seeds

When running your Cypress tests you may find that you want to clean up your seeders and/or database between tests. In your Seeder class you can add a clean() method along-side your run() method mentioned above to provide the necessary processes to ensure you can undo any changes made to the database and have your tests run fresh when you need them to.

<?php

use WP_Cypress\Seeder\Seeder;

class CategoriesSeeder extends Seeder {
	const CATEGORIES = [
		'Test',
		'New Test',
	];

	public function run() {
		foreach( self::CATEGORIES as $category ) {
			wp_insert_term( $category, 'category' );
		}
	}

	public function clean() {
		foreach( self::CATEGORIES as $category ) {
			$term = get_term_by( 'name', $category, 'category' );
			wp_delete_term( $term->term_id, 'category' );
		}
	}
}

You can run the seeder clean() method in your tests by using cy.cleanThenSeed() to run the clean before executing your seeder, or cy.seedClean() to run the clean up on its own.

describe("Categories.", () => {
  before(() => {
    cy.cleanThenSeed("CategoriesSeeder"); // Run the cleaner then seed.
  });

  it("I can add a new category.", () => {
    cy.visitAdmin();
    cy.visit("/wp-admin/edit-tags.php?taxonomy=category");
    // ...
  });

  after(() => {
    cy.seedClean("CategoriesSeeder"); // Only clean, no seeding.
  });
});