Getting Cypress JS to interact with CKEditor

Because .type() doesn’t submit when selecting the textarea.

CKEditor
CkEditor iframe with custom toolbar

While writing a few Cypress.io tests I ran into a problem of manipulating text in a CKEditor window.

Without diving completely into how CKEditor implements the editable iframe, my first thought was to use the native textarea field and skip adding content to the WYSIWYG all together.

Using the native type() function

// The underlying `textarea`

cy.get("#html_body")
.type("<p>HTML body</p>");
Cypress native type command
Cypress error, can’t type in hidden inputs

Cypress doesn’t like typing into hidden input element elements.

Adding the force:true config doesn’t fare much better. With Javascript turned on, CKEditor overwrites the textarea on submit and that value is lost. 😒

Cypress interacting with an iFrame

Next stop is to search “cypress type in ckeditor” which leads to the issue Cannot target elements inside of an iframe #136.

Reading through the working examples lead to something like this:

// Find the `contenteditable` element within the iframe and type

cy.get("#html_body")
  .then(function ($iframe) {
    const $body = $iframe.contents().find("body");

    cy.wrap($body[0])
      .type("<p>HTML body</p>");
  });
Cypress doesn't error
Doesn’t error, but also doesn’t submit

This does find the DOM element and says that it was typed, but it doesn’t actually result in the words being visible in the CKEditor or submitted with the form. 😢

Interacting with JS page objects

Last ditch effort is to break outside of Cypress and set the data in CKEditor natively then try to make the same call from within the Cypress test.

CKEditor has setData() and getData() functions for getting contents in and out of the editor window.

// Set the contents of the CKEditor natively on the page

CKEDITOR.instances["html_body"].setData("<p>HTML body</p>");

Now to call that from within Cypress, led to a search for “cypress get page JS objects” and then to this issue: How can I execute a JavaScript command #897 and the .window() function.

Success!

// Call out to the page window and use the CKEDITOR object

cy.window()
  .then(win => {
    win.CKEDITOR.instances["html_body"].setData("<p>HTML body</p>");
  });
Setting the content of CKEditor with Javascript
Setting the content of CKEditor with Javascript

Turning the solution into a reusable command

// Define the command

Cypress.Commands.add("type_ckeditor", (element, content) => {
  cy.window()
    .then(win => {
      win.CKEDITOR.instances[element].setData(content);
    });
});

// Use the command

cy.type_ckeditor("html_body", "<p>HTML body</p>");

With this approach it is possible to use any of the CKEDITOR.editor object functions.

Stress testing a site with Apache’s ab tool, part 1

Apache’s AB tool is a great way to really put stress on a server. I have compiled a list of the parameters I use to test my sites and applications.

First we have to make sure AB can hit the desired page and get the desired results. The most basic page is the homepage of a site, use the command below to send as many single requests as it can in 1 second

ab http://example.com/

But that is great and dandy but what happens if we want to try to stress a page that hits the database and has to do some actual dynamic work

ab http://example.com/search.php?q=Trees

Last but not least what if the site is behind a login that is an http form and not an htaccess form? That is where POST variables come into play, it is a little trickier but doable. Here is the command I use to hit a page behind a login.

ab -p ~/Documents/post.txt -T application/x-www-form-urlencoded -e http://example.com/manager/

Here is what my post.txt file contains:

email=test@domain.com&password=testing&amp;submit=Login

Next we need to get these results to a file so we can work with them and have a record of progress as we tweak our site. It can be done with the “-e” parameter. An example is below:

ab http://example.com/search.php?q=Trees -e ~/Documents/results1.csv

What that does is hits the search page and puts the results in the results1.csv file. It is useful to put the file at the end of the command since you will want to change the filename on each run to keep a history of your results.

The csv file is separated into two columns. The first is the percentage complete and the second is the time in ms that it took to get to that percentage.

The first thing you want to look at is the zero percent. This is your latency, it is the amount of time it takes to fulfill the first request. You want this number to be as low as possible. I am running my site on a development server on my local network so the times will be lower but at the end I will show the results from the testing server.

ab -p ~/Documents/aci_post.txt -T application/x-www-form-urlencoded -e ~/Documents/aci_output.csv -kc 10 -t 10 http://aci/manager/makes.php

Hold tight, more coming soon…