Metadata-Version: 2.4
Name: galaxy-selenium
Version: 26.0.1.dev0
Summary: Galaxy Selenium interaction framework
Home-page: https://github.com/galaxyproject/galaxy
Author: Galaxy Project and Community
Author-email: galaxy-committers@lists.galaxyproject.org
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/x-rst
License-File: LICENSE
Requires-Dist: galaxy-navigation
Requires-Dist: galaxy-util
Requires-Dist: axe-selenium-python
Requires-Dist: PyYAML
Requires-Dist: requests
Requires-Dist: selenium!=4.11.0,!=4.11.1,!=4.11.2
Requires-Dist: playwright
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Dynamic: license-file


.. image:: https://badge.fury.io/py/galaxy-selenium.svg
   :target: https://pypi.org/project/galaxy-selenium/


Galaxy Browser Automation Framework
------------------------------------

.. note::
   The package is named ``galaxy-selenium`` for historical reasons, but a more accurate name
   would be ``galaxy-browser-automation`` since it supports both Selenium and Playwright backends.

Overview
--------

This package provides a browser automation framework for Galaxy_ with:

* **Multi-backend support**: Selenium and Playwright backends with a unified API
* **Protocol-based architecture**: Clean separation between Galaxy logic and browser interaction
* **Comprehensive testing**: Full unit test coverage for both backends
* **CLI tooling**: Utilities for building command-line automation scripts
* **Type safety**: Full type hints with mypy validation

* Code: https://github.com/galaxyproject/galaxy

.. _Galaxy: http://galaxyproject.org/


Architecture
------------

.. rubric:: Core Interfaces

The framework is built around two main protocol interfaces:

**HasDriverProtocol** (``has_driver_protocol.py``)
    Defines ~60+ browser automation operations including:

    - Element finding (by ID, selector, XPath, etc.)
    - Wait methods (visible, clickable, absent, etc.)
    - Interactions (click, hover, drag-and-drop, keyboard input)
    - Navigation (URLs, frames, alerts)
    - JavaScript execution
    - Accessibility testing (axe-core integration)

**WebElementProtocol** (``web_element_protocol.py``)
    Defines the common element API:

    - ``text``, ``click()``, ``send_keys()``, ``clear()``
    - ``get_attribute()``, ``is_displayed()``, ``is_enabled()``
    - ``find_element()``, ``find_elements()``
    - ``value_of_css_property()`` for CSS introspection


.. rubric:: Architecture Diagram

::

    ┌─────────────────────────────────────────────────────┐
    │         Galaxy Application Layer                     │
    │                                                       │
    │  NavigatesGalaxy (navigates_galaxy.py)              │
    │  - Galaxy-specific page objects                      │
    │  - Workflow interactions                             │
    │  - History management                                │
    │  - Tool execution                                    │
    └────────────────┬────────────────────────────────────┘
                     │ extends
                     ↓
    ┌─────────────────────────────────────────────────────┐
    │      Browser Automation Abstraction Layer           │
    │                                                       │
    │  HasDriverProxy (has_driver_proxy.py)               │
    │  - Delegates to HasDriverProtocol implementation     │
    │  - Runtime backend selection via composition         │
    └────────────────┬────────────────────────────────────┘
                     │ uses
                     ↓
    ┌──────────────────────────────────┬──────────────────┐
    │   HasDriverProtocol              │                  │
    │   (has_driver_protocol.py)       │                  │
    │   - Abstract interface           │                  │
    │   - ~60+ operations              │                  │
    └──────────────┬───────────────────┴──────────────────┘
                   │ implemented by
         ┌─────────┴──────────┐
         ↓                    ↓
    ┌─────────────┐    ┌──────────────────┐
    │  HasDriver  │    │ HasPlaywright    │
    │             │    │ Driver           │
    │ Selenium    │    │                  │
    │ backend     │    │ Playwright       │
    │             │    │ backend          │
    └──────┬──────┘    └────────┬─────────┘
           │                    │
           ↓                    ↓
    ┌─────────────┐    ┌──────────────────┐
    │ WebElement  │    │ PlaywrightElement│
    │ (Selenium)  │    │ (wrapper)        │
    │             │    │                  │
    │ implements  │    │ implements       │
    │ protocol    │    │ protocol         │
    └─────────────┘    └──────────────────┘
           │                    │
           └──────────┬─────────┘
                      ↓
           WebElementProtocol
           (web_element_protocol.py)


.. rubric:: Implementations

**Selenium Backend** (``has_driver.py``)
    - Uses Selenium WebDriver
    - Direct WebElement support (implements protocol natively)
    - Mature, widely-used automation framework
    - Supports remote execution (Selenium Grid)

**Playwright Backend** (``has_playwright_driver.py``)
    - Uses Playwright sync API
    - PlaywrightElement wrapper (adapts ElementHandle to protocol)
    - Modern automation with auto-waiting
    - Fast and reliable for modern web apps
    - Local execution only (no remote support)

Both implementations:

- Share identical test suite (150+ parametrized tests)
- Provide consistent API via protocols
- Support headless and headed modes
- Include full type hints


.. rubric:: Separation of Concerns

::

    Application Logic          │  Browser Automation
    (Galaxy-specific)         │  (Generic, reusable)
    ─────────────────────────────────────────────────
    navigates_galaxy.py       │  has_driver_protocol.py
    - Galaxy UI interactions  │  - Abstract interface
    - Workflow automation     │  - Element finding
    - History operations      │  - Wait strategies
    - Tool wrappers           │  - Interactions
                              │
    smart_components.py       │  has_driver.py
    - Galaxy component        │  - Selenium impl
      wrappers                │
    - Page object patterns    │  has_playwright_driver.py
                              │  - Playwright impl
                              │
                              │  web_element_protocol.py
                              │  - Element interface

**Key Principle**: Galaxy-specific logic lives in ``navigates_galaxy.py`` and extends the
generic browser automation protocols. This separation allows:

- Testing browser automation independently
- Reusing automation primitives across projects
- Switching backends without changing application code
- Clear boundaries between concerns


Testing
-------

The framework includes comprehensive unit tests in ``test/unit/selenium/test_has_driver.py``:

- **Parametrized tests**: Every test runs against Selenium, Playwright, and proxied backends
- **150+ test cases** covering all protocol methods
- **Test fixtures**: Reusable HTML pages served via local HTTP server
- **Scope-optimized**: Session-scoped server, function-scoped drivers

Run tests from the package directory::

    # All tests
    uv run pytest tests/seleniumtests/test_has_driver.py -v

    # Specific test class
    uv run pytest tests/seleniumtests/test_has_driver.py::TestElementFinding -v

    # Type checking
    make mypy

.. warning::
    Always run pytest from the package directory (``packages/selenium/``), not from the
    monorepo root. Running from root can cause fixture scope issues.


Building CLI Tools
------------------

The ``cli.py`` module provides infrastructure for building command-line automation tools.

.. rubric:: Core Components

**add_selenium_arguments(parser)**
    Adds standard CLI arguments:

    - ``--selenium-browser``: Browser choice (chrome, firefox, auto)
    - ``--selenium-headless``: Headless mode flag
    - ``--backend``: Backend selection (selenium, playwright)
    - ``--galaxy_url``: Target Galaxy instance URL
    - ``--selenium-remote``: Remote execution (Selenium only)

**DriverWrapper**
    Adapts argparse args to a NavigatesGalaxy instance:

    - Handles backend selection
    - Manages virtual display (for headless Selenium)
    - Provides Galaxy navigation utilities
    - Cleanup via ``finish()`` method

.. rubric:: Example: dump_tour.py

The ``scripts/dump_tour.py`` script demonstrates CLI tool development:

.. code-block:: python

    #!/usr/bin/env python
    import argparse
    from galaxy.selenium import cli

    def main(argv=None):
        args = _arg_parser().parse_args(argv)
        driver_wrapper = cli.DriverWrapper(args)

        # Use driver_wrapper for automation
        callback = DumpTourCallback(driver_wrapper, args.output)
        driver_wrapper.run_tour(args.tour, tour_callback=callback)

    def _arg_parser():
        parser = argparse.ArgumentParser(description="Walk a Galaxy tour")
        parser.add_argument("tour", help="tour to walk")
        parser.add_argument("-o", "--output", help="screenshot output dir")
        parser = cli.add_selenium_arguments(parser)  # Add standard args
        return parser

    class DumpTourCallback:
        def handle_step(self, step, step_index: int):
            self.driver_wrapper.save_screenshot(f"{output}/{step_index}.png")

Usage::

    # With Selenium backend
    python dump_tour.py my_tour.yaml --backend selenium --selenium-headless

    # With Playwright backend
    python dump_tour.py my_tour.yaml --backend playwright --galaxy_url http://localhost:8080


.. rubric:: Building Your Own CLI Tool

1. **Import the CLI utilities**::

    from galaxy.selenium import cli

2. **Create argument parser**::

    parser = argparse.ArgumentParser(description="My automation tool")
    parser.add_argument("--my-option", help="Custom option")
    parser = cli.add_selenium_arguments(parser)  # Add standard args

3. **Create DriverWrapper**::

    args = parser.parse_args()
    driver_wrapper = cli.DriverWrapper(args)

4. **Use NavigatesGalaxy API**::

    # driver_wrapper has all NavigatesGalaxy methods
    driver_wrapper.navigate_to(url)
    driver_wrapper.click_selector("#my-button")
    driver_wrapper.wait_for_selector_visible(".result")

5. **Clean up**::

    driver_wrapper.finish()  # Quits driver and stops virtual display


Development
-----------

.. rubric:: Package Structure

::

    packages/selenium/
    ├── galaxy/selenium/          # Symlink to lib/galaxy/selenium/
    ├── tests/seleniumtests/      # Symlink to test/unit/selenium/
    ├── README.rst                # This file
    └── pyproject.toml

    lib/galaxy/selenium/          # Actual source code
    ├── has_driver_protocol.py    # Protocol interface
    ├── has_driver.py             # Selenium implementation
    ├── has_playwright_driver.py  # Playwright implementation
    ├── web_element_protocol.py   # Element interface
    ├── playwright_element.py     # Element wrapper
    ├── navigates_galaxy.py       # Galaxy-specific logic
    ├── smart_components.py       # Component wrappers
    ├── cli.py                    # CLI utilities
    └── scripts/
        └── dump_tour.py          # Example CLI tool

    test/unit/selenium/           # Actual tests
    ├── conftest.py               # Pytest fixtures
    ├── test_has_driver.py        # Main test suite
    └── fixtures/                 # HTML test pages


.. rubric:: Running Commands

Always use ``uv run`` from the package directory::

    # Run tests
    uv run pytest tests/seleniumtests/test_has_driver.py -v

    # Type checking
    make mypy

    # Linting
    uv run ruff check .


.. rubric:: Adding New Low-Level Browser Operations

Low-level operations are generic browser automation primitives that work with both backends.

**Manual Process:**

1. **Add to protocol** (``has_driver_protocol.py``)::

    @abstractmethod
    def my_new_operation(self, param: str) -> bool:
        """Do something useful."""
        ...

2. **Implement in Selenium** (``has_driver.py``)::

    def my_new_operation(self, param: str) -> bool:
        # Selenium implementation
        return self.driver.do_something(param)

3. **Implement in Playwright** (``has_playwright_driver.py``)::

    def my_new_operation(self, param: str) -> bool:
        # Playwright implementation
        return self.page.do_something(param)

4. **Update proxy** (``has_driver_proxy.py``)::

    def my_new_operation(self, param: str) -> bool:
        """Do something useful."""
        return self._driver_impl.my_new_operation(param)

5. **Add tests** (``test_has_driver.py``)::

    def test_my_new_operation(self, has_driver_instance, base_url):
        """Test new operation works on both backends."""
        has_driver_instance.navigate_to(f"{base_url}/test.html")
        result = has_driver_instance.my_new_operation("test")
        assert result is True

**Automated Process:**

Use the ``/add-browser-operation`` slash command to automate these steps::

    /add-browser-operation scroll element to center of viewport

This command will generate all the necessary code across all files and create tests.


.. rubric:: Adding New Smart Component Operations

Smart component operations are higher-level conveniences that may require adding low-level
operations first. These operations make Galaxy components more ergonomic to use in tests.

**When to Add Smart Operations:**

- When you find yourself repeating a pattern of low-level operations
- When Galaxy-specific UI patterns need convenient wrappers
- When you want to express test intent more clearly

**Process:**

1. **Determine if low-level support exists**:

   Check if the required browser operation exists in ``HasDriverProtocol``. If not,
   add it first using the process above (or ``/add-browser-operation``).

2. **Add to SmartTarget** (``smart_components.py``):

   Add a method to the ``SmartTarget`` class::

    def my_smart_operation(self, **kwds):
        """High-level operation description."""
        # Delegate to has_driver protocol methods
        element = self._has_driver.wait_for_visible(self._target, **kwds)
        return self._has_driver.my_low_level_operation(element)

3. **Consider return value wrapping**:

   If your operation returns a Component or Target, wrap it::

    def get_child_component(self, name: str):
        """Get a child component and wrap it smartly."""
        child = self._target.get_child(name)
        return self._wrap(child)  # Returns SmartTarget

4. **Add tests** (``test/unit/selenium/test_smart_components.py``):

   Test with both backends using the ``has_driver_instance`` fixture::

    def test_my_smart_operation(self, has_driver_instance, base_url):
        has_driver_instance.navigate_to(f"{base_url}/smart_components.html")

        # Use SmartComponent wrapping
        component = SmartComponent(MyComponent(), has_driver_instance)
        result = component.my_target.my_smart_operation()

        assert result is not None

**Example: Adding a "wait_for_and_hover" operation**

This demonstrates when you need to add a low-level operation first:

1. **Check low-level support**: ``hover()`` already exists in ``HasDriverProtocol`` ✓

2. **Add to SmartTarget**::

    def wait_for_and_hover(self, **kwds):
        """Wait for element to be visible and hover over it."""
        element = self._has_driver.wait_for_visible(self._target, **kwds)
        self._has_driver.hover(element)
        return element

3. **Usage in tests**::

    # Before: Multiple steps
    element = driver.wait_for_visible(component.menu)
    driver.hover(element)

    # After: One expressive call
    component.menu.wait_for_and_hover()

**Example: Adding operation requiring new low-level support**

When the operation needs a new browser primitive:

1. **Add low-level operation** (see "Adding New Low-Level Browser Operations"):

   Add ``scroll_to_center(element)`` to protocols and implementations

2. **Add smart wrapper**::

    def wait_for_and_scroll_to_center(self, **kwds):
        """Wait for element and scroll it to viewport center."""
        element = self._has_driver.wait_for_visible(self._target, **kwds)
        self._has_driver.scroll_to_center(element)
        return element

3. **Test both levels**:

   - Test low-level in ``test_has_driver.py``
   - Test smart wrapper in ``test_smart_components.py``


See Also
--------

* `Selenium Documentation <https://www.selenium.dev/documentation/>`_
* `Playwright Documentation <https://playwright.dev/python/>`_
* `Galaxy Testing Documentation <https://docs.galaxyproject.org/en/latest/dev/writing_tests.html>`_

History
-------

.. to_doc

-----------
26.0.1.dev0
-----------



-------------------
26.0.0 (2026-04-08)
-------------------


=========
Bug fixes
=========

* Attempt to fix transiently failing tests that click this tab. by `@jmchilton <https://github.com/jmchilton>`_ in `#21376 <https://github.com/galaxyproject/galaxy/pull/21376>`_
* Fix selenium test test_rename_history by `@davelopez <https://github.com/davelopez>`_ in `#21835 <https://github.com/galaxyproject/galaxy/pull/21835>`_

============
Enhancements
============

* Replace Copy Dataset Mako with Vue Component by `@guerler <https://github.com/guerler>`_ in `#17507 <https://github.com/galaxyproject/galaxy/pull/17507>`_
* Selenium test cases for IGV. by `@jmchilton <https://github.com/jmchilton>`_ in `#21034 <https://github.com/galaxyproject/galaxy/pull/21034>`_
* Selenium test for #20886 (sharing private histories) by `@jmchilton <https://github.com/jmchilton>`_ in `#21040 <https://github.com/galaxyproject/galaxy/pull/21040>`_
* Remove jquery from legacy onload helpers and Rule Builder by `@guerler <https://github.com/guerler>`_ in `#21063 <https://github.com/galaxyproject/galaxy/pull/21063>`_
* Add Playwright Backend Support to Galaxy Browser Automation Framework by `@jmchilton <https://github.com/jmchilton>`_ in `#21102 <https://github.com/galaxyproject/galaxy/pull/21102>`_
* Implement workflow completion monitoring with extensible hooks by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21532 <https://github.com/galaxyproject/galaxy/pull/21532>`_
* Clean up code with pyupgrade by `@nsoranzo <https://github.com/nsoranzo>`_ in `#21540 <https://github.com/galaxyproject/galaxy/pull/21540>`_
* Drop support for Python 3.9 by `@nsoranzo <https://github.com/nsoranzo>`_ in `#21583 <https://github.com/galaxyproject/galaxy/pull/21583>`_

-------------------
25.1.2 (2026-03-09)
-------------------

No recorded changes since last release

-------------------
25.1.1 (2026-02-03)
-------------------


=========
Bug fixes
=========

* Usability fixes for sample sheet selection.  by `@jmchilton <https://github.com/jmchilton>`_ in `#21503 <https://github.com/galaxyproject/galaxy/pull/21503>`_

-------------------
25.1.0 (2025-12-12)
-------------------


=========
Bug fixes
=========

* Fix transient selenium error when adding collection input. by `@jmchilton <https://github.com/jmchilton>`_ in `#20460 <https://github.com/galaxyproject/galaxy/pull/20460>`_

============
Enhancements
============

* Implement Sample Sheets  by `@jmchilton <https://github.com/jmchilton>`_ in `#19305 <https://github.com/galaxyproject/galaxy/pull/19305>`_
* Refactor Object Store Selection Modals UI by `@itisAliRH <https://github.com/itisAliRH>`_ in `#19697 <https://github.com/galaxyproject/galaxy/pull/19697>`_
* Selenium tests for various 24.2 features. by `@jmchilton <https://github.com/jmchilton>`_ in `#20215 <https://github.com/galaxyproject/galaxy/pull/20215>`_
* Split Login and Register, enable OIDC Registration. by `@uwwint <https://github.com/uwwint>`_ in `#20287 <https://github.com/galaxyproject/galaxy/pull/20287>`_
* Add short term storage expiration indicator to history items by `@davelopez <https://github.com/davelopez>`_ in `#20332 <https://github.com/galaxyproject/galaxy/pull/20332>`_
* Type annotation fixes for mypy 1.16.0 by `@nsoranzo <https://github.com/nsoranzo>`_ in `#20424 <https://github.com/galaxyproject/galaxy/pull/20424>`_
* Clean up code from pyupgrade by `@nsoranzo <https://github.com/nsoranzo>`_ in `#20642 <https://github.com/galaxyproject/galaxy/pull/20642>`_
* New History List Using GCard by `@itisAliRH <https://github.com/itisAliRH>`_ in `#20744 <https://github.com/galaxyproject/galaxy/pull/20744>`_

-------------------
25.0.4 (2025-11-18)
-------------------

No recorded changes since last release

-------------------
25.0.3 (2025-09-23)
-------------------

No recorded changes since last release

-------------------
25.0.2 (2025-08-13)
-------------------

No recorded changes since last release

-------------------
25.0.1 (2025-06-20)
-------------------

No recorded changes since last release

-------------------
25.0.0 (2025-06-18)
-------------------


=========
Bug fixes
=========

* Revise consistently failing edam tool panel view test. by `@jmchilton <https://github.com/jmchilton>`_ in `#19762 <https://github.com/galaxyproject/galaxy/pull/19762>`_
* Wait for Gbutton to become enabled by `@mvdbeek <https://github.com/mvdbeek>`_ in `#20131 <https://github.com/galaxyproject/galaxy/pull/20131>`_
* Fix workflow bookmark filtering by `@davelopez <https://github.com/davelopez>`_ in `#20325 <https://github.com/galaxyproject/galaxy/pull/20325>`_

============
Enhancements
============

* Workflow Editor Activity Bar by `@ElectronicBlueberry <https://github.com/ElectronicBlueberry>`_ in `#18729 <https://github.com/galaxyproject/galaxy/pull/18729>`_
* Fix UP031 errors - Part 4 by `@nsoranzo <https://github.com/nsoranzo>`_ in `#19235 <https://github.com/galaxyproject/galaxy/pull/19235>`_
* Workflow Run Form Enhancements by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#19294 <https://github.com/galaxyproject/galaxy/pull/19294>`_
* Empower Users to Build More Kinds of Collections, More Intelligently by `@jmchilton <https://github.com/jmchilton>`_ in `#19377 <https://github.com/galaxyproject/galaxy/pull/19377>`_
* Click to edit history name in `HistoryPanel` by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#19665 <https://github.com/galaxyproject/galaxy/pull/19665>`_
* Fix Tours and add tooltips to history items by `@guerler <https://github.com/guerler>`_ in `#19734 <https://github.com/galaxyproject/galaxy/pull/19734>`_
* Introduce reusable GCard component for unified card layout by `@itisAliRH <https://github.com/itisAliRH>`_ in `#19785 <https://github.com/galaxyproject/galaxy/pull/19785>`_
* Add history sharing and accessibility management view by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#19786 <https://github.com/galaxyproject/galaxy/pull/19786>`_
* Replace backend-based page creation controller endpoint by `@guerler <https://github.com/guerler>`_ in `#19914 <https://github.com/galaxyproject/galaxy/pull/19914>`_
* Implement dataset collection support in workflow landing requests by `@mvdbeek <https://github.com/mvdbeek>`_ in `#20004 <https://github.com/galaxyproject/galaxy/pull/20004>`_
* Add ZIP explorer to import individual files from local or remote ZIP archives by `@davelopez <https://github.com/davelopez>`_ in `#20054 <https://github.com/galaxyproject/galaxy/pull/20054>`_
* Client refactorings ahead of #19377.   by `@jmchilton <https://github.com/jmchilton>`_ in `#20059 <https://github.com/galaxyproject/galaxy/pull/20059>`_
* Revise transiently failing data source test. by `@jmchilton <https://github.com/jmchilton>`_ in `#20157 <https://github.com/galaxyproject/galaxy/pull/20157>`_
* Visualization-First Display functionality by `@dannon <https://github.com/dannon>`_ in `#20190 <https://github.com/galaxyproject/galaxy/pull/20190>`_
* Touch up Dataset View by `@guerler <https://github.com/guerler>`_ in `#20290 <https://github.com/galaxyproject/galaxy/pull/20290>`_
* DatasetView and Card Polish by `@dannon <https://github.com/dannon>`_ in `#20342 <https://github.com/galaxyproject/galaxy/pull/20342>`_

-------------------
24.2.4 (2025-06-17)
-------------------


=========
Bug fixes
=========

* Always set copy_elements to true by `@mvdbeek <https://github.com/mvdbeek>`_ in `#19985 <https://github.com/galaxyproject/galaxy/pull/19985>`_

-------------------
24.2.3 (2025-03-16)
-------------------

No recorded changes since last release

-------------------
24.2.2 (2025-03-08)
-------------------

No recorded changes since last release

-------------------
24.2.1 (2025-02-28)
-------------------


=========
Bug fixes
=========

* Set content-type to text/plain if dataset not safe by `@mvdbeek <https://github.com/mvdbeek>`_ in `#19563 <https://github.com/galaxyproject/galaxy/pull/19563>`_

-------------------
24.2.0 (2025-02-11)
-------------------


=========
Bug fixes
=========

* Fixes for errors reported by mypy 1.11.0 by `@nsoranzo <https://github.com/nsoranzo>`_ in `#18608 <https://github.com/galaxyproject/galaxy/pull/18608>`_
* Fix transiently failing selenium tooltip issues by `@jmchilton <https://github.com/jmchilton>`_ in `#18847 <https://github.com/galaxyproject/galaxy/pull/18847>`_
* release testing - UI tests for new workflow parameters by `@jmchilton <https://github.com/jmchilton>`_ in `#19182 <https://github.com/galaxyproject/galaxy/pull/19182>`_

============
Enhancements
============

* Masthead Revision by `@guerler <https://github.com/guerler>`_ in `#17927 <https://github.com/galaxyproject/galaxy/pull/17927>`_
* Moves Libraries from Masthead to Activity Bar by `@guerler <https://github.com/guerler>`_ in `#18468 <https://github.com/galaxyproject/galaxy/pull/18468>`_
* Replace History Dataset Picker in Library Folder by `@itisAliRH <https://github.com/itisAliRH>`_ in `#18518 <https://github.com/galaxyproject/galaxy/pull/18518>`_
* Workflow Invocation view improvements by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#18615 <https://github.com/galaxyproject/galaxy/pull/18615>`_
* Guide users to collection builders by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#18857 <https://github.com/galaxyproject/galaxy/pull/18857>`_
* Workflow license and creator edit keyboard access by `@itisAliRH <https://github.com/itisAliRH>`_ in `#18936 <https://github.com/galaxyproject/galaxy/pull/18936>`_
* Workflow landing improvements by `@mvdbeek <https://github.com/mvdbeek>`_ in `#18979 <https://github.com/galaxyproject/galaxy/pull/18979>`_
* Backport of Workflow Editor Activity Bar by `@dannon <https://github.com/dannon>`_ in `#19212 <https://github.com/galaxyproject/galaxy/pull/19212>`_
* Various list of pairs builder usability fixes. by `@jmchilton <https://github.com/jmchilton>`_ in `#19248 <https://github.com/galaxyproject/galaxy/pull/19248>`_
* Workflow Inputs Activity by `@ElectronicBlueberry <https://github.com/ElectronicBlueberry>`_ in `#19252 <https://github.com/galaxyproject/galaxy/pull/19252>`_

-------------------
24.1.4 (2024-12-11)
-------------------


=========
Bug fixes
=========

* Persist uploaded data between Regular and Collection upload tabs by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#19083 <https://github.com/galaxyproject/galaxy/pull/19083>`_

-------------------
24.1.3 (2024-10-25)
-------------------

No recorded changes since last release

-------------------
24.1.2 (2024-09-25)
-------------------

No recorded changes since last release

-------------------
24.1.1 (2024-07-02)
-------------------


=========
Bug fixes
=========

* Fix (I think) a transiently failing selenium error. by `@jmchilton <https://github.com/jmchilton>`_ in `#18065 <https://github.com/galaxyproject/galaxy/pull/18065>`_

============
Enhancements
============

* Add admin activity to activity bar by `@guerler <https://github.com/guerler>`_ in `#17877 <https://github.com/galaxyproject/galaxy/pull/17877>`_
* Add galaxy to user agent by `@mvdbeek <https://github.com/mvdbeek>`_ in `#18003 <https://github.com/galaxyproject/galaxy/pull/18003>`_
* Consolidate Visualization container, avoid using default iframe by `@guerler <https://github.com/guerler>`_ in `#18016 <https://github.com/galaxyproject/galaxy/pull/18016>`_
* Update Python dependencies by `@galaxybot <https://github.com/galaxybot>`_ in `#18063 <https://github.com/galaxyproject/galaxy/pull/18063>`_
* Empower users to bring their own storage and file sources by `@jmchilton <https://github.com/jmchilton>`_ in `#18127 <https://github.com/galaxyproject/galaxy/pull/18127>`_

-------------------
24.0.3 (2024-06-28)
-------------------

No recorded changes since last release

-------------------
24.0.2 (2024-05-07)
-------------------

No recorded changes since last release

-------------------
24.0.1 (2024-05-02)
-------------------


=========
Bug fixes
=========

* Set from_tool_form: true when saving new workflow by `@mvdbeek <https://github.com/mvdbeek>`_ in `#17972 <https://github.com/galaxyproject/galaxy/pull/17972>`_

-------------------
24.0.0 (2024-04-02)
-------------------


=========
Bug fixes
=========

* Update tour testing selector usage. by `@jmchilton <https://github.com/jmchilton>`_ in `#14005 <https://github.com/galaxyproject/galaxy/pull/14005>`_
* Fix history filters taking up space in `GridList` by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#17652 <https://github.com/galaxyproject/galaxy/pull/17652>`_

============
Enhancements
============

* New Workflow List and Card View by `@itisAliRH <https://github.com/itisAliRH>`_ in `#16607 <https://github.com/galaxyproject/galaxy/pull/16607>`_
* Python 3.8 as minimum by `@mr-c <https://github.com/mr-c>`_ in `#16954 <https://github.com/galaxyproject/galaxy/pull/16954>`_
* Vueifiy History Grids by `@guerler <https://github.com/guerler>`_ in `#17219 <https://github.com/galaxyproject/galaxy/pull/17219>`_
* Adds delete, purge and undelete batch operations to History Grid by `@guerler <https://github.com/guerler>`_ in `#17282 <https://github.com/galaxyproject/galaxy/pull/17282>`_
* Custom Multiselect by `@ElectronicBlueberry <https://github.com/ElectronicBlueberry>`_ in `#17331 <https://github.com/galaxyproject/galaxy/pull/17331>`_
* Enable ``warn_unreachable`` mypy option by `@mvdbeek <https://github.com/mvdbeek>`_ in `#17365 <https://github.com/galaxyproject/galaxy/pull/17365>`_
* Update to black 2024 stable style by `@nsoranzo <https://github.com/nsoranzo>`_ in `#17391 <https://github.com/galaxyproject/galaxy/pull/17391>`_
* Adds published histories to grid list by `@guerler <https://github.com/guerler>`_ in `#17449 <https://github.com/galaxyproject/galaxy/pull/17449>`_
* Consolidate resource grids into tab views by `@guerler <https://github.com/guerler>`_ in `#17487 <https://github.com/galaxyproject/galaxy/pull/17487>`_

-------------------
23.2.1 (2024-02-21)
-------------------


============
Enhancements
============

* Vueify Data Uploader by `@guerler <https://github.com/guerler>`_ in `#16472 <https://github.com/galaxyproject/galaxy/pull/16472>`_
* Create reusable `FilterMenu` with advanced options by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#16522 <https://github.com/galaxyproject/galaxy/pull/16522>`_
* Implement datatype upload warnings by `@jmchilton <https://github.com/jmchilton>`_ in `#16564 <https://github.com/galaxyproject/galaxy/pull/16564>`_
* Update Python dependencies by `@galaxybot <https://github.com/galaxybot>`_ in `#16577 <https://github.com/galaxyproject/galaxy/pull/16577>`_
* Vueify Tool Form Data Selector by `@guerler <https://github.com/guerler>`_ in `#16578 <https://github.com/galaxyproject/galaxy/pull/16578>`_
* Workflow Comments 💬 by `@ElectronicBlueberry <https://github.com/ElectronicBlueberry>`_ in `#16612 <https://github.com/galaxyproject/galaxy/pull/16612>`_
* Workflow Embed by `@ElectronicBlueberry <https://github.com/ElectronicBlueberry>`_ in `#16657 <https://github.com/galaxyproject/galaxy/pull/16657>`_
* Remove "Create Workflow" form and allow workflow creation in editor by `@ahmedhamidawan <https://github.com/ahmedhamidawan>`_ in `#16938 <https://github.com/galaxyproject/galaxy/pull/16938>`_

-------------------
23.1.4 (2024-01-04)
-------------------

No recorded changes since last release

-------------------
23.1.3 (2023-12-01)
-------------------

No recorded changes since last release

-------------------
23.1.2 (2023-11-29)
-------------------

No recorded changes since last release

-------------------
23.1.1 (2023-10-23)
-------------------


=========
Bug fixes
=========

* Improve robustness of collection upload tests. by `@jmchilton <https://github.com/jmchilton>`_ in `#16093 <https://github.com/galaxyproject/galaxy/pull/16093>`_
* Accessibility fixes for workflows, login, and registration. by `@jmchilton <https://github.com/jmchilton>`_ in `#16146 <https://github.com/galaxyproject/galaxy/pull/16146>`_
* Login/Register fixes by `@dannon <https://github.com/dannon>`_ in `#16652 <https://github.com/galaxyproject/galaxy/pull/16652>`_

============
Enhancements
============

* Upgraded to new multiselect Tags component for Workflows, DatasetList, Attributes by `@hujambo-dunia <https://github.com/hujambo-dunia>`_ in `#15225 <https://github.com/galaxyproject/galaxy/pull/15225>`_
* Add basic selenium test for shared histories by `@davelopez <https://github.com/davelopez>`_ in `#15538 <https://github.com/galaxyproject/galaxy/pull/15538>`_
* Initial end-to-end tests for separate quota sources per object store by `@jmchilton <https://github.com/jmchilton>`_ in `#15800 <https://github.com/galaxyproject/galaxy/pull/15800>`_
* Vueify Select field by `@guerler <https://github.com/guerler>`_ in `#16010 <https://github.com/galaxyproject/galaxy/pull/16010>`_
* implement admin jobs filtering by `@martenson <https://github.com/martenson>`_ in `#16020 <https://github.com/galaxyproject/galaxy/pull/16020>`_
* Selenium test for displaying workflows with problems in pages. by `@jmchilton <https://github.com/jmchilton>`_ in `#16085 <https://github.com/galaxyproject/galaxy/pull/16085>`_
* Integrate accessibility testing into Selenium testing by `@jmchilton <https://github.com/jmchilton>`_ in `#16122 <https://github.com/galaxyproject/galaxy/pull/16122>`_
* bring grids for (published) pages on par with workflows by `@martenson <https://github.com/martenson>`_ in `#16209 <https://github.com/galaxyproject/galaxy/pull/16209>`_
* Small test decorator improvements. by `@jmchilton <https://github.com/jmchilton>`_ in `#16220 <https://github.com/galaxyproject/galaxy/pull/16220>`_
* Initial e2e test for history storage. by `@jmchilton <https://github.com/jmchilton>`_ in `#16221 <https://github.com/galaxyproject/galaxy/pull/16221>`_
* Selenium test for page history links. by `@jmchilton <https://github.com/jmchilton>`_ in `#16222 <https://github.com/galaxyproject/galaxy/pull/16222>`_
* E2E Tests for Edit Dataset Attributes Page by `@jmchilton <https://github.com/jmchilton>`_ in `#16224 <https://github.com/galaxyproject/galaxy/pull/16224>`_
* Selenium type fixes and annotations. by `@jmchilton <https://github.com/jmchilton>`_ in `#16242 <https://github.com/galaxyproject/galaxy/pull/16242>`_
* e2e test for workflow license selector by `@jmchilton <https://github.com/jmchilton>`_ in `#16243 <https://github.com/galaxyproject/galaxy/pull/16243>`_

-------------------
23.0.6 (2023-10-23)
-------------------

No recorded changes since last release

-------------------
23.0.5 (2023-07-29)
-------------------

No recorded changes since last release

-------------------
23.0.4 (2023-06-30)
-------------------

No recorded changes since last release

-------------------
23.0.3 (2023-06-26)
-------------------

No recorded changes since last release

-------------------
23.0.2 (2023-06-13)
-------------------


============
Enhancements
============

* Port selenium setup to non-deprecated selenium options by `@mvdbeek <https://github.com/mvdbeek>`_ in `#16215 <https://github.com/galaxyproject/galaxy/pull/16215>`_

-------------------
23.0.1 (2023-06-08)
-------------------


============
Enhancements
============

* Add support for launching workflows via Tutorial Mode by `@hexylena <https://github.com/hexylena>`_ in `#15684 <https://github.com/galaxyproject/galaxy/pull/15684>`_

-------------------
20.9.0 (2020-10-15)
-------------------

* First release from the 20.09 branch of Galaxy.

-------------------
20.5.0 (2020-07-04)
-------------------

* First release from the 20.05 branch of Galaxy.
