Simplify testing with Cypress

Anyone who has ever started programming knows the situation. You write a component that works at first sight, but then has a lot of bugs when you use it. In the development phase this is quite natural, but if the application is handed over to a customer without much testing, so the big bang is not far away.

Now you sit there and have to test several 1000 elements, which affect every changes. Repeating tests several times is time-consuming and nerve-racking.

But fortunately there is the test framwork Cypress, which was developed especially for Web application.

The special thing about Cypress is that everything runs automatically. Manual clicking is a thing of the past.

You can read a detailed feature description at: https://docs.cypress.io/guides/overview/why-cypress.html#Our-mission

Start with Cypress

Install Cypress

First of all, we navigate to our project folder in the terminal and then install all the necessary packages there.

$ cd/your/project/path

npm:

$ npm install cypress --save-dev

yarn:

$ yarn add cypress --dev

Open Cypress

npm:

$ npx cypress open

yarn:

$ yarn run cypress open

Cypress User Interface

The main menu should look something like this:

As you can see, the tool already provides many finished examples. To check if everything works, you can simply click on a sample test and a new window will open where the test will be executed.

The Cypress Test-Runner opens and should look something like this:

The First Steps

In this section I will give you a short summary what you should know for the start.

1. create a test file

  • All test files come in the folder: cypress/intergration
  • naming convention: fileName_spec.js or fileName.spec.js
  • describe(), it(), context() and specify() contain the actual test and you can also use them to structure your test and give it a name.

File structure in an example:

// -- Start: Our Application Code --
function add (a, b) {
  return a + b
}
// -- End: Our Application Code --

// -- Start: Our Cypress Tests --
describe('Unit test our math functions', function() {
  context('math', function() {
    it('can add numbers', function() {
      expect(add(1, 2)).to.eq(3)
    })
})
// -- End: Our Cypress Tests --

2. Write test

As soon as you have created the test file, Cypress automatically updates the test list and your test should be selectable in the menu.

This section shows the basic functions.

Visit the test website: cy.visit()

This function checks the link and returns a true if a 2XX status like 200 is returned. Otherwise a false is returned and the test fails.

describe('My First Test', function() {
  it('Test PHMU Website', function() {
    cy.visit('https://www.phmu.de/')
  })
})
  • As you can see, the functions in the command log are displayed as uppercase letters. Here in our example VISIT.
  • A click on it, the addressed element is visually displayed in function.
  • All tests are displayed as a timeline and you can “jump back” the time and see exactly when and where the test failed or invoked.

Query elements

In Cypress we can query and pick an element from our test website . if it exist a true will be retrun

The common functions for this are:

contains(content) – Returns the DOM element containing the corresponding innerText..

describe('My First Test', function() {
  it('Test PHMU Website', function() {
    cy.visit('https://www.phmu.de/')
  })
  it('Test contain PHMU slogan', function() {
    cy.contains('Unser Herz schlägt digital')
  })
})

get(selector) – Returns the DOM element selected with the selector.

describe('My First Test', function() {
  it('Test PHMU Website', function() {
    cy.visit('https://www.phmu.de/')
  })
  it('Test contain PHMU slogan', function() {
    cy.get('img[class=image]')
    //Sucht ein img element mit der CSS-Klasse image
  })
})

Interacting with Elements

After you have queried the elements in the previous step, it is also possible to interact with the elements. If interaction with an element is not possible, the test will be displayed as failed.

type()

describe('My First Test', function() {
  it('Test contact formular', function() {
    cy.visit('https://www.phmu.de/workshops')
  })
  it('Test firstname input', function() {
    cy.get('input[id="firstname"]').type('Tung')
  })
})

click()

describe('My First Test', function() {
  it('Test contact formular', function() {
    cy.visit('https://www.phmu.de/workshops')
  })
  it('Test firstname input', function() {
    cy.get('button[id="submit"]').click()
  })
})

select()

describe('My First Test', function() {
  it('Test contact formular', function() {
    cy.visit('https://www.phmu.de/workshops')
  })
  it('Test firstname input', function() {
    cy.get('select[id="title"]').select("Doctor")
  })
})

Assertion

With should() you can check if an element is what you expect it to be. As an example, we want to make sure that the current URL is the expected URL.

describe('My First Test', function() {
  it('Test PHMU Website', function() {
    cy.visit('https://www.phmu.de/')
  })
  it('Test workshop link', function() {
    cy.get(a[href="/workshop"]).click
    cy.url().should('include', '/workshop')
  })
})

In this blog I have only given you the most necessary information for Cypress. Cypress is too big to put everything in one blog.

As I have already mentioned, I highly recommend you to read the documentation. Besides the good documentation it also contains Best Practices to test effectively.

Links

Setting up Tailwind CSS in a WordPress Theme using gulp.js

Tailwind CSS as a utility-based framework ensures an incredibly efficient workflow when developing modern frontends. To use it in your WordPress Theme you could simply serve it from CDN. But for going beyond Tailwind’s rudimentary functionality you can’t avoid setting it up locally in your Theme. In this article we will set up Tailwind CSS in a WordPress Theme using gulp.js.

WPGulp and Gulp-PostCSS

To integrate Tailwind into your WordPress Theme you should install WPGulp first. WPGulp is a plugin to simplify gulp.js setups in WordPress. Additionally, you will need the gulp plugin of PostCSS to process Tailwind.

npx wpgulp
npm install -D gulp-postcss

Now you have installed a complete gulp setup that generates compact CSS files from SCSS. Inside your wpgulp.config.js you can configure your project paths and other variables. Specify the location of your SCSS files and where your CSS shall be generated. Since your project is now based on SCSS you should adapt your previous stylesheets.

Installing Tailwind CSS

At this point we are ready to integrate Tailwind into our theme:

npm install tailwindcss

Add Tailwind to your primary SCSS file:

@tailwind base;
@tailwind components;
@tailwind utilities;

To customize Tailwind individually, you can generate a config file:

npx tailwind init

In the created tailwind.config.js you can configure Tailwind as you like. More at

Integration von Tailwind CSS in gulp

Now we have everything we need to configure Tailwind with gulp. In our gulpfile.babel.js we will add PostCSS and Tailwind to the CSS-related plugins at first:

// CSS related plugins
// ...
const postcss = require( ‘gulp-postcss’ );
const tailwindcss = require( ‘tailwindcss’ );
// ...

Both plugins are imported into our gulp file as constants. Now we want gulp to use them. The gulp tasks styles and stylesRTL generate our finale CSS files and right-to-left stylesheets. Here we will insert PostCSS and Tailwind:

gulp.task( ‘styles’. () => {
  return gulp
    .src( config.stlyeSRC, { allowEmpty: true })
    // ...
    .pipe( postcss([
      tailwindcss( ‘./path/to/your/tailwind.config.js’ ),
      require( ‘autoprefixer’ )
    ]) )
    // ...
});
// ...
gulp.task( ‘stylesRTL’. () => {
  return gulp
    .src( config.stlyeSRC, { allowEmpty: true })
    // ...
    .pipe( postcss([
      tailwindcss( ‘./path/to/your/tailwind.config.js’ ),
      require( ‘autoprefixer’ )
    ]) )
    // ...
});
// ...

Once done we can test if our setup works by simply adding a Tailwind class i.e. bg-red-500 to any HTML element in one of your PHP files.

Now you can run npm start. If all the styles are generated successfully you can check your site if the new Tailwind styles are displayed correctly. If so, congratulations! You just have set up Tailwind CSS in your WordPress Theme. Now you can customize your Tailwind theme in the tailwind.config.js.

Links:

Sending emails with Netlify Functions

Let’s say you’ve built your first modern static website (JAMStack) and want to make it more dynamic, e.g. by sending emails with dynamic content and file attachments. But you don’t want to set up or use your server for this. We explain how to do this in this post.

What do you need?

1. Mailing service

First of all, you need a mailing service that sends your emails. You shouldn’t send emails from your email server, but use a larger service provider to avoid the risk of being classified as a spam sender, for example. To send an email, you address the service API with an API key and hand over all the data that should be contained in the email and the mailing service then sends it to the target address.

There are many services to choose from and you should choose the one that suits you best in terms of features and price. Since I enjoyed working with POSTMARK on my last project, in this post I will introduce how to use this service.

2. Netlify

Next, we need a small amount of server-side code to protect the API key on the API request. Lambda functions are ideal for this. A URL endpoint is called up and a given code is executed when it is called. Netlify supports this, so it would be a good idea to host your site on it.

Step 1: Set up the mail service

Set up POSTMARK

The first thing we do is log into Postmark and go through all the steps until we get to the dashboard and have access to the API token.

API Token

Provide the API key for Netlify

To protect the API key, the key should only be made available when executing server-side codes. In Netlify we have to assign the key to a variable under “Environment”.

API Key Environment

Step 2: write functions

How do we create a Netlify function? Very easily. In your project folder, you create a folder with the name “functions”. In this, you then create all the JavaScript files that you need. In our case, we create the file send-email.js.

/project
   ... your entire website or whatever ...
   /functions/
         send-email.js

Use Postmark Node Library

Postmark provides its Node.js library and with a look at the documentation, we discover a simple code example for testing right at the beginning.

const serverToken = "xxxx-xxxxx-xxxx-xxxxx-xxxxxx" //API Key
let postmark = require("postmark")
let client = new postmark.ServerClient(serverToken);

exports.handler = (event, context, callback) => {
client.sendEmail(
    {
        From: "from@example.com", //Deine Emailadresse
        To: "to@example.com", //Ziel Emailadresse
        Subject: "test email",
        HtmlBody: "test",
        TextBody: "test"
    }
).then(response => {
    console.log(response.To);
    console.log(response.SubmittedAt);
    console.log(response.Message);
    console.log(response.MessageID);
    console.log(response.ErrorCode);
});
}

If you are new or not familiar with the AWS Lambda functions – no problem! I’ll give you a brief overview of the individual parameters that our handler receives.

  • event is an object that contains data on the request
  • context contains the user information when using Identity for user authentication
  • callback is a function we can use to create a response

With the callback () method we can test whether our request has arrived at the Mailing Service API.

  callback(null, {
    statusCode: 200,
    body: 'I am on my way !'
  })
}

Step 3: testing

Netlify Dev

Now we have written our first Netlify function and would like to test our work. There is a small tool for this called Netlify Dev. With it, we can simulate a dev server that gives us a local URL with which we can execute and test our functions in the development environment.

After installing and running it should look something like this:

Netlify Dev

Testing the function

To call our Lambda function, we need to address it with a URL like the one below:

http://localhost:8888/.netlify/functions/send-email

If everything went well, the recipient will be happy about your first email 🙂

Testing E-Mail

Step 4: Fill the email with data

Congratulations, you have now sent your first email with the Netlify function. Unfortunately, the content is still static and boring. To breathe new life into your mail, we need to make the code more dynamic.

Let’s say you want to email several congratulations to friends and add a text file with a personal message as an attachment.

You fill in all data with a form and these are saved as an object, e.g .:

const congratulation = {
  targetEmail: "test@gmail.com", 
  reason: "Geburtstag",
  firstname: "Peter",
  message: "Alles Gute zum Geburtstag. Es freut mich das du erwachsen 
           wirst"
}

Now, this data has to be transferred to the URL of the send-mail.js function when sending. To do this, we use an HTTP request with the URL function as the target address with the form data as the payload.

axios({
          method: 'POST',
          headers: { 'content-type': 'application/json' },
          url: '/.netlify/functions/send-email',
          data: congratulation, //payload
      })

Next, we have to fill the content of the e-mail with the data from the payload in our send-mail.js function. It is advisable to use console.log (event) when developing to display all data from the request in the terminal.

Netlify E-Mail

To add an attachment, just take a look at the Postmark Node.js documentation.

const attachment = new 
                    postmark.Models.Attachment("Glückwunschtext.txt", 
                    Buffer.from("payload.message").toString("base64"), 
                    "text");

client.sendEmail(
    {
        From: "from@example.com", //Deine Emailadresse
        To: "to@example.com", //Ziel Emailadresse
        Subject: "test email",
        HtmlBody: "test",
        TextBody: "test"
        Attachments: [attachment],
    })

The fully adapted function then looks like this in the end.

const serverToken = "xxxx-xxxxx-xxxx-xxxxx-xxxxxx" //API Key
let postmark = require("postmark")
let client = new postmark.ServerClient(serverToken);

exports.handler = (event, callback) => {
console.log(event) 
const payload = JSON.parse(event.body)

 const attachment = new 
                    postmark.Models.Attachment("Glückwunschtext.txt", 
                    Buffer.from("payload.message").toString("base64"), 
                    "text");

client.sendEmail(
    {
        From: "tung@phmu.de", //Deine Emailadresse
        To: payload.targetEmail, //Ziel Emailadresse
        Subject: payload.reason, 
        TextBody: `Liebe ${payload.firstname}, 
                  du hast eine Glückwunschemail erhalten`,
        Attachments: [attachment],
    })
} 

The content of the emails sent should then look like this:

Von: tung@phmu.de
An: test@gmail.com
Betreff: Geburtstag

Anhang: Glückwunschtext.txt

Nachricht: 
Liebe Peter, 
du hast eine Glückwunschemail erhalten             

As you can see, sending emails with Netlify Functions is not that complicated. You could now make the emails even fancier such as B. Add HTML code and … But I’ll leave that to you 😉

Real Time Preview for Gatsby Websites with the sanity.io Headless CMS

Modern static sites, also known as JAMStack sites, offer a range of benefits, such as speed, security and reliability. One area where they are still lacking compared to mature options like WordPress is the ability for authors to see previews of their content before publishing it. Because the website has to be rebuild after every change, fast iteration cycles are broken.

In a number of recent projects we have had good experiences with Gatsby as a static site framework. When working with Gatsby, developers get great fast feedback, because Gatsby supports Hot Module Reloading (-> running code is updated with changes without reloading the page). In a recent project we managed to enable the same workflow for authors and editors.

The solution is based on the Headless CMS sanity.io, which provides content updates in real time over WebSockets. The sanity team has created a gatsby source plugin, that adds a listener to the Gatsby development server that refreshes the page with live content updates. To allow authors to work without a local development server, we are running the server in the cloud. This enables authors and editors to work with just a browser.


This preview can go beyond what is possible with WordPress:

  • All edits in Sanity Studio are preview in real time, without saving the changes. This also applies to other data types like color pickers.
  • The preview works for the entire website, not just posts are pages, so changes in menus and changes to global settings can also be previewed.

Here’s how to do it

You need

1. Gatsby + Sanity

To allow Gatsby to access content form sanity, you need to install and set up gatsby-source-sanity. Add the following settings to your gatsby-config.js to do so:

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-source-sanity',
      options: {
          // find this on manage.sanity.io/projects
        projectId: sanityProjectID,
        // probably 'production' or 'development'
        dataset: datasetID,
        // create this on the project page on manage.sanity.io unter Settings > API
        token: YOUR_SANITY_TOKEN,
        watchMode: true,
        overlayDrafts: true,
      },
    },
  ],
}

The interesting options here are watchMode, which enables the listener that runs with the Gatsby development server and overlayDrafts which includes content that is not yet saved and published.

2. gatsby develop in the Cloud

To allow editors and authors without programming experience to use the preview, we want to run the gatsby develop process, that is usually run locally, on a web server. To do so, we need to start it with special options, by adding a script to package.json

"serve-preview": "NODE_ENV=development gatsby develop --host 0.0.0.0 --p $PORT"

Replace ‘$PORT’ with the port you want to run on if you’re not using a PaaS like Heroku or Render that provides the port as a variable.

To run the preview you can use any server with Node.js. Copy the project to the server, install it with yarn and start it with yarn serve

A simpler alternative is using a PaaS such asHeroku or Render. There you only need to set up your project with the UI and configure “build” (yarn) and “start” (yarn serve-preview) commands.

3. Preview Links in Sanity

To allow authors to quickly access the preview for a specific piece of content, sanity offers the ability to provide a function that maps content to preview URLs. It can look like this, for example:

// resolvePreviewURLs.js
const baseURL = 'https://your-preview.herokuapp.com'

export default function resolvePreviewURLs(document) {
  switch (document._type) {
    case 'page': return `${baseURL}/${document.slug.current}`;
    case 'post': return `${baseURL}/post/${document.id}`;
    case 'author': return `${baseURL}/info/people/${document.slug.current}`;
    default: return baseURL;
  }
}

This function has to be provided to sanity via the parts system by adding the following to your sanity.json:

{
  "parts": [
    {
      "implements": "part:@sanity/production-preview/resolve-production-url",
      "path": "./resolvePreviewURLs.js"
    }
  ]
}

You also need to install the @sanity/production-preview plugin with:

sanity install @sanity/production-preview

Afterwards the Open Preview (Ctrl + Alt + O) is available in Sanity Studio

We can help you

If you also need a preview system for your static site, we are happy to help. We can support the entire process of developing and running modern JAMStack websites with complex requirements.

Contact Us

Install WordPress locally in less than a minute

Hosting and developing WordPress locally always takes some effort. First of all, a local server and a MySQL database are required to be able to install WordPress at all. For a long time, tools like MAMP for the Mac were the good companions of a WordPress developer. Since tools and workflow should move with the times, there have been major changes here. We present our current WordPress workflow and the tools we use for it.

Basic setup for our workflow

Setting up the tools

Modern workflows separate the development environment from the live environment. Since errors can occur again and again during development, it must be ensured that the actual live page is not affected. Our workflow always has the following three WordPress versions:

  1. Locally on the developer’s computer
  2. Test on the staging server separately from the live version
  3. Live version

First of all, features or adjustments are implemented locally on the developer’s computer. If a completed work step can be tested, the update is uploaded to the test server. This includes a WordPress installation that is completely separate from the live version and can be accessed, for example, on the domain test.deindomain.de. We will only update the live versions with the new functions once the feature has been tested there without errors

Setting up the tools

As soon as you have downloaded Local from FlyWheel, you can start with the local setup. In the first step, you start the program.

To create a new local WordPress site, start the Local wizard with Create New Site. The name of the new WordPress site is now requested. If you want to select additional options, such as a stored blueprint, you can do this under the Advanced Options. The local domain can also be adjusted here and the folder directory selected. In the next step, you have to select the server configuration. If you don’t need any special features here, you can simply leave the preset preferred active and click on.

In the last step, the WP-Admin data is requested, i.e. the data with which you want to log into your WordPress after installation.

Then Local sets up the local machine and after a short waiting period, you have created your WordPress site. The actual development can now finally begin! 😉

A quick look at the local interface

When Local has created your page, the page will reappear in the left sidebar. If you choose it, you can see different data about your local machine. For one thing, you can start or stop them. The machine must of course be started if you want to call it up in the browser. You can find the link for this under View Site and with a click on Admin you come directly to the WP Admin area. In addition to data such as the WordPress version, PHP version, or the page path, you will find other features at the bottom that are our little highlight. You can create a live link to your local machine.

With this link, the WordPress site can also be accessed externally, and feedback on the current state of development can be obtained quickly without having to deploy the site first.

Synchronize existing WordPress installations

We have now set up a local WordPress site and can start or stop it as we wish. In the following articles, I will explain how the local WordPress installation can be synchronized with an existing live version and how to secure the development and deployment workflow with Git.

Part 2: Importing the content of a live version into the local WordPress instance

Part 3: Deployment of the WordPress theme using Git and DeployHQ