# Welcome to de-test docs
Here you can learn how to get 100% of the **detest** library power. Check out the API including all the test types. For a live example visit [detest example](https://github.com/MikeyZat/detest-example).
## Table of contents
* [API format](#api-format)
* [Global settings](#global-settings)
- [name](#name)
- [url](#url)
- [debug](#debug)
- [timeout](#timeout)
* [CLI](#cli)
* [Test cases](#test-cases)
+ [Local settings](#local-settings)
- [url](#url-1)
- [run](#run)
- [width](#width)
- [height](#height)
* [Test types](#test-types)
+ [Styles](#styles)
- [selector](#selector)
- [xpath](#xpath)
- [Any css style property](#any-css-style-property)
+ [Layout](#layout)
- [selector or xpath](#selector-or-xpath)
- [position](#position)
- [contains](#contains)
* [Enhanced test types](#enhanced-test-types)
+ [Contrast](#contrast)
* [Output](#output)
* [Utilities](#utilities)
+ [Nested test cases](#nested-test-cases)
+ [Using common components frameworks](#using-common-components-frameworks)
## API format
All the tests options are configured using a `yaml` format (usually in a `detest.yaml` file). It should be easy to read for anyone but if you need more guidance, check out [YAML tutorial](https://www.cloudbees.com/blog/yaml-tutorial-everything-you-need-get-started).
## Global settings
These settings have effect on all test scenarios. You can always override them using [CLI](#cli) or [local settings](#local-settings).
#### name
type: `String`
You can specify name for all test cases. This is for display/organization purpose only and will be shown in test output.
```yaml
name: Design testing of local app
```
#### url
type: `String`
You must specify the tested web application starting point. This is required for detest to work correctly.
```yaml
url: localhost:3000
# or
url: https://www.youtube.com
```
#### debug
type: `Boolean`
You can turn on this flag in order to see the debug logs which might help you find out the reason for tests failure.
```yaml
debug: True
```
#### timeout
type: `Number`
You can specify the timeout (in milliseconds) for puppeteer methods. Defaults to `15000ms`.
```yaml
timeout: 5000
```
## CLI
Using Command Line Interface you can set (or override) any of the global settings options:
```bash
detest -u localhost:3000 --debug
```
Additionally, you specify the detest configuration file name (defaults to `detest.yaml`):
```bash
detest -c another-set-of-tests.yaml
```
If you need more information, use the `-h` or `--help` option:
```bash
detest -h
```
## Test cases
In this section you specify the actual test suites that `detest` library should run on your web application. You start it with the `tests: ` keyword and follow with the array of test scenarios. Each of the test suites has its `type`, set of `local settings` and usually array of `test-cases` to run.
```yaml
tests:
- name: Home page on desktop
type: styles
test_cases:
- selector: ".App"
text-align: center
display: block
# ...
- name: Home page on mobile
type: layout
width: 375
run: False
test_cases:
# ...
```
### Local settings
For each test suite you can override **any** of the [global settings](#global-settings). In addition you can specify:
#### url
type: `String`
You can use relative paths to create url for specific test scenario:
```yaml
url: "/pricing"
# will resolve to localhost:3000/pricing
# if global url is localhost:3000
```
#### run
type `Boolean`
You can set it to `False` in order to omit this test suite. It's useful for debugging & *tdd* approach.
```yaml
run: False
```
#### width
type: `Number`
Browser width size (in px) that the Puppeteer will use when running this test scenario. Especially useful for testing RWD of your web application.
```yaml
width: 375
```
#### height
type: `Number`
Browser height size (in px) that the Puppeteer will use when running this test scenario.
```yaml
height: 800
```
## Test types
For each test scenario you specify its `type`. Each of them is followed by `test_cases` where you can write your test cases using a proper API (according to the test type). Different test types are used for various purposes, so check out their descriptions below.
```yaml
- type: styles
test_cases:
- selector: ".App"
color: "#fafafa"
```
### Styles
This test type is meant to check if:
1. specific elements exist on the page
2. elements **visible styles** match design expectations
Each of the `test_case` has following attributes:
#### selector
type: `String`
Allows you to identify the html page element you want to test. Anything that works for `document.querySelector()` function will work here.
#### xpath
type: `String`
Alternative way to identify the tested element. However, the **selector** (if passed) is always preferred to **xpath**.
#### Any css style property
type: `String | Number`
Then you specify any style you expect the tested element to have. Detest will verify the actual, styles visible on the page, not these that are put in css files.
Example:
```yaml
test_cases:
- selector: ".App"
text-align: center
display: block
- selector: "#root > div > div > img"
color: "rgb(255,255,255)"
- xpath: '//*[@id="root"]/div/div'
background-color: "#282c34"
width: "1600px"
color: white
```
### Layout
This test type is meant to check if:
1. specific element can be found on exact (x,y) position on the page
2. there is a correct number of specific elements on the page (or inside another element e.g. header)
Each of the `test_case` has following attributes:
#### selector or xpath
Same role as [here](#selector).
#### position
type: `{ x: Number, y: Number }`
Optional: Verify if the element is visible on the page, on position (x, y).
#### contains
type: `Array<{ selector/xpath: String, count?: Number }>`
Optional: It checks if each of elements in the array (identified either by selector or xpath) is presented `count` times within the **main element**. If `count` is omitted, it's set to 1 by default.
Example:
```yaml
test_cases:
- selector: header
position:
x: 0
y: 20
contains:
- selector: a
count: 3
- selector: .MuiTypography-h6
- selector: main
contains:
- selector: .MuiCard-root
count: 3
```
## Enhanced test types
This test types allow you to automatically verify your web application design, without specifying any `test-cases`. However, their local settings API is the same as for normal test types.
### Contrast
This test type is meant to validate contrast ratio of all the text elements on the page according to WCAG2.0.
```yaml
- name: Test contrast ratio for pricing page
type: contrast
url: /pricing
```
## Output
The final output includes:
1. Test names
```bash
INFO [2021-09-22 20:58:39.874 +0200]: Starting test case suite: Home page on desktop
```
2. Information of each test case evaluation
```bash
# Subtest: [STYLES SERVICE]: Checking element: .App
ok 1 - check if element .App exists
ok 2 - compare if element .App styles match
1..2
ok 1 - [STYLES SERVICE]: Checking element: .App # time=11.157ms
```
3. Debug logs (if `debug: True`)
```bash
DEBUG [2021-09-22 21:03:06.745 +0200]: Returning browser reference as its already launched
```
4. Tests summary
```bash
TESTS SUMMARY
TOTAL TEST CASES RUN:
88
TOTAL TEST CASES PASSED:
88
TOTAL TEST CASES FAILED:
0
SUCCESS RATIO
100.00%
```
In case of test failure you will see the difference between expectations and actual value found on the page:
```bash
not ok 2 - compare if element .App styles match
---
diff: |
--- expected
+++ actual
@@ -1,4 +1,4 @@
Object {
"text-align": "center",
- "display": "inline",
+ "display": "block",
}
```
In this case, we expected `display: inline` but `display: block` was found instead.
## Utilities
A couple of utilities that might help you in everyday test writing.
### Nested test cases
Applies for test types: `styles, layout`
New attributes: `inside`, `isDirectChild`
Suppose that you have following html structure:
```html
<div id="free">
<div class="MuiCardHeader-root">...</div>
<div class="MuiCardHeader-content">
<h2>$0</h2>
<div>
<div>
<button>Sign up for free</button>
</div>
</div>
```
then instead of repeating the `#free` selector everytime like this:
```yaml
- selector: "#free"
height: 332
- selector: "#free > .MuiCardHeader-root"
padding: 16
background-color: "#eee"
- selector: "#free h2"
font-size: 48
font-family: "Roboto, Helvetica, Arial, sans-serif"
- selector: "#free button"
color: "#3f51b5"
```
you can use the `inside` attribute to test all descendant of `#free` element like this:
```yaml
- selector: "#free"
height: 332
inside:
- selector: ".MuiCardHeader-root"
isDirectChild: True
padding: 16
background-color: "#eee"
- selector: "h2"
font-size: 48
font-family: "Roboto, Helvetica, Arial, sans-serif"
- selector: "button"
color: "#3f51b5"
```
The `isDirectChild` (defaults to `False`) specifies that an element is direct child of its parent. In case of selector it's equivalent to : `$parentSelector > $childSelector`.
You can also nest `xpath` in the same way as `selector`!
Nesting level is **not** limited to one, you can nest your tests **how many times you want!**
### Using common components frameworks
Detest has additional support for following UI components frameworks/libraries:
- [Material UI](https://mui.com/)
- [Bootstrap v.5](https://getbootstrap.com/)
If you are using one of them, you can specify it in the global config:
```yaml
global:
# ...
UI_framework: material
# or
# UI_framework: bootstrap
```
Now instead of specifying a detailed selector/xpath for every element you would like to test, you can use the **component name** (camel cased) and it will be automatically mapped to a proper selector.
Example:
```yaml
- name: Pricing tab on desktop
type: styles
test_cases:
- selector: "bar"
width: 1600
height: 64
background-color: "#3f51b5"
- selector: "#pro"
height: 356
inside:
- selector: "cardHeader"
padding: 16
background-color: "#eee"
- name: Welcome page layout desktop
type: layout
test_cases:
- selector: main
contains:
- selector: "outlinedInput"
count: 2
```