enjoy-qa
v1.7.3
Published
create your cypress test automation scripts with easy-to-use human readable commands
Downloads
27
Maintainers
Readme
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?
- Create any plain text file (let's call it
my-example.enjoy
); - Type the following instructions:
find .primary-cta-button
run
text is Save
done
- Run
./node_modules/enjoy-qa/bin/index.js -i my-example.enjoy -o my-example.enjoy.output
; - Open the file
my-example.enjoy.output
with Cypress instructions generated;
cy.get('.primary-cta-button')
.should('have.text', 'Save');
- Add these instructions to your existing Cypress project or send them to QA engineers who work with Cypress API directly;
- No tabs or spaces in the beginning of a new line is required (but the examples below would have them for readability);
- 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 textHello
;
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 attributevalid_html_attribute_name
with the value123
;
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 to123
(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
andsecondary-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 haveimport ... 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