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

[WIP] Unit Test for dashboard #706

Open
wants to merge 29 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
195e8b3
Added IDs to UI components
proy30 Aug 10, 2024
8f2f0b8
Added some more IDs to UI components
proy30 Aug 11, 2024
79064a7
Added 'close' button in lattice settings
proy30 Aug 11, 2024
142f8b6
Removed functionality that converted user input
proy30 Aug 11, 2024
fe7ff90
Added unit test for running FODO simulation on dashboard
proy30 Aug 11, 2024
8c70aad
Added subprocess to start up server with pytest
proy30 Aug 11, 2024
699ef52
Attempt to fix flaky test
proy30 Aug 12, 2024
4e96f06
Add seleniumbase dependency in CI workflows for testing
proy30 Aug 12, 2024
3e22383
Added dashboard dependencies in stubs.yml
proy30 Aug 12, 2024
2c3e6c3
Added missing dashboard dependencies to stubs.yml
proy30 Aug 12, 2024
5087204
Update CI & Requirements Files
ax3l Aug 12, 2024
8a8f24a
pytest: Graceful Skipping
ax3l Aug 12, 2024
af48f6b
Unit test interacts with phase space projections
proy30 Aug 18, 2024
4c01f6c
time adjustments
proy30 Aug 18, 2024
01a46ee
adjust format
proy30 Aug 18, 2024
0ebffef
attempt to run headless
proy30 Aug 18, 2024
7b624cd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 18, 2024
4294ff9
Fixed UnboundLocalError and PermissionError
proy30 Sep 19, 2024
a46d047
Replace time.sleep() with alternative
proy30 Sep 19, 2024
61047e3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 19, 2024
a212bd5
Redid logic to show simulation is complete
proy30 Sep 19, 2024
551010d
test
proy30 Oct 3, 2024
2c9ae3e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 19, 2024
ed259e6
try new directory to launch application
proy30 Nov 22, 2024
4c9ad85
Adjust testing for updated ui
proy30 Nov 22, 2024
032936c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 22, 2024
8d58fd6
Adjust docstring
proy30 Nov 23, 2024
11a5c95
Merge branch 'topic-dashboard-test' of github.com:proy30/impactx into…
proy30 Nov 23, 2024
364e20d
test new
proy30 Nov 25, 2024
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
4 changes: 3 additions & 1 deletion .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ jobs:
- name: install pip dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade build packaging setuptools wheel pytest
python3 -m pip install --upgrade build packaging setuptools wheel
python3 -m pip install --upgrade -r requirements_mpi.txt
python3 -m pip install --upgrade -r src/python/impactx/dashboard/requirements.txt
python3 -m pip install --upgrade -r src/python/impactx/dashboard/requirements.txt
python3 -m pip install --upgrade -r examples/requirements.txt
python3 -m pip install --upgrade -r tests/python/requirements.txt
set -e
python3 -m pip install --upgrade pipx
python3 -m pipx install openPMD-validator
- name: CCache Cache
Expand Down
22 changes: 20 additions & 2 deletions .github/workflows/stubs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,24 @@ jobs:
- name: Dependencies
run: |
.github/workflows/dependencies/gcc-openmpi.sh
python3 -m pip install -U pybind11-stubgen pre-commit
python3 -m pip install -U pybind11-stubgen
python3 -m pip install seleniumbase pytest

# Added: Install Firefox and geckodriver
- name: Install Browser Dependencies
run: |
sudo apt-get update
sudo apt-get install -y firefox-esr xvfb
wget https://github.com/mozilla/geckodriver/releases/download/v0.33.0/geckodriver-v0.33.0-linux64.tar.gz
tar -xzf geckodriver-v0.33.0-linux64.tar.gz
sudo mv geckodriver /usr/local/bin/
sudo chmod +x /usr/local/bin/geckodriver

# Added: Start virtual display
- name: Start Virtual Display
run: |
Xvfb :99 -screen 0 1280x1024x24 > /dev/null 2>&1 &
echo "DISPLAY=:99" >> $GITHUB_ENV

- name: Set Up Cache
uses: actions/cache@v4
Expand Down Expand Up @@ -81,7 +98,8 @@ jobs:

- name: Unit tests
run: |
mpiexec -np 1 python3 -m pytest tests/python/
export DISPLAY=:99
mpiexec -np 1 python3 -m pytest -v tests/python/

- uses: stefanzweifel/git-auto-commit-action@v5
name: Commit Updated Stub Files
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@ jobs:

python3 -m pip install -U pip
python3 -m pip install -U build packaging setuptools wheel
python3 -m pip install -U build packaging setuptools wheel
python3 -m pip install -U -r requirements.txt
python3 -m pip install -U -r src/python/impactx/dashboard/requirements.txt
python3 -m pip install -U -r examples/requirements.txt
python3 -m pip install -U -r src/python/impactx/dashboard/requirements.txt
python3 -m pip install -U -r tests/python/requirements.txt
python3 -m pip install -U openPMD-validator
- name: Build
Expand Down Expand Up @@ -184,6 +186,7 @@ jobs:
python3 -m pip install -U -r requirements.txt
python3 -m pip install -U -r src/python/impactx/dashboard/requirements.txt
python3 -m pip install -U -r examples/requirements.txt
python3 -m pip install -U -r src/python/impactx/dashboard/requirements.txt
python3 -m pip install -U -r tests/python/requirements.txt
python3 -m pip install -U openPMD-validator
- name: Build
Expand Down
3 changes: 2 additions & 1 deletion src/python/impactx/dashboard/Analyze/plotsMain.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def on_filtered_data_change(**kwargs):

@ctrl.add("run_simulation")
def run_simulation_and_store():
state.simulation_complete = (True,)
state.plot_options = available_plot_options(simulationClicked=True)
run_simulation_impactX()
update_plot()
Expand Down Expand Up @@ -228,7 +229,7 @@ def plot():
with vuetify.VCard(style="height: 50vh; width: 150vh;"):
with vuetify.VTabs(v_model=("active_tab", 0)):
vuetify.VTab("Plot")
vuetify.VTab("Interact")
vuetify.VTab("Interact", id="interact")
vuetify.VDivider()
with vuetify.VTabsItems(v_model="active_tab"):
with vuetify.VTabItem():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ def on_distribution_type_change(**kwargs):

@ctrl.add("updateDistributionParameters")
def on_distribution_parameter_change(parameter_name, parameter_value, parameter_type):
parameter_value, input_type = generalFunctions.determine_input_type(parameter_value)
error_message = generalFunctions.validate_against(parameter_value, parameter_type)

update_distribution_parameters(parameter_name, parameter_value, error_message)
Expand Down Expand Up @@ -198,13 +197,15 @@ def card():
with vuetify.VCol(cols=6):
vuetify.VCombobox(
label="Select Distribution",
id="selected_distribution",
v_model=("selectedDistribution",),
items=("listOfDistributions",),
dense=True,
)
with vuetify.VCol(cols=6):
vuetify.VSelect(
v_model=("selectedDistributionType",),
id="selected_distribution_type",
label="Type",
items=(["Twiss", "Quadratic Form"],),
dense=True,
Expand All @@ -221,6 +222,7 @@ def card():
):
vuetify.VTextField(
label=("parameter.parameter_name",),
id=("parameter.parameter_name",),
v_model=("parameter.parameter_default_value",),
suffix=("parameter.parameter_units",),
change=(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def card(self):
vuetify.VTextField(
v_model=("npart",),
label="Number of Particles",
id="npart",
error_messages=("npart_validation",),
change=(
ctrl.on_input_change,
Expand All @@ -154,6 +155,7 @@ def card(self):
vuetify.VTextField(
v_model=("kin_energy",),
label="Kinetic Energy",
id="kin_energy",
error_messages=("kin_energy_validation",),
change=(
ctrl.on_input_change,
Expand All @@ -167,6 +169,7 @@ def card(self):
vuetify.VSelect(
v_model=("kin_energy_unit",),
label="Unit",
id="kin_energy_unit",
items=(["meV", "eV", "keV", "MeV", "GeV", "TeV"],),
change=(ctrl.kin_energy_unit_change, "[$event]"),
dense=True,
Expand All @@ -175,6 +178,7 @@ def card(self):
with vuetify.VCol(cols=8, classes="py-0"):
vuetify.VTextField(
label="Bunch Charge",
id="bunch_charge_C",
v_model=("bunch_charge_C",),
error_messages=("bunch_charge_C_validation",),
change=(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ def on_add_lattice_element_click():
def on_lattice_element_parameter_change(
index, parameter_name, parameter_value, parameter_type
):
parameter_value, input_type = generalFunctions.determine_input_type(parameter_value)
error_message = generalFunctions.validate_against(parameter_value, parameter_type)

update_latticeElement_parameters(
Expand Down Expand Up @@ -253,6 +252,7 @@ def card():
with vuetify.VCol(cols=8):
vuetify.VCombobox(
label="Select Accelerator Lattice",
id="selected_lattice",
v_model=("selectedLattice", None),
items=("listOfLatticeElements",),
error_messages=("isSelectedLatticeListEmpty",),
Expand All @@ -262,6 +262,7 @@ def card():
with vuetify.VCol(cols="auto"):
vuetify.VBtn(
"ADD",
id="add_button",
color="primary",
dense=True,
classes="mr-2",
Expand All @@ -270,6 +271,7 @@ def card():
with vuetify.VCol(cols="auto"):
vuetify.VBtn(
"CLEAR",
id="clear_button",
color="secondary",
dense=True,
classes="mr-2",
Expand All @@ -279,6 +281,7 @@ def card():
vuetify.VIcon(
"mdi-cog",
click="showDialog_settings = true",
id="lattice_settings_icon",
)
with vuetify.VRow():
with vuetify.VCol():
Expand Down Expand Up @@ -337,6 +340,7 @@ def card():
):
vuetify.VTextField(
label=("parameter.parameter_name",),
id=("parameter.parameter_name + index",),
v_model=(
"parameter.parameter_default_value",
),
Expand Down Expand Up @@ -420,6 +424,7 @@ def dialog_lattice_settings():
with vuetify.VCol(no_gutters=True):
vuetify.VTextField(
v_model=("nsliceDefaultValue",),
id="nslice_default_value",
change=(
ctrl.nsliceDefaultChange,
"['nslice', $event]",
Expand All @@ -431,3 +436,13 @@ def dialog_lattice_settings():
style="max-width: 75px",
classes="ma-0 pa-0",
)
vuetify.VDivider()
with vuetify.VCardActions():
vuetify.VSpacer()
vuetify.VBtn(
"Close",
id="lattice_settings_close",
color="primary",
text=True,
click="showDialog_settings = false",
)
2 changes: 1 addition & 1 deletion src/python/impactx/dashboard/Input/trameFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ def create_route(route_title, mdi_icon):
with vuetify.VListItemIcon():
vuetify.VIcon(mdi_icon)
with vuetify.VListItemContent():
vuetify.VListItemTitle(route_title)
vuetify.VListItemTitle(route_title, id=f"{route_title}_route")
14 changes: 14 additions & 0 deletions src/python/impactx/dashboard/Toolbar/toolbarMain.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def plot_options():
v_model=("active_plot", "1D plots over s"),
items=("plot_options",),
label="Select plot to view",
id="select_plot",
hide_details=True,
dense=True,
style="max-width: 250px",
Expand All @@ -61,11 +62,23 @@ def plot_options():
def run_simulation_button():
vuetify.VBtn(
"Run Simulation",
id="run_simulation_button",
style="background-color: #00313C; color: white; margin: 0 20px;",
click=ctrl.run_simulation,
disabled=("disableRunSimulationButton", True),
)

@staticmethod
def show_simulation_complete():
vuetify.VAlert(
"Simulation Complete",
v_model=("simulation_complete", False),
id="simulation_complete",
type="success",
dense=True,
classes="mt-4",
)

@staticmethod
def dashboard_info():
"""
Expand Down Expand Up @@ -106,6 +119,7 @@ def run_toolbar():

(ToolbarElements.dashboard_info(),)
(vuetify.VSpacer(),)
(ToolbarElements.show_simulation_complete(),)
(ToolbarElements.run_simulation_button(),)

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion src/python/impactx/dashboard/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
# GUI
# -----------------------------------------------------------------------------
def init_terminal():
with xterm.XTerm(v_if="$route.path == '/Run'") as term:
with xterm.XTerm(v_show="$route.path == '/Run'", id="xterm_component") as term:
ctrl.terminal_print = term.writeln


Expand Down
9 changes: 9 additions & 0 deletions tests/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ file(MAKE_DIRECTORY ${pytest_rundir})
file(COPY ${ImpactX_SOURCE_DIR}/examples
DESTINATION ${pytest_rundir})

file(COPY ${ImpactX_SOURCE_DIR}/src/python/impactx/dashboard
DESTINATION ${pytest_rundir})

# run
add_test(NAME ${pytest_name}
COMMAND ${Python_EXECUTABLE} -m pytest -s -vvvv
Expand All @@ -22,3 +25,9 @@ set_property(TEST ${pytest_name} APPEND PROPERTY ENVIRONMENT "OMP_NUM_THREADS=2"

# set PYTHONPATH and PATH (for .dll files)
impactx_test_set_pythonpath(${pytest_name})

# Add environment variables needed for dashboard tests
set_property(TEST ${pytest_name} APPEND PROPERTY ENVIRONMENT
"DISPLAY=:99"
"PYTHONPATH=${pytest_rundir}:$ENV{PYTHONPATH}"
)
92 changes: 92 additions & 0 deletions tests/python/dashboard/test_dashboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import importlib

import pytest
from util import (
check_until_visible,
set_input_value,
start_dashboard,
wait_for_dashboard_ready,
wait_for_ready,
)

TIMEOUT = 60


@pytest.mark.skipif(
importlib.util.find_spec("seleniumbase") is None,
reason="seleniumbase is not available",
)
def test_dashboard():
"""
This test runs the FODO example on the dashboard and verifies
that the simulation has run successfully.
"""
from seleniumbase import SB

app_process = None

try:
with SB(headless=True) as sb:
app_process = start_dashboard()
wait_for_dashboard_ready(app_process, timeout=TIMEOUT)

url = "http://localhost:8080/index.html#/Input"
sb.open(url)

wait_for_ready(sb, ".trame__loader", TIMEOUT)

# Adjust beam properties
set_input_value(sb, "npart", 10000)
set_input_value(sb, "kin_energy", 2.0e3)
set_input_value(sb, "bunch_charge_C", 1.0e-9)

# Change distribution type to "Quadratic"
sb.click("#selected_distribution_type")
sb.click("div.v-list-item__title:contains('Quadratic Form')")

# Adjust beam distribution
set_input_value(sb, "selected_distribution", "Waterbag")
set_input_value(sb, "lambdaX", 3.9984884770e-5)
set_input_value(sb, "lambdaY", 3.9984884770e-5)
set_input_value(sb, "lambdaT", 1.0e-3)
set_input_value(sb, "lambdaPx", 2.6623538760e-5)
set_input_value(sb, "lambdaPy", 2.6623538760e-5)
set_input_value(sb, "lambdaPt", 2.0e-3)
set_input_value(sb, "muxpx", -0.846574929020762)
set_input_value(sb, "muypy", 0.846574929020762)
set_input_value(sb, "mutpt", 0.0)

# Adjust lattice configuration
sb.click("#lattice_settings_icon")
set_input_value(sb, "nslice_default_value", 25)
sb.click("#lattice_settings_close")
sb.click("#clear_button")
set_input_value(sb, "selected_lattice", "Drift")
sb.click("#add_button")
set_input_value(sb, "ds0", 0.25)
set_input_value(sb, "selected_lattice", "Quad")
sb.click("#add_button")
set_input_value(sb, "ds1", 1.0)
set_input_value(sb, "k1", 1.0)
set_input_value(sb, "selected_lattice", "Drift")
sb.click("#add_button")
set_input_value(sb, "ds2", 0.5)
set_input_value(sb, "selected_lattice", "Quad")
sb.click("#add_button")
set_input_value(sb, "ds3", 1.0)
set_input_value(sb, "k3", -1.0)
set_input_value(sb, "selected_lattice", "Drift")
sb.click("#add_button")
set_input_value(sb, "ds4", 0.25)

# Run simulation
sb.click("#Run_route")
sb.click("#run_simulation_button")

assert check_until_visible(
sb, "#simulation_complete"
), "Simulation did not complete successfully."

finally:
if app_process is not None:
app_process.terminate()
Loading
Loading