diff --git a/.github/workflows/ui.yml b/.github/workflows/ui.yml index 1b9b428f61..06c06920a1 100644 --- a/.github/workflows/ui.yml +++ b/.github/workflows/ui.yml @@ -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 diff --git a/.gitignore b/.gitignore index 7040a04949..5b4c770ba5 100644 --- a/.gitignore +++ b/.gitignore @@ -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/* diff --git a/demo/blocks_inputs/config.json b/demo/blocks_inputs/config.json deleted file mode 100644 index fe4342ff47..0000000000 --- a/demo/blocks_inputs/config.json +++ /dev/null @@ -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": "
Let's do some kinematics! Choose the speed and angle to see the trajectory.
\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 - } - ] -} \ No newline at end of file diff --git a/demo/blocks_outputs/config.json b/demo/blocks_outputs/config.json deleted file mode 100644 index f76ac02dc7..0000000000 --- a/demo/blocks_outputs/config.json +++ /dev/null @@ -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": [] -} \ No newline at end of file diff --git a/demo/blocks_page_load/config.json b/demo/blocks_page_load/config.json deleted file mode 100644 index 7051c6e8ee..0000000000 --- a/demo/blocks_page_load/config.json +++ /dev/null @@ -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 - } - ] -} \ No newline at end of file diff --git a/demo/blocks_simple_squares/config.json b/demo/blocks_simple_squares/config.json deleted file mode 100644 index 7f48639594..0000000000 --- a/demo/blocks_simple_squares/config.json +++ /dev/null @@ -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 - } - ] -} \ No newline at end of file diff --git a/demo/blocks_xray/config.json b/demo/blocks_xray/config.json deleted file mode 100644 index b4cdad3be5..0000000000 --- a/demo/blocks_xray/config.json +++ /dev/null @@ -1,354 +0,0 @@ -{ - "version": "3.1.4", - "mode": "blocks", - "dev_mode": true, - "components": [ - { - "id": 1, - "type": "markdown", - "props": { - "value": "With this model you can lorem ipsum
\nTry out all the components!
", - "name": "markdown", - "visible": true, - "style": {} - } - }, - { - "id": 35, - "type": "row", - "props": { - "type": "row", - "visible": true, - "style": { - "equal_height": false, - "mobile_collapse": true - } - } - }, - { - "id": 36, - "type": "column", - "props": { - "type": "column", - "variant": "panel", - "visible": true, - "style": {} - } - }, - { - "id": 37, - "type": "column", - "props": { - "type": "column", - "variant": "default", - "visible": true, - "style": {} - } - }, - { - "id": 0, - "type": "textbox", - "props": { - "lines": 1, - "max_lines": 20, - "value": "Lorem ipsum", - "label": "Textbox", - "show_label": true, - "name": "textbox", - "visible": true, - "style": {} - } - }, - { - "id": 1, - "type": "textbox", - "props": { - "lines": 3, - "max_lines": 20, - "placeholder": "Type here..", - "value": "", - "label": "Textbox 2", - "show_label": true, - "name": "textbox", - "visible": true, - "style": {} - } - }, - { - "id": 2, - "type": "number", - "props": { - "value": 42.0, - "label": "Number", - "show_label": true, - "name": "number", - "visible": true, - "style": {} - } - }, - { - "id": 3, - "type": "slider", - "props": { - "minimum": 10, - "maximum": 20, - "step": 0.1, - "value": 15, - "label": "Slider: 10 - 20", - "show_label": true, - "name": "slider", - "visible": true, - "style": {} - } - }, - { - "id": 4, - "type": "slider", - "props": { - "minimum": 0, - "maximum": 20, - "step": 0.04, - "value": 0, - "label": "Slider: step @ 0.04", - "show_label": true, - "name": "slider", - "visible": true, - "style": {} - } - }, - { - "id": 5, - "type": "checkbox", - "props": { - "value": false, - "label": "Checkbox", - "show_label": true, - "name": "checkbox", - "visible": true, - "style": {} - } - }, - { - "id": 6, - "type": "checkboxgroup", - "props": { - "choices": [ - "foo", - "bar", - "baz" - ], - "value": [ - "foo", - "bar" - ], - "label": "CheckboxGroup", - "show_label": true, - "name": "checkboxgroup", - "visible": true, - "style": {} - } - }, - { - "id": 7, - "type": "radio", - "props": { - "choices": [ - "foo", - "bar", - "baz" - ], - "value": "baz", - "label": "Radio", - "show_label": true, - "name": "radio", - "visible": true, - "style": {} - } - }, - { - "id": 8, - "type": "dropdown", - "props": { - "choices": [ - "foo", - "bar", - "baz" - ], - "label": "Dropdown", - "show_label": true, - "name": "dropdown", - "visible": true, - "style": {} - } - }, - { - "id": 9, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "label": "Image", - "show_label": true, - "name": "image", - "visible": true, - "style": {} - } - }, - { - "id": 10, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "select", - "streaming": false, - "mirror_webcam": true, - "label": "Image w/ Cropper", - "show_label": true, - "name": "image", - "visible": true, - "style": {} - } - }, - { - "id": 11, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "canvas", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "label": "Sketchpad", - "show_label": true, - "name": "image", - "visible": true, - "style": {} - } - }, - { - "id": 12, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "webcam", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "label": "Webcam", - "show_label": true, - "name": "image", - "visible": true, - "style": {} - } - }, - { - "id": 13, - "type": "video", - "props": { - "source": "upload", - "mirror_webcam": true, - "label": "Video", - "show_label": true, - "name": "video", - "visible": true, - "style": {} - } - }, - { - "id": 14, - "type": "audio", - "props": { - "source": "upload", - "streaming": false, - "label": "Audio", - "show_label": true, - "name": "audio", - "visible": true, - "style": {} - } - }, - { - "id": 15, - "type": "audio", - "props": { - "source": "microphone", - "streaming": false, - "label": "Microphone", - "show_label": true, - "name": "audio", - "visible": true, - "style": {} - } - }, - { - "id": 16, - "type": "file", - "props": { - "file_count": "single", - "label": "File", - "show_label": true, - "name": "file", - "visible": true, - "style": {} - } - }, - { - "id": 17, - "type": "dataframe", - "props": { - "headers": [ - "Name", - "Age", - "Gender" - ], - "datatype": [ - "str", - "str", - "str" - ], - "row_count": [ - 1, - "dynamic" - ], - "col_count": [ - 3, - "dynamic" - ], - "value": { - "headers": [ - "Name", - "Age", - "Gender" - ], - "data": [ - [ - "", - "", - "" - ] - ] - }, - "max_rows": 20, - "overflow_row_behaviour": "paginate", - "wrap": false, - "label": "Dataframe", - "show_label": true, - "name": "dataframe", - "visible": true, - "style": {} - } - }, - { - "id": 18, - "type": "timeseries", - "props": { - "x": "time", - "y": [ - "price", - "value" - ], - "colors": [ - "pink", - "purple" - ], - "label": "df2", - "show_label": true, - "name": "timeseries", - "visible": true, - "style": {} - } - }, - { - "id": 38, - "type": "row", - "props": { - "type": "row", - "visible": true, - "style": { - "mobile_collapse": false - } - } - }, - { - "id": 39, - "type": "button", - "props": { - "value": "Clear", - "variant": "secondary", - "name": "button", - "visible": true, - "style": {} - } - }, - { - "id": 40, - "type": "button", - "props": { - "value": "Submit", - "variant": "primary", - "name": "button", - "visible": true, - "style": {} - } - }, - { - "id": 41, - "type": "column", - "props": { - "type": "column", - "variant": "panel", - "visible": true, - "style": {} - } - }, - { - "id": 42, - "type": "statustracker", - "props": { - "cover_container": true, - "name": "statustracker", - "visible": true, - "style": {} - } - }, - { - "id": 19, - "type": "textbox", - "props": { - "lines": 1, - "max_lines": 20, - "value": "", - "label": "Textbox", - "show_label": true, - "interactive": false, - "name": "textbox", - "visible": true, - "style": {} - } - }, - { - "id": 20, - "type": "label", - "props": { - "label": "Label", - "show_label": true, - "interactive": false, - "name": "label", - "visible": true, - "style": {} - } - }, - { - "id": 21, - "type": "audio", - "props": { - "source": "upload", - "streaming": false, - "label": "Audio", - "show_label": true, - "interactive": false, - "name": "audio", - "visible": true, - "style": {} - } - }, - { - "id": 22, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "label": "Image", - "show_label": true, - "interactive": false, - "name": "image", - "visible": true, - "style": {} - } - }, - { - "id": 23, - "type": "video", - "props": { - "source": "upload", - "mirror_webcam": true, - "label": "Video", - "show_label": true, - "interactive": false, - "name": "video", - "visible": true, - "style": {} - } - }, - { - "id": 24, - "type": "highlightedtext", - "props": { - "color_map": { - "punc": "pink", - "test 0": "blue" - }, - "show_legend": false, - "label": "HighlightedText", - "show_label": true, - "interactive": false, - "name": "highlightedtext", - "visible": true, - "style": {} - } - }, - { - "id": 25, - "type": "highlightedtext", - "props": { - "show_legend": true, - "label": "HighlightedText", - "show_label": true, - "interactive": false, - "name": "highlightedtext", - "visible": true, - "style": {} - } - }, - { - "id": 26, - "type": "json", - "props": { - "label": "JSON", - "show_label": true, - "interactive": false, - "name": "json", - "visible": true, - "style": {} - } - }, - { - "id": 27, - "type": "html", - "props": { - "value": "", - "label": "HTML", - "show_label": true, - "interactive": false, - "name": "html", - "visible": true, - "style": {} - } - }, - { - "id": 28, - "type": "file", - "props": { - "file_count": "single", - "label": "File", - "show_label": true, - "interactive": false, - "name": "file", - "visible": true, - "style": {} - } - }, - { - "id": 29, - "type": "dataframe", - "props": { - "headers": [ - 1, - 2, - 3 - ], - "datatype": [ - "str", - "str", - "str" - ], - "row_count": [ - 1, - "dynamic" - ], - "col_count": [ - 3, - "dynamic" - ], - "value": { - "headers": [ - 1, - 2, - 3 - ], - "data": [ - [ - "", - "", - "" - ] - ] - }, - "max_rows": 20, - "overflow_row_behaviour": "paginate", - "wrap": false, - "label": "Dataframe", - "show_label": true, - "interactive": false, - "name": "dataframe", - "visible": true, - "style": {} - } - }, - { - "id": 30, - "type": "dataframe", - "props": { - "headers": [ - 1, - 2, - 3 - ], - "datatype": [ - "str", - "str", - "str" - ], - "row_count": [ - 1, - "dynamic" - ], - "col_count": [ - 3, - "dynamic" - ], - "value": { - "headers": [ - 1, - 2, - 3 - ], - "data": [ - [ - "", - "", - "" - ] - ] - }, - "max_rows": 20, - "overflow_row_behaviour": "paginate", - "wrap": false, - "label": "Numpy", - "show_label": true, - "interactive": false, - "name": "dataframe", - "visible": true, - "style": {} - } - }, - { - "id": 31, - "type": "timeseries", - "props": { - "x": "time", - "y": [ - "price", - "value" - ], - "label": "Timeseries", - "show_label": true, - "interactive": false, - "name": "timeseries", - "visible": true, - "style": {} - } - }, - { - "id": 43, - "type": "row", - "props": { - "type": "row", - "visible": true, - "style": { - "mobile_collapse": false - } - } - }, - { - "id": 44, - "type": "button", - "props": { - "value": "Flag", - "variant": "secondary", - "name": "button", - "visible": true, - "style": {} - } - }, - { - "id": 45, - "type": "dataset", - "props": { - "components": [ - "textbox", - "textbox", - "number", - "slider", - "slider", - "checkbox", - "checkboxgroup", - "radio", - "dropdown", - "image", - "image", - "image", - "image", - "video", - "audio", - "audio", - "file", - "dataframe", - "timeseries" - ], - "headers": [ - "Textbox", - "Textbox 2", - "Number", - "Slider: 10 - 20", - "Slider: step @ 0.04", - "Checkbox", - "CheckboxGroup", - "Radio", - "Dropdown", - "Image", - "Image w/ Cropper", - "Sketchpad", - "Webcam", - "Video", - "Audio", - "Microphone", - "File", - "Dataframe", - "df2" - ], - "samples": [ - [ - "the quick brown fox", - "jumps over the lazy dog", - 10, - 12, - 4, - true, - [ - "foo", - "baz" - ], - "baz", - "bar", - "cheetah1.jpg", - "cheetah1.jpg", - "cheetah1.jpg", - "cheetah1.jpg", - "world.mp4", - "cantina.wav", - "cantina.wav", - "titanic.csv", - [ - [ - 1, - 2, - 3 - ], - [ - 3, - 4, - 5 - ] - ], - "time.csv" - ], - [ - "the quick brown fox", - "jumps over the lazy dog", - 10, - 12, - 4, - true, - [ - "foo", - "baz" - ], - "baz", - "bar", - "cheetah1.jpg", - "cheetah1.jpg", - "cheetah1.jpg", - "cheetah1.jpg", - "world.mp4", - "cantina.wav", - "cantina.wav", - "titanic.csv", - [ - [ - 1, - 2, - 3 - ], - [ - 3, - 4, - 5 - ] - ], - "time.csv" - ], - [ - "the quick brown fox", - "jumps over the lazy dog", - 10, - 12, - 4, - true, - [ - "foo", - "baz" - ], - "baz", - "bar", - "cheetah1.jpg", - "cheetah1.jpg", - "cheetah1.jpg", - "cheetah1.jpg", - "world.mp4", - "cantina.wav", - "cantina.wav", - "titanic.csv", - [ - [ - 1, - 2, - 3 - ], - [ - 3, - 4, - 5 - ] - ], - "time.csv" - ] - ], - "type": "index", - "name": "dataset", - "visible": true, - "style": {} - } - }, - { - "id": 46, - "type": "markdown", - "props": { - "value": "Learn more about Gradio
", - "name": "markdown", - "visible": true, - "style": {} - } - } - ], - "theme": "default", - "css": null, - "title": "Kitchen Sink", - "enable_queue": false, - "layout": { - "id": 32, - "children": [ - { - "id": 33 - }, - { - "id": 34 - }, - { - "id": 35, - "children": [ - { - "id": 36, - "children": [ - { - "id": 37, - "children": [ - { - "id": 0 - }, - { - "id": 1 - }, - { - "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": 38, - "children": [ - { - "id": 39 - }, - { - "id": 40 - } - ] - } - ] - }, - { - "id": 41, - "children": [ - { - "id": 42 - }, - { - "id": 19 - }, - { - "id": 20 - }, - { - "id": 21 - }, - { - "id": 22 - }, - { - "id": 23 - }, - { - "id": 24 - }, - { - "id": 25 - }, - { - "id": 26 - }, - { - "id": 27 - }, - { - "id": 28 - }, - { - "id": 29 - }, - { - "id": 30 - }, - { - "id": 31 - }, - { - "id": 43, - "children": [ - { - "id": 44 - } - ] - } - ] - } - ] - }, - { - "id": 45 - }, - { - "id": 46 - } - ] - }, - "dependencies": [ - { - "targets": [ - 40 - ], - "trigger": "click", - "inputs": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18 - ], - "outputs": [ - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31 - ], - "backend_fn": true, - "js": null, - "status_tracker": null, - "queue": null, - "api_name": "predict", - "scroll_to_output": true, - "show_progress": true, - "documentation": [ - [ - [ - "text", - "str | None" - ], - [ - "text", - "str | None" - ], - [ - "numeric input", - "float | None" - ], - [ - "numeric input", - "float" - ], - [ - "numeric input", - "float" - ], - [ - "boolean input", - "bool" - ], - [ - "list of selected choices", - "List[str]" - ], - [ - "selected choice", - "str" - ], - [ - "selected choice", - "str" - ], - [ - "base64 url data, or (if tool == \"sketch) a dict of image and mask base64 url data", - "str | Dict" - ], - [ - "base64 url data, or (if tool == \"sketch) a dict of image and mask base64 url data", - "str | Dict" - ], - [ - "base64 url data, or (if tool == \"sketch) a dict of image and mask base64 url data", - "str | Dict" - ], - [ - "base64 url data, or (if tool == \"sketch) a dict of image and mask base64 url data", - "str | Dict" - ], - [ - "JSON object with filename as 'name' property and base64 data as 'data' property", - "Dict[str, str] | None" - ], - [ - "JSON object with filename as 'name' property and base64 data as 'data' property", - "Dict[str, str] | None" - ], - [ - "JSON object with filename as 'name' property and base64 data as 'data' property", - "Dict[str, str] | None" - ], - [ - "List of JSON objects with filename as 'name' property and base64 data as 'data' property", - "List[Dict[str, str]] | None" - ], - [ - "2D array of str, numeric, or bool data", - "DataframeData" - ], - [ - "Dict with keys 'data': 2D array of str, numeric, or bool data, 'headers': list of strings for header names, 'range': optional two element list designating start of end of subrange.", - "Dict | None" - ] - ], - [ - [ - "text", - "str | None" - ], - [ - "Object with key 'label' representing primary label, and key 'confidences' representing a list of label-confidence pairs", - "Dict | None" - ], - [ - "base64 url data", - "str" - ], - [ - "base64 url data", - "str" - ], - [ - "base64 url data", - "str" - ], - [ - "List of (word, category) tuples", - "Optional[List[Tuple[str, str | float | None]]]" - ], - [ - "List of (word, category) tuples", - "Optional[List[Tuple[str, str | float | None]]]" - ], - [ - "JSON output", - "Dict | List | None" - ], - [ - null, - "None" - ], - [ - "JSON object with key 'name' for filename, 'data' for base64 url, and 'size' for filesize in bytes", - "Dict" - ], - [ - "JSON object with key 'headers' for list of header names, 'data' for 2D array of string or numeric data", - "Dict" - ], - [ - "JSON object with key 'headers' for list of header names, 'data' for 2D array of string or numeric data", - "Dict" - ], - [ - "JSON object with key 'headers' for list of header names, 'data' for 2D array of string or numeric data", - "Dict" - ] - ] - ] - }, - { - "targets": [ - 39 - ], - "trigger": "click", - "inputs": [], - "outputs": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 37 - ], - "backend_fn": false, - "js": "() => [\"\", \"\", null, 15, 0, null, [], \"baz\", null, null, null, null, null, null, null, null, null, null, null, \"\", null, null, null, null, null, null, null, null, null, null, null, null, {\"variant\": null, \"visible\": true, \"__type__\": \"update\"}]\n ", - "status_tracker": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": true - }, - { - "targets": [ - 44 - ], - "trigger": "click", - "inputs": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31 - ], - "outputs": [], - "backend_fn": true, - "js": null, - "status_tracker": null, - "queue": false, - "api_name": null, - "scroll_to_output": false, - "show_progress": true - }, - { - "targets": [ - 45 - ], - "trigger": "click", - "inputs": [ - 45 - ], - "outputs": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18 - ], - "backend_fn": true, - "js": null, - "status_tracker": null, - "queue": false, - "api_name": null, - "scroll_to_output": false, - "show_progress": true - } - ] -} \ No newline at end of file diff --git a/demo/outbreak_forecast/config.json b/demo/outbreak_forecast/config.json deleted file mode 100644 index 102d543553..0000000000 --- a/demo/outbreak_forecast/config.json +++ /dev/null @@ -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 - } - ] -} \ No newline at end of file diff --git a/demo/outbreak_forecast/run.py b/demo/outbreak_forecast/run.py index 529f706fa1..1f96759c80 100644 --- a/demo/outbreak_forecast/run.py +++ b/demo/outbreak_forecast/run.py @@ -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() diff --git a/ui/package.json b/ui/package.json index 9cfa5f9dc9..d5c57f9ebf 100644 --- a/ui/package.json +++ b/ui/package.json @@ -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", diff --git a/ui/packages/app/package.json b/ui/packages/app/package.json index 59ce85f28b..c0ee7ea53e 100644 --- a/ui/packages/app/package.json +++ b/ui/packages/app/package.json @@ -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" } } diff --git a/ui/packages/app/snapshots/blocks_layout.spec.ts b/ui/packages/app/snapshots/blocks_layout.spec.ts new file mode 100644 index 0000000000..990f7f3e3b --- /dev/null +++ b/ui/packages/app/snapshots/blocks_layout.spec.ts @@ -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(); +}); diff --git a/ui/packages/app/snapshots/blocks_xray.spec.ts b/ui/packages/app/snapshots/blocks_xray.spec.ts new file mode 100644 index 0000000000..6b6cf16f14 --- /dev/null +++ b/ui/packages/app/snapshots/blocks_xray.spec.ts @@ -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(); +}); diff --git a/ui/packages/app/snapshots/kitchen_sink.spec.ts b/ui/packages/app/snapshots/kitchen_sink.spec.ts new file mode 100644 index 0000000000..16ec00df78 --- /dev/null +++ b/ui/packages/app/snapshots/kitchen_sink.spec.ts @@ -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(); +}); diff --git a/ui/packages/app/test/blocks_inputs.spec.ts b/ui/packages/app/test/blocks_inputs.spec.ts index 0473334fb0..ce61235ef4 100644 --- a/ui/packages/app/test/blocks_inputs.spec.ts +++ b/ui/packages/app/test/blocks_inputs.spec.ts @@ -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"); }); diff --git a/ui/packages/app/test/blocks_kinematics.spec.ts b/ui/packages/app/test/blocks_kinematics.spec.ts index 1bd3f07b91..ed9a977778 100644 --- a/ui/packages/app/test/blocks_kinematics.spec.ts +++ b/ui/packages/app/test/blocks_kinematics.spec.ts @@ -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/") + ]); }); diff --git a/ui/packages/app/test/blocks_page_load.spec.ts b/ui/packages/app/test/blocks_page_load.spec.ts index b284f40c2f..cf45678d4f 100644 --- a/ui/packages/app/test/blocks_page_load.spec.ts +++ b/ui/packages/app/test/blocks_page_load.spec.ts @@ -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" ); }); diff --git a/ui/packages/app/test/blocks_xray.spec.ts b/ui/packages/app/test/blocks_xray.spec.ts index de9c14dd0d..14f1ca30eb 100644 --- a/ui/packages/app/test/blocks_xray.spec.ts +++ b/ui/packages/app/test/blocks_xray.spec.ts @@ -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`); }); diff --git a/ui/packages/app/test/create_demo_configs.py b/ui/packages/app/test/create_demo_configs.py index 0cf4a45d9b..a3aeee87b3 100644 --- a/ui/packages/app/test/create_demo_configs.py +++ b/ui/packages/app/test/create_demo_configs.py @@ -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() - \ No newline at end of file + 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() diff --git a/ui/packages/app/test/input_output.spec.ts b/ui/packages/app/test/input_output.spec.ts index 5923c1b1a5..4da8aefd12 100644 --- a/ui/packages/app/test/input_output.spec.ts +++ b/ui/packages/app/test/input_output.spec.ts @@ -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"); }); diff --git a/ui/packages/app/test/kitchen_sink.spec.ts b/ui/packages/app/test/kitchen_sink.spec.ts index fb62c32343..61957a1bcf 100644 --- a/ui/packages/app/test/kitchen_sink.spec.ts +++ b/ui/packages/app/test/kitchen_sink.spec.ts @@ -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" diff --git a/ui/packages/app/test/outbreak_forecast.spec.ts b/ui/packages/app/test/outbreak_forecast.spec.ts index dc26b2b16a..275e038e1f 100644 --- a/ui/packages/app/test/outbreak_forecast.spec.ts +++ b/ui/packages/app/test/outbreak_forecast.spec.ts @@ -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); diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index fcfc245980..d044e03067 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -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: