# AIlab-comparison-engine
Comparison Engine refactored from AIlab-UI-Diff using Object-Oriented Programming.
#### Setup
- install dependencies using `poetry lock` and `poetry install`
- create `.env` file with `API_KEY`
- run the virtual environment using `poetry shell`
- run the Flask server with `python app.py`
- go to `frontend` folder and install dependencies using `npm install`
- run the Node server with `node server.js`
- go to http://localhost:3000/compare
- select test case to compare
- run the comparison engine
- wait a few seconds
- select elements to display
On the next run, you can launch the comparison engine using `./run_servers.sh`
Give it execute permissions using `chmod +x run_servers.sh`
---
#### Endpoints
Backend (Flask)
- `/` [GET]: **docs**
- `/api/compare` [POST]: **json payload (diffs without DOM trees)**
- `/api/compare/preprocess` [POST]: **preprocess DOM trees**
- `/api/compare/detailed` [POST]: **detailed DOM trees**
- `/api/compare/layout` [POST]: **layout DOM trees**
Frontend (Node)
- `/compare` [GET]: **selection tool**
- `/compare` [POST]: **rendered results**
The Flask server is launched on port `8001`
The Node server is launched on port `3000`
---
#### Request
The request must be in JSON format (keys provided below).
In case of a missing URL for the DOM files, the algorithm will be changed to `pixel`.
You can pass data to the engine in 3 ways.
1. Provide the comparison ID and environment:
```json
{
"comparisonId": "z9WOyd9V",
"env": "prod"
}
```
2. Send test case containing required keys:
(`test_case_name` and `comparison_mode` are optional)
**The options for ``"algorithm"`` are ``"PIXEL"``, ``"DOM-ELEMENT"``, and ``"AI-MODEL"``.**
**Comparison using ``"AI-MODEL"`` will do pixel comparison as preprocessing.** So if the results from ``"AI-MODEL"`` look wierd, try ``"PIXEL"`` to see the diffs before model detection.
**For branch UIDIFF-114, ``"DOM-ELEMENT"`` is not recommended. Bugs may exist.**
```json
{
"test_case_name": "Example Page SB",
"options": {
"algorithm": "dom-element",
"moved_tolerance": "30",
"comparison_mode": "detailed"
},
"base_dom": "https://ailab.dev.visualtest.io/test-case-01-example-page-sb/base.json",
"target_dom": "https://ailab.dev.visualtest.io/test-case-01-example-page-sb/target.json",
"base_img": "https://ailab.dev.visualtest.io/test-case-01-example-page-sb/base.png",
"target_img": "https://ailab.dev.visualtest.io/test-case-01-example-page-sb/target.png"
}
```
3. Send a file (directly or via URL) containing a test case list and choose one in `/compare`.
---
#### Response
The response is in JSON format (keys provided below).
By default, there is no `elements` dictionary.
DOM elements are provided on separate endpoints.
```json
{
"diffs": {
"detailed": "detailed_diffs",
"layout": "layout_diffs",
},
"images": {
"base": {
"url": "base_img_file.img_url",
"height": "base_img_file.height",
"width": "base_img_file.width",
},
"target": {
"url": "target_img_file.img_url",
"height": "target_img_file.height",
"width": "target_img_file.width",
}
},
"elements": {
"preprocess": {
"base": "base_dom.preprocessed_dom_list",
"target": "target_dom.preprocessed_dom_list",
},
"detailed": {
"base": "base_dom.detailed_tree converted to list",
"target": "target_dom.detailed_tree converted to list",
},
"layout": {
"base": "base_dom.layout_tree converted to list",
"target": "target_dom.layout_tree converted to list",
}
},
"logs": {
"errors":"logs with level equal to error",
"warnings": "logs with level equal to warning",
"info": "logs with level equal to info",
"debug": "logs with level equal to debug",
},
"config": "the whole configuration",
"version": "number",
}
```
---
#### Diffs
All `elements` are converted into `detailed_diffs`.
This is necessary to display elements in the `comparison-view`.
`detailed_diffs` and `layout_diffs` share the same format as the following example:
```
[
{
"diff_type": "changed",
"base": {
"id": 0,
"tag": "IMG",
"top": 770,
"left": 592,
"width": 1072,
"height": 628,
"dom_id": 308,
"xpath": "/HTML[1]/BODY[1]/DIV[3]",
"css_selector": " > HTML#1 > BODY#39 > DIV#73.pt_saspage inline-flow"
},
"target": {
"id": 0,
"tag": "IMG",
"top": 772,
"left": 592,
"width": 1072,
"height": 674,
"dom_id": 304,
"xpath": "/HTML[1]/BODY[1]/DIV[3]",
"css_selector": " > HTML#1 > BODY#36 > DIV#70.pt_saspage inline-flow"
},
"similarity_score": 0.689,
"sensitivity": "null for detailed diff and value range in [0, 1, 2] for layout diff", ,
"description": [
"Element content changed",
"Element height grew 46px"
],
"ignore": false
},
{
"diff_type": "added",
"base": {},
"target": {
"id": 31,
"tag": "DIV",
"top": 2736,
"left": 548,
"width": 2360,
"height": 754,
"dom_id": 558,
"xpath": "/HTML[1]/BODY[1]/DIV[3]/MAIN[1]",
"css_selector": " > HTML#1 > BODY#36 > DIV#70.pt_saspage inline-flow > MAIN#228.clearfix"
},
"similarity_score": null,
"sensitivity": "null for detailed diff and value range in [0, 1, 2] for layout diff",
"description": [
"Element was added"
],
"ignore": false
}
]
```