1.7.3 • Published 1 year ago

enjoy-qa v1.7.3

Weekly downloads
-
License
MIT
Repository
-
Last release
1 year ago

What is enjoy-qa?

enjoy-qa is a library designed for everyone working on QA automation of web projects. One of the most popular frameworks to create end-to-end or UI integration tests is Cypress. Cypress has a great documentaion on their website. But still assumes you are familiar with JavaScript to some extent.

But what if you're not? Here enjoy-qa comes into play. It lets you write your automation instructions in a human readable format and then converts them into valid Cypress commands.

enjoy-qa requires 0 background of JavaScript to automate web QA process with Cypress. Let's make it possible to write automation tests for everyone in your team.

How does it work?

  1. Create any plain text file (let's call it my-example.enjoy);
  2. Type the following instructions:
  find .primary-cta-button
  run
    text is Save
  done
  1. Run ./node_modules/enjoy-qa/bin/index.js -i my-example.enjoy -o my-example.enjoy.output;
  2. Open the file my-example.enjoy.output with Cypress instructions generated;
  cy.get('.primary-cta-button')
    .should('have.text', 'Save');
  1. Add these instructions to your existing Cypress project or send them to QA engineers who work with Cypress API directly;
  2. No tabs or spaces in the beginning of a new line is required (but the examples below would have them for readability);
  3. Save output file as a commonjs export (since v1.7.0)
  Run `./node_modules/enjoy-qa/bin/index.js -i my-example.enjoy -o my-example.enjoy.js -as commonjs`;

Detailed explanation (aka API).

Searching for elements.

99% of cases every enjoy-qa file would start with find command that lets you search for any valid CSS selector on a web page to apply some actions/checks to that. By default it returns a set of all found elements on a web page.

Example

Let's say there is the following html markup:

<form class="account-creation">
  ...
  <button class="cta">Submit</button>
  ...
  <div>Some text goes here</div>
  <div>Yet another text goes here</div>
</form>

You need to apply some checks for the button element with the class cta. Then the button can be found as:

  find .account-creation .cta

Example

Let's say there is the following html markup:

<form class="account-creation">
  ...
  <button class="cta">Submit</button>
  ...
  <div>Some text goes here</div>
  <div>Yet another text goes here</div>
</form>

You need to find all div elements inside of the account-creation form. Then those div elements can be found as:

  find .account-creation div

Example

Let's say there is the following html markup:

<form class="account-creation">
  ...
  <button class="cta">Submit</button>
  ...
  <div>Some text goes here</div>
  <div>Yet another text goes here</div>
</form>

You need to access the second found div element inside of the account-creation form. That div element can be found as:

  find 2 .account-creation div

Number after find selects a certain element from the ones being found.

##Assess found elements. Once you've found the elements to be tested the following instructions can be used to do that.

  run
    some assessment instructions go here
  done

run is always applied to the last element(s) found with find. To do actual tests you can use any of the following assessment instructions inside of

  run
    some assessment instructions go here
  done
  • text is Hello - (fixed in 1.6.0) checks that a found element has the text Hello;

Example

Test that all elements with the class cta have text Hello world

  find .cta
  run
    text is Hello world
  done

Example (since 1.5.0)

Test that all elements with the class cta have text Hello world! (surrounded by empty characters).

  find .cta
  run
    text is < Hello world! >
  done

Test that all elements with the class cta have text <<<Hello world>>>!

  find .cta
  run
    text is < <<<Hello world>>>! >
  done
  • disabled is true|false - checks that found elements have (do not have) attribute disabled (useful for html button or input tags);
  • checked is true|false - checks that found elements have (do not have) attribute checked (useful for checkbox or radio buttons);
  • attr_<valid_html_attribute_name> is 123 - checks that found elements have html attribute valid_html_attribute_name with the value 123;

Example

Let's say there is the following html markup:

<ul class="list">
  <li class="item" data-type="item">One</li>
  <li class="item" data-type="item">Two</li>
  <li class="item" data-type="item">Three</li>
</ul>

Test that each element with the class item has the attribute data-type="item"

find .list .item
run
  attr_data-type is item
done
  • value = 123 - (fixed in 1.5.2) does not check anything but sets the value attribute of an input to 123 (used with html input tags);
  • offset from <number> .parent-css-class is 8;7 - checks that found elements are shifted by 8 pixels to the right and 7 pixels to the bottom from .parent-css-class element; Since v1.7.0 it is also possible to pass an optional parameter <number> (any natural number) to calculate offset from a certain element in collection of element.

Example (since v1.7.0)

Let's say there is the following html markup:

<ul class="list">
  <li class="item">One</li>
  <li class="item"><input type="checkbox" class="js-box" /> Two</li>
  <li class="item">Three</li>
</ul>

We assume that the offset of the checkbox js-box from its' parent - the second li tag is 4 pixels left and 4 pixels top;

find .list
run
  offset from 2 .item is 4;4
done

Example

Let's say there is the following html markup:

<div class="wrapper">
  <div data-user-info>
    Some user information...
  </div>
</div>

We assume that the offset of the section data-user-info from the element with wrapper class is 16 pixels left and 12 pixels top;

  find [data-user-info]
  run
    offset from .wrapper is 16;12
  done
  • not_to_exist - (since 1.4.0) checks that found elements are not present on a page (are not a part of the HTML structure);

Example

Let's say there is the following html markup:

  <div class="wrapper">
    <button type="button" class="js-cta">Show Greetings</button>
  </div>

Once the button is pressed the html structure becomes the following:

  <div class="wrapper">
    <button type="button" class="js-cta">Show Greetings</button>
    <div class="js-greeting greeting">Hello my friend!</div>
  </div>

The initial absense of the element with the class js-greeting should be tested. It can be done as follows:

find .js-greeting
run
  not_to_exist
done

Then after the js-cta button is clicked the greeting section appears.

find .js-cta
run
  trigger click
    find .js-greeting
    run
      text Hello my friend!
    done
  done
done

Any other assessment instruction will be treated as a css property check, i.e. a css property name. Example

Let's say there is the following html markup:

<div class="cta"></div>

To test that the element has a 2-pixel border the following instructions can be used:

  find .cta
  run
    border is 2px solid red
  done

##Working with events. Once we've found the elements to be tested the following instructions can be used to emulate a user behavior by dispatching events to those elements. So far enjoy-qa supports the following list of UI events:

  • mousedown - dispatches mousedown event to an element;
  • mouseup - dispatches mouseup event to an element;
  • click - clicks on an element;
  • focus - sets a focus into an element (if possible);
  • blur - puts a focus away from an element;
  • submit - submits an html form;
  • select - chooses an option with a certain value from a selectbox;
  • check - (fixed in v1.7.3)checks a box or a radio button;
  • uncheck - (fixed in 1.7.3) unchecks a box or a radio button;
  • input - (since 1.6.0, fixed in 1.6.1) dispatches input event to an element (useful for input fields);

To work with events the following instructions can be used:

run
  ...
  trigger <ui_event_name>
    ...
  done
  ...
done

Pay attention that

  trigger
    ...
  done

clause should be surrounded by

  run
    ...
  done

It can not stand alone;

Another set of

  run
    ...
  done

instructions can be executed inside of

  trigger
    ...
  done

Example (fixed in 1.5.1)

An event is always dispatched only to the first found element in a set. Let's say there is the following html markup:

  <button type="button" class="js-cta">Red button</button>
  <button type="button" class="js-cta">Green button</button>
  <button type="button" class="js-cta">Blue button</button>

We need to click each element with the class js-cta. The following instructions will dispatch click event to the first found js-cta element only.

  find .js-cta
  run
    trigger click
      ...
    done
  done

To dispatch click event to other buttons you can either add a unique css class to each of those, or use find <number> .js-cta command that was introduced previously.

Example

Let's say there is the following html markup:

  <button class="text-ctrl" data-text="red" type="button">
    Change label
  </button>
  <label class="text">
    Red Text
  </label>
  <label class="text">
    Yellow Text
  </label>

When we click on the button text-ctrl the second label text (with the text "Yellow Text") should change its' text to "Blue Text". The following instructions can be used to test this case:

  find .text-ctrl
  run
    trigger click
      find 2 .text
      run
        text is Blue Text
      done
    done
  done

Example

Let's say there is the following html markup:

  <select class="numbers">
    <option value="1">One</option>
    <option value="2">One</option>
    <option value="3">One</option>
  </select>
  <button class="counter" type="button">
    Next
  </button>

Every time the button with the class counter is clicked an option that has the value attribute with the serial number of click should be selected. The following instructions can be used to test this case:

  find .counter
  run
    trigger click
    done
  done

  find .numbers
  run
    trigger select 1
    done
  done

  find .counter
  run
    trigger click
    done
  done

  find .numbers
  run
    trigger select 2
    done
  done

  find .counter
  run
    trigger click
    done
  done

  find .numbers
  run
    trigger select 3
    done
  done

##Timers Timers might come into handy especially if you need to wait for some time until animation is done or a status update appears on a page after the backend responds back, etc. To work with timers the following instruction can be used:

wait <number>

to wait for of milliseconds or

wait <number> s

to wait for of seconds. It is important to keep in mind that wait <number> [s] can not run between find and run ... done instructions. It should go either before those or afterwards.

Example

Let's say there is the following html markup:

  <select class="numbers">
    <option value="1">One</option>
    <option value="2">One</option>
    <option value="3">One</option>
  </select>
  <button class="counter" type="button">
    Next
  </button>

Once the button with the class counter is clicked each option in selectbox numbers is chosen from the first to the last with an interval of 400 milliseconds between selection. The following instructions can be used to test this case:

  find .counter
  run
    trigger click
    done
  done

  find .numbers
  run
    trigger select 1
    done
  done

  wait 400

  find .numbers
  run
    trigger select 2
    done
  done

  wait 400

  find .numbers
  run
    trigger select 3
    done
  done

##define & apply (since 1.3.0) define & apply instructions might come into handy especially if you have a set of rules that have to be applied multiple times to different parts of the test suite.

define is there to initialize a set of tests that would be invoked later with apply within any of

  run
    ...
  done

instructions.

You can not declare event-based instructions inside of define at the moment though. But any assessment-based instructions (is or =) are allowed.

Example

Let's say there is the following html markup:

  <button type="button" class="js-cta">
    Click me
  </button>

Once the button is focused it has to have a solid #0953b4 border of 2px and a background-color of #1e79f1. Once the button loses its' focus (= receives a blur event) it has to have a solid #4897ff border of 2px and a background-color of #8bbdff. Without define & apply the following instructions can be used to test this case:

  find .js-cta
  run
    border is 2px solid #4897ff
    background-color is #8bbdff

    trigger focus
      find .js-cta
      run
        border is 2px solid #0953b4
        background-color is #1e79f1
      done
    done

    trigger blur
      find .js-cta
      run
        border is 2px solid #4897ff
        background-color is #8bbdff
      done
    done
  done

With define & apply the same test can be achieved as follows:

  define default-cta
    border is 2px solid #4897ff
    background-color is #8bbdff
  done

  define focused-cta
    border is 2px solid #0953b4
    background-color is #1e79f1
  done

  find .js-cta
  run
    apply_default-cta

    trigger focus
      find .js-cta
      run
        apply_focused-cta
      done
    done

    trigger blur
      find .js-cta
      run
        apply_default-cta
      done
    done
  done

##Imports (since v1.7.0) Once your enjoy-qa file becomes too large it might make sense to split that into separate files. To achieve that you can use the following instruction:

import
  ...
done

Example

Let's assume there is a file called home_page.enjoy that has the following instructions:

  find .wrapper
  run
    background-color is #f8f8f8
    max-width is 500px
  done

  find .wrapper .primary-cta
  run
    border is 1px solid #999
    background-color is #eee
    color is #338
  done

  find .wrapper .secondary-cta
  run
    border is 1px solid #aaa
    color is #040404
  done

What we could do to reduce the size of home_page.enjoy file and improve its' readibility is reorganize its' content in the following way:

  • create another directory called cta_buttons;
  • create a separate file for each button (primary-cta.enjoy and secondary-cta.enjoy) inside of that directory;

./cta_buttons/primary-cta.enjoy:

  find .wrapper .primary-cta
  run
    border is 1px solid #999
    background-color is #eee
    color is #338
  done

./cta_buttons/secondary-cta.enjoy:

  find .wrapper .secondary-cta
  run
    border is 1px solid #aaa
    color is #040404
  done

The contents of home_page.enjoy would become the following:

  find .wrapper
  run
    background-color is #f8f8f8
    max-width is 500px
  done

  import
    ./cta_buttons/primary-cta.enjoy
    ./cta_buttons/secondary-cta.enjoy
  done

Whenever enjoy-qa comes across the following instructions

import
  ./cta_buttons/primary-cta.enjoy
  ./cta_buttons/secondary-cta.enjoy
done
  • it builds the path to each of the files relatively to the home_page.enjoy file;
  • it reads the contents of each of those;
  • home_page.enjoy is treated as if it didn't have import ... done instructions at all;

Please keep in mind that cyclic dependencies are not allowed, i.e. you can not import ./cta_buttons/primary-cta.enjoy from ./cta_buttons/secondary-cta.enjoy and at the same time ./cta_buttons/secondary-cta.enjoy from ./cta_buttons/primary-cta.enjoy.

##Single line comments (since v1.7.0) Let's assume there are following instructions:

  define default-cta
    border is 2px solid #4897ff
    background-color is #8bbdff
  done

  define focused-cta
    border is 2px solid #0953b4
    background-color is #1e79f1
  done

  find .js-cta
  run
    apply_default-cta

    trigger focus
      find .js-cta
      run
        apply_focused-cta
      done
    done

    trigger blur
      find .js-cta
      run
        apply_default-cta
      done
    done
  done

Starting from the version 1.7.0 enjoy-qa provides a way of adding single line comments to your instructions:

  # Set of css styles for default button state;
  define default-cta
    border is 2px solid #4897ff
    background-color is #8bbdff
  done

A comment line should always start with the sharp sign # and could consist of any unicode character.

Keep in mind that each comment line should have its' own # at the beginning, i.e. you can not span a single line of comments over several ones just by appending a new line character.

The following will generate an error:

  # Set of css styles for default button state;
  the comment is improperly spanned over two lines;

  define default-cta
    border is 2px solid #4897ff
    background-color is #8bbdff
  done

Comments will be translated into valid single line JavaScript comments in the output.

Please keep in mind that single line comments can be used inside of any block of instructions except for

import
  ...
done

Example

  define default-cta
    # border is 2px solid #4897ff ---> will turn into // border is 2px solid #4897ff
    # background-color is #8bbdff ---> will turn into // background-color is #8bbdff
  done

  # define focused-cta ---> will generate an error message since the name of the instruction was commented out
    border is 2px solid #0953b4
    background-color is #1e79f1
  done

  # find .js-cta ---> will generate an error message about unexpected token "run" followed below
  run
    # apply_default-cta ---> will work properly, generating // apply_default-cta

    trigger focus
      find .js-cta
      run
        apply_focused-cta
      done
    done

    trigger blur
      find .js-cta
      run
        # appling a set of css rules specifically for ---> will work properly
        # default button state once blur is fired; ---> will work properly
        apply_default-cta
      done
    done
  done

  import
    # ./another_set_of_rules ----> will generate an error as a try to load the file "# ./another_set_of_rules"
  done

  # But will work perfectly fine commented out altogether;
  #import
    #./another_set_of_rules
  #done
1.7.3

1 year ago

1.7.2

1 year ago

1.7.1

1 year ago

1.7.0

1 year ago

1.6.1

1 year ago

1.5.2

1 year ago

1.6.0

1 year ago

1.5.1

1 year ago

1.5.0

1 year ago

1.4.1

1 year ago

1.4.0

1 year ago

1.3.1

1 year ago

1.3.0

1 year ago

1.2.0

1 year ago

1.1.0

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago