In this tutorial we'll look at how you can use the #theme property of a render array to define custom HTML. With this information, module developers can use render arrays to define content, and theme developers can understand how elements in a render array are converted to HTML and which templates they can override to change the output for a specific element.
Learn how to:
- Use
hook_theme()to define a new theme hook and define default values for variables - Create a corresponding Twig template file that outputs the variables and any custom HTML markup
- Use a preprocess function to add additional variables for the Twig template file you created
- Use the new theme hook in conjunction with a
#themeproperty in a render array to link your Twig template file to actual content
By the end of this tutorial you should know how to define new templates to output content as HTML. You should also have a better understanding of how Twig template files are linked to elements in a render array.
There are a bunch of existing render elements, most commonly Form API elements. You need to know how to discover and make use of existing elements. In this tutorial, we'll learn how to:
- Locate a list of elements provided by Drupal core
- Figure out what properties apply to each element
- Use any render element type when defining content or forms in our code
By the end of this tutorial you should know what render element types are available for you to use, and how to find the details you'll need in order to implement them in your own render arrays.
It's best practice to access any of the services provided by Drupal via the service container to ensure the decoupled nature of these systems is respected. In order to do so, you need to know what services exists, and then, where possible, use dependency injection to use them in your code.
This tutorial walks through the process of:
- Discovering existing services and learn their machine name
- Using the machine name of service to request a copy from the service container
Want to know if the person that's viewing your custom block is authenticated? Need to change the elements visible on the page based on a user's permissions or roles? Want to display a welcome message for users returning to your site?
All of these things require knowing who the user is that's currently accessing a page. This can be accomplished by using the current_user service to load an object that contains information about the current user as well as methods for checking permissions and retrieving additional information.
In this tutorial we'll:
- Define what "current user" means
- Use the
current_userservice to retrieve an implementation of\Drupal\Core\Session\AccountInterface - Retrieve information about, and check the permissions of, the current user
- Add cacheability metadata when rendering user-specific output
By the end of this tutorial you should be able to retrieve and make use of information about the application's current user in order to perform logic in your code that customizes the response for different users.
In order to run tests, your Drupal site needs additional development requirements installed using Composer.
By default, when you download Drupal as a zip file or tarball, these packages will not be installed, since they're used for development purposes.
In this tutorial, we'll walk through the steps to make sure we've got Composer available. Next we'll install the dependencies. Then we'll talk about why you shouldn't have development dependencies available on your production site. Thankfully, Composer can help make this easy to manage.
Simpletest has been removed from Drupal 9. If you're preparing to upgrade your site to the latest version of Drupal and you have Simpletests in your codebase that extend WebTestBase you'll need to update them to use PHPUnit's BrowserTestBase class instead. This will ensure your tests don't depend on a deprecated testing framework. By the end of this tutorial, you should be able to convert WebTestBase-based tests to use PHPUnit's BrowserTestBase class instead.
In this tutorial, we will look at the various types of tests and testing frameworks included in Drupal core. We'll also provide an overview of how the different frameworks operate and the types of situations where each of the different frameworks is useful.
Previously, in Implement a Functional Test, we learned how to tell BrowserTestBase to use the Standard installation profile in order to get our test passing, letting the Standard profile implicitly provide our dependencies. We mentioned that doing so probably wasn't the best decision and that we should explicitly declare those dependencies instead.
In this tutorial, we'll walk through how to explicitly declare our test's dependencies. When in doubt, it's generally considered a best practice to be as explicit about the dependencies of our tests as possible. By the end of this tutorial, you should be able to:
- Understand why we want to explicitly declare our dependencies.
- Determine what the dependencies really are and make a list of them.
- Implement each dependency in our list.
- Emerge with a thorough passing test.
In this tutorial, we'll walk through the basics of how to implement a functional test by extending Drupal's BrowserTestBase class. We'll assume you've already determined that you need to write a functional test and that you've Set up a Functional Test.
In this tutorial, we'll:
- Determine the specifications of the test.
- Walk through the behavior we want to test.
- Document our test in the test class.
- Implement the testing steps.
- Decide how to deal with dependencies (for now). (We'll go into details about handling test dependencies in Implement Drupal Functional Test Dependencies.)
Let's write somewhat strict unit tests in a Drupal module. By the end of this tutorial, you will be able to:
- Understand what makes a unit test different from other types of tests.
- Determine the specifications of a unit test.
- Use mocking to isolate units under test, and to force code flow to achieve high coverage.
We'll start out with a brief introduction to unit tests. Then we'll look at a contrived example of a Drupal controller class for illustration purposes. Next, we'll test two units of this controller class, each requiring different mock styles.
In this gentle introduction to testing, we'll walk through what testing is and why it's important to your project. Then we'll define some terms you'll be likely to see while working with tests so that we're all on the same page. After reading through this tutorial you'll understand enough of the basic vocabulary to get started running (and eventually writing) tests for your Drupal site.
In order for Drupal to be able to locate and run the tests you create, the files need to be put in the correct place. In this tutorial, we'll take a look at the different types of test frameworks that are included along with core. We'll also see how Drupal expects our test files to be organized so that the test runners can find them.
When running tests with PHPUnit we need to specify a phpunit.xml file that contains the configuration that we want to use. Often times (and in much of the existing documentation) the recommendation is to copy the core/phpunit.xml.dist file to core/phpunit.xml and make your changes there. And this works fine, until something like a composer install or composer update ends up deleting your modified file. Instead, you should copy the file to a different location in your project and commit it to your version control repository.
In this tutorial we'll:
- Learn how to move, and modify, the phpunit.xml.dist file provided by Drupal core
- Understand the benefits of doing so
- Demonstrate how to run
phpunitwith an alternative configuration file
By the end of this tutorial you should be able to commit your phpunit.xml configuration file to your project's Git repository and ensure it doesn't get accidentally deleted.
In this tutorial, we'll run tests in several different ways using the PHPUnit tools available in Drupal. We'll learn about various environment variables you'll need to supply to the test runner depending on which type of test you're running. And we'll learn various ways to get reports on the test results. By the end of this tutorial, you should understand how to run Drupal tests using PHPUnit.
Drupal core comes with a run-tests.sh script to help with running tests. This script has some distinct advantages over running tests directly via PHPUnit. It runs all tests in their own separate process, and can therefore handle PHP fatal errors without killing the test run. It's also the mechanism that the Drupal CI tools use to run tests; so, it can be handy when debugging tests that are failing on Drupal.org.
In this tutorial we'll:
- Look at the available options for the core run-tests.sh script
- Go through some examples of running tests using run-tests.sh
By the end of this tutorial you'll know how to run your tests using run-test.sh.
In this tutorial, we'll walk through the process of setting up a functional test. Then, we'll learn how to run it using two different test runners. This setup process allows us to be sure we're not getting false positives from the test runners. We'll be working on a functional test, but these techniques apply with minimum modification to all the Drupal PHPUnit-based tests.
By the end of this tutorial, you should be able to set up and run functional tests in Drupal using two different test runners.
This tutorial will clarify some basic ideas about software testing. We'll give some strategies for testing and illustrate types of tests and when and why you'd use them. This document is written with Drupal in mind, but the concepts apply for other development environments you'll encounter as well. The tools will be different, but the ideas apply universally. By the end of this tutorial, you should understand what testing is for and how different types of tests support different purposes and outcomes.
In order to run functional tests that require JavaScript be executed for the feature to work, the tests need to be run in a browser that supports JavaScript. This is accomplished by using the WebDriver API in combination with an application like ChromeDriver or Selenium, which can remotely control a browser.
The exact setup for running functional tests is dependent on your development environment. We'll walk through a couple of common examples including using Docker (via DDEV) and stand-alone applications.
In this tutorial we'll:
- Learn how to install and run ChromeDriver and other necessary tools either in a Docker environment, or locally.
- Configure the relevant PHPUnit environment variables so they contain values appropriate for our specific environment.
- Execute Drupal's functional JavaScript tests via the
phpunitcommand.
By the end of this tutorial you should be able to install the applications required to run functional JavaScript tests in a browser, and know how to configure PHPUnit to make use of them.
Themes and modules can alter the list of theme hook suggestions in order to add new ones, remove existing ones, or reorder the list. This powerful feature allows for the definition of custom logic in your application that can tell Drupal to use different templates based on your own unique needs. You might for example; use a different page template for authenticated users, or a custom block template for someone's birthday.
In this tutorial we'll cover:
- Adding new theme hook suggestions from a theme using
hook_theme_suggestions_HOOK_alter() - Altering the list of theme hook suggestions
- Removing theme hook suggestions
- Reordering the list of theme hook suggestions
When a user creates a view, they can set access rules, and restrict who can see the view. The core Views module allows you to limit access by a user's permissions, or roles. If your project requires custom access rules you can define a custom Views access plugin. This will allow you to determine a user's access based on any custom logic you might have.
In this tutorial we'll:
- Define a custom Views access plugin that determines access based on data stored in a field on the user entity type.
- Learn the difference between access checks for routes and access checks for Views displays, and how to use each of them.
- Use our new custom access handler when defining a view.
By the end of this tutorial you should know how to define a custom Views access plugin and use it to grant access to a view.