Cypress Automated Testing for Kentico 12

By Tyler Pfohl On April 17, 2020

Cypress Automated Testing for Kentico 12
In the world of quality assurance, automation has become very popular in the last few years. Automated testing can include unit testing, integration testing, regression testing, and much more. Historically, automated UI tests have been mainly created using Selenium WebDriver hooked up to various frameworks, wrappers, and libraries. With so many options and different coding languages supported, the implementation of these tests was often clunky and unreliable.

Enter Cypress. Cypress is an all-in-one end-to-end testing tool that works on any front-end framework or website. It is easy to install, runs quickly, and all of the tests are written in JavaScript, which keeps things consistent and reliable. There are new features being added frequently, and the community behind Cypress continues to grow.

You may be wondering how Cypress can be used to automate features within Kentico. Follow along as I explain how to create a basic test for Kentico 12. If you are using a previous version of Kentico, the general practices in this post can be translated to work with those versions as well.

Disclaimer

Kentico’s administration side is mostly made up of iframe elements, which are often nested inside other iframes. Cypress does not currently have native support for interacting with iframes, but there are several workarounds that work fairly well. I will be using a workaround in this post that I have had success with, but I plan on updating this post once Cypress officially supports iframe interaction. You can track the feature request here.

Set Up

To get started, make sure Cypress is installed on your machine. If you haven’t installed it yet, head to the install guide. Once Cypress is properly installed and working correctly, there are a few more requirements to complete before we start writing the tests.
  1. In the root of your Cypress install, open up cypress.json and add the following line between the curly brackets: “chromeWebSecurity”: false
    • This allows Cypress to access the content within an iframe element.
  2. Install cypress-pipe in the root of your Cypress install by running: npm install cypress-pipe -D
  3. Add the following line to your cypress/support/index.js file: import 'cypress-pipe'
    • This allows you to easily create custom Cypress commands, which we will use for accessing elements within an iframe.

Writing Tests

Now that Cypress is set up the way we want it, we can start creating our automated tests for Kentico. This is a good time to think about what kinds of tests you want to create. For example, you may want to test creating a new user on your site and then check that the user was successfully added to the Users application within Kentico.

In my example, I will be logging into Kentico and checking the Users application for a specific user. By following along, you should be able to use these steps to write basic tests for many Kentico features and applications.

1. Create a new JavaScript file in cypress/integration and name it whatever you want.
  • I named my file kentico_demo.js for this example.
2. Add in the following code to get started.
  • The first line is a triple-slash directive to enable IntelliSense for Cypress.
  • The rest of the code mentioned below can simply be added inside the it() callback function.
/// <reference types="cypress" />

describe('Kentico Demo', function () {
    it('logs in to Kentico and tests admin features', function () {
        // This is where the code will go
    })
})
3. Add the following custom command for locating elements within an iframe.
// Custom command to find an element within an iframe
const findInIframe = (selector) => ($iframe) => $iframe.contents().find(selector)
4. Navigate to the Kentico admin.
  • This URL may differ for you depending on how your site is set up.
  • If you don’t have baseUrl set within cypress.json, then you will need to provide the full URL when running the cy.visit command.
  • If you have baseUrl set, then you just need to provide the path of the URL when running the cy.visit command like the example below.
// Navigate to the Kentico admin
cy.visit('admin')
cy.url().should('contain', 'CMSPages')
5. Log in to the Kentico admin.
  • Double-check that the inputs for the username and password are the same on your environment. If you need to change the element selectors, feel free to do so.
  • Don’t forget to add your own username and password to the type commands. If you need to keep your credentials secure, look into using environment variables.
// Login to Kentico
cy.get('#Login1_UserName').clear().type('YOUR_USERNAME')
cy.get('#Login1_Password').clear().type('YOUR_PASSWORD')
cy.get('#Login1_LoginButton').click()
cy.url().should('contain', 'Admin/CMSAdministration.aspx')

6. Navigate to your Kentico application.
  • Although the URL looks like a randomly generated string when you navigate to an application, that string is actually unique for each application and it doesn’t change.
  • Simply navigate to the application you want to visit in your test and copy the URL into the visit command.
  • In my example, I am navigating to the Users application, so I am checking that the URL contains the unique string, and I am also checking that the breadcrumb bar contains the word “Users”.
// Navigate to your application
cy.visit('Admin/cmsadministration.aspx#51836837-1d6b-4087-a85c-9c09420d0e98')
cy.url().should('contain', '51836837-1d6b-4087-a85c-9c09420d0e98')
cy.get('#js-nav-breadcrumb').should('contain', 'Users') 
7. Now that we have navigated to the application that we want to test, most of the remaining steps will involve the iframes within Kentico.
  • In my testing, I have found that there is almost always a main iframe that contains everything below the Kentico header, and then there is usually at least one more iframe that contains the main content within that application.
  • To find the iframes in your application, right-click the page and select the inspect option that your browser provides. When the developer tools open, search the DOM for “<iframe>” to see all of the iframes that the page contains. The first result will be the main iframe and the additional results are the nested iframes.
  • Simply grab the ID from each iframe element and use them in the following step.
8. Create an alias for the nested iframe that you will be interacting with
  • In this line of code, the main iframe ID should be passed to the get command, and the nested iframe ID should be passed to the findInIframe command.
  • If you need to target a third nested iframe in your application, simply add another chained .pipe(findInIframe(‘SELECTOR’)) command before the as command.
  • When we use the as command, the value we pass becomes the new alias name. In my example, I named the alias “iframe,” which we can target by using cy.get(‘@iframe’) and then chaining additional commands after it. Don’t forget to include the “@” before the name!
// Create an alias for the nested iframe
cy.get('#m_c_layoutElem_cmsdesktop')
    .pipe(findInIframe('#m_c_plc_lt_ctl00_VerticalTabs_l_c'))
    .as('iframe') 
9. It’s time to start interacting with elements within the nested iframe.
  • In my example, I type the string “autotest” into the user search and then click the search button.
  • To test your application, simply change the element selector within the findInIframe command and then perform any actions or assertions you wish on that element.
// Perform a search for a user
cy.get('@iframe')
    .pipe(findInIframe('#m_c_plc_lt_ctl01_Listing_gridElem_cf_txtSearch'))
    .type('autotest', { force: true })
cy.get('@iframe')
    .pipe(findInIframe('#m_c_plc_lt_ctl01_Listing_gridElem_cf_btnSearch'))
    .click()
cy.wait(3000)
cy.get('#cms-loader').should('not.be.visible') 
10. Sometimes when performing a search or doing other actions within an iframe, the iframes will reload or a loading dialog will block the elements on the page.
  • In some rare cases, you may need to wait for a couple of seconds after performing an action like I did in the example above after searching. This is not recommended, but working with iframes can sometimes cause unexpected issues.
  • If you need to wait for the loading dialog to disappear, copy the last line in the above example.
11. Next, it’s time to start doing some asserts to make sure we are seeing the results we expect.
  • In my example, I am checking that the search bar contains my search term, the users table only has one result, and the email matches what I expect.
// Verify the user search result
cy.get('@iframe')
    .pipe(findInIframe('#m_c_plc_lt_ctl01_Listing_gridElem_cf_txtSearch'))
    .should('be.visible').and('have.value', 'autotest')
cy.get('@iframe')
    .pipe(findInIframe('#m_c_plc_lt_ctl01_Listing_gridElem_v > tbody > tr'))
    .its('length').should('eq', 1)
cy.get('@iframe')
    .pipe(findInIframe('#m_c_plc_lt_ctl01_Listing_gridElem_v > tbody > tr > td'))
    .eq(4).should('contain', 'autotest@test.com')
After finding the user, it’s time to edit the user.
  • In my example, I am clicking the edit button on the user row and verifying the breadcrumb bar contains the user’s name.
// Edit the user
cy.get('@iframe')
    .pipe(findInIframe('#m_c_plc_lt_ctl01_Listing_gridElem_v_ctl02_aedit'))
    .should('be.visible').click()
cy.get('#cms-loader').should('not.be.visible')
cy.get('.breadcrumb-last').should('exist').and('contain', 'Automation Test') 
13. Finally, it’s time to handle a third iframe which is nested within the first two.
  • In my example, there is a third iframe on the edit user page.
  • Using the same method we used for the first iframe alias, I will be targeting the main iframe, the first nested iframe, and the second nested iframe.
  • To keep the two aliases unique, I named this alias “iframe2”.
  • We can then target that alias to find elements within it to perform actions. In my example, I am verifying that the email on the edit page matches the email from the users table.
// Verify the edit user information
cy.get('#m_c_layoutElem_cmsdesktop')
    .pipe(findInIframe('#m_c_plc_lt_ctl00_VerticalTabs_l_c'))
    .pipe(findInIframe('#m_c_plc_lt_ctl00_VerticalTabs_l_c'))
    .as('iframe2')
cy.get('@iframe2')
    .pipe(findInIframe('#m_c_txtEmail_txtEmailInput'))
    .should('have.value', 'autotest@test.com')

Running Tests

After your test is completed and you have saved your file, run your test to make sure it passes.
  • Run the following command in the root of your Cypress install: npx cypress open
    • This will open the Cypress Test Runner
  • After the Test Runner opens, find your test file in the list of tests and click it to run it
    • A new browser window should open, and your test will run
    • You can track the progress of the test as it runs through each step
    • If a failure occurs, the runner will provide a detailed error message and will show you the exact step that failed
      • After making the necessary changes, run your test again until it passes

Conclusion

This is just a small example of the power that Cypress has as an automated testing tool for Kentico. Although it doesn’t handle iframes perfectly, it’s still easy to write basic tests for various Kentico applications. Combining these tests with the tests for your actual site allows you to verify that the main site and Kentico admin are both functioning correctly.

Hopefully, you can use the steps above as a guide to creating your own Kentico tests for your site. Feel free to expand on the functionality and get as in-depth as you want to with actions and assertions. Remember to run your tests frequently as you write them so you can catch any issues immediately. After you have completed a test, run it a few times to make sure it passes consistently.

Thanks for taking the time to check out my post. Are you currently using Cypress in your day-to-day work? What are some of the tests you have written so far? Have you discovered a better way to automate Kentico on your own? We love feedback, so feel free to leave a comment below!

Share This Post:

Twitter Pinterest Facebook Google+
Click here to read more Kentico posts
Start a Project with Us
Photo of the author, Tyler Pfohl

About the author

Tyler originates from the corn-filled land of Iowa and has loved technology since he was little. Originally he wanted to become a programmer but his older brother introduced him to the amazing world of QA in 2014. Ever since then, he has developed a hunger for ensuring high quality. His latest passion is using automation to quickly find issues on web pages. When he’s not making his computer work for him, you can usually find him playing video games, riding his bike, or trying a new craft beer.

View other posts by Tyler

Subscribe to Updates

Stay up to date on what BizStream is doing and keep in the loop on the latest with Kentico.