Jonas Siewertsen

Addon testing in Statamic 3

How to test Statamic tags

I am recently building an e-commerce addon for Statamic 3 and wanted to test my Tags. Let me show you how I did it.


JANUARY 14TH, 2020

Introduction

Tags are really helpful in Statamic and are making templating a breeze. This will give you the possibility, to implement custom functions wherever they are needed inside a template. You can easily reuse them etc. They are just great and do have a clean syntax.

Setting up your test suite

To test tags, you need a test suite of course. You can find a detailed explanation of how to do that in this post:
How I do set up my test suite for a Statamic addon

In this article, the test will be written in the view of an addon creation. If your tags have been written as application code inside Statamic, they can be tested exactly the same way.

How to test if our tag has been registered?

Create a Test class

<?php

namespace Tests\Unit; // Adopt to your namespace

use yourname\addonname\Tests\TestCase;

class NumbersTest extends TestCase
{
    public $tag;

    public function setUp(): void {
        parent::setUp();

        // Room for some set ups
    }

    // Tests will go here
}

First, we should test if the tag has been registered correctly:

/** @test */
public function numbers_has_been_registered()
{
	$this->assertTrue(isset(app()['statamic.tags']['numbers']));
}	

To understand this test, let's do some code diving into the core and see how tags are being registered

// ExtensionsServiceProvider.php
// I did simplify the code a little :-)

protected function registerExtension($extension)
{
	$this->app['statamic.tagss'][$extension::handle()] = $extension;
}

Every tag will be passed into the app and we can simply check if it's there. Let's create the tag class, register ist and get the test to green. (More reading)

<?php

namespace yourname\addonname\Tags; // modify if needed

use Statamic\Tags\Tags as StatamicTags;

class Numbers extends StatamicTags
{
	// Tag functions goes here
}

Register it inside your addon service Provider

protected $tags = [
    \your\name\Tags\Numbers::class,
];

If done correctly, your test will pass now.

How to test the tag return values

In real life, you should write your test first and implement the code afterward. For a better explanation, we will do it the other way around.

<?php

namespace yourname\addonname\Tags;

use Statamic\Tags\Tags as StatamicTags;

class Numbers extends StatamicTags
{
	public function index()
	{
		// In real life, you could fetch some data from a collection, api, ...
		return 44'; // { { numbers }}
	}

	public function string()
	{
		// The same 
		return 'forty-four'; // { { numbers:string }}
	}

	public function own() {
		return $this->params->get('number'); // { { number:own number="12" }}
	}
}

We are only interested in testing the return values. If tags will be rendered correctly in general, has already been covered by the Statamic Gentlemen. Let's not worry about this part.

To do so, we will simply instantiate the class and test the return.

<?php

namespace Tests\Unit; // Adopt to your namespace

use yourname\addonname\Tests\TestCase;

class NumbersTest extends TestCase
{
    public $tag;

    public function setUp(): void {
        parent::setUp();

        $this->tag = new /Yourname/Addonname/Tags/Numbers();
    }

    /** @test */
    public function it_will_return_our_number()
    {
        $this->assertEquals($this->tag->index(), 44);
    }

	/** @test */
    public function it_will_return_our_number_as_string()
    {
		$this->assertEquals($this->tag->string(), 'forty-four');
	}

	/** @test */
	public function it_will_return_our_own_number() {
		$this->tag->setParameters(['number' => 99]);

		$this->assertEquals($this->tag->own(), 99);
	}

}

With this setup, you can easily test complex tags as well. For more flexibility, you could use more parameters, pull data from an external API or whatever you can think of.

Enjoy testing!