Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 2 additions & 29 deletions shiny/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,33 +484,6 @@ def try_import_module(module: str) -> Optional[types.ModuleType]:
return importlib.import_module(module)


# The template choices are defined here instead of in `_template_utiles.py` in
# order to delay loading the questionary package until shiny create is called.

# These templates are copied over fromt the `shiny/templates/app_templates`
# directory. The process for adding new ones is to add your app folder to
# that directory, and then add another entry to this dictionary.
app_template_choices = {
"Basic app": "basic-app",
"Sidebar layout": "basic-sidebar",
"Basic dashboard": "dashboard",
"Intermediate dashboard": "dashboard-tips",
"Navigating multiple pages/panels": "basic-navigation",
"Custom JavaScript component ...": "js-component",
"Choose from the Shiny Templates website": "external-gallery",
}

# These are templates which produce a Python package and have content filled in at
# various places based on the user input. You can add new ones by following the
# examples in `shiny/templates/package-templates` and then adding entries to this
# dictionary.
package_template_choices = {
"Input component": "js-input",
"Output component": "js-output",
"React component": "js-react",
}


@main.group(help="""Add files to enhance your Shiny app.""")
def add() -> None:
pass
Expand Down Expand Up @@ -545,7 +518,7 @@ def test(
app: Path | None,
test_file: Path | None,
) -> None:
from ._template_utils import add_test_file
from ._main_add_test import add_test_file

add_test_file(app_file=app, test_file=test_file)

Expand Down Expand Up @@ -609,7 +582,7 @@ def create(
dir: Optional[Path | str] = None,
package_name: Optional[str] = None,
) -> None:
from ._template_utils import use_template_github, use_template_internal
from ._main_create import use_template_github, use_template_internal

print(f"dir is {dir}")

Expand Down
122 changes: 122 additions & 0 deletions shiny/_main_add_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
from __future__ import annotations

import os
import sys
from pathlib import Path

import click
import questionary

from ._main_utils import cli_action, cli_bold, cli_code, path_rel_wd


def add_test_file(
*,
app_file: Path | None,
test_file: Path | None,
):
if app_file is None:

def path_exists(x: Path) -> bool | str:
if not isinstance(x, (str, Path)):
return False
if Path(x).is_dir():
return "Please provide a file path to your Shiny app"
return Path(x).exists() or f"Shiny app file can not be found: {x}"

app_file_val = questionary.path(
"Enter the path to the app file:",
default=path_rel_wd("app.py"),
validate=path_exists,
).ask()
else:
app_file_val = app_file
# User quit early
if app_file_val is None:
sys.exit(1)
app_file = Path(app_file_val)

if test_file is None:

def path_does_not_exist(x: Path) -> bool | str:
if not isinstance(x, (str, Path)):
return False
if Path(x).is_dir():
return "Please provide a file path for your test file."
if Path(x).exists():
return "Test file already exists. Please provide a new file name."
if not Path(x).name.startswith("test_"):
return "Test file must start with 'test_'"
return True

test_file_val = questionary.path(
"Enter the path to the test file:",
default=path_rel_wd(
os.path.relpath(app_file.parent / "tests" / "test_app.py", ".")
),
validate=path_does_not_exist,
).ask()
else:
test_file_val = test_file

# User quit early
if test_file_val is None:
sys.exit(1)
test_file = Path(test_file_val)

# Make sure app file exists
if not app_file.exists():
raise FileExistsError("App file does not exist: ", test_file)
# Make sure output test file doesn't exist
if test_file.exists():
raise FileExistsError("Test file already exists: ", test_file)
if not test_file.name.startswith("test_"):
return "Test file must start with 'test_'"

# if app path directory is the same as the test file directory, use `local_app`
# otherwise, use `create_app_fixture`
is_same_dir = app_file.parent == test_file.parent

test_name = test_file.name.replace(".py", "")
rel_path = os.path.relpath(app_file, test_file.parent)

template = (
f"""\
from playwright.sync_api import Page

from shiny.playwright import controller
from shiny.run import ShinyAppProc


def {test_name}(page: Page, local_app: ShinyAppProc):

page.goto(local_app.url)
# Add test code here
"""
if is_same_dir
else f"""\
from playwright.sync_api import Page

from shiny.playwright import controller
from shiny.pytest import create_app_fixture
from shiny.run import ShinyAppProc

app = create_app_fixture("{rel_path}")


def {test_name}(page: Page, app: ShinyAppProc):

page.goto(app.url)
# Add test code here
"""
)
# Make sure test file directory exists
test_file.parent.mkdir(parents=True, exist_ok=True)

# Write template to test file
test_file.write_text(template)

# next steps
click.echo()
click.echo(cli_action(cli_bold("Next steps:")))
click.echo(f"- Run {cli_code('pytest')} in your terminal to run all the tests")
Loading