add snapshot testing (#2438)

* add snapshot testing

* bump ci image

* tweak

* tweak

* fix gitgignore

* fix gitgignore

* dedicated snapshot script

* clean up tests

* tweaks

* fix ci

* fix script

* oops

* fix
This commit is contained in:
pngwn 2022-10-12 17:30:42 +01:00 committed by GitHub
parent 3a2de9b415
commit ed4f3e4ffd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 179 additions and 3284 deletions

View File

@ -22,7 +22,7 @@ concurrency:
jobs:
quick-checks:
name: static checks
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.1
@ -54,11 +54,11 @@ jobs:
cache: pnpm
cache-dependency-path: ui/pnpm-lock.yaml
- run: pip install -r ../requirements.txt
- run: pip install -r ../demo/outbreak_forecast/requirements.txt
- run: pip install gradio
- run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install chromium
- run: pnpm build
- run: pnpm test:browser
- run: pnpm test:browser:full
- name: Upload failed tests screenshots
if: failure()
uses: actions/upload-artifact@v3

2
.gitignore vendored
View File

@ -26,6 +26,7 @@ gradio_cached_examples/
.coverage
coverage.xml
test.txt
**/snapshots/**/*.png
# Demos
demo/tmp.zip
@ -33,6 +34,7 @@ demo/files/*.avi
demo/files/*.mp4
demo/all_demos/demos/*
demo/all_demos/requirements.txt
demo/*/config.json
# Etc
.idea/*

View File

@ -1,302 +0,0 @@
{
"version": "3.1.4",
"mode": "blocks",
"dev_mode": true,
"components": [
{
"id": 1,
"type": "textbox",
"props": {
"lines": 2,
"max_lines": 20,
"value": "",
"label": "Input",
"show_label": true,
"name": "textbox",
"visible": true,
"style": {}
}
},
{
"id": 2,
"type": "textbox",
"props": {
"lines": 1,
"max_lines": 20,
"value": "",
"label": "Input 2",
"show_label": true,
"name": "textbox",
"visible": true,
"style": {}
}
},
{
"id": 3,
"type": "textbox",
"props": {
"lines": 1,
"max_lines": 20,
"value": "",
"label": "Output",
"show_label": true,
"name": "textbox",
"visible": true,
"style": {}
}
},
{
"id": 4,
"type": "button",
"props": {
"value": "Submit",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
},
{
"id": 5,
"type": "row",
"props": {
"type": "row",
"visible": true,
"style": {}
}
},
{
"id": 6,
"type": "image",
"props": {
"image_mode": "RGB",
"source": "upload",
"tool": "editor",
"streaming": false,
"mirror_webcam": true,
"show_label": true,
"name": "image",
"visible": true,
"style": {}
}
},
{
"id": 7,
"type": "image",
"props": {
"image_mode": "RGB",
"source": "upload",
"tool": "editor",
"streaming": false,
"mirror_webcam": true,
"show_label": true,
"name": "image",
"visible": true,
"style": {}
}
},
{
"id": 8,
"type": "button",
"props": {
"value": "Mirror Image",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
},
{
"id": 9,
"type": "markdown",
"props": {
"value": "<h2>Text Examples</h2>\n",
"name": "markdown",
"visible": true,
"style": {}
}
},
{
"id": 10,
"type": "dataset",
"props": {
"components": [
"textbox",
"textbox"
],
"headers": [
"Input",
"Input 2"
],
"samples": [
[
"hi",
"Adam"
],
[
"hello",
"Eve"
]
],
"type": "index",
"name": "dataset",
"visible": true,
"style": {}
}
},
{
"id": 11,
"type": "markdown",
"props": {
"value": "<h2>Image Examples</h2>\n",
"name": "markdown",
"visible": true,
"style": {}
}
},
{
"id": 12,
"type": "dataset",
"props": {
"components": [
"image"
],
"headers": [],
"samples": [
[
"lion.jpg"
]
],
"type": "index",
"name": "dataset",
"visible": true,
"style": {}
}
}
],
"theme": "default",
"css": null,
"title": "Gradio",
"enable_queue": false,
"layout": {
"id": 0,
"children": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
},
{
"id": 4
},
{
"id": 5,
"children": [
{
"id": 6
},
{
"id": 7
}
]
},
{
"id": 8
},
{
"id": 9
},
{
"id": 10
},
{
"id": 11
},
{
"id": 12
}
]
},
"dependencies": [
{
"targets": [
4
],
"trigger": "click",
"inputs": [
1,
2
],
"outputs": [
3
],
"backend_fn": true,
"js": null,
"queue": null,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
},
{
"targets": [
8
],
"trigger": "click",
"inputs": [
6
],
"outputs": [
7
],
"backend_fn": true,
"js": null,
"queue": null,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
},
{
"targets": [
10
],
"trigger": "click",
"inputs": [
10
],
"outputs": [
1,
2,
3
],
"backend_fn": true,
"js": null,
"queue": false,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
},
{
"targets": [
12
],
"trigger": "click",
"inputs": [
12
],
"outputs": [
6,
7
],
"backend_fn": true,
"js": null,
"queue": false,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
}
]
}

View File

@ -1,128 +0,0 @@
{
"version": "3.1.4",
"mode": "blocks",
"dev_mode": true,
"components": [
{
"id": 1,
"type": "markdown",
"props": {
"value": "<p>Let's do some kinematics! Choose the speed and angle to see the trajectory.</p>\n",
"name": "markdown",
"visible": true,
"style": {}
}
},
{
"id": 2,
"type": "row",
"props": {
"type": "row",
"visible": true,
"style": {}
}
},
{
"id": 3,
"type": "slider",
"props": {
"minimum": 1,
"maximum": 30,
"step": 0.1,
"value": 25,
"label": "Speed",
"show_label": true,
"name": "slider",
"visible": true,
"style": {}
}
},
{
"id": 4,
"type": "slider",
"props": {
"minimum": 0,
"maximum": 90,
"step": 0.1,
"value": 45,
"label": "Angle",
"show_label": true,
"name": "slider",
"visible": true,
"style": {}
}
},
{
"id": 5,
"type": "plot",
"props": {
"show_label": true,
"name": "plot",
"visible": true,
"style": {}
}
},
{
"id": 6,
"type": "button",
"props": {
"value": "Run",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
}
],
"theme": "default",
"css": null,
"title": "Gradio",
"enable_queue": false,
"layout": {
"id": 0,
"children": [
{
"id": 1
},
{
"id": 2,
"children": [
{
"id": 3
},
{
"id": 4
}
]
},
{
"id": 5
},
{
"id": 6
}
]
},
"dependencies": [
{
"targets": [
6
],
"trigger": "click",
"inputs": [
3,
4
],
"outputs": [
5
],
"backend_fn": true,
"js": null,
"": null,
"queue": null,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
}
]
}

View File

@ -1,325 +0,0 @@
{
"mode": "blocks",
"components": [
{
"id": 1,
"type": "column",
"props": {
"type": "column",
"variant": "default",
"css": {},
"default_value": true
}
},
{
"id": 2,
"type": "textbox",
"props": {
"lines": 1,
"max_lines": 20,
"default_value": "",
"label": "Small Textbox",
"show_label": false,
"name": "textbox",
"css": {}
}
},
{
"id": 3,
"type": "textbox",
"props": {
"lines": 5,
"max_lines": 20,
"default_value": "",
"label": "Large Textbox",
"show_label": false,
"name": "textbox",
"css": {}
}
},
{
"id": 4,
"type": "number",
"props": {
"label": "Number",
"show_label": false,
"name": "number",
"css": {}
}
},
{
"id": 5,
"type": "checkbox",
"props": {
"default_value": false,
"label": "Checkbox",
"show_label": false,
"name": "checkbox",
"css": {}
}
},
{
"id": 6,
"type": "checkboxgroup",
"props": {
"choices": [
"One",
"Two",
"Three"
],
"default_value": [],
"label": "Checkbox Group",
"show_label": false,
"name": "checkboxgroup",
"css": {}
}
},
{
"id": 7,
"type": "radio",
"props": {
"choices": [
"One",
"Two",
"Three"
],
"default_value": "One",
"label": "Radio",
"show_label": false,
"name": "radio",
"css": {}
}
},
{
"id": 8,
"type": "dropdown",
"props": {
"choices": [
"One",
"Two",
"Three"
],
"default_value": "One",
"label": "Dropdown",
"show_label": false,
"name": "dropdown",
"css": {}
}
},
{
"id": 9,
"type": "slider",
"props": {
"minimum": 0,
"maximum": 100,
"step": 1,
"default_value": 0,
"label": "Slider",
"show_label": false,
"name": "slider",
"css": {}
}
},
{
"id": 10,
"type": "audio",
"props": {
"source": "upload",
"show_label": false,
"name": "audio",
"css": {}
}
},
{
"id": 11,
"type": "file",
"props": {
"file_count": "single",
"show_label": false,
"name": "file",
"css": {}
}
},
{
"id": 12,
"type": "video",
"props": {
"source": "upload",
"show_label": false,
"name": "video",
"css": {}
}
},
{
"id": 13,
"type": "image",
"props": {
"image_mode": "RGB",
"source": "upload",
"tool": "editor",
"show_label": false,
"name": "image",
"css": {}
}
},
{
"id": 14,
"type": "timeseries",
"props": {
"show_label": false,
"name": "timeseries",
"css": {}
}
},
{
"id": 15,
"type": "dataframe",
"props": {
"datatype": "str",
"row_count": 1,
"col_count": 3,
"default_value": [
[
"",
"",
""
],
[
"",
"",
""
],
[
"",
"",
""
]
],
"max_rows": 20,
"overflow_row_behaviour": "paginate",
"show_label": false,
"name": "dataframe",
"css": {}
}
},
{
"id": 16,
"type": "html",
"props": {
"default_value": "",
"show_label": false,
"name": "html",
"css": {}
}
},
{
"id": 17,
"type": "json",
"props": {
"default_value": "\"\"",
"show_label": false,
"name": "json",
"css": {}
}
},
{
"id": 18,
"type": "markdown",
"props": {
"default_value": "",
"name": "markdown",
"css": {}
}
},
{
"id": 19,
"type": "label",
"props": {
"show_label": false,
"name": "label",
"css": {}
}
},
{
"id": 20,
"type": "highlightedtext",
"props": {
"show_legend": false,
"default_value": "",
"show_label": false,
"name": "highlightedtext",
"css": {}
}
}
],
"theme": "default",
"enable_queue": false,
"layout": {
"id": 0,
"children": [
{
"id": 1,
"children": [
{
"id": 2
},
{
"id": 3
},
{
"id": 4
},
{
"id": 5
},
{
"id": 6
},
{
"id": 7
},
{
"id": 8
},
{
"id": 9
},
{
"id": 10
},
{
"id": 11
},
{
"id": 12
},
{
"id": 13
},
{
"id": 14
},
{
"id": 15
},
{
"id": 16
},
{
"id": 17
},
{
"id": 18
},
{
"id": 19
},
{
"id": 20
}
]
}
]
},
"dependencies": []
}

View File

@ -1,68 +0,0 @@
{
"version": "3.1.4",
"mode": "blocks",
"dev_mode": true,
"components": [
{
"id": 1,
"type": "textbox",
"props": {
"lines": 1,
"max_lines": 20,
"value": "Frank",
"label": "Name",
"show_label": true,
"name": "textbox",
"visible": true,
"style": {}
}
},
{
"id": 2,
"type": "textbox",
"props": {
"lines": 1,
"max_lines": 20,
"value": "",
"label": "Output",
"show_label": true,
"name": "textbox",
"visible": true,
"style": {}
}
}
],
"theme": "default",
"css": null,
"title": "Gradio",
"enable_queue": false,
"layout": {
"id": 0,
"children": [
{
"id": 1
},
{
"id": 2
}
]
},
"dependencies": [
{
"targets": [],
"trigger": "load",
"inputs": [
1
],
"outputs": [
2
],
"backend_fn": true,
"js": false,
"queue": null,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
}
]
}

View File

@ -1,114 +0,0 @@
{
"version": "3.0.6",
"mode": "blocks",
"dev_mode": true,
"components": [
{
"id": 1,
"type": "variable",
"props": {
"value": 0,
"show_label": true,
"name": "variable",
"visible": true,
"style": {}
}
},
{
"id": 2,
"type": "number",
"props": {
"value": 0.0,
"show_label": true,
"name": "number",
"visible": true,
"style": {
"text_color": "blue",
"container_bg_color": "yellow"
}
}
},
{
"id": 3,
"type": "button",
"props": {
"value": "Next Square",
"variant": "secondary",
"name": "button",
"visible": true,
"elem_id": "btn",
"style": {
"rounded": false,
"bg_color": "purple"
}
}
},
{
"id": 4,
"type": "variable",
"props": {
"value": {
"a": "a"
},
"show_label": true,
"name": "variable",
"visible": true,
"style": {}
}
},
{
"id": 5,
"type": "json",
"props": {
"show_label": true,
"name": "json",
"visible": true,
"style": {}
}
}
],
"theme": "default",
"css": "#btn {color: red}",
"enable_queue": false,
"layout": {
"id": 0,
"children": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
},
{
"id": 4
},
{
"id": 5
}
]
},
"dependencies": [
{
"targets": [
3
],
"trigger": "click",
"inputs": [
1,
4
],
"outputs": [
1,
2,
4,
5
],
"backend_fn": true,
"js": null,
"queue": null
}
]
}

View File

@ -1,354 +0,0 @@
{
"version": "3.1.4",
"mode": "blocks",
"dev_mode": true,
"components": [
{
"id": 1,
"type": "markdown",
"props": {
"value": "<h1>Detect Disease From Scan</h1>\n<p>With this model you can lorem ipsum</p>\n<ul>\n<li>ipsum 1</li>\n<li>ipsum 2</li>\n</ul>\n",
"name": "markdown",
"visible": true,
"style": {}
}
},
{
"id": 2,
"type": "checkboxgroup",
"props": {
"choices": [
"Covid",
"Malaria",
"Lung Cancer"
],
"value": [],
"label": "Disease to Scan For",
"show_label": true,
"name": "checkboxgroup",
"visible": true,
"style": {}
}
},
{
"id": 3,
"type": "tabs",
"props": {
"visible": true,
"style": {}
}
},
{
"id": 4,
"type": "tabitem",
"props": {
"label": "X-ray",
"visible": true,
"style": {}
}
},
{
"id": 5,
"type": "row",
"props": {
"type": "row",
"visible": true,
"style": {}
}
},
{
"id": 6,
"type": "image",
"props": {
"image_mode": "RGB",
"source": "upload",
"tool": "editor",
"streaming": false,
"mirror_webcam": true,
"show_label": true,
"name": "image",
"visible": true,
"style": {}
}
},
{
"id": 7,
"type": "json",
"props": {
"show_label": true,
"name": "json",
"visible": true,
"style": {}
}
},
{
"id": 8,
"type": "button",
"props": {
"value": "Run",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
},
{
"id": 9,
"type": "statustracker",
"props": {
"cover_container": true,
"name": "statustracker",
"visible": true,
"style": {}
}
},
{
"id": 10,
"type": "tabitem",
"props": {
"label": "CT Scan",
"visible": true,
"style": {}
}
},
{
"id": 11,
"type": "row",
"props": {
"type": "row",
"visible": true,
"style": {}
}
},
{
"id": 12,
"type": "image",
"props": {
"image_mode": "RGB",
"source": "upload",
"tool": "editor",
"streaming": false,
"mirror_webcam": true,
"show_label": true,
"name": "image",
"visible": true,
"style": {}
}
},
{
"id": 13,
"type": "json",
"props": {
"show_label": true,
"name": "json",
"visible": true,
"style": {}
}
},
{
"id": 14,
"type": "button",
"props": {
"value": "Run",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
},
{
"id": 15,
"type": "statustracker",
"props": {
"cover_container": true,
"name": "statustracker",
"visible": true,
"style": {}
}
},
{
"id": 16,
"type": "button",
"props": {
"value": "Upload Results",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
},
{
"id": 17,
"type": "statustracker",
"props": {
"cover_container": false,
"name": "statustracker",
"visible": true,
"style": {}
}
}
],
"theme": "default",
"css": null,
"title": "Gradio",
"enable_queue": false,
"layout": {
"id": 0,
"children": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3,
"children": [
{
"id": 4,
"children": [
{
"id": 5,
"children": [
{
"id": 6
},
{
"id": 7
}
]
},
{
"id": 8
},
{
"id": 9
}
]
},
{
"id": 10,
"children": [
{
"id": 11,
"children": [
{
"id": 12
},
{
"id": 13
}
]
},
{
"id": 14
},
{
"id": 15
}
]
}
]
},
{
"id": 16
},
{
"id": 17
}
]
},
"dependencies": [
{
"targets": [
8
],
"trigger": "click",
"inputs": [
2,
6
],
"outputs": [
7
],
"backend_fn": true,
"js": null,
"queue": null,
"api_name": "xray_model",
"scroll_to_output": false,
"show_progress": true,
"documentation": [
[
[
"list of selected choices",
"List[str]"
],
[
"base64 url data, or (if tool == \"sketch) a dict of image and mask base64 url data",
"str | Dict"
]
],
[
[
"JSON output",
"Dict | List | None"
]
]
]
},
{
"targets": [
14
],
"trigger": "click",
"inputs": [
2,
12
],
"outputs": [
13
],
"backend_fn": true,
"js": null,
"queue": null,
"api_name": "ct_model",
"scroll_to_output": false,
"show_progress": true,
"documentation": [
[
[
"list of selected choices",
"List[str]"
],
[
"base64 url data, or (if tool == \"sketch) a dict of image and mask base64 url data",
"str | Dict"
]
],
[
[
"JSON output",
"Dict | List | None"
]
]
]
},
{
"targets": [
16
],
"trigger": "click",
"inputs": [
13,
7
],
"outputs": [],
"backend_fn": true,
"js": null,
"queue": null,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
}
]
}

View File

@ -1,68 +0,0 @@
{
"version": "3.1.4",
"mode": "blocks",
"dev_mode": true,
"components": [
{
"id": 1,
"type": "textbox",
"props": {
"lines": 1,
"max_lines": 20,
"value": "",
"label": "Input-Output",
"show_label": true,
"name": "textbox",
"visible": true,
"style": {}
}
},
{
"id": 2,
"type": "button",
"props": {
"value": "Run",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
}
],
"theme": "default",
"css": null,
"title": "Gradio",
"enable_queue": false,
"layout": {
"id": 0,
"children": [
{
"id": 1
},
{
"id": 2
}
]
},
"dependencies": [
{
"targets": [
2
],
"trigger": "click",
"inputs": [
1
],
"outputs": [
1
],
"backend_fn": true,
"js": null,
"status_tracker": null,
"queue": null,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,457 +0,0 @@
{
"version": "3.1.4",
"mode": "interface",
"dev_mode": true,
"components": [
{
"id": 7,
"type": "row",
"props": {
"type": "row",
"visible": true,
"style": {
"equal_height": false,
"mobile_collapse": true
}
}
},
{
"id": 8,
"type": "column",
"props": {
"type": "column",
"variant": "panel",
"visible": true,
"style": {}
}
},
{
"id": 9,
"type": "column",
"props": {
"type": "column",
"variant": "default",
"visible": true,
"style": {}
}
},
{
"id": 0,
"type": "dropdown",
"props": {
"choices": [
"Matplotlib",
"Plotly",
"Bokeh"
],
"label": "Plot Type",
"show_label": true,
"name": "dropdown",
"visible": true,
"style": {}
}
},
{
"id": 1,
"type": "slider",
"props": {
"minimum": 1,
"maximum": 4,
"step": 0.01,
"value": 3.2,
"label": "R",
"show_label": true,
"name": "slider",
"visible": true,
"style": {}
}
},
{
"id": 2,
"type": "dropdown",
"props": {
"choices": [
"January",
"February",
"March",
"April",
"May"
],
"label": "Month",
"show_label": true,
"name": "dropdown",
"visible": true,
"style": {}
}
},
{
"id": 3,
"type": "checkboxgroup",
"props": {
"choices": [
"USA",
"Canada",
"Mexico",
"UK"
],
"value": [
"USA",
"Canada"
],
"label": "Countries",
"show_label": true,
"name": "checkboxgroup",
"visible": true,
"style": {}
}
},
{
"id": 4,
"type": "checkbox",
"props": {
"value": false,
"label": "Social Distancing?",
"show_label": true,
"name": "checkbox",
"visible": true,
"style": {}
}
},
{
"id": 10,
"type": "row",
"props": {
"type": "row",
"visible": true,
"style": {
"mobile_collapse": false
}
}
},
{
"id": 11,
"type": "button",
"props": {
"value": "Clear",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
},
{
"id": 12,
"type": "button",
"props": {
"value": "Submit",
"variant": "primary",
"name": "button",
"visible": true,
"style": {}
}
},
{
"id": 13,
"type": "column",
"props": {
"type": "column",
"variant": "panel",
"visible": true,
"style": {}
}
},
{
"id": 14,
"type": "statustracker",
"props": {
"cover_container": true,
"name": "statustracker",
"visible": true,
"style": {}
}
},
{
"id": 5,
"type": "plot",
"props": {
"label": "output",
"show_label": true,
"interactive": false,
"name": "plot",
"visible": true,
"style": {}
}
},
{
"id": 15,
"type": "row",
"props": {
"type": "row",
"visible": true,
"style": {
"mobile_collapse": false
}
}
},
{
"id": 16,
"type": "button",
"props": {
"value": "Flag",
"variant": "secondary",
"name": "button",
"visible": true,
"style": {}
}
},
{
"id": 17,
"type": "dataset",
"props": {
"components": [
"dropdown",
"slider",
"dropdown",
"checkboxgroup",
"checkbox"
],
"headers": [
"Plot Type",
"R",
"Month",
"Countries",
"Social Distancing?"
],
"samples": [
[
"Matplotlib",
2,
"March",
[
"Mexico",
"UK"
],
true
],
[
"Plotly",
3.6,
"February",
[
"Canada",
"Mexico",
"UK"
],
false
],
[
"Bokeh",
1.2,
"May",
[
"UK"
],
true
]
],
"type": "index",
"name": "dataset",
"visible": true,
"style": {}
}
}
],
"theme": "default",
"css": null,
"title": "Gradio",
"enable_queue": false,
"layout": {
"id": 6,
"children": [
{
"id": 7,
"children": [
{
"id": 8,
"children": [
{
"id": 9,
"children": [
{
"id": 0
},
{
"id": 1
},
{
"id": 2
},
{
"id": 3
},
{
"id": 4
}
]
},
{
"id": 10,
"children": [
{
"id": 11
},
{
"id": 12
}
]
}
]
},
{
"id": 13,
"children": [
{
"id": 14
},
{
"id": 5
},
{
"id": 15,
"children": [
{
"id": 16
}
]
}
]
}
]
},
{
"id": 17
}
]
},
"dependencies": [
{
"targets": [
12
],
"trigger": "click",
"inputs": [
0,
1,
2,
3,
4
],
"outputs": [
5
],
"backend_fn": true,
"js": null,
"queue": null,
"api_name": "predict",
"scroll_to_output": true,
"show_progress": true,
"documentation": [
[
[
"selected choice",
"str"
],
[
"numeric input",
"float"
],
[
"selected choice",
"str"
],
[
"list of selected choices",
"List[str]"
],
[
"boolean input",
"bool"
]
],
[
[
"plot type mapped to plot base64 data",
"Dict[str, str] | None"
]
]
]
},
{
"targets": [
11
],
"trigger": "click",
"inputs": [],
"outputs": [
0,
1,
2,
3,
4,
5,
9
],
"backend_fn": false,
"js": "() => [null, 3.2, null, [], null, null, {\"variant\": null, \"visible\": true, \"__type__\": \"update\"}]\n ",
"queue": null,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
},
{
"targets": [
16
],
"trigger": "click",
"inputs": [
0,
1,
2,
3,
4,
5
],
"outputs": [],
"backend_fn": true,
"js": null,
"queue": false,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
},
{
"targets": [
17
],
"trigger": "click",
"inputs": [
17
],
"outputs": [
0,
1,
2,
3,
4,
5
],
"backend_fn": true,
"js": null,
"status_tracker": null,
"queue": false,
"api_name": null,
"scroll_to_output": false,
"show_progress": true
}
]
}

View File

@ -1,7 +1,9 @@
import gradio as gr
from math import sqrt
import matplotlib
matplotlib.use('Agg')
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
import plotly.express as px
@ -17,41 +19,51 @@ def outbreak(plot_type, r, month, countries, social_distancing):
pop_count = {"USA": 350, "Canada": 40, "Mexico": 300, "UK": 120}
if social_distancing:
r = sqrt(r)
df = pd.DataFrame({'day': x})
df = pd.DataFrame({"day": x})
for country in countries:
df[country] = ( x ** (r) * (pop_count[country] + 1))
df[country] = x ** (r) * (pop_count[country] + 1)
if plot_type == "Matplotlib":
fig = plt.figure()
plt.plot(df['day'], df[countries].to_numpy())
plt.plot(df["day"], df[countries].to_numpy())
plt.title("Outbreak in " + month)
plt.ylabel("Cases")
plt.xlabel("Days since Day 0")
plt.legend(countries)
return fig
elif plot_type == "Plotly":
fig = px.line(df, x='day', y=countries)
fig.update_layout(title="Outbreak in " + month,
xaxis_title="Cases",
yaxis_title="Days Since Day 0")
fig = px.line(df, x="day", y=countries)
fig.update_layout(
title="Outbreak in " + month,
xaxis_title="Cases",
yaxis_title="Days Since Day 0",
)
return fig
else:
raise ValueError("A plot type must be selected")
inputs = [
gr.Dropdown(["Matplotlib", "Plotly"], label="Plot Type"),
gr.Slider(1, 4, 3.2, label="R"),
gr.Dropdown(["January", "February", "March", "April", "May"], label="Month"),
gr.CheckboxGroup(["USA", "Canada", "Mexico", "UK"], label="Countries",
value=["USA", "Canada"]),
gr.Checkbox(label="Social Distancing?"),
]
gr.Dropdown(["Matplotlib", "Plotly"], label="Plot Type"),
gr.Slider(1, 4, 3.2, label="R"),
gr.Dropdown(["January", "February", "March", "April", "May"], label="Month"),
gr.CheckboxGroup(
["USA", "Canada", "Mexico", "UK"], label="Countries", value=["USA", "Canada"]
),
gr.Checkbox(label="Social Distancing?"),
]
outputs = gr.Plot()
demo = gr.Interface(fn=outbreak, inputs=inputs, outputs=outputs, examples=[
demo = gr.Interface(
fn=outbreak,
inputs=inputs,
outputs=outputs,
examples=[
["Matplotlib", 2, "March", ["Mexico", "UK"], True],
["Plotly", 3.6, "February", ["Canada", "Mexico", "UK"], False],
], cache_examples=True)
],
cache_examples=True,
)
demo.launch()
if __name__ == "__main__":
demo.launch()

View File

@ -17,7 +17,7 @@
"ts:check": "svelte-check --tsconfig tsconfig.json",
"test": "vitest dev",
"test:run": "vitest run",
"test:browser": "pnpm --filter @gradio/app test:browser",
"test:browser": "pnpm --filter @gradio/app test:browser:full",
"test:browser:full": "run-s build test:browser",
"test:browser:debug": "pnpm --filter @gradio/app test:browser:debug"
},
@ -27,7 +27,7 @@
"private": true,
"dependencies": {
"@gradio/tootils": "workspace:^0.0.1",
"@playwright/test": "^1.24.2",
"@playwright/test": "^1.27.1",
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.44",
"@tailwindcss/forms": "^0.5.0",
"@testing-library/dom": "^8.11.3",
@ -39,7 +39,7 @@
"happy-dom": "^2.49.0",
"node-html-parser": "^5.3.3",
"npm-run-all": "^4.1.5",
"playwright": "^1.24.2",
"playwright": "^1.27.1",
"plotly.js-dist-min": "^2.10.1",
"polka": "^1.0.0-next.22",
"postcss": "^8.4.5",

View File

@ -8,7 +8,9 @@
"build:website": "vite build --mode production:website --emptyOutDir",
"build:local": "vite build --mode production:local --emptyOutDir",
"preview": "vite preview",
"test:browser": "python test/create_demo_configs.py && pnpm exec playwright test test/ --config=../../playwright.config.js",
"test:snapshot": "pnpm exec playwright test snapshots/ --config=../../playwright.config.js",
"test:browser": "pnpm exec playwright test test/ --config=../../playwright.config.js",
"test:browser:full": "python test/create_demo_configs.py && pnpm exec playwright test test/ --config=../../playwright.config.js",
"test:browser:debug": "pnpm exec playwright test test/ --debug --config=../../playwright.config.js"
},
"dependencies": {
@ -37,7 +39,6 @@
"@gradio/video": "workspace:^0.0.1",
"d3-dsv": "^3.0.1",
"mime-types": "^2.1.34",
"playwright": "^1.22.2",
"svelte-i18n": "^3.3.13"
}
}

View File

@ -0,0 +1,18 @@
import { test, expect, Page } from "@playwright/test";
function mock_demo(page: Page, demo: string) {
return page.route("**/config", (route) => {
return route.fulfill({
headers: {
"Access-Control-Allow-Origin": "*"
},
path: `../../../demo/${demo}/config.json`
});
});
}
test("blocks layout", async ({ page }) => {
await mock_demo(page, "blocks_layout");
await page.goto("http://localhost:3000");
await expect(page).toHaveScreenshot();
});

View File

@ -0,0 +1,18 @@
import { test, expect, Page } from "@playwright/test";
function mock_demo(page: Page, demo: string) {
return page.route("**/config", (route) => {
return route.fulfill({
headers: {
"Access-Control-Allow-Origin": "*"
},
path: `../../../demo/${demo}/config.json`
});
});
}
test("blocks xray", async ({ page }) => {
await mock_demo(page, "blocks_xray");
await page.goto("http://localhost:3000");
await expect(page).toHaveScreenshot();
});

View File

@ -0,0 +1,18 @@
import { test, expect, Page } from "@playwright/test";
function mock_demo(page: Page, demo: string) {
return page.route("**/config", (route) => {
return route.fulfill({
headers: {
"Access-Control-Allow-Origin": "*"
},
path: `../../../demo/${demo}/config.json`
});
});
}
test("kitchen sink", async ({ page }) => {
await mock_demo(page, "kitchen_sink");
await page.goto("http://localhost:3000");
await expect(page).toHaveScreenshot();
});

View File

@ -30,14 +30,17 @@ test("renders the correct elements", async ({ page }) => {
await mock_api(page, [["hi dawood"]]);
await page.goto("http://localhost:3000");
const textboxOne = await page.locator("label:has-text('Input')").first();
const textboxTwo = await page.locator("label:has-text('Input')").last();
const submit = await page.locator("text=Submit");
const textboxes = await page.getByLabel("Input");
const textboxOne = await textboxes.first();
const textboxTwo = await textboxes.last();
await textboxOne.fill("hi");
await textboxTwo.fill("dawood");
await Promise.all([submit.click(), page.waitForResponse("**/api/predict/")]);
await expect(await page.inputValue("label:has-text('Output')")).toEqual(
"hi dawood"
);
await Promise.all([
page.click('text="Submit"'),
page.waitForResponse("**/api/predict/")
]);
await expect(await page.getByLabel("Output")).toHaveValue("hi dawood");
});

View File

@ -30,6 +30,8 @@ test("renders the correct elements", async ({ page }) => {
await mock_api(page, [[25, 45]]);
await page.goto("http://localhost:3000");
const button = await page.locator("button");
await Promise.all([button.click(), page.waitForResponse("**/api/predict/")]);
await Promise.all([
page.click("button"),
page.waitForResponse("**/api/predict/")
]);
});

View File

@ -30,13 +30,11 @@ test("renders the correct elements", async ({ page }) => {
await mock_api(page, [["Welcome! This page has loaded for Frank"]]);
await page.goto("http://localhost:3000");
const textbox = await page.locator("label:has-text('Name')");
const textbox = await page.getByLabel("Name");
await textbox.fill("Frank");
await expect(await page.inputValue("label:has-text('Name')")).toEqual(
"Frank"
);
await expect(await page.inputValue("label:has-text('Output')")).toEqual(
await expect(await textbox).toHaveValue("Frank");
await expect(await page.getByLabel("Output")).toHaveValue(
"Welcome! This page has loaded for Frank"
);
});

View File

@ -32,7 +32,7 @@ test("renders the correct elements", async ({ page }) => {
const description = await page.locator(".output-markdown");
await expect(description).toContainText("Detect Disease From Scan");
const checkboxes = await page.locator("data-testid=checkbox-group");
const checkboxes = await page.getByTestId("checkbox-group");
await expect(checkboxes).toContainText("Covid Malaria Lung Cancer");
const tabs = await page.locator("button", { hasText: /X-ray|CT Scan/ });
@ -58,8 +58,8 @@ test("can run an api request and display the data", async ({ page }) => {
await page.goto("http://localhost:3000");
await page.check("label:has-text('Covid')");
await page.check("label:has-text('Lung Cancer')");
await page.getByLabel("Covid").check();
await page.getByLabel("Lung Cancer").check();
const run_button = await page.locator("button", { hasText: /Run/ }).first();
@ -68,6 +68,6 @@ test("can run an api request and display the data", async ({ page }) => {
page.waitForResponse("**/api/predict/")
]);
const json = await page.locator("data-testid=json").first();
const json = await page.getByTestId("json").first();
await expect(json).toContainText(`Covid: 0.75, Lung Cancer: 0.25`);
});

View File

@ -1,10 +1,23 @@
import os
import subprocess
demo_names = set()
snapshots_dir = os.path.join(os.path.dirname(__file__), "../snapshots")
for f in os.listdir(os.path.dirname(__file__)):
if ".spec.ts" in f:
split_tup = f.split(".")
command = f'python ../../../../demo/write_config.py {split_tup[0]} ../../../../demo/{split_tup[0]}/config.json'
process = subprocess.Popen(command.split(), stdout=subprocess.PIPE, cwd=os.path.dirname(__file__))
output, error = process.communicate()
demo_names.add(f.split(".")[0])
for f in os.listdir(snapshots_dir):
if ".spec.ts" in f and not os.path.isdir(os.path.join(snapshots_dir, f)):
demo_names.add(f.split(".")[0])
for demo in demo_names:
print("Generating demo: " + demo)
command = f"python ../../../../demo/write_config.py {demo} ../../../../demo/{demo}/config.json"
process = subprocess.Popen(
command.split(), stdout=subprocess.PIPE, cwd=os.path.dirname(__file__)
)
output, error = process.communicate()

View File

@ -30,12 +30,12 @@ test("a component acts as both input and output", async ({ page }) => {
await mock_api(page, [["tset"]]);
await page.goto("http://localhost:3000");
const textbox = await page.locator("label:has-text('Input-Output')");
const button = await page.locator("button");
const textbox = await page.getByLabel("Input-Output");
await textbox.fill("test");
await Promise.all([button.click(), page.waitForResponse("**/api/predict/")]);
await expect(await page.inputValue("label:has-text('Input-Output')")).toEqual(
"tset"
);
await Promise.all([
page.click("button"),
page.waitForResponse("**/api/predict/")
]);
await expect(await textbox).toHaveValue("tset");
});

View File

@ -30,17 +30,17 @@ test("test inputs", async ({ page }) => {
await mock_demo(page, "kitchen_sink");
await page.goto("http://localhost:3000");
const textbox = await page.locator("label:has-text('Textbox')").nth(0);
const textbox = await page.getByLabel("Textbox").nth(0);
await expect(textbox).toHaveValue("Lorem ipsum");
await textbox.fill("hello world");
await expect(textbox).toHaveValue("hello world");
const textbox2 = await page.locator("label:has-text('Textbox 2')");
const textbox2 = await page.getByLabel("Textbox 2");
await textbox2.fill("hello world");
await expect(textbox2).toHaveValue("hello world");
const number = await page.locator("label:has-text('Number')");
const number = await page.getByLabel("Number");
await expect(number).toHaveValue("42");
await number.fill("10");
await expect(number).toHaveValue("10");
@ -218,10 +218,10 @@ test("test outputs", async ({ page }) => {
page.waitForResponse("**/api/predict/")
]);
const textbox = await page.locator("label:has-text('Textbox')").nth(2);
const textbox = await page.getByLabel("Textbox").nth(2);
await expect(textbox).toHaveValue("the quick brown fox, selected:foo, baz");
const label = await page.locator("data-testid=label");
const label = await page.getByTestId("label");
await expect(label).toContainText(`negative
negative
46%
@ -231,10 +231,10 @@ test("test outputs", async ({ page }) => {
15%`);
const highlight_text_color_map = await page
.locator("data-testid=highlighted-text")
.getByTestId("highlighted-text")
.nth(0);
const highlight_text_legend = await page
.locator("data-testid=highlighted-text")
.getByTestId("highlighted-text")
.nth(1);
await expect(highlight_text_color_map).toContainText(
" HighlightedText The art quick brown adj fox nn jumped vrb testing testing testing over prp the art testing lazy adj dogs nn . punc test 0 test 0 test 1 test 1 test 2 test 2 test 3 test 3 test 4 test 4 test 5 test 5 test 6 test 6 test 7 test 7 test 8 test 8 test 9 test 9"

View File

@ -30,17 +30,13 @@ test("matplotlib", async ({ page }) => {
await mock_demo(page, "outbreak_forecast");
await mock_api(page, [[{ type: "matplotlib", plot: BASE64_PLOT_IMG }]]);
await page.goto("http://localhost:3000");
await page
.locator("text=Plot Type MatplotlibPlotlyBokeh >> select")
.selectOption("Matplotlib");
await page
.locator("text=Month JanuaryFebruaryMarchAprilMay >> select")
.selectOption("January");
await page.locator('label:has-text("Social Distancing?")').click();
const submit_button = await page.locator("text=Submit");
await page.getByLabel("Plot Type").selectOption("Matplotlib");
await page.getByLabel("Month").selectOption("January");
await page.getByLabel("Social Distancing?").check();
await Promise.all([
submit_button.click(),
page.click("text=Submit"),
page.waitForResponse("**/api/predict/")
]);
@ -60,17 +56,13 @@ test("plotly", async ({ page }) => {
]
]);
await page.goto("http://localhost:3000");
await page
.locator("text=Plot Type MatplotlibPlotlyBokeh >> select")
.selectOption("Plotly");
await page
.locator("text=Month JanuaryFebruaryMarchAprilMay >> select")
.selectOption("January");
await page.locator('label:has-text("Social Distancing?")').click();
const submit_button = await page.locator("text=Submit");
await page.getByLabel("Plot Type").selectOption("Plotly");
await page.getByLabel("Month").selectOption("January");
await page.getByLabel("Social Distancing?").check();
await Promise.all([
submit_button.click(),
page.click("text=Submit"),
page.waitForResponse("**/api/predict/")
]);
await expect(page.locator(".js-plotly-plot")).toHaveCount(1);

59
ui/pnpm-lock.yaml generated
View File

@ -5,7 +5,7 @@ importers:
.:
specifiers:
'@gradio/tootils': workspace:^0.0.1
'@playwright/test': ^1.24.2
'@playwright/test': ^1.27.1
'@sveltejs/vite-plugin-svelte': ^1.0.0-next.44
'@tailwindcss/forms': ^0.5.0
'@testing-library/dom': ^8.11.3
@ -18,7 +18,7 @@ importers:
happy-dom: ^2.49.0
node-html-parser: ^5.3.3
npm-run-all: ^4.1.5
playwright: ^1.24.2
playwright: ^1.27.1
plotly.js-dist-min: ^2.10.1
polka: ^1.0.0-next.22
postcss: ^8.4.5
@ -38,7 +38,7 @@ importers:
vitest: ^0.12.7
dependencies:
'@gradio/tootils': link:packages/tootils
'@playwright/test': 1.24.2
'@playwright/test': 1.27.1
'@sveltejs/vite-plugin-svelte': 1.0.0-next.44_svelte@3.49.0+vite@2.9.5
'@tailwindcss/forms': 0.5.0_tailwindcss@3.1.6
'@testing-library/dom': 8.11.3
@ -50,7 +50,7 @@ importers:
happy-dom: 2.49.0
node-html-parser: 5.3.3
npm-run-all: 4.1.5
playwright: 1.24.2
playwright: 1.27.1
plotly.js-dist-min: 2.11.1
polka: 1.0.0-next.22
postcss: 8.4.6
@ -104,7 +104,6 @@ importers:
'@gradio/video': workspace:^0.0.1
d3-dsv: ^3.0.1
mime-types: ^2.1.34
playwright: ^1.22.2
svelte-i18n: ^3.3.13
dependencies:
'@gradio/atoms': link:../atoms
@ -132,7 +131,6 @@ importers:
'@gradio/video': link:../video
d3-dsv: 3.0.1
mime-types: 2.1.34
playwright: 1.22.2
svelte-i18n: 3.3.13
packages/atoms:
@ -393,7 +391,7 @@ importers:
'@gradio/upload': link:../upload
'@gradio/video': link:../video
devDependencies:
'@sveltejs/adapter-auto': 1.0.0-next.80
'@sveltejs/adapter-auto': 1.0.0-next.82
'@sveltejs/kit': 1.0.0-next.318
autoprefixer: 10.4.2_postcss@8.4.6
postcss: 8.4.6
@ -560,13 +558,13 @@ packages:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.13.0
/@playwright/test/1.24.2:
resolution: {integrity: sha512-Q4X224pRHw4Dtkk5PoNJplZCokLNvVbXD9wDQEMrHcEuvWpJWEQDeJ9gEwkZ3iCWSFSWBshIX177B231XW4wOQ==}
/@playwright/test/1.27.1:
resolution: {integrity: sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==}
engines: {node: '>=14'}
hasBin: true
dependencies:
'@types/node': 17.0.14
playwright-core: 1.24.2
playwright-core: 1.27.1
dev: false
/@polka/url/1.0.0-next.21:
@ -580,12 +578,12 @@ packages:
estree-walker: 2.0.2
picomatch: 2.3.1
/@sveltejs/adapter-auto/1.0.0-next.80:
resolution: {integrity: sha512-352WoZr9fQgxJqgNENvxRr2gsA+wTF6V9AVaQaaatDYd3RVEBaXTYOOalFaRLSa25mRUJaLYP2aaliqczMl23g==}
/@sveltejs/adapter-auto/1.0.0-next.82:
resolution: {integrity: sha512-TWckpkD7fLwwNcHHN7gDuV+xpu07NJ6aaMa6p9FgeFF16yBeEyGVtsM2bpujjS+u0w6IP4VGsRWEMOOF2b/WYA==}
dependencies:
'@sveltejs/adapter-cloudflare': 1.0.0-next.38
'@sveltejs/adapter-netlify': 1.0.0-next.78
'@sveltejs/adapter-vercel': 1.0.0-next.77
'@sveltejs/adapter-netlify': 1.0.0-next.80
'@sveltejs/adapter-vercel': 1.0.0-next.78
transitivePeerDependencies:
- encoding
- supports-color
@ -599,16 +597,16 @@ packages:
worktop: 0.8.0-next.14
dev: true
/@sveltejs/adapter-netlify/1.0.0-next.78:
resolution: {integrity: sha512-Yyn/j/0QcLK3Db442ducLUZmyvkO74j7Gdcwu9xN0fQN3kBlCJP9Itx5o4SySrPFGc4Q8cLJ5ELNg+mWduLBAA==}
/@sveltejs/adapter-netlify/1.0.0-next.80:
resolution: {integrity: sha512-L7Y3hXenJwmPbuzG+o8eUPm/6F3KpHHPUKRgoryYKgVjYGEHt1y1Go1k0JF6Tww8WF59y/j+ljWcBo9RU7MpeQ==}
dependencies:
'@iarna/toml': 2.2.5
esbuild: 0.15.7
set-cookie-parser: 2.4.8
dev: true
/@sveltejs/adapter-vercel/1.0.0-next.77:
resolution: {integrity: sha512-r4MqtP+lzx83HfcvI8PU0Yxzmxt6WQq9nzZETLboJouJzhSBUFIN5RmNZfEn6nNIlUwZbGQUEK/FxsRnnxI/Ig==}
/@sveltejs/adapter-vercel/1.0.0-next.78:
resolution: {integrity: sha512-K7zOlVwX/MV/b6iUbrY7QVn+v8ABBSEi6rjIfYiXCZc+j0nS5WNrcH1/Qdk/pzxK+7O5OuaNZAw3QylJDV5CZw==}
dependencies:
'@vercel/nft': 0.22.0
esbuild: 0.15.7
@ -2851,34 +2849,19 @@ packages:
engines: {node: '>=4'}
dev: false
/playwright-core/1.22.2:
resolution: {integrity: sha512-w/hc/Ld0RM4pmsNeE6aL/fPNWw8BWit2tg+TfqJ3+p59c6s3B6C8mXvXrIPmfQEobkcFDc+4KirNzOQ+uBSP1Q==}
/playwright-core/1.27.1:
resolution: {integrity: sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==}
engines: {node: '>=14'}
hasBin: true
dev: false
/playwright-core/1.24.2:
resolution: {integrity: sha512-zfAoDoPY/0sDLsgSgLZwWmSCevIg1ym7CppBwllguVBNiHeixZkc1AdMuYUPZC6AdEYc4CxWEyLMBTw2YcmRrA==}
engines: {node: '>=14'}
hasBin: true
dev: false
/playwright/1.22.2:
resolution: {integrity: sha512-hUTpg7LytIl3/O4t0AQJS1V6hWsaSY5uZ7w1oCC8r3a1AQN5d6otIdCkiB3cbzgQkcMaRxisinjMFMVqZkybdQ==}
/playwright/1.27.1:
resolution: {integrity: sha512-xXYZ7m36yTtC+oFgqH0eTgullGztKSRMb4yuwLPl8IYSmgBM88QiB+3IWb1mRIC9/NNwcgbG0RwtFlg+EAFQHQ==}
engines: {node: '>=14'}
hasBin: true
requiresBuild: true
dependencies:
playwright-core: 1.22.2
dev: false
/playwright/1.24.2:
resolution: {integrity: sha512-iMWDLgaFRT+7dXsNeYwgl8nhLHsUrzFyaRVC+ftr++P1dVs70mPrFKBZrGp1fOKigHV9d1syC03IpPbqLKlPsg==}
engines: {node: '>=14'}
hasBin: true
requiresBuild: true
dependencies:
playwright-core: 1.24.2
playwright-core: 1.27.1
dev: false
/plotly.js-dist-min/2.11.1: