Testing WooGraphQL locally

Editing the WPGraphQL API can be tricky at times, even more so when dealing with a massive plugin like WooCommerce. Don’t let this discourage you though, it’s possible to simplify this development process with some application of Test-Driven Development (TDD). Now if you’ve ever been told anything about TDD, it’s probably that TDD doesn’t always fit everyone’s development process. Nonetheless, the argument I’m trying to make here is that by using TDD and following this guide, you’ll learn how to make proper changes to the WPGraphQL/WooGraphQL schema as well as write code that you know works regardless of where the GraphQL request came from or where the WPGraphQL server is installed.

Codeception & the wp-browser module

WPGraphQL and WooGraphQL both use the Codeception testing framework alongside the wp-browser module created by Luca Tumedei for running the automated test suite. We’ll be using Codeception scaffolding to generate all the tedious test code, but this will not be an in-depth guide on either of these libraries. It’s not required to process with this tutorial, but it’s highly recommended that after finishing this tutorial you take a look at the documentation for both.

Setting up WordPress for testing

Before we can begin testing we need a local WordPress installation. If you already have a local installation for development that you wish to use, make a backup database for testing and skip to Setting up Codeception. If you don’t have a local installation or simply don’t want to risk your local installation, you can use the scripts provided by WPGraphQL and WooGraphQL to create one for testing in a temporary directory.

Prerequisites

Have PHPMySQL or PostgreSQLComposer, and WP-CLI installed as well as terminal/shell/command-line access.

  1. Start by cloning WooGraphQL.
  2. Open your terminal.
  3. Copy the .env.testing to .env by executing the following in your terminal in the WooGraphQL root directory.
  1. Open the .env and update the highlighted environmental variables to match your machine setup. 
  2. The last thing to do is run the WordPress testing environment and install script in the terminal.

This will create and configure a WordPress installation in a temporary directory for the purpose of testing.

Setting up Codeception

Now that we have set up our testing environment, let’s run the tests. To do this we will need to install the Codeception and the rest of our devDependencies

  1. Run composer install in the terminal.
  2. Next copy the codeception.dist.yml.
  1. Open codeception.yml and make the following changes.  

Now you are all set to run the tests.

Running the tests

Now we’re ready to get started with testing. There is a small issue you may have with our testing environment. The WordPress installation we created doesn’t support end-to-end (e2e) testing, however, this won’t be a problem. WPGraphQL is an API and most of the time you can get away with just ensuring that your query works, and WPGraphQL provides a few functions that will allow us to do just that.

Well, let’s get started by running all the unit tests. Back in your terminal run the following:

If everything is how it should be you should get all passing tests. 

Writing your first WooGraphQL and WPGraphQL WPUnit test

The rest of this guide walks through creating a competent WP Unit test and implemented the functionality needed to ensure that test is passed. For the most part, everything used here can be used when making changes to WPGraphQL as well as many of the WPGraphQL extensions created by @jasonbahl, myself, and the WPGraphQL community.

The functionality we’ll be adding in the coming steps will be to add the Integer field itemCount on the Cart object type. To do this we’ll be.

  1. Generating a WPUnit test file Now typically for a feature so small it would be enough to update the first test in the CartQueriesTest class to include the desired itemCount field, however to the purpose of this guide we’ll be creating a new test file named ItemCountTest.
  2. Writing our test The name says it all.
  3. Run the test expecting failure The purpose of this step will be used to introduce WPGraphQL‘s Error Reporting and the codecept_debug function.
  4. Implementing our changes This step will do some exploring into how WooGraphQL and WPGraphQL work behind the scenes, and dive into some key components. After acquiring a grasp of WPGraphQL execution implementing the desired changes with being trivial.
  5. Run test expecting success The final step will be to the ItemCountTest looking for success this time.

Generating a WPUnit test file

The PHP testing suite used by WPGraphQL and WooGraphQL is Codeception, but they don’t manage the codeception/codeception in Composer. That is done by the lucatume/wp-browser package. This package was developed and maintained by the average dev Luca Tumedei, wp-browser is a suite of Codeception modules that provide tools designed specifically for testing WordPress sites, themes, and plugins on multiple levels. The lucatume/wp-browser package functions as a one-stop shop managing Codeception and all its dependencies for WPGraphQL and many of its extensions.

So having done everything above, and finally being ready for development, begin by generating the ItemCountTest test file with the Codeception generate command. Run the following in your terminal from the project root directory

This will generate a new test file at tests/wpunit/ItemCountTest.php. The generate is an easy-to-use tool of convenience. You learn more about it here.

The ItemCountTest.php file should be a familiar site to anyone who used Codeception or PHPUnit (which Codeception is built on).

Setup ( ) TearDown ( ) and others

These functions execute before and after every function. The setUp( ), in particular, is the perfect place to create objects such as posts, products, orders, etc to test with as well as set any WordPress options that may be needed or interfere with the tests. The tearDown() is good for deleting things that Codeception and wp-browser miss, which isn’t much so it is not uncommon for the function to be left with an empty stub.

There’s also the wpSetUpBeforeClass( $factory ) and wpTearDownAfterClass( $factory ) that are run before all the tests, however, their use-case is even rarer then tearDown() on account that these methods are static and don’t have access to the same $this context as the setUp()tearDown() or test*() function.

test*() functions

Class functions that are prefixed with test our tests. These functions are run in isolation for the most part. The test function must be publicly accessed. The purpose of the test function is to confirm the correct data is provided by when requested. This is done using the Assert library provided by PHPUnit which is wrapped by the Codeception framework and used by will everything on top of it.

Writing our test

Making changes to GraphQL API is always a rather top-down affair, meaning you’ll have an idea of how you want the query to look before you have an idea of how you want the implementation to look. For example, the query in relation to the changes we want to make will be as follows.

Nothing special, but if you sent this query to the WPGraphQL server you’d get back.

This shouldn’t be surprising, in the next section we’ll be taking this query and creating our test around it.

If you didn’t already know, an itemCount field already exists. It just happens to be under the connection of the content as a field you can access like this.

WooGraphQL Codeception Helpers

WooCommerce is a vast WordPress plugin with a lot of moving parts and getting them all to play nicely can be a daunting task. To address this WooGraphQL provides a number of helpers for creating just the right scenario for testing our queries. In this guide, you’ll be exposed to the cart and product helpers, but there are quite a few. However, documentation on them is pretty nonexistent at the time of the creation of this guide. Until this is rectified, it’s recommended that you view helper files directly to get a general idea of what they are and their capabilities.

Our setUp()

Let’s finish and begin writing out the test by creating our scenario with the setUp(). Our scenario for this test is rather simple, our query just need some products and those products have to be in the cart. Using product and cart helpers we can do this in a few lines of code.

And that’s it, the scenario is created. You may be confused, but we’ll break it down.

This just assigned the product and cart helpers to simple reusable class members for later use in the coming test and the rest of the setUp().

The $product array holds the product_ids and quantitys of products being added to our cart. create_simple( $args = array() ) creates a new simple product with a random name and price and returns the product_id of the newly created product. There are create_external( $args = array() ), create_grouped( $args = array() ) and create_variable( $args = array() ),, as well as many more, create functions for creating other objects related to products.

$this->cart->add( ...$this->products );

And finally, you have probably figured out that this adds the products in $products to the cart. cart helper functions as a glorified wrapper for the WC()->cart instance with extra features for testing.

Now that our scenario is set. Let’s get to our test. We’ll start by changing the name of the test to testItemCountField and assign our query to a string variable

Simple enough, next we’ll run our query through WPGraphQL using graphql( $request_data = [] ).

graphql() is a function provided by WPGraphQL. It will process a GraphQL request and return the results as an associative array. This makes it a great tool for testing our queries.

If you’ve taken a look at any of the other tests in WooGraphQL you may have noticed this snippet of code every always every graphql() call. codecept_debug( $data ) is a debug function that dumps the value of $data to the console. This dump information can be viewed by using the --debug flag when using Codeception’s run command. Its use here is great because when we run our test later in debug mode we’ll know exactly what WPGraphQL is returning for our query.

The last step in our test is to confirm that we received the correct values for our itemCount field.

And that’s our test.

Run the test expecting failure

Now that the test is created, we will run it expecting failure and using the --debug flag.

Running this statement in the terminal will make Codeception run just the ItemCountTest in debug mode. This way we can see exactly WPGraphQL returns for our query.

 Running the test will result in the error above. Cannot query field “itemCount” on type “Cart”. The error is quite easy to understand. We cannot query a field that doesn’t yet exist.

Implementing our changes

Before when jumping into the code, let’s discuss how WPGraphQL and WooGraphQL process requests.

How WPGraphQL works

When a request is made to WordPress, during the after_setup_theme action WPGraphQL initializes the Router class which is in charge of determining whether the request is a GraphQL request and acting accordingly. If the request is a GraphQL request, a Request class instance is created. Its job is to load the schema and process the request. The first part of loading the schema and our focal point for purpose is the initialization of the TypeRegistry and specify the execution of graphql_register_types action. This hook serves the purpose of providing a location to register types not defined by WPGraphQL.

How WooGraphQL works

WooGraphQL uses graphql_register_types to register WooCommerce specific types. If you’re familiar with WordPress, you’re most like familiar with Custom Post-types (CPTs) the core data object used by WordPress. If you’re not too familiar with WooCommerce, (or even if you are), you may be wondering why the CPTs in WooCommerce has such a different schema shape from the CPTs defined by WPGraphQL. This is due to the fact that WooCommerce wraps its CPT objects, (WP_Post), in data store objects. These data stores provide decorator functionality that is widely used by WooCommerce extension. WooGraphQL uses data stores as the source for its CPT schema shapes. All other types like the cart and shipping zones are sourced by custom data objects saved in custom databases and accessed using WooCommerce built-in functionality.

Implementing our changes

Now to implement the changes we simply need to register our itemCount field to the Cart object type.

Simple enough, right? Now we can slap this at the end of the TypeRegistry and it would be fine, however for a pull request that wouldn’t work. So let’s include this the inside the register_graphql_object_type() call for the Cart type with the rest of Cart fields. This call can be found in Cart_Type::register_cart() in 

includes/type/object/class-cart-type.php.

And the changes are made. Let’s run our test!!

Run test expecting success

Now if you re-run vendor/bin/codecept run wpunit ItemCountTest 

And we have passed, and if we want to see our query response use the --debug flag 

Going Forward

If you have already, you should at least take a look at the following

  • Documentation on extending WPGraphQLHere.
  • WooCommerce REST API Docs, seeing as it has been and continues to be the base template for the WooGraphQL schema.

If you plan on contributing you should see the following as both WPGraphQL and WooGraphQL uses them.

Next: Testing Quick-Start Guide