To perform create, update, and delete (CRUD) operations with Drupal core's JSON:API via React there are a few things you'll need to understand. First, how to format the POST, PATCH, and DELETE requests necessary to add, edit, and delete Drupal entities. Next, how to handle authentication, and cross-site request forgery (CSRF) tokens. Over the next few tutorials we will create a simple but powerful React application that can add, edit, and delete Drupal node content.
This tutorial contains:
- An overview of the application we're building
- Information about making secure authenticated requests to Drupal's JSON:API
- An overview of the API requests we'll use to create, update, and delete nodes
By the end of this tutorial, you should have a picture of the application we're going to build, and know how to make the API requests we'll use in our application.
Using React we can do more than just list content. By using the POST, PATCH, and PUT methods of Drupal core's JSON:API web service we can also add, update, and delete, content entities. To demonstrate how this works we'll create a small React application with a form that lets you add, edit, and delete article nodes.
In this tutorial we'll:
- Learn how to handle user authentication and CSRF tokens in a React application
- Create a single React component that outputs a form to add or edit content
- Create a wrapper around the JavaScript
fetchAPI to assist in dealing with requests to Drupal's JSON:API
By the end of this tutorial you should know how to create, edit, and delete content in a Drupal site using a React application.
Now that we know how to build a working application in React and embed the application in Drupal, let's make a stand-alone version of our application which can be used outside the context of a Drupal module or theme. In the next few tutorials we'll look at how to create a fully decoupled React application whose only interactions with Drupal happen via API requests.
In this tutorial we'll:
- Introduce differences we need to account for in a fully decoupled application
- Provide an example of what the final project will look like
By the end of this tutorial you should have a better understanding of what we're trying to create in the rest of this series.
⚠️Note: See Use Vite to Start a Decoupled React Application for a modern approach to scaffolding a decoupled React application.
Using create-react-app we can scaffold a stand-alone React application with boilerplate configuration and organization already in place. It's a great way to get started using React, as well as the ecosystem of associated tools like Webpack, Jest, and Babel. After creating the scaffolding, we'll port the code we wrote in previous tutorials to the new structure.
In this tutorial we'll:
- Use
create-react-appto scaffold a new React project - Refactor existing code into the organizational structure used by
create-react-app - Confirm that our code runs
By the end of this tutorial, you should know what create-react-app is and how to get started using it.
When you create a fully decoupled application, the code in your application can't rely on things like the fetch() function's same-origin policy and the browser's use of cookies to authenticate requests. Instead, you need to use alternative methods like OAuth or JSON Web Tokens (JWTs).
We'll focus on setting up and using Drupal as an OAuth provider, and allowing a decoupled application to authenticate users via OAuth. This same technique applies just as well if you want to use JWTs.
In this tutorial, we'll:
- Install the Simple OAuth Drupal module, and configure it to work with the authorization code grant flow to allow our code to obtain an access token.
- Demonstrate how to retrieve and use an OAuth access token to make authenticated requests.
By the end of this tutorial, you should know how to install and configure the Simple OAuth module and make authenticated API requests using an OAuth authorization code grant flow.
To perform POST, PUT, and DELETE operations to Drupal's JSON:API from a decoupled React app, you need an OAuth 2 access token. Modern best practice for browser apps is to use the authorization code grant with PKCE (Proof Key for Code Exchange). You'll redirect the user to Drupal to sign in, receive an authorization code at your redirect URI, exchange it for tokens, attach the access token to API requests, and refresh it when it expires.
In this tutorial we'll:
- Add lightweight OAuth helper functions that implement authorization code + PKCE and refresh.
- Create a tiny UI to trigger the log in flow and handle the auth callback.
- Wrap
fetch()to automatically includeAuthorization: Bearer ...and handle refresh. - And finally, update our existing components to use that wrapper.
By the end of this tutorial, you should be able to make authenticated JSON:API requests from React using fetch with a modern OAuth flow.
React Fast Refresh (formerly Hot Module Replacement) is a technique for using Webpack to update the code that your browser renders without requiring a page refresh. With fast refresh configured it's possible to edit your JavaScript (and CSS) files in your IDE and have the browser update the page without requiring a refresh, allowing you to effectively see the results of your changes in near real time. If you're editing JavaScript or CSS it's amazing. And, it's one of the reasons people love the developer experience of working with React so much.
If you're writing React code as part of a Drupal theme it's possible configure fast refresh to work with Drupal. Doing so will allow live reloading of any JavaScript and CSS processed by Webpack.
In this tutorial we'll:
- Walk through configuring Webpack and fast refresh for a Drupal theme
- Add an
npm run start:hmrcommand that will start the webpack-dev-server in hot mode - Configure the webpack-dev-server to proxy requests to Drupal so we can view our normal Drupal pages
By the end of this tutorial you should know how to configure Webpack to allow the use of React's fast refresh feature to your Drupal theme and preview changes to your React code in real time.
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.
The testing suite for the Drupalize.Me site uses a different strategy for functional JavaScript testing. We use a tool called Nightwatch.js that allows us to write our tests in JavaScript that runs commands against a web browser. This browser automation allows us to test the types of interactions that a typical user of our website might encounter. It also allows us to test JavaScript code using JavaScript, and execute our tests in different browsers. In this tutorial we'll take a look at how to set up Nightwatch.js, and what the syntax looks like for a couple of basic tests.
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.