Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(testing): Add shiny add test CLI command; Add quarto page for testing #1461

Merged
merged 15 commits into from
Jun 22, 2024
Merged
10 changes: 9 additions & 1 deletion docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ deps: $(PYBIN) dev-htmltools dev-shinylive ## Install build dependencies
$(PYBIN)/pip install pip --upgrade
$(PYBIN)/pip install ..[doc]

quartodoc: quartodoc_build_core quartodoc_build_express quartodoc_post ## Build quartodocs for express and core
quartodoc: quartodoc_build_core quartodoc_build_express quartodoc_build_test quartodoc_post ## Build quartodocs for express and core

## Build interlinks for API docs
quartodoc_interlinks: $(PYBIN)
Expand Down Expand Up @@ -78,6 +78,14 @@ quartodoc_build_express: $(PYBIN) quartodoc_interlinks
&& mv objects.json _objects_express.json \
&& echo "::endgroup::"

## Build test API docs
quartodoc_build_test: $(PYBIN) quartodoc_interlinks
. $(PYBIN)/activate \
&& echo "::group::quartodoc build test docs" \
schloerke marked this conversation as resolved.
Show resolved Hide resolved
&& quartodoc build --config _quartodoc-testing.yml --verbose \
&& mv objects.json _objects_express.json \
&& echo "::endgroup::"

## Clean up after quartodoc build
quartodoc_post: $(PYBIN)
. $(PYBIN)/activate \
Expand Down
4 changes: 3 additions & 1 deletion docs/_combine_objects_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ def write_objects_file(objects: QuartodocObject, path: str) -> None:
print("\nCombining objects json files...")
objects_core = read_objects_file("_objects_core.json")
objects_express = read_objects_file("_objects_express.json")
objects_test = read_objects_file("_objects_test.json")

items_map: dict[str, QuartodocObjectItem] = {}

for item in [*objects_core.items, *objects_express.items]:
for item in [*objects_core.items, *objects_express.items, *objects_test.items]:
if item.name in items_map:
continue
items_map[item.name] = item
Expand All @@ -58,6 +59,7 @@ def write_objects_file(objects: QuartodocObject, path: str) -> None:

print("Core:", objects_core.count)
print("Express:", objects_express.count)
print("Test:", objects_test.count)
schloerke marked this conversation as resolved.
Show resolved Hide resolved
print("Combined:", objects_ret.count)

# Save combined objects file info
Expand Down
2 changes: 2 additions & 0 deletions docs/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ website:
file: api/express/index.qmd
- text: "Core API"
file: api/core/index.qmd
- text: "Testing API"
file: api/test/index.qmd
right:
- icon: github
href: https://github.com/posit-dev/py-shiny
Expand Down
1 change: 1 addition & 0 deletions docs/_quartodoc-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ quartodoc:
- types.SilentException
- types.SilentCancelOutputException
- types.SafeException

schloerke marked this conversation as resolved.
Show resolved Hide resolved
- title: Deprecated
desc: ""
contents:
Expand Down
166 changes: 166 additions & 0 deletions docs/_quartodoc-testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
quartodoc:
style: pkgdown
dir: api/testing
out_index: index.qmd
package: shiny
rewrite_all_pages: false
sidebar: api/testing/_sidebar.yml
dynamic: true
renderer:
style: _renderer.py
show_signature_annotations: false
sections:
- title: Testing
desc: "Testing Methods to make it easier to run and test user's Shiny apps."
contents:
- kind: page
path: PlaywrightControls
flatten: true
summary:
name: "Playwright Controls"
desc: "Methods for interacting with Shiny app controls."
- title: UI Layouts
desc: Methods for interacting with Shiny app multiple UI component controls.
contents:
- name: playwright.controls.Accordion
dynamic: false
- name: playwright.controls.AccordionPanel
dynamic: false
- name: playwright.controls.Card
dynamic: false
- name: playwright.controls.Popover
dynamic: false
- name: playwright.controls.Sidebar
dynamic: false
- name: playwright.controls.Tooltip
dynamic: false
- title: UI Inputs
desc: Methods for interacting with Shiny app input value controls.
contents:
- name: playwright.controls.InputActionLink
dynamic: false
- name: playwright.controls.InputCheckbox
dynamic: false
- name: playwright.controls.InputCheckboxGroup
dynamic: false
- name: playwright.controls.InputDarkMode
dynamic: false
- name: playwright.controls.InputDate
dynamic: false
- name: playwright.controls.InputDateRange
dynamic: false
- name: playwright.controls.InputFile
dynamic: false
- name: playwright.controls.InputNumeric
dynamic: false
- name: playwright.controls.InputPassword
dynamic: false
- name: playwright.controls.InputRadioButtons
dynamic: false
- name: playwright.controls.InputSelect
dynamic: false
- name: playwright.controls.InputSelectize
dynamic: false
- name: playwright.controls.InputSlider
dynamic: false
- name: playwright.controls.InputSliderRange
dynamic: false
- name: playwright.controls.InputSwitch
dynamic: false
- name: playwright.controls.InputTaskButton
dynamic: false
- name: playwright.controls.InputText
dynamic: false
- name: playwright.controls.InputTextArea
- title: Value boxes
desc: Methods for interacting with Shiny app valuebox controls.
contents:
- name: playwright.controls.ValueBox
dynamic: false
- title: Navigation (tab) panels
desc: Methods for interacting with Shiny app UI content controls.
contents:
- name: playwright.controls.NavItem
dynamic: false
- name: playwright.controls.NavsetBar
dynamic: false
- name: playwright.controls.NavsetCardPill
dynamic: false
- name: playwright.controls.NavsetCardTab
dynamic: false
- name: playwright.controls.NavsetCardUnderline
dynamic: false
- name: playwright.controls.NavsetHidden
dynamic: false
- name: playwright.controls.NavsetPill
dynamic: false
- name: playwright.controls.NavsetPillList
dynamic: false
- name: playwright.controls.NavsetTab
dynamic: false
- name: playwright.controls.NavsetUnderline
dynamic: false
- title: Upload and download
desc: Create UI for uploading and downloading files.
contents:
- name: playwright.controls.DownloadButton
dynamic: false
- name: playwright.controls.DownloadLink
dynamic: false
- title: Rendering outputs
desc: Render output in a variety of ways.
contents:
- name: playwright.controls.OutputCode
dynamic: false
- name: playwright.controls.OutputDataFrame
dynamic: false
- name: playwright.controls.OutputImage
dynamic: false
- name: playwright.controls.OutputPlot
dynamic: false
- name: playwright.controls.OutputTable
dynamic: false
- name: playwright.controls.OutputText
dynamic: false
- name: playwright.controls.OutputTextVerbatim
dynamic: false
- name: playwright.controls.OutputUi
- kind: page
path: PlaywrightExpect
flatten: true
summary:
name: "Playwright Expect"
desc: "Methods for testing the state of a locator within a Shiny app."
contents:
- name: playwright.expect.expect_to_change
dynamic: false
- name: playwright.expect.expect_attribute_to_have_value
dynamic: false
- name: playwright.expect.expect_to_have_class
dynamic: false
- name: playwright.expect.expect_not_to_have_class
dynamic: false
- name: playwright.expect.expect_to_have_style
dynamic: false
- kind: page
path: Pytest
flatten: true
summary:
name: "Pytest"
desc: "Fixtures used for testing Shiny apps with Pytest."
contents:
- name: pytest.create_app_fixture
dynamic: false
- name: pytest.ScopeName
dynamic: false
- kind: page
path: Run
flatten: true
summary:
name: "Run"
desc: "Methods for starting a local Shiny app in the background"
contents:
- name: run.run_shiny_app
dynamic: false
- name: run.ShinyAppProc
dynamic: false
26 changes: 26 additions & 0 deletions shiny/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,32 @@ def try_import_module(module: str) -> Optional[types.ModuleType]:
}


@main.command(
help="""Add a test file for a specified app.

Add an empty test file for a specified app. You will be prompted with
a destination folder. If you don't provide a destination folder, it will be added in the current working
directory based on the app name.

After creating the shiny app file, you can use `pytest` to run the tests:

pytest APPDIR/test_APPNAME.py
"""
)
@click.option(
"--app",
"-a",
type=str,
help="Please provide the path to the app for which you want to create a test file.",
)
def add_tests(
schloerke marked this conversation as resolved.
Show resolved Hide resolved
app_dir: Path,
schloerke marked this conversation as resolved.
Show resolved Hide resolved
) -> None:
from ._template_utils import add_test_file

add_test_file(app_dir)


@main.command(
help="""Create a Shiny application from a template.

Expand Down
19 changes: 19 additions & 0 deletions shiny/_template_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,22 @@ def rename_unlink(file_to_rename: str, file_to_delete: str, dir: Path = app_dir)
(app_dir / "app-core.py").rename(app_dir / "app.py")

return app_dir


def add_test_file(app_dir: Path):
test_file = app_dir / "test_app.py"
test_file.write_text(
schloerke marked this conversation as resolved.
Show resolved Hide resolved
"""
from shiny.playwright.controls import <import_required_control>
from shiny.run import ShinyAppProc
from playwright.sync_api import Page
from shiny.pytest import create_app_fixture

app = create_app_fixture(f"{app_dir}/app.py")
schloerke marked this conversation as resolved.
Show resolved Hide resolved


def test_app(page: Page, app: ShinyAppProc):
page.goto(app.url)
# Add tests code here
"""
)
2 changes: 2 additions & 0 deletions shiny/playwright/controls/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from ._controls import (
Accordion,
AccordionPanel,
Card,
DownloadButton,
DownloadLink,
Expand Down Expand Up @@ -77,6 +78,7 @@
"ValueBox",
"Card",
"Accordion",
"AccordionPanel",
"Sidebar",
"Popover",
"Tooltip",
Expand Down
Loading
Loading