Flashtest is Javascript library for generating tests written with jest and puppeteer. You just interact with UI as a usual user and test is generated for you!
- For now library exposes only component for React users.
- Library was tested only in Chrome.
- It is experimental library and wasn't tested properly yet on real projects. So it may have bugs in generated code.
-
Tests generated by library check real work of your whole application by testing
the most significant things:
changes to the DOM and requests. -
You can create a lot of tests for different scenarious in short time.
This library generates test written with jest and puppeteer. So first you need to setup jest and puppeteer to work together, otherwise you will not be able to run generated tests. There is awesome jest-puppeteer for this.
After you set up jest with puppeteer run:
npm i flashtest --save-dev
import { CollectorComponent } from "flashtest";
// your usual App component
const App = () => (
// ...
);
const RenderedApp = () => (
// wrapping your usual App component with CollectorComponent.
// CollectorComponent renders helper window.
// This window allows to interact with library in convenient way
<CollectorComponent>
<App />
</CollectorComponent>
);
ReactDOM.render(<RenderedApp />, document.getElementById("app"));
interaction elements
(these elements are alsotesteable
): buttons, inputs, textareas, clickable divs and so on;testeable elements
: divs, spans and so on;
The rule of thumb is: first add data-hook
attribute to your interaction elements
, because if you miss to add data-hook
attribute to interaction element
, and then interact
with this element you will get broken code. Now there is no way to detect this wrong usage before
actual test generating.
Run two scripts:
- Your actual React app with
CollectorComponent
- If you set
saveToFs
to true inCollectorComponent
props, you need to run backend part:npm run flashtest-sever
Just open your page, and interact with elements.
When you finished all your interactions press Finish
button in helper window. If test is successfully generated you will
get corresponding message in helper window. Generated code is output to console or saved to file depending on saveToFs
prop of CollectorComponent.
When you got generated code in test file just run it,
if it passes - good!
If test fails at once after generating check next things:
- Your jest puppeteer setup, to check this one just create simple test with jest and puppeteer and run it.
- Check if you added
data-hook
attribute to allinteraction elements
you interacted with. - If you use async requests, check if data sent by backend didn't change.
- Check sections Async requests, Usage rules and Current Support
If these things are fine, it means that more likely there is a bug in library. Feel free to create issue!
There is example repo.
if set to true
, request will be sent to backend part
and generated code will be saved in file.
If you set saveToFs
to true
and didn't run backend part, code will be output to console.
if set to true
, comments will be added to generated code. These comments just help you to understand code.
path to folder where generated tests will be saved, is relative to app root folder.
This prop will be ignored if saveToFs
is false
.
port where backend part is running.
Note: serverPort
should equal to -p
arg passed to flashtest-server
!
if set to true
, responses will be mocked with puppeteer's request.respond.
If contentType
header of response starts with image
, such response will not be mocked.
You can run backend part with npm run flashtest-server
- it is needed only if you set saveToFs
to true
.
By default express server will run on 3000 port. If you want to change port, specify -p
arg:
npm run flashtest-server -p 3333
Note: -p
arg should equal to serverPort prop of CollectorComponent!
Library tracks requests which are sent with only fetch, if you use XMLHttpRequest library will just miss these requests.
HTMLElement
was only checked,SVGElement
and others weren't checked yet.- Special buttons such as
Esc
,Backspace
and similar ones aren't supported yet. - Body of request isn't checked in tests, only url and method are checked.
- Url change isn't supported. If you want to create test for particular url, go to this url, reload page and start
interacting process
from scratch. - HTMLElement with
contentEditable
attribute isn't handled properly yet, so generated code will be broken if you use this element and adddata-hook
attribute to it. - Change to following elements aren't checked in generated code:
input[type="checkbox"]
,input[type="radio"]
andselect
because in these cases DOM isn't changed.
-
When you start to add
data-hook
attribute, pay great attention tointeraction elements
(input, button, textarea, clickable divs...), because if you forget to adddata-hook
attribute to these elements and interact with them during test generating, generated test will be broken. -
Add
data-hook
to yourtesteable elements
as lowest as possible, try to avoid wrapping static text where it is possible. It is needed to avoid putting useless info in generated code.Example of bad usage:
<div data-hook="some-data-hook-name"> Some static text <span> [value that changes when some button is clicked] </span> </div>
Example of good usage:
<div> Some static text <span data-hook="some-data-hook-name"> [value that changes when some button is clicked] </span> </div>
One more example of good usage:
div
andspan
both havedata-hook
attribute, it may be needed ifdiv
element for example has some DOM attribute(e.g.className
) that changes dynamically:<div data-hook="some-div-data-hook-name" className="[dynamic-className]"> Some static text <span data-hook="some-span-data-hook-name"> [value that changes when some button is clicked] </span> </div>
-
When you did some action that led to sending request(for example clicked submit button), don't do any other actions until request is finished. If you do, code generating will more likely end up with error, or generated code will be broken.
You will get corresponding warning in helper window if you break this rule.
-
Don't change url, url change isn't supported yet.
You will get corresponding warning in helper window if you break this rule.
-
Make all
data-hook
attributes unique.You will get corresponding warning in helper window if you break this rule.
-
When you click on
input
/textarea
element, before entering value please wait 1 second. If you start to enter value too fast, order of triggered events is unusual. This point is planned to be automated in future, but now please keep in mind it.You will get corresponding warning in helper window if you break this rule.
In this section
Element
means HTMLElement withdata-hook
attribute.
-
If
Element
has children which areinteraction elements
and content of thisElement
is changed, this change will not be tracked by library, it is needed to reduce size of tested html.
Consider this piece of code:<div data-hook="div"> [input value] <input data-hook="input" /> </div>
When user typed value in input, only attribute value of input will be checked, but outerHTML of div will not be checked.
If you want to check this one, it should be:<div data-hook="div"> <span data-hook="input value">[input value]</span> <input data-hook="input" /> </div>
Note: it is not related to case when HTMLElement is added to the DOM, in this case outerHTML of added HTMLElement will be checked despite of its children.
-
If
Element
is added to the DOM, outerHTML is checked in tests.
If content ofElement
changed(TextNode changed/added), innerHTML is checked in tests. -
If
Element
is added to the DOM, and there are children of this element with data-hook attribute, library will search children with data-hook attribute of the most nested sub-trees and check outerHTML of them.
Example: When nextElement
is added to the DOM:<div data-hook="root-div"> <span data-hook="span1">Some text</span> <div data-hook="div1"> <div data-hook="div1-nested"> <span data-hook="span2">Some text2</span> </div> </div> <div data-hook="div2"> <input data-hook="input" value="val" /> </div> </div>
outerHTML of next elements will be checked in tests:
[data-hook="span1"]
,[data-hook="span2"]
,[data-hook="input"]
. -
If TextNode is changed and direct parentElement doesn't have data-hook attribute, this change will not be checked in tests. If you want to track this change, add data-hook attribute to direct parent of TextNode.
Change to span WILL NOT be checked in code:
<div data-hook="div"> <span>[input value]</span> <input data-hook="input" /> </div>
Change to span IS GOING to be checked in code:
<div data-hook="div"> <span data-hook="span">[input value]</span> <input data-hook="input" /> </div>
Flashtest is MIT licensed.