React Testing Library with Jest – Installation and Configuration

React Testing Library is a newer library that simplifies the testing of React components.

It provides utility functions built on top of react-dom and react-dom/test-utils that enable developers to write intuitive tests that relate to how actual users interact with your app.

This post covers the installation and configuration of React Testing Library in a React project that was “created from scratch”, i.e. not based on Create React App (CRA).

This post covers common considerations for a modern react project seen in industry:

  • Support for ES6+ language features via babel
  • Support for testing custom hooks
  • CSS Modules / SCSS Modules for component styling
  • Support for components that import multimedia files such as images, fonts, and audio
  • Support for the react-spring animation library.
  • Working with eslint

Installing React Testing Library

Change your working directory to the root of your project.

Use your favorite package manager to install react-testing-library and jest-dom as dev dependencies. The following examples use yarn:

yarn add --dev @testing-library/react 
yarn add --dev @testing-library/jest-dom

I like to install jest on its own:

yarn add --dev jest

I recommend including the jest plugin for eslint:

yarn add --dev eslint-plugin-jest

Add the babel-jest package to support the latest ES6+ language features:

yarn add --dev babel-jest

If you’d like to be able to test custom hooks, install @testing-library/react-hooks and react-test-renderer. The version of react-test-renderer should match the version of React, so edit the version number in the example below to reflect what you see in package.json:

yarn add --dev @testing-library/react-hooks
yarn add --dev react-test-renderer@^16.12.0

Note the minimum supported version of React for @testing-library/react-hooks and react-test-renderer is 16.9.0.

Check out the hooks testing documentation at:

Finally, install the identity-obj-proxy package to support CSS/SCSS Modules. When configured, all classNames defined in component will be returned as-is when run in tests vs. replaced with a hashed version as they would in a production build. This helps facilitate snapshot testing because you can rely on classNames being static. If you are not using CSS/SCSS Modules, you can skip this step:

yarn add --dev identity-obj-proxy

Configuring ESLint

Eslint will complain about your tests in its default configuration. This is because, among other things, your test files will use functions such as test() and expect() without explicitly including them.

Open your eslint configuration file to make some changes to support jest. Your eslint configuration could be housed in a .eslintrc.json file or a functional equivalent such as any .eslintrc.* file or via an eslintConfig key in package.json.

To configure eslint to work with jest, ensure that there is a "jest": true entry in the env section of your configuration:

"env": {
    "commonjs": true,
    "jest": true,
    "es6": true

Add the "jest" plugin to the plugins array:

  "plugins": [

If you’d like to use the recommended linter rules for jest, add plugin:jest/recommended to the extends array. In the example below, I also add the recommended style rules provided by plugin:jest/style:

  "extends": [

Supporting Static File Imports

Jest tests will cough if your React components import images, fonts, audio, and other static files. This is because the components are not being run through webpack (or whatever asset bundler you may be using). Imported files such as JPG images will be interpreted as JavaScript code, and that simply won’t work. We can solve this issue with a mock.

Create a test/ folder in the root of your project, and add a __mocks__ subfolder.

Note that this particular file/folder structure is entirely optional; you may wish to use something different in your project.

Create a file fileMock.js and paste the following JavaScript code inside:

module.exports = 'test-file-stub'

In the next section of this post, we will configure jest to use fileMock.js.

Configuring Jest

Jest can be configured by adding a jest.config.js file to the root of your project folder, or via a top-level jest key in package.json.

An example of a basic jest.config.js follows. This particular configuration supports babel via babel-jest, tells jest to look for tests under app/ and test/ folders, and tells it to ignore the node_modules/ and public/ paths.

Consider the patterns defined in the testMatch array. You should revise these to suit your needs. For example, many projects place code in a src/ folder vs. an app/ folder. The following example will match any files ending in .test.js or .test.jsx in the app/ folder, and any files ending in .test.js in the test/ folder.

module.exports = {
  roots: ['<rootDir>'],
  transform: {
    '\\.(js|jsx)?$': 'babel-jest',
  testMatch: [
    '<rootDir>/app/**/*.test.{js, jsx}',
  moduleFileExtensions: ['js', 'jsx', 'json', 'node'],
  testPathIgnorePatterns: ['/node_modules/', '/public/'],
  setupFilesAfterEnv: [
  moduleNameMapper: { },

An example of an expanded configuration that supports CSS Modules / SCSS Modules, imports of images/svg’s/fonts/audio files, and the react-spring library follows.

Note the moduleNameMapper object and how we’ve added a mapping for stylesheet files, multimedia imports, and react-spring. Note how we reference the fileMock.js file we created earlier.

If you do not use react-spring in your project, you can omit the 2x entries for it.

module.exports = {
  roots: ['<rootDir>'],
  transform: {
    '\\.(js|jsx)?$': 'babel-jest',
  testMatch: [
    '<rootDir>/app/**/*.test.{js, jsx}',
  moduleFileExtensions: ['js', 'jsx', 'json', 'node'],
  testPathIgnorePatterns: ['/node_modules/', '/public/'],
  setupFilesAfterEnv: [
  moduleNameMapper: {
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/test/__mocks__/fileMock.js',
    'react-spring/renderprops': '<rootDir>/node_modules/react-spring/renderprops.cjs', // define this entry before 'react-spring'
    'react-spring': '<rootDir>/node_modules/react-spring/web.cjs',

Full documentation for the configuration file can be found on the Jest website:

Running Tests

In the scripts section of your package.json file, define scripts for test, test:watch, and test:coverage that invoke jest:

"scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage --colors",

You can now run these scripts via your package manager, e.g. yarn test or yarn test:watch.

The watch feature will monitor your project files for changes and automatically run your tests when they do. The coverage tool attempts to calculate your test coverage.

Write Some Tests

There are plenty of resources on how to write tests with react-testing-library and with jest.

Get started with the react-testing-library docs at:

Kent C. Dodds, one of the authors of react-testing-library, has a great blog where he covers topics related to testing and using the library, and he provides plenty of examples:

An example of a very basic test for a hypothetical button component called ActionButton follows:

import React from 'react'

import { render } from '@testing-library/react'
import ActionButton from './ActionButton.jsx'

const testLabel = 'TEST_LABEL'

test('confirm ActionButton renders with label', () => {
  const { getByText } = render(<ActionButton buttonStyle="back" label={testLabel} />)

I think one of the coolest features of react-testing-library is fireEvent() function, enabling you to test how your components behave in response to clicks, keypresses, and other events. This provides powerful capabilities for integration testing.

import { render, fireEvent } from '@testing-library/react'

Check out the ‘cheatsheet’ included in the react-testing-library docs:

Good luck with your tests!

Using Formik 2 with React Material Design

Formik is perhaps the leading choice of library to help implement forms in React. Version 2 was recently released and it introduces new hooks as well as improved support for checkboxes and select fields.

This post covers basic usage of Formik v2 with the TextField, Radio, and Checkbox components provided by the Material UI library.

Starting with a blank Create React App project, add the appropriate dependencies:

yarn add formik
yarn add @material-ui/core

You may also wish to add the Roboto font to Material UI per the installation guide.

Start by importing the Formik component.

import { Formik } from 'formik'

Next add the Formik component to your app. It has two required props: initialValues and onSubmit.

The initialValues prop is for specifying an object with properties that correspond to each field in your form. Each key of the object should match the name of an element in your form.

The onSubmit prop receives a function that is called when the form is submitted. The function is passed a data parameter containing the submitted form’s data, and an object with properties that contain a number of functions that you can use to help disable the submit button, reset the form, and more (refer to the docs). In the example below, the function implementation simply logs the data to the console.

The Formik component accepts a function as a child. Formik provides a number of properties as a parameter to the function. The most immediately relevant properties that can be pulled out using destructuring are values (an object that represents the current state of the form), and the functions handleChange, handleBlur, and handleSubmit.

For Material, import a TextField and a Button component:

import TextField from '@material-ui/core/TextField'
import Button from '@material-ui/core/Button'

And incorporate them into Formik as follows:

function App() {
  return (
        initialValues={{ example: '' }}
        onSubmit={(data) => {
      >{({ values, handleChange, handleBlur, handleSubmit }) => (
        <form onSubmit={handleSubmit}>
          <TextField name="example" onChange={handleChange} onBlur={handleBlur} value={values.example} />
          <Button type="submit">Submit</Button>

To simplify the tedious process of adding values, handleChange, handleBlur, and handleSubmit you can use Formik’s helper components Form and Field.

The Form component replaces the standard HTML form tag. It is automagically passed the onSubmit/handleSubmit function (via internal use of the Context API) so you don’t need to add this every time.

The Field component needs to only be passed a name and type prop. It automagically gets the value, onChange, and onBlur.

A Field component with type “text” will render a default HTML5 input by default. To use Material, there’s another prop, as, where you can pass a component that you want the field to render as. As long as the component you pass is capable of accepting value, onChange, and onBlur props (as Material’s TextField does) then you can use it. The Field component will also pass any additional props it is given (e.g. placeholder) to the component specified in the as prop.

import { Formik, Form, Field } from 'formik'
function App() {
  return (
        initialValues={{ example: '' }}
        onSubmit={(data) => {
      >{({ values }) => (
          <Field name="example" type="input" as={TextField} />
          <Button type="submit">Submit</Button>

The same technique works for checkboxes and radio buttons as the following example demonstrates:

import Radio from '@material-ui/core/Radio'
import Checkbox from '@material-ui/core/Checkbox'
function App() {
  return (
        initialValues={{ example: '', name: '', bool: false, multi: [], one: '' }}
        onSubmit={(data) => {
      >{({ values }) => (
            <Field name="example" type="input" as={TextField} />
            <Field name="name" type="input" as={TextField} />
            <Field name="bool" type="checkbox" as={Checkbox} />
            <Field name="multi" value="asdf" type="checkbox" as={Checkbox} />
            <Field name="multi" value="fdsa" type="checkbox" as={Checkbox} />
            <Field name="multi" value="qwerty" type="checkbox" as={Checkbox} />
            <Field name="one" value="sun" type="radio" as={Radio} />
            <Field name="one" value="moon" type="radio" as={Radio} />
          <Button type="submit">Submit</Button>

However, if we want to show labels beside our fields, we run into an issue with how React Material is implemented. It uses a FormControlLabel component that is in turn passed the component to render via its control prop. Check the docs at:

This doesn’t jive well with our current paradigm. It is cleanest to implement a custom field.

Formik v2 adds a very convenient hook called useField() to facilitate creating a custom field. The hook returns an array containing a field object that contains the value, onChange, etc. and a meta object which is useful for form validation. It contains properties such as error and touched.

import { useField } from 'formik'

In the example below, the value, onChange, etc properties are added to the FormControlLabel as props using the spread operator: {...field}.

import FormControlLabel from '@material-ui/core/FormControlLabel'
function ExampleRadio({ label, ...props }) {
  const [ field, meta ] = useField(props)

  return (
    <FormControlLabel {...field} control={<Radio />} label={label} />


Now the ExampleRadio component that was implemented with the help of the useField() hook can replace the Field component with type “radio” in the above examples:

<ExampleRadio name="one" value="sun" type="radio" label="sun" />

So there you have it, a basic use of Formik 2 with React Material that works for the most popular form fields.

Refer to the docs to learn more about useField and the meta object and how it is relevant to form validation:

The docs also publish a validation guide:

How to use aws-sdk for NodeJS with AWS Translate

This post covers using the aws-sdk for NodeJS with AWS Translate.

The code examples are written in ES and transpiled with Babel.

Install the AWS SDK

First, install the aws-sdk package in your project using your favourite package manager:

yarn add aws-sdk
# OR
npm i aws-sdk

Ensure There’s a Working AWS Profile

Ensure that you have an AWS profile and configuration properly setup for your user. An AWS Profile is typically stored inside the ~/.aws folder inside your home directory.

Suppose you have a profile named firxworx. An example entry of a useful entry in ~/.aws/config for that profile is:

[profile firxworx]
region = ca-central-1
output = json

A corresponding entry in the ~/.aws/credentials file that specifies credentials for the example firxworx profile looks like this:


Refer to the AWS Docs if you need to create a profile and obtain an Access Key ID and Secret Access Key.

Write Your Code

Start by importing the aws-sdk package:

import AWS from 'aws-sdk'

Next, configure AWS by specifying which profile’s credentials to use:

const credentials = new AWS.SharedIniFileCredentials({ profile: 'firxworx' })
AWS.config.credentials = credentials

Specify any other config options. The following line locks AWS to the most current API version (at the time of writing):

AWS.config.apiVersions = {
  translate: '2017-07-01',

Reference the AWS Translate homepage and take note of which regions AWS Translate is currently available in. If you need to specify a region that’s different than the default listed in your AWS profile, or you wish for your code to be explicit about which region it’s using, add the following line. Change the region to the valid region that you would like to use:

  region: 'ca-central-1'

If you are using any Custom Terminologies, be sure to define them in the same region that you are about to use for AWS Translate. Custom Terminologies are lists of translation overrides that can be uploaded into the AWS Console. They are useful for ensuring that brand names, terms of art, trademarks, etc are translated correctly. Custom Terminology definitions are only available within the region that they were created and saved in.

Next, create an instance of AWS Translate:

const awsTranslate = new AWS.Translate()

At this point everything is setup to write a function that can translate text.

The following implements an async function called awsTranslate(). The function’s params include specifying a hypothetical custom terminology named example-custom-terminology-v1. Do not specify any value in the TerminologyNames array if you are not using any custom terminologies.

A key insight here is the .promise() method in the line containing awsTranslate.translateText(params).promise() which causes the API to return a promise.

async function asyncTranslate(langFrom, langTo, text) {
  const params = {
    SourceLanguageCode: langFrom,
    TargetLanguageCode: langTo,
    Text: text,
    TerminologyNames: [

  try {
    const translation = await awsTranslate.translateText(params).promise()
    return translation.TranslatedText
  } catch (err) {
    console.log(err, err.stack)

The langFrom and langTo must be language codes as understood by AWS Translate. Refer to the docs for a current list of supported language codes:

If you had a hypothetical index.js entry point for your NodeJS application and wanted to use the above function, an example invocation could be:

(async () => {

  const translation = await asyncTranslate('en', 'fr', 'Hello World')


Custom SVG Icons for Gutenberg Blocks in WordPress

This post covers a straightforward way to use custom SVG icons in Gutenberg blocks.

You can use an SVG icon for your block, to appear

The content of this post is intended as an updated alternative to some of the methods covered in older tutorials such as Zac Gordon’s 2017 post How to Add Custom Icons to Gutenberg Editor Blocks in WordPress.

Install Dependencies

Use npm or yarn to install the @svgr/webpack and url-loader dependencies:

yarn add @svgr-webpack --dev
yarn add url-loader --dev

Add the following to the rules array in your webpack config:

  test: /\.svg$/,
  use: [ '@svgr/webpack', 'url-loader' ],

If you are using the boilerplate @wordpress/scripts included webpack.config, a convenient example is in the docs where the boilerplate config is loaded and spread (via the spread operator) into a custom config file where you can then make customizations of your own, such as adding the above block to support SVG’s.

The docs actually use @svgr/webpack as their example of a the customized webpack.config that extends the boilerplate, but the docs don’t cover how to actually make use of the @svgr/webpack package.

For convenience, I copied the following example from the WordPress Developer Docs:

const defaultConfig = require("@wordpress/scripts/config/webpack.config")

module.exports = {
  module: {
    rules: [
        test: /\.svg$/,
        use: ["@svgr/webpack", "url-loader"]

Using SVG Icons as Components

You can now import icons as Reqct Components in your blocks.js (or whichever) file where you call registerBlockType() to register a new block:

import { ReactComponent as MyIcon } from '../../assets/svg/ui/icon.svg'

As an aside, note that you also have the option of importing a base-64-encoded svg via the default export created by @svgr/webpack: import myIconSvg from '../../assets/svg/ui/icon.svg'

Specifying the SVG Icon for your Block

In the block configuration object passed to registerBlockType(), specify your icon component without encapsulating it in a JSX tag:

registerBlockType( 'example/my-block', {
  icon: MyIcon

Using SVG Icon Components in Block edit() and save() Methods

You can also use the component you imported (e.g. <MyIcon />) as a JSX tag in your edit and save functions.

registerBlockType( 'example/my-block', {
  icon: MyIcon
  edit: () => (<div><MyIcon /></div>)

Note About SVG’s

Not all SVG’s are created equal. I have had success with those that define a square viewBox and set a width and height of “1em”.

Arduino FastLED Totem with NeoPixels and a Button

I created a “festival totem” prototype project and posted the code to github: The project is implemented with an Arduino Nano, WS2812B “Neopixels”, and the FastLED library.

The project consists of 6x LED strips that are each 11-pixels in length. They are wired together and hot-glued vertically around the diameter of the end of a bamboo shaft in an up-down-up-down-up-down pattern.

The primary effect is a “fire torch” that features a modified version of the Fire2012 animation by Mark Kriegsman.

The project implements handful of other effects that can be switched to using a button that’s implemented with an interrupt on Pin D2 of the Arduino. Most of them are sourced from the FastLED demo reel and modified as necessary for the totem.

The function compute_bottom_to_top_offset() in the code is used to compute the index of a given pixel on a given strip (of the 6) such that the pattern moves from bottom-to-top. This is used to replicate an effect on one strip across all of the strips.

The project is powered by a stock 5V battery charger and the NeoPixels are powered via the Arduino Nano’s 5V pin. Since this pin is limited to 500mA of output, the FastLED function set_max_power_in_volts_and_milliamps() limits power consumption.

The project ran successfully without issues at Harvest Festival 2019 in Ontario. It would be a great candidate to ruggedize and bring to Burning Man.

Check out the project on Github for the code and a description of the hardware/schematic.

Creating an Invoice Component with Dynamic Line Items using React

This post walks through the steps to creating an Invoice component in React that supports adding + removing line items and features automatic calculation of totals as a user inputs values.

The source code to follow along with is available on github at:

A live demo can be viewed at:

I use SCSS Modules for styling but you could easily refactor the code to use your favourite method for styling components.

SCSS Modules are an easy choice because the latest v2 of create-react-app (released Oct 1 2018) introduces out-of-the-box support for CSS Modules that can be written in CSS (default) or SASS/SCSS with the addition of the node-sass package. Version 1 required users to manually customize their webpack configuration if they wanted to use CSS Modules.

The code is relevant to React v16.6.3.

Project Setup

This project is based on the create-react-app starter. To get started with the yarn package manager:

yarn create react-app react-simple-invoice

The following dependencies are installed:

yarn add node-sass
yarn add react-icons

The create-react-app boilerplate can then be customized to use sass modules: all .css files are renamed to .scss and the .module.scss suffix filename convention is applied where applicable.

I added a bare-bones global stylesheet in styles/index.scss where I import Normalize.css (as _normalize.scss).

All of the component styles assume box-sizing border-box and that normalize.css is in place.

Implementing an Invoice Component

The most significant part of an Invoice component are arguably the line items that can be added and removed. The following provides an overview for how this functionality is implemented:

Initial scaffolding

Start by creating components/Invoice.js and components/Invoice.modules.scss.

Tear up the initial Invoice component as a class-based component. Import a couple helpful icons from react-icons and the Invoice scss module:

import React, { Component } from 'react'
import { MdAddCircle as AddIcon, MdCancel as DeleteIcon } from 'react-icons/md'
import styles from './Invoice.module.scss'

class Invoice extends Component {

  locale = 'en-US'
  currency = 'USD'

  render = () => {
    return (
      <div><h1>I am an Invoice</h1></div>


export default Invoice

The locale and currency are stored in the class for the sake of example. In a broader app, these might be injected as props and/or come in from a context or global state.

React will move towards functional components across the board in upcoming versions. However, for now, class-based components still reign for interactive/dynamic components that maintain their own state.

Define state

The Invoice’s state maintains a tax rate and an array of line item objects that have the following properties: name, description, quantity, and price.

Define the initial state with a 0% tax rate and a single blank line item:

  state = {
    taxRate: 0.00,
    lineItems: [
        name: '',
        description: '',
        quantity: 0,
        price: 0.00,

Displaying line items

Inside the component’s render() method, JSX is used to display each line item reflected in the component’s state.

The Array map() function is used to iterate over each line item.

The key for each line item is simply set to its index in the state array. For more information on the necessity of keys in React, refer to the docs regarding Lists and Keys.

Each form input element is created as a Controlled Component. This means that React completely controls the element’s state (including whatever value is currently being stored by the form element Component) rather than leaving this to the element itself. To accomplish this, each input specifies an onChange event handler whose job it is to update the component’s state every time a user changes the value of an input.

Each input’s value is set to its corresponding value in the Invoice’s state.

The various styles and functions referenced will be implemented next:

{, i) => (
    <div className={`${styles.row} ${styles.editable}`} key={i}>
    <div><input name="name" type="text" value={} onChange={this.handleLineItemChange(i)} /></div>
    <div><input name="description" type="text" value={item.description} onChange={this.handleLineItemChange(i)} /></div>
    <div><input name="quantity" type="number" step="1" value={item.quantity} onChange={this.handleLineItemChange(i)} onFocus={this.handleFocusSelect} /></div>
    <div className={styles.currency}><input name="price" type="number" step="0.01" min="0.00" max="9999999.99" value={item.price} onChange={this.handleLineItemChange(i)} onFocus={this.handleFocusSelect} /></div>
    <div className={styles.currency}>{this.formatCurrency( item.quantity * item.price )}</div>
        <button type="button"
        ><DeleteIcon size="1.25em" /></button>

Implement onChange handler

When a user types a value into an input, the onChange event fires and the handleLineItemChange(elementIndex) function is called.

The Invoice’s state is updated to reflect the input’s latest value:

  handleLineItemChange = (elementIndex) => (event) => {

    let lineItems =, i) => {
      if (elementIndex !== i) return item
      return {...item, []:}



The handleLineItemChange() handler accepts an elementIndex param that corresponds to the line item’s position in the lineItems array. As an event handler, the function is also passed an event object.

The Invoice’s state is updated by creating a new version of the lineItems array. The new version features a line item object and property (name, description, quantity, price) modified to correspond to the changed input’s new value. The this.setState() function is then called to update the Invoice component with the updated state.

The new array is created by calling map() on the this.state.lineItems‘s Array and passing a function that updates the appropriate value.

As map() loops through each element, our function checks if that element’s index matches that of the input that triggered handleLineItemChange(). When it matches, an updated version of the line item is returned. When it doesn’t match, the line item is returned as-is.

The implementation works because the name of each form input input (available as corresponds to a the property name of the line item.

Implement onFocus Handler

It is sometimes convenient for users to have an input automatically select its entire value whenever it receives focus.

I think this applies to the quantity and price inputs so I added an onFocus handler called onFocusSelect(). It is implemented as follows:

  handleFocusSelect = (event) => {

Implement Handler for Adding a Line Item

When the “Add Line Item” button is clicked, the onClick() event calls the handleAddLineItem() function.

A new line item is added to the Invoice by adding a new line item object to the component state’s lineItems array.

The Array concat() method is used to create a new array based on the current lineItems array. It concatenates a second array containing a new blank line item object. setState() is then called to update the state.

  handleAddLineItem = (event) => {

      lineItems: this.state.lineItems.concat(
        [{ name: '', description: '', quantity: 0, price: 0.00 }]


Implement Handler for Removing a Line Item

Each line item features a Delete button to remove it from the invoice.

Each Delete button’s onClick() event calls this.handleRemoveLineItem(i) where i is the index of line item.

The Array filter() method is used to return a new array that omits the object at the i‘th position of the original array. this.setState() updates the component state.

  handleRemoveLineItem = (elementIndex) => (event) => {
      lineItems: this.state.lineItems.filter((item, i) => {
        return elementIndex !== i

Implement Calculation and Formatting Functions

The component implements a number of helper functions to calculate and format tax and total amounts:

  formatCurrency = (amount) => {
    return (new Intl.NumberFormat(this.locale, {
      style: 'currency',
      currency: this.currency,
      minimumFractionDigits: 2,
      maximumFractionDigits: 2

  calcTaxAmount = (c) => {
    return c * (this.state.taxRate / 100)

  calcLineItemsTotal = () => {
    return this.state.lineItems.reduce((prev, cur) => (prev + (cur.quantity * cur.price)), 0)

  calcTaxTotal = () => {
    return this.calcLineItemsTotal() * (this.state.taxRate / 100)

  calcGrandTotal = () => {
    return this.calcLineItemsTotal() + this.calcTaxTotal()

Implement Styles

CSS Modules (or SCSS Modules in this case) are great for ensuring there are no naming conflicts in projects with multiple Components that might use the same class names.

The ComponentName.modules.scss file looks and works just like any normal SCSS file except the classes are invoked in JSX slightly differently.

Notice the import line: import styles from './Invoice.module.scss'

To apply a give .example style to a given component, you would refer to styles.example in the className prop:

<ExampleComponent className={styles.example}>

For multiple and/or conditional styles, ES6 strings + interpolation can be used to add additional expressions:

<ExampleComponent className={`${styles.example} ${styles.anotherExample}`} />

Refer to the repo on github to see how it all comes together.

Resolve Google Lighthouse Audit “does not provide fallback content” with GatsbyJS

Google’s Lighthouse Audit Tool is great for evaluating the performance of a site and for confirming just how awesome static sites created with GatsbyJS + React can be.

A common point reduction seen by Gatsby developers is: Does not provide fallback content when JavaScript is not available, with the description: “The page body should render some content if its scripts are not available”.

This post is here to help you resolve that and get one step closer to a perfect score.

The audit requirement

Google explains: “Your app should display some content when JavaScript is disabled, even if it’s just a warning to the user that JavaScript is required to use the app”.

One might think that React Helmet offers a potential solution, however it’s not applicable in this case. Helmet is specifically a document head manager and even though <noscript> tags are valid inside a document head, the audit rule specifically refers to the page body.

Adding tags to the page body above Components injected by Gatsby

Copy html.js from .cache/default-html.js in your Gatsby project folder to your src/ folder, renaming it to html.js:

cp .cache/default-html.js src/html.js

html.js will now take precendence over Gatsby’s boilerplate version.

Open html.js. Between {this.props.preBodyComponents} and before the <div> that contains Gatsby’s body components, you can insert a tag such as:

<noscript>This website requires JavaScript. To contact us, please send us an email at: <a href=""></a></noscript>

Voila, one more checkbox on your Lighthouse audit results!

For more information about html.js see:

Editing WordPress’ wp-config.php with wp-cli and adding variables with sed

The WordPress CLI (command line interface) is a huge step for enabling developers and devops/sysadmin folks manage their WordPress installations. It’s awesome for writing scripts to automate key tasks.

This post covers editing the WordPress configuration file wp-config.php with the WP-CLI’s wp config command, as well as using the sed command to address a key missing feature of WP-CLI: the ability to add new config variables.

There are plenty of reasons you might want to edit wp-config.php via a script or directly via the command line. For example, developers might appreciate a bash script that sets WP_DEBUG to true, and a devops person might want to create an automated deploy process that ensures key SMTP settings are in place.

The rest of this post will assume your WP-CLI command can be invoked with wp. Depending on how you installed it, the command might be available to you as wp-cli or wp-cli.phar. If you are running wp-cli’s phar file directly, substitute php wp-cli.phar in place of wp in the examples.

Editing config variables with wp-cli’s config command

WP-CLI supports modifying config variables in wp-config.php via wp config.

This is a great feature, albeit with the noted catch that wp config only works for a given variable if that variable is already defined in wp-config.php. I’ll show you how to work around that and add variables with sed in the next section.

The following example uses sudo to run wp config as the _www web server user, the default web server user on MacOS. On Ubuntu and many other linux distros, this user is likely www-data:

sudo -u _www wp config set FS_METHOD 'direct'
sudo -u _www wp config set DISABLE_WP_CRON true
sudo -u _www wp config set WP_DEBUG true
sudo -u _www wp config set WP_DEBUG_LOG true

These are some of the most popular config options that developers and admins want to modify.

Adding config variables to wp-config.php using sed

There are a number of command-line utilities on Linux and Unix-like systems that can edit text files. One of the most popular is sed, the quintessential stream editor. Unix admins have been working with streams forever, long before NodeJS made it cool :).

sed is pre-installed on most systems and can be used directly in the Terminal or inside a bash (or other shell) script.

The following example uses sed to add config variables to wp-config.php right before the well-known “That’s all, stop editing!” comment line found in the file.

This snippet works on MacOS and elsewhere. MacOS and OSX, as well as their related family in the BSD/unix world, generally bundle a classic POSIX-compliant version of the sed command which is more limited vs. the more common and more popular GNU sed that ships with major linux distributions like Ubuntu. If you’re on linux, delete the double quotes '' immediately following the -i flag to be compatible with GNU sed.

Editing wp-config.php with sed:

sed -i '' '/\/\* That.s all, stop editing! Happy blogging. \*\// i\
define( "FS_METHOD", "direct" ); \
define( "WP_DEBUG", true ); \
define( "WP_DEBUG_LOG", true ); \
define( "DISABLE_WP_CRON", true ); \
' wp-config.php

The -i option tells sed to edit the file in-place i.e. modify the file directly. Otherwise, sed lives up to its name and streams output to stdout.

The MacOS version of sed requires a backup file to be specified as the first argument whenever the -i option is used. You can pass empty quotes '' to specify no backup file as demonstrated in the example.

The linux version of sed does not require a backup filename to be specified. You can simply delete the '' arguments as noted above.

The way that single and double quotes are used is very important for getting this command to work. Getting them right is one of the trickiest parts about using sed.

Also note how backslashes are used at the end of each line. This is required to make the command portable and universal: classic sed (BSD/Unix/MacOS) does not recognize \n as a placeholder for the newline character while GNU sed (linux) does. The backslashes enable a trick to use actual newlines instead of placeholders.

Finally, my example adds comment lines that start with // FX_SCRIPT before each change (get it? FX = firxworx, the name of this blog!). I do this to make it easy to search with grep and/or visually look for changes in wp-config.php files that were made by my scripts. You may wish to follow a similar practice. This makes it easier to write other scripts that might find and comment out or delete these entries at a later time.

Adding a custom endpoint to WordPress’ REST API to upload files

This guide provides an overview and examples that demonstrate how to create a custom endpoint for WordPress’ REST API that files can be uploaded to.

The particular examples in this post support a CSV file upload but they are easily modified to accept other types of files.

The ability to upload data files in common formats such as CSV, JSON, XLS, etc. is a common requirement found in many business applications. I hope it is useful to you :).


This post assumes the file upload functionality is restricted to administrator-level users that have authenticated by logging into the wp-admin dashboard.

No special auth plugins are required to use the REST API because the user is logged in and assumed to be using their web browser to upload the file.

In order to have the REST API accept file uploads from a remote source such as another website or app, a remote script, or a detached front-end user interface implemented with something like React, consider the various alternative authentication methods available for the WP REST API such as OAuth or Application Passwords that can be supported by installing plugins.

File upload form

For the sake of our example, assume we’ve made a plugin that creates an admin panel that features an HTML form with a file upload input. JavaScript will be used to handle the form submission and send the file to the REST API.

Note the file could be sent from anywhere as long as the server (e.g. CORS) and WordPress is configured correctly (e.g. to support remote authentication using something like OAuth).

The form’s file input element might be something like:

<input id="csv" name="file" type="file" accept=".csv" required /> 

To accept other file formats, add or change the “.csv” value passed to the accept attribute (prop) above.

We also assume our plugin has employed the wp_localize_script() technique to make the following variables available to JavaScript:

  • pluginConfig.restURL — value set to the output of esc_url_raw( rest_url() )
  • pluginConfig.restNonce — value set to the output of wp_create_nonce( 'wp_rest' )

For more information regarding how and why this is done, see the official REST API Handbook.

In short, JavaScript needs to know the URL of where to send the file and the value of a nonce. The nonce is related to a security measure implemented by WordPress that helps discourage CSRF attacks.

The following JavaScript code makes use of the newer FormData API and uses JQuery’s $.ajax() method to POST the CSV to the API endpoint.

The code assumes a standard HTML form with class “import” (<form class="import"...>) and:

  • a file <input /> tag with id="csv" and name="file"
  • a submit <button> (or <input type="submit"... />) with class="csv-submit"

The specific classes and id’s are used to target the form and obtain the values/data from its inputs.

( function($) {

  'use strict';

  $(document).ready( function() {
    $('.import').on('click', '.csv-submit', function(event) {

      var file = $('input#csv')[0].files[0];
      var formData = new FormData();

      formData.append( 'file', file );

      // append any other formData 
      // e.g. any id fields, etc as necessary here

        url: pluginConfig.restURL + '/import/csv',
        data: formData,
        processData: false,
        contentType: false,
        method: 'POST',
        cache: false,
        beforeSend: function ( xhr ) {
          xhr.setRequestHeader( 'X-WP-Nonce', pluginConfig.restNonce );
     .done(function(data) { 
        // handle success 
      .fail(function(jqXHR, textStatus, errorThrown) {
        // handle failure


Moving into the WordPress side of things, we need to add an endpoint to handle the file upload.

There are tons of ways to structure plugins when it comes to WordPress. The following example isolates the REST-related functionality in its own class called MyPluginRestAPI.

It is assumed that our plugin require()‘s the class file, creates an instance of the class, and then calls the instance’s init() method.

It’s up to you to handle errors. For this example, assume that a subclass of PHP’s Exception class named PluginException exists and that it implements a hypothetical restApiErrorResponse() method. Assume the method sends an error response back to the client by calling WordPress’ rest_ensure_response() function with a WP_Error object as its argument.

Note the following uses some PHP7.1+ syntax. Earlier versions of PHP may not support private constants (which are very new at the time of writing) or the square bracket syntax for defining arrays (use array() instead).

class MyPluginRestAPI {

  private const BASE = 'myplugin/v1';

  public function init() {
    add_action( 'rest_api_init', [ $this, 'initRoutes'] );

  public function initRoutes() {
    register_rest_route( self::BASE, '/import/csv', [
            'methods' => [ 'POST' ],
            'callback' => [ $this, 'importCSVPostRequestHandler' ],
            'permission_callback' => [ $this, 'enforceAdminPermissions' ],
            'args' => [
              // ... 
    ] );

  public function enforceAdminPermissions() {
    if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'administrator' ) ) ) {
      return new WP_Error( 'rest_forbidden', esc_html__( 'Private', 'myplugin' ), array( 'status' => 401 ) );
    return true;

  public function importCSVPostRequestHandler( WP_REST_Request $request ) {

    // if you sent any parameters along with the request, you can access them like so:
    // $myParam = $request->get_param('my_param');

    $permittedExtension = 'csv';
    $permittedTypes = ['text/csv', 'text/plain'];

    $files = $request->get_file_params();
    $headers = $request->get_headers();

    if ( !empty( $files ) && !empty( $files['file'] ) ) {
      $file = $files['file'];

    try {
      // smoke/sanity check
      if (! $file ) {
        throw new PluginException( 'Error' );
      // confirm file uploaded via POST
      if (! is_uploaded_file( $file['tmp_name'] ) ) {
        throw new PluginException( 'File upload check failed ');
      // confirm no file errors
      if (! $file['error'] === UPLOAD_ERR_OK ) {
        throw new PluginException( 'Upload error: ' . $file['error'] );
      // confirm extension meets requirements
      $ext = pathinfo( $file['name'], PATHINFO_EXTENSION );
      if ( $ext !== $permittedExtension ) {
        throw new PluginException( 'Invalid extension. ');
      // check type
      $mimeType = mime_content_type($file['tmp_name']);
      if ( !in_array( $file['type'], $permittedTypes )
          || !in_array( $mimeType, $permittedTypes ) ) {
            throw new PluginException( 'Invalid mime type' );
    } catch ( PluginException $pe ) {
      return $pe->restApiErrorResponse( '...' );

    // we've passed our checks, now read and process the file
    $handle = fopen( $file['tmp_name'], 'r' );
    $headerFlag = true;
    while ( ( $data = fgetcsv( $handle, 1000, ',' ) ) !== FALSE ) { // next arg is field delim e.g. "'"
      // skip csv's header row / first iteration of loop
      if ( $headerFlag ) {
        $headerFlag = false;
      // process rows in csv body
      if ( $data[0] ) {
        $field1  = sanitize_text_field( $data[0] );
        $field2  = sanitize_text_field( $data[1] );
        // ... 
        // your code here to do something with the data
        // such as put it in the database, write it to a file, send it somewhere, etc. 
        // ...
    fclose( $handle );
    // return any necessary data in the response here
    return rest_ensure_response( ['success' => true] );


Note the series of checks to ensure the uploaded file has the right MIME type, correct extension, was uploaded via POST, and was received with no errors. These are important for both security and file integrity.

The last thing you want to do is enable a possible attacker to upload an executable script (such as a PHP file) and then be able to trigger it (e.g. by visiting the direct URL for the file or finding a way to get a user to access the file).

In terms of methods implemented by the class:

  • initRoutes() calls register_rest_route() to register the custom route
  • enforceAdminPermissions() implements a permission callback to ensure the user is an administrator
  • importCSVPostRequestHandler() handles the POST request

Note that the CSV is assumed to have a header row with column labels. The code is easily revised to accommodate cases where there is no header row.

I hope this helps! If you get stuck, please ask your questions in the comments, and remember that I’m available as a consultant to assist with your project 🙂 .

Installing gulp4 with babel to support an ES6 gulpfile

This guide covers installing gulp4 with babel to support ES6 syntax in your gulpfile.

Gulp is a task automation tool that has emerged as one of the standard build tools to automate the web development workflow. Babel is a compiler/transpiler that enables developers to use next-generation ECMAScript syntax (ES6 and beyond) instead of older JavaScript (ES5) syntax.

Gulp4 and ES6+ work together swimmingly to help you write cleaner, easier-to-read, and more maintainable gulpfile’s.

Installing gulp4

At the time of writing, the default gulp package installs gulp 3.x. The following will install and configure gulp4.

Gulp has two key parts: gulp and the gulp-cli command line tools. The idea is that gulp-cli should be installed globally on a developer’s machine while gulp should be installed locally on a per-project basis. This helps ensure compatibility with different versions of gulp that will inevitably arise when maintaining projects of different vintages.

To use gulp4, cli version 2.0 or greater is required. Check the version on your system with:

gulp -v

If the command returns a command not found error, then you probably don’t have gulp installed at all (or at least don’t have it available in your PATH).

If the command outputs a version lower than 2.0, you may need to uninstall any globally-installed gulp (and/or gulp-cli) and then install the current version gulp-cli before proceeding.

To install gulp-cli globally, run ONE of the following commands, depending on your preference of package manager. npm is the classic node package management tool and yarn is a newer tool developed by Facebook that addresses certain shortcomings with npm.

yarn global add gulp-cli
# OR
npm install gulp-cli -g

Test the install by running gulp -v and ensuring the version output is greater than 2.0. Next, install the gulp@next package. The @next part specifies the next-generation gulp4.

Assuming you have already run npm init or yarn init and have a package.json file, execute the following command in your project’s root directory:

yarn add gulp@next --dev
npm install gulp@next --save-dev

Installing babel

yarn add @babel/core --dev
yarn add @babel/preset-env --dev
yarn add @babel/register --dev
# OR 
npm install @babel/core --save-dev
npm install @babel/preset-env --save-dev
npm install @babel/register --save-dev

Next, create a .babelrc file in your project’s root folder and specify the current version of node as the target:

  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "current"

Create your gulpfile

Create your gulpfile with the filename gulpfile.babel.js. The babel.js suffix ensures that babel will be used to process the file.

The following example demonstrates a few ES6+ features: optional semicolons, import statements, and the “fat arrow” syntax for defining functions:

'use strict'

import gulp from 'gulp'

gulp.task('task-name', () => {
  // example 
  return gulp.src('/path/to/src')

Gulp4 features a new task execution system that introduces the functions gulp.series() and gulp.parallel() that can execute gulp tasks in either series (one-after-another) or parallel (at the same time). This makes a lot of workflows much easier to define vs. previous versions!

Another nice feature is that gulp4 supports returning a child process to signal task completion. This makes it cleaner to execute commands within a gulp task, which can help with build and deployment related tasks.

The following example defines a default build task that runs two functions/tasks in series using gulp.series(). The build task is defined using the ES6 const keyword and exported as the default function/task for the gulpfile. The example doSomething() and doAnotherThing() functions/tasks are also exported.

'use strict'

import gulp from 'gulp'

export function doSomething {
  // example 
  return gulp.src('/path/to/src')

export function doAnotherThing {
  // example 
  return gulp.src('/path/to/src')

const build = gulp.series(doSomething, doAnotherThing)

export default build